Java tutorial
/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * For further information about Alkacon Software, please see the * company website: http://www.alkacon.com * * For further information about OpenCms, please see the * project website: http://www.opencms.org * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.alkacon.vie.client; import com.alkacon.vie.shared.I_Entity; import com.alkacon.vie.shared.I_EntityAttribute; import java.util.ArrayList; import java.util.List; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArrayString; import com.google.gwt.event.logical.shared.HasValueChangeHandlers; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.shared.EventHandler; import com.google.gwt.event.shared.GwtEvent; import com.google.gwt.event.shared.HandlerManager; import com.google.gwt.event.shared.HandlerRegistration; /** * The entity wrapper.<p> */ public final class Entity extends JavaScriptObject implements HasValueChangeHandlers<Entity>, I_Entity { /** Place holder value for empty strings. */ // HACK: this place holder is only used because the current native VIE implementation does // not support empty strings as values private static final String EMPTY_STRING = "########empty-string########"; /** * Constructor, for internal use only.<p> */ protected Entity() { } /** * Helper method for firing a 'value changed' event.<p> * * @param entity the entity that changed */ private static void fireValueChangedEvent(Entity entity) { ValueChangeEvent.fire(entity, entity); } /** * @see com.alkacon.vie.shared.I_Entity#addAttributeValue(java.lang.String, com.alkacon.vie.shared.I_Entity) */ public void addAttributeValue(String attributeName, I_Entity value) { internalAddAttributeValue(attributeName, value); registerChange((Entity) value); } /** * @see com.alkacon.vie.shared.I_Entity#addAttributeValue(java.lang.String, java.lang.String) */ public native void addAttributeValue(String attributeName, String value) /*-{ if (value == "") { value = @com.alkacon.vie.client.Entity::EMPTY_STRING; } this .setOrAdd( @com.alkacon.vie.client.Vie::addPointyBrackets(Ljava/lang/String;)(attributeName), value); }-*/; /** * Adds this handler to the widget. * * @param <H> the type of handler to add * @param type the event type * @param handler the handler * * @return {@link HandlerRegistration} used to remove the handler */ public <H extends EventHandler> HandlerRegistration addHandler(final H handler, GwtEvent.Type<H> type) { return ensureHandlers().addHandler(type, handler); } /** * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler) */ public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Entity> handler) { return addHandler(handler, ValueChangeEvent.getType()); } /** * @see com.alkacon.vie.shared.I_Entity#createDeepCopy(java.lang.String) */ public I_Entity createDeepCopy(String entityId) { I_Entity result = Vie.getInstance().createEntity(entityId, getTypeName()); for (I_EntityAttribute attribute : getAttributes()) { if (attribute.isSimpleValue()) { List<String> values = attribute.getSimpleValues(); for (String value : values) { result.addAttributeValue(attribute.getAttributeName(), value); } } else { List<I_Entity> values = attribute.getComplexValues(); for (I_Entity value : values) { I_Entity valueCopy = ((Entity) value).createDeepCopy(null); result.addAttributeValue(attribute.getAttributeName(), valueCopy); } } } return result; } /** * @see com.google.gwt.event.shared.HasHandlers#fireEvent(com.google.gwt.event.shared.GwtEvent) */ public void fireEvent(GwtEvent<?> event) { if (getHandlerManager() != null) { getHandlerManager().fireEvent(event); } } /** * @see com.alkacon.vie.shared.I_Entity#getAttribute(java.lang.String) */ public I_EntityAttribute getAttribute(String attributeName) { String internaltAttributeName = Vie.addPointyBrackets(attributeName); if (!hasAttribute(internaltAttributeName)) { return null; } if (isSimpleAttribute(internaltAttributeName)) { return new EntityAttribute(attributeName, getSimpleValues(internaltAttributeName)); } return new EntityAttribute(attributeName, getComplexValues(internaltAttributeName)); } /** * @see com.alkacon.vie.shared.I_Entity#getAttributes() */ public List<I_EntityAttribute> getAttributes() { List<I_EntityAttribute> result = new ArrayList<I_EntityAttribute>(); JsArrayString attributeNames = getAttributeNames(); for (int i = 0; i < attributeNames.length(); i++) { I_EntityAttribute attribute = getAttribute(attributeNames.get(i)); if (attribute != null) { result.add(attribute); } } return result; } /** * @see com.alkacon.vie.shared.I_Entity#getId() */ public native String getId() /*-{ try { var subject = this.getSubject(); } catch (error) { console.log(error); } subject = @com.alkacon.vie.client.Vie::removePointyBrackets(Ljava/lang/String;)(subject); return subject; }-*/; /** * @see com.alkacon.vie.shared.I_Entity#getTypeName() */ public native String getTypeName() /*-{ var type = this.get('@type'); var result = (typeof type === 'string') ? type : type.id; return @com.alkacon.vie.client.Vie::removePointyBrackets(Ljava/lang/String;)(result); }-*/; /** * @see com.alkacon.vie.shared.I_Entity#hasAttribute(java.lang.String) */ public native boolean hasAttribute(String attributeName) /*-{ return this .has(@com.alkacon.vie.client.Vie::addPointyBrackets(Ljava/lang/String;)(attributeName)); }-*/; /** * Returns if the entity has the given type.<p> * * @param type the type * * @return <code>true</code> if the entity has the given type */ public native boolean hasType(String type) /*-{ return this .hasType(@com.alkacon.vie.client.Vie::addPointyBrackets(Ljava/lang/String;)(type)); }-*/; /** * @see com.alkacon.vie.shared.I_Entity#insertAttributeValue(java.lang.String, com.alkacon.vie.shared.I_Entity, int) */ public void insertAttributeValue(String attributeName, I_Entity value, int index) { I_EntityAttribute attribute = getAttribute(attributeName); if (index < 0) { throw new IndexOutOfBoundsException("Index should be > 0"); } if ((attribute == null) && (index > 0)) { throw new IndexOutOfBoundsException("Index of " + index + " to big."); } if (attribute == null) { setAttributeValue(attributeName, value); } else { List<I_Entity> values = attribute.getComplexValues(); if (index > values.size()) { throw new IndexOutOfBoundsException("Index of " + index + " to big."); } if (index == values.size()) { addAttributeValue(attributeName, value); } else { removeAttributeSilent(attributeName); for (int i = 0; i < values.size(); i++) { if (i == index) { addAttributeValue(attributeName, value); } addAttributeValue(attributeName, values.get(i)); } } } } /** * @see com.alkacon.vie.shared.I_Entity#insertAttributeValue(java.lang.String, java.lang.String, int) */ public void insertAttributeValue(String attributeName, String value, int index) { I_EntityAttribute attribute = getAttribute(attributeName); if (index < 0) { throw new IndexOutOfBoundsException("Index should be > 0"); } if ((attribute == null) && (index > 0)) { throw new IndexOutOfBoundsException("Index of " + index + " to big."); } if (attribute == null) { setAttributeValue(attributeName, value); } else { List<String> values = attribute.getSimpleValues(); if (index > values.size()) { throw new IndexOutOfBoundsException("Index of " + index + " to big."); } if (index == values.size()) { addAttributeValue(attributeName, value); } else { removeAttributeSilent(attributeName); for (int i = 0; i < values.size(); i++) { if (i == index) { addAttributeValue(attributeName, value); } addAttributeValue(attributeName, values.get(i)); } } } } /** * Removes the given attribute.<p> * * @param attributeName the attribute name */ public native void removeAttribute(String attributeName) /*-{ this .unset(@com.alkacon.vie.client.Vie::addPointyBrackets(Ljava/lang/String;)(attributeName)); }-*/; /** * @see com.alkacon.vie.shared.I_Entity#removeAttributeSilent(java.lang.String) */ public native void removeAttributeSilent(String attributeName) /*-{ this .unset( @com.alkacon.vie.client.Vie::addPointyBrackets(Ljava/lang/String;)(attributeName), { silent : true }); }-*/; /** * @see com.alkacon.vie.shared.I_Entity#removeAttributeValue(java.lang.String, int) */ public void removeAttributeValue(String attributeName, int index) { if (!hasAttribute(attributeName)) { return; } I_EntityAttribute attribute = getAttribute(attributeName); if (attribute.isSingleValue() && (index == 0)) { removeAttribute(attributeName); } else { removeAttributeSilent(attributeName); if (attribute.isSimpleValue()) { for (int i = 0; i < attribute.getSimpleValues().size(); i++) { if (i != index) { addAttributeValue(attributeName, attribute.getSimpleValues().get(i)); } } } else { for (int i = 0; i < attribute.getComplexValues().size(); i++) { if (i != index) { addAttributeValue(attributeName, attribute.getComplexValues().get(i)); } } } } } /** * @see com.alkacon.vie.shared.I_Entity#setAttributeValue(java.lang.String, com.alkacon.vie.shared.I_Entity) */ public void setAttributeValue(String attributeName, I_Entity value) { internalSetAttributeValue(attributeName, value); registerChange((Entity) value); } /** * @see com.alkacon.vie.shared.I_Entity#setAttributeValue(java.lang.String, com.alkacon.vie.shared.I_Entity, int) */ public void setAttributeValue(String attributeName, I_Entity value, int index) { if (!(value instanceof Entity)) { throw new UnsupportedOperationException("May only set native entities as values."); } if ((index == 0) && !hasAttribute(attributeName)) { setAttributeValue(attributeName, value); } I_EntityAttribute attribute = getAttribute(attributeName); if ((index == 0) && attribute.isSingleValue()) { setAttributeValue(attributeName, value); } else { List<I_Entity> values = attribute.getComplexValues(); if (index >= values.size()) { throw new IndexOutOfBoundsException("Index of " + index + " to big."); } removeAttributeSilent(attributeName); for (int i = 0; i < values.size(); i++) { if (i == index) { addAttributeValue(attributeName, value); } else { addAttributeValue(attributeName, values.get(i)); } } } } /** * @see com.alkacon.vie.shared.I_Entity#setAttributeValue(java.lang.String, java.lang.String) */ public native void setAttributeValue(String attributeName, String value) /*-{ if (value == "") { value = @com.alkacon.vie.client.Entity::EMPTY_STRING; } attributeName = @com.alkacon.vie.client.Vie::addPointyBrackets(Ljava/lang/String;)(attributeName); this.unset(attributeName, { silent : true }); this.setOrAdd(attributeName, value); }-*/; /** * @see com.alkacon.vie.shared.I_Entity#setAttributeValue(java.lang.String, java.lang.String, int) */ public void setAttributeValue(String attributeName, String value, int index) { I_EntityAttribute attribute = getAttribute(attributeName); if ((attribute == null) || ((index == 0) && attribute.isSingleValue())) { setAttributeValue(attributeName, value); } else { List<String> values = attribute.getSimpleValues(); if (index >= values.size()) { throw new IndexOutOfBoundsException("Index of " + index + " to big."); } removeAttributeSilent(attributeName); for (int i = 0; i < values.size(); i++) { if (i == index) { addAttributeValue(attributeName, value); } else { addAttributeValue(attributeName, values.get(i)); } } } } /** * @see com.alkacon.vie.shared.I_Entity#toJSON() */ public native String toJSON() /*-{ return JSON.stringify(this); }-*/; /** * Sets the entity changed, triggering the value changed event.<p> */ protected native void setChanged() /*-{ this.change(); }-*/; /** * Binds the {@link #com.alkacon.vie.client.Entity.fireValueChangedEvent(Entity)} method * to the native change function and sets the handler manager for this instance.<p> * * @param handlerManager the handler manager to use */ private native void bindChange(HandlerManager handlerManager)/*-{ this.handlerManager = handlerManager; var self = this; this .bind( "change", function() { @com.alkacon.vie.client.Entity::fireValueChangedEvent(Lcom/alkacon/vie/client/Entity;)(self); }); }-*/; /** * Ensures the existence of the handler manager. * * @return the handler manager * */ private HandlerManager ensureHandlers() { if (getHandlerManager() == null) { bindChange(new HandlerManager(this)); } return getHandlerManager(); } /** * Returns the names of the available attributes.<p> * * @return the attribute names */ private native JsArrayString getAttributeNames() /*-{ var names = new Array(); var attributes = this.attributes; for ( var key in attributes) { names .push(@com.alkacon.vie.client.Vie::removePointyBrackets(Ljava/lang/String;)(key)); } return names; }-*/; /** * Returns the values of the given attribute as an array of entities.<p> * Check if the given attribute is of complex type first!!<p> * * @param attributeName the name of the attribute * * @return the attribute values */ private native I_EntityCollection getComplexValues(String attributeName) /*-{ var attr = this.get(attributeName); return attr; }-*/; /** * Returns the handler manager.<p> * * @return the handler manager */ private native HandlerManager getHandlerManager()/*-{ return this.handlerManager; }-*/; /** * Returns the values of the given attribute as an array of entities.<p> * Check if the given attribute is of complex type first!!<p> * * @param attributeName the name of the attribute * * @return the attribute values */ private native JsArrayString getSimpleValues(String attributeName) /*-{ var attr = this.get(attributeName); if (typeof attr === 'string') { attr = [ attr ]; } if (attr != null) { for ( var i = 0; i < attr.length; i++) { if (attr[i] == @com.alkacon.vie.client.Entity::EMPTY_STRING) { attr[i] = ""; } } } return attr; }-*/; /** * Internal method to add a complex attribute value.<p> * * @param attributeName the attribute name * @param value the value */ private native void internalAddAttributeValue(String attributeName, I_Entity value) /*-{ this .setOrAdd( @com.alkacon.vie.client.Vie::addPointyBrackets(Ljava/lang/String;)(attributeName), value); }-*/; /** * Internal method to set a complex attribute value.<p> * * @param attributeName the attribute name * @param value the value */ private native void internalSetAttributeValue(String attributeName, I_Entity value) /*-{ attributeName = @com.alkacon.vie.client.Vie::addPointyBrackets(Ljava/lang/String;)(attributeName); this.unset(attributeName, { silent : true }); this.set(attributeName, value); }-*/; /** * Returns if the given attribute is of the simple type.<p> * * @param attributeName the name of the attribute * * @return <code>true</code> is this is a simple type attribute */ private native boolean isSimpleAttribute(String attributeName) /*-{ var attr = this.get(attributeName); if (typeof attr === 'string') { return true; } if (attr.isEntity) { return false; } if (Object.prototype.toString.call(attr) === '[object Array]') { if (typeof attr[0] === 'string') { return true; } } return false; }-*/; /** * Registers the change event of the new child to trigger change on this entity.<p> * * @param child the child to register */ private native void registerChange(Entity child) /*-{ var self = this; child.bind("change", function() { self.change(); }); }-*/; }