All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.birt.report.model.api.DesignElementHandle Maven / Gradle / Ivy

There is a newer version: 4.6.0-20160607
Show newest version
/*******************************************************************************
 * Copyright (c) 2004 Actuate Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *  Actuate Corporation  - initial API and implementation
 *******************************************************************************/

package org.eclipse.birt.report.model.api;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.birt.report.model.activity.ActivityStack;
import org.eclipse.birt.report.model.api.activity.SemanticException;
import org.eclipse.birt.report.model.api.command.ContentException;
import org.eclipse.birt.report.model.api.command.ExtendsException;
import org.eclipse.birt.report.model.api.command.NameException;
import org.eclipse.birt.report.model.api.command.PropertyNameException;
import org.eclipse.birt.report.model.api.command.StyleException;
import org.eclipse.birt.report.model.api.command.TemplateException;
import org.eclipse.birt.report.model.api.command.UserPropertyException;
import org.eclipse.birt.report.model.api.core.IDesignElement;
import org.eclipse.birt.report.model.api.core.IModuleModel;
import org.eclipse.birt.report.model.api.core.IStructure;
import org.eclipse.birt.report.model.api.core.Listener;
import org.eclipse.birt.report.model.api.core.UserPropertyDefn;
import org.eclipse.birt.report.model.api.elements.DesignChoiceConstants;
import org.eclipse.birt.report.model.api.elements.SemanticError;
import org.eclipse.birt.report.model.api.elements.structures.PropertyBinding;
import org.eclipse.birt.report.model.api.metadata.IChoice;
import org.eclipse.birt.report.model.api.metadata.IElementDefn;
import org.eclipse.birt.report.model.api.metadata.IElementPropertyDefn;
import org.eclipse.birt.report.model.api.metadata.IPropertyType;
import org.eclipse.birt.report.model.api.metadata.ISlotDefn;
import org.eclipse.birt.report.model.api.util.StringUtil;
import org.eclipse.birt.report.model.api.util.XPathUtil;
import org.eclipse.birt.report.model.command.ComplexPropertyCommand;
import org.eclipse.birt.report.model.command.ContentCommand;
import org.eclipse.birt.report.model.command.EncryptionCommand;
import org.eclipse.birt.report.model.command.ExtendsCommand;
import org.eclipse.birt.report.model.command.NameCommand;
import org.eclipse.birt.report.model.command.PropertyCommand;
import org.eclipse.birt.report.model.command.StyleCommand;
import org.eclipse.birt.report.model.command.TemplateCommand;
import org.eclipse.birt.report.model.command.UserPropertyCommand;
import org.eclipse.birt.report.model.core.ContainerContext;
import org.eclipse.birt.report.model.core.DesignElement;
import org.eclipse.birt.report.model.core.Module;
import org.eclipse.birt.report.model.core.Structure;
import org.eclipse.birt.report.model.core.StructureContext;
import org.eclipse.birt.report.model.core.StyleElement;
import org.eclipse.birt.report.model.elements.Library;
import org.eclipse.birt.report.model.elements.MultiViews;
import org.eclipse.birt.report.model.elements.ReportDesign;
import org.eclipse.birt.report.model.elements.TemplateElement;
import org.eclipse.birt.report.model.elements.interfaces.IDesignElementModel;
import org.eclipse.birt.report.model.elements.interfaces.IReportItemModel;
import org.eclipse.birt.report.model.elements.interfaces.IStyleModel;
import org.eclipse.birt.report.model.i18n.MessageConstants;
import org.eclipse.birt.report.model.i18n.ThreadResources;
import org.eclipse.birt.report.model.metadata.ElementDefn;
import org.eclipse.birt.report.model.metadata.ElementPropertyDefn;
import org.eclipse.birt.report.model.metadata.ElementRefValue;
import org.eclipse.birt.report.model.metadata.PropertyDefn;
import org.eclipse.birt.report.model.metadata.ReferenceValue;
import org.eclipse.birt.report.model.metadata.StructRefValue;
import org.eclipse.birt.report.model.util.CommandLabelFactory;
import org.eclipse.birt.report.model.util.ModelUtil;
import org.eclipse.birt.report.model.util.ReferenceValueUtil;

import com.ibm.icu.util.ULocale;

/**
 * Base class for all report elements. Provides a high-level interface to the
 * BIRT report model. This class provides generic services for all elements.
 * Derived classes provide specialized methods for each element type.
 * 

* Element handles are immutable. Once created, they always point to the same * element. Handles also cannot point to a null element. An assertion will be * raised if the derived classes are created with a null element. *

* For a complete description of the services available for any design element, * see the class description for the * {@link org.eclipse.birt.report.model.core.DesignElement}class. * * @see SlotHandle * @see org.eclipse.birt.report.model.core.DesignElement */ public abstract class DesignElementHandle implements IDesignElementModel { /** * Provides overall information about the root element. If the element is on * the design tree, the root is corresponding library/design. If the element * is not on the tree, the root is the module of ElementFactory that creates * this DesignElementHandle. */ protected final Module module; /** * API slot handle array for all slots of this element. */ private SlotHandle[] slotHandles = null; /** * Property handle for element type properties. */ private Map propHandles = new HashMap( ); /** * Constructs a handle with the given module. * * @param module * the module */ public DesignElementHandle( Module module ) { this.module = module; } /** * Constructs slot handles in the constructor to make sure that getMumble() * methods won't construct any new instance. */ final protected void initializeSlotHandles( ) { int slotCount = getDefn( ).getSlotCount( ); if ( slotCount == 0 ) { return; } Iterator iter1 = ( (ElementDefn) getDefn( ) ) .slotsIterator( ); if ( slotHandles == null ) { slotHandles = new SlotHandle[slotCount]; for ( int i = 0; i < slotCount; i++ ) { slotHandles[i] = new SlotHandle( this, iter1.next( ) .getSlotID( ) ); } } } /** * Constructs slot handles in the constructor to make sure that getMumble() * methods won't construct any new instance. */ protected void cachePropertyHandles( ) { List contents = getElement( ).getPropertyDefns( ); for ( int i = 0; i < contents.size( ); i++ ) { ElementPropertyDefn propDefn = (ElementPropertyDefn) contents .get( i ); if ( !propDefn.isElementType( ) ) continue; PropertyHandle pHandle = new PropertyHandle( this, propDefn ); propHandles.put( propDefn.getName( ), pHandle ); } } /** * Returns the report design only when the module is report design. * Otherwise, null is returned. So this method can also be used to check * whether this element is in report design or library. * * @return the report design, or null if the module is not report design. * @deprecated replaced by getModule() */ public ReportDesign getDesign( ) { if ( module instanceof ReportDesign ) return (ReportDesign) module; return null; } /** * Returns the module on which this handle is attached. The returned module * must be ReportDesign or Library. * * @return the module on which this handle is attached. */ public Module getModule( ) { return module; } /** * Returns the handle of report design only when the module is report * design. Otherwise, null is returned. * * @return the handle of report design, or null if the module is not report * design. * @deprecated replaced by getModuleHandle() */ public ReportDesignHandle getDesignHandle( ) { if ( getDesign( ) != null ) return (ReportDesignHandle) getDesign( ).getHandle( module ); return null; } /** * Returns the handle of module. The returned module must be * ReportDesignHandle or LibraryHandle. * * @return the handle of module */ public ModuleHandle getModuleHandle( ) { return (ModuleHandle) getModule( ).getHandle( getModule( ) ); } /** * Returns the element to which this handle is attached. * * @return The attached element. Will be null if the handle is not attached. */ public abstract DesignElement getElement( ); /** * Gets the definition of the element. The definition provides meta-data * about the element, such as its type name, list of defined properties, * list of slots and so on. * * @return the meta-data definition of the element */ public IElementDefn getDefn( ) { return getElement( ).getDefn( ); } /** * Returns the value of a property as a generic object. The value is the * internal property value, it is not localized. For a property with the * element reference type, the reference element name is returned. * * @param propName * the name of the property of interest * @return the value of the property. The type of the returned object * depends on the property type. * @see #getIntProperty * @see #getStringProperty * @see #getFloatProperty * @see #getNumberProperty */ public Object getProperty( String propName ) { // Must be attached to use this method. DesignElement element = getElement( ); Object value = element.getProperty( module, propName ); PropertyDefn defn = (PropertyDefn) getPropertyDefn( propName ); return ModelUtil.wrapPropertyValue( module, defn, value ); } /** * Returns the value of a property as a string which is locale independent. * * @param propName * the name of the property * @return the internal string property value of the property. */ public String getStringProperty( String propName ) { return getElement( ).getStringProperty( module, propName ); } /** * Return a localized string version of the property. This method will works * for all property types except a list. Dates and numbers will be converted * using the current locale. Display name will be returned for a choice or a * color property. * * @param propName * the name of the property * @return a localized string version of the property. */ public String getDisplayProperty( String propName ) { return getElement( ).getDisplayProperty( module, propName ); } /** * Returns the value of a property as a Boolean. * * @param propName * the name of the property * @return the value as a boolean */ public boolean getBooleanProperty( String propName ) { return getElement( ).getBooleanProperty( module, propName ); } /** * Returns the value of a property as an integer. * * @param propName * the name of the property. * @return the value as an integer. Return 0 if the value cannot be * converted to an integer. */ public int getIntProperty( String propName ) { return getElement( ).getIntProperty( module, propName ); } /** * Returns the value of a property as a double. * * @param propName * the name of the property. * @return the value as a double. Returns null if the value * cannot be converted to a double. */ public double getFloatProperty( String propName ) { return getElement( ).getFloatProperty( module, propName ); } /** * Returns the value of a property as a number (BigDecimal). * * @param propName * the name of the property. * @return the value as a number. Returns null if the value * cannot be converted to a number. */ public BigDecimal getNumberProperty( String propName ) { return getElement( ).getNumberProperty( module, propName ); } /** * Returns a handle to work with a Dimension property. Returns null if the * given property is not defined or not dimension property. * * @param propName * name of the property. * @return a corresponding DimensionHandle to deal with the dimension * property. Return null if the property is defined or * not dimension property. * * @see DimensionHandle */ public DimensionHandle getDimensionProperty( String propName ) { ElementPropertyDefn propDefn = getElement( ).getPropertyDefn( propName ); if ( propDefn == null ) return null; if ( propDefn.getTypeCode( ) != IPropertyType.DIMENSION_TYPE ) return null; return new DimensionHandle( this, propDefn ); } /** * Returns a handle to work with a color property. Returns null if the given * property is not defined or not color property. * * @param propName * name of the property. * @return a corresponding ColorHandle to with with the color property. * Return null if the given property is not defined or * not color property. * * @see ColorHandle */ public ColorHandle getColorProperty( String propName ) { ElementPropertyDefn propDefn = getElement( ).getPropertyDefn( propName ); if ( propDefn == null ) return null; if ( propDefn.getTypeCode( ) != IPropertyType.COLOR_TYPE ) return null; return new ColorHandle( this, propDefn ); } /** * Gets the font handle for the element. If this element defines a font * family property, return a FontHandle. Otherwise, return * null. * * @return a corresponding FontHandle or null. * * @see FontHandle */ protected FontHandle getFontProperty( ) { ElementPropertyDefn propDefn = getElement( ).getPropertyDefn( IStyleModel.FONT_FAMILY_PROP ); if ( propDefn == null ) return null; return new FontHandle( this ); } /** * Returns the value of an element reference property. Returns a handle to * the referenced element, or null if the reference is * unresolved or unset. * * @param propName * the name of the property. * @return a corresponding DesignElement handle to the referenced element */ public DesignElementHandle getElementProperty( String propName ) { DesignElement target = getElement( ).getReferenceProperty( module, propName ); if ( target == null ) return null; return target.getHandle( target.getRoot( ) ); } /** * Gets the value of a property as a list. * * @param module * the module * @param propName * the name of the property to get * @return the value as an ArrayList, or null if the property * is not set or the value is not a list * @deprecated replaced by {@link #getListProperty(String)} */ public List getListProperty( Module module, String propName ) { return getElement( ).getListProperty( module, propName ); } /** * Gets the value of a property as a list. * * @param module * the module * @param propName * the name of the property to get * @return the value as an ArrayList, or null if the property * is not set or the value is not a list */ public List getListProperty( String propName ) { PropertyHandle propHandle = getPropertyHandle( propName ); return propHandle == null ? null : propHandle.getListValue( ); } /** * Sets the value of a property from a generic object. The value can be any * of the supported types: String, Double, Integer, BigDecimal or one of the * specialized property types. The type of object allowed depends on the * type of the property. * * @param propName * the property name * @param value * the value to set * @throws SemanticException * if the property is undefined on the element or the value is * invalid. */ public void setProperty( String propName, Object value ) throws SemanticException { // Must be attached to use this method. DesignElement element = getElement( ); PropertyCommand cmd = new PropertyCommand( module, element ); cmd.setProperty( propName, value ); } /** * Sets the value of a property to an integer. * * @param propName * the property name * @param value * the value to set * @throws SemanticException * If the property value cannot be converted from an integer, or * if the value of a choice is incorrect. */ public void setIntProperty( String propName, int value ) throws SemanticException { setProperty( propName, Integer.valueOf( value ) ); } /** * Sets the value of a property to a string. Use this for properties such as * expressions, labels, HTML, or XML. Also use it to set the value of a * choice using the internal string name of the choice. Use it to set the * value of a dimension when using specified units, such as "10pt". * * @param propName * the property name * @param value * the value to set * @throws SemanticException * if the value of a choice or other property is incorrect. */ public void setStringProperty( String propName, String value ) throws SemanticException { setProperty( propName, value ); } /** * Sets the value of a property to a double. When used for dimension * properties, the units of the dimension are assumed to be in application * units. * * @param propName * the property name * @param value * the value to set * @throws SemanticException * If the property value cannot be converted from a double. */ public void setFloatProperty( String propName, double value ) throws SemanticException { setProperty( propName, new Double( value ) ); } /** * Sets the value of a property to a number (BigDecimal). * * @param propName * the property name * @param value * the value to set * @throws SemanticException * if the property value cannot be converted from a number. */ public void setNumberProperty( String propName, BigDecimal value ) throws SemanticException { setProperty( propName, value ); } /** * Sets the boolean value to the property. * * @param propName * the name of the property to set * @param value * the boolean value to set * @throws SemanticException * if the property is not defined or value is invalid */ public void setBooleanProperty( String propName, boolean value ) throws SemanticException { setProperty( propName, Boolean.valueOf( value ) ); } /** * Clears the value of a property. Clearing a property removes any value set * for the property on this element. After this, the element will now * inherit the property from its parent element, style, or from the default * value for the property. * * @param propName * the name of the property to clear. * @throws SemanticException * if the property is not defined on this element */ public void clearProperty( String propName ) throws SemanticException { setProperty( propName, null ); } /** * Clears values of all properties. Clearing a property removes any value * set for the property on this element. After this, the element will now * inherit the property from its parent element, style, or from the default * value for the property. * * @throws SemanticException * if the property is not defined on this element */ public void clearAllProperties( ) throws SemanticException { List props = getDefn( ).getProperties( ); ActivityStack stack = module.getActivityStack( ); stack.startTrans( CommandLabelFactory .getCommandLabel( MessageConstants.CLEAR_PROPERTIES_MESSAGE ) ); try { for ( int i = 0; i < props.size( ); i++ ) { PropertyDefn propDefn = (PropertyDefn) props.get( i ); String propName = propDefn.getName( ); if ( ( IDesignElementModel.NAME_PROP.equals( propName ) ) ) { NameCommand nameCmd = new NameCommand( module, getElement( ) ); try { nameCmd.checkName( null ); } catch ( NameException e ) { continue; } } PropertyHandle propHandle = getPropertyHandle( propName ); if ( propHandle.isLocal( ) ) propHandle.clearValue( ); } } catch ( SemanticException e ) { stack.rollback( ); throw e; } stack.commit( ); } /** * Returns true if this element has any locally-defined * property values. Returns false otherwise. * * @return True if the element has property values, false if not. */ public boolean hasLocalProperties( ) { return getElement( ).hasLocalPropertyValues( ); } /** * Adds a user-defined property definition. The property definition must * have a valid name and property type. The other attributes can be set * either before or after adding the property to the element. The * application can modify the property definition directly before adding the * property to an element. However, the application must use a structure * handle to modify the definition after it has been added to an element. * * @param prop * the user property definition to add. The name and property * type must be valid. * @throws UserPropertyException * if the element is not allowed to have user property or the * user property definition is invalid, or if the value of the * user-defined choice is invalid for the type of user property * definition, the property type is incorrect. */ public void addUserPropertyDefn( UserPropertyDefn prop ) throws UserPropertyException { DesignElement element = getElement( ); UserPropertyCommand cmd = new UserPropertyCommand( module, element ); cmd.addUserProperty( prop ); } /** * Adds a report item to the given slot at the given position. The item must * be newly created and not yet added to the design. * * @param child * handle to the newly created element * @param slotId * slot id in which the child item will be added. * @param pos * position in the slot that the child item will be added. * @throws ContentException * if the element is not allowed in the slot * @throws NameException * if the element has a duplicate or illegal name * */ public void addElement( DesignElementHandle child, int slotId, int pos ) throws ContentException, NameException { SlotHandle slotHandle = getSlot( slotId ); if ( slotHandle != null ) slotHandle.add( child, pos ); } /** * Adds a report item to the end of the given slot. The item must be newly * created and not yet added to the design. * * @param child * handle to the newly created element * @param slotId * slot id in which the child item will be added. * @throws ContentException * if the element is not allowed in the slot * @throws NameException * if the element has a duplicate or illegal name * */ public void addElement( DesignElementHandle child, int slotId ) throws ContentException, NameException { SlotHandle slotHandle = getSlot( slotId ); if ( slotHandle != null ) slotHandle.add( child ); } /** * Returns the methods defined on the element definition. * * @return List contains the methods. * */ public List getMethods( ) { List methods = getElement( ).getDefn( ) .getMethods( ); if ( getElement( ).isInSlot( IModuleModel.PAGE_SLOT ) ) { // Added for bugzila 276665, filter the method "onPageBreak" if the // element is contained by a master page. for ( IElementPropertyDefn method : methods ) { if ( IReportItemModel.ON_PAGE_BREAK_METHOD.equals( method .getName( ) ) ) { methods.remove( method ); break; } } } return methods; } /** * Sets a bunch of property values on the element. If this operation should * be treated as a whole, execution should be in a transaction. * * @param properties * a Map store the property values keyed by the property name. * @throws SemanticException * if the property is undefined on the element or the value is * invalid. * @see #setProperty(String, Object) */ public void setProperties( Map properties ) throws SemanticException { if ( properties == null ) return; for ( Iterator iter = properties.entrySet( ).iterator( ); iter .hasNext( ); ) { Entry entry = (Entry) iter.next( ); setProperty( (String) entry.getKey( ), entry.getValue( ) ); } } /** * Clears all the content within the given slot. If this operation should be * treated as a whole, execution should be in a transaction. * * @param slotId * id of the slot to be cleared. * @throws SemanticException */ public void clearContents( int slotId ) throws SemanticException { SlotHandle slotHandle = getSlot( slotId ); if ( slotHandle == null ) return; for ( int i = slotHandle.getCount( ) - 1; i >= 0; i-- ) { slotHandle.dropAndClear( i ); } } /** * Removes an existing user property definition from the element. This * method will remove all existing values for the property, in both this * element and all its derived elements. * * @param propName * the name of the user property to remove * @throws UserPropertyException * If the property is not found. */ public void dropUserPropertyDefn( String propName ) throws UserPropertyException { DesignElement element = getElement( ); UserPropertyCommand cmd = new UserPropertyCommand( module, element ); cmd.dropUserProperty( propName ); } /** * Returns a handle to the element that this element extends. * * @return the parent element. Returns null if this element * does not have a parent, or if the extends name does not resolve * to a valid element. */ public DesignElementHandle getExtends( ) { DesignElement parent = getElement( ).getExtendsElement( ); if ( parent == null ) return null; return parent.getHandle( parent.getRoot( ) ); } /** * Sets this element to extend the given element. * * @param parent * handle to the element that this element is to extend. If * null, then this element will no longer extend * another element. * @throws ExtendsException * if the parent element is of the wrong type as this element. */ public void setExtends( DesignElementHandle parent ) throws ExtendsException { ExtendsCommand cmd = new ExtendsCommand( module, getElement( ) ); cmd.setExtendsElement( parent ); } /** * Sets the name of the element that this element extends. The name must * resolve to an element of the same type as this element. * * @param name * the name of the element that this one is to extend * @throws ExtendsException * if no element exists with the given name, or if the element * is of the wrong type. */ public void setExtendsName( String name ) throws ExtendsException { DesignElement element = getElement( ); ExtendsCommand cmd = new ExtendsCommand( module, element ); cmd.setExtendsName( name ); } /** * Localize the element, break the parent/child relationship and set all the * extended properties locally. * * @throws SemanticException * the element can not be localized properly. It may be because * that the element is not extended from a parent, or that same * properties can not be localized on the element or the content * elements inside it. */ public void localize( ) throws SemanticException { DesignElement element = getElement( ); ExtendsCommand cmd = new ExtendsCommand( module, element ); cmd.localizeElement( ); } /** * Sets this element to extend the given element. * * @param parent * the element that this element is to extend * @throws ExtendsException * If the parent element is of the wrong type as this element. * * @deprecated by {@link #setExtends(DesignElementHandle)} */ public void setExtendsElement( DesignElement parent ) throws ExtendsException { ExtendsCommand cmd = new ExtendsCommand( module, getElement( ) ); cmd.setExtendsElement( parent ); } /** * Returns the shared style, if any, as a style handle. A shared style is a * style that defines in the "styles" slot of the report design. * * @return a handle to the shared style used by this element. Returns null * if the style is not set, or if the element does not support a * style. * * @see #setStyle(SharedStyleHandle) * @see #setStyleElement(StyleElement) * @see #setStyleName(String) */ public SharedStyleHandle getStyle( ) { DesignElement style = getElement( ).getStyle( module ); if ( style == null ) return null; return (SharedStyleHandle) style.getHandle( module ); } /** * Sets the name of the shared style for this element. * * @param name * the name of the shared style. If null, then the * shared style name is cleared. * @throws StyleException * If the name is not valid, or if this element does not support * a style. * * @see #getStyle() */ public void setStyleName( String name ) throws StyleException { DesignElement element = getElement( ); StyleCommand cmd = new StyleCommand( module, element ); cmd.setStyle( name ); } /** * Sets the shared style element for this element. * * @param obj * the shared style. If null, then the shared style * is cleared. * @throws StyleException * If this element does not support a style. * @see #getStyle() * * @deprecated by {@link #setStyle(SharedStyleHandle)} */ public void setStyleElement( StyleElement obj ) throws StyleException { DesignElement element = getElement( ); StyleCommand cmd = new StyleCommand( module, element ); cmd.setStyleElement( obj ); } /** * Sets the shared style element for this element. * * @param style * the handle to the shared style. If null, then the shared style * is cleared. * @throws StyleException * if this element does not support a style. * @see #getStyle() */ public void setStyle( SharedStyleHandle style ) throws StyleException { if ( style == null ) setStyleElement( null ); else setStyleElement( (StyleElement) style.getElement( ) ); } /** * Returns a handle to work with the style properties of this element. Use a * style handle to work with the specific getter/setter methods for each * style property. The style handle is not necessary to work with style * properties generically. *

* Note a key difference between this method and the * getStyle( ) method. This method returns a handle to the * this element. The getStyle( ) method returns a * handle to the shared style, if any, that this element references. * * @return a style handle to work with the style properties of this element. * Returns null if this element does not have style * properties. */ public StyleHandle getPrivateStyle( ) { if ( getDefn( ).hasStyle( ) ) return new PrivateStyleHandle( module, getElement( ) ); return null; } /** * Returns the name of this element. Returns null if the * element does not have a name. Many elements do not require a name. The * name does not inherit. If this element does not have a name, it will not * inherit the name of its parent element. * * @return the element name, or null if the name is not set */ public String getName( ) { return getElement( ).getName( ); } /** * Returns the full name of this element. Generally, the full name is * identical with the name of the element. That is the returned value is * just what returned by {@link #getName()}.However, some elements have a * local name scope and its full name is not the name of the element itself. * For example, the name of the level is managed by its contaienr dimension * element. Therefore its full name is that name of the container dimension * appends character '/' and appends the name of the level itself, like * dimensionName/levelName. If the level has no container dimension, then * its full name is the same as the name. * * @return the full name of the element */ public String getFullName( ) { return getElement( ).getFullName( ); } /** * Gets the name of this element. The returned element name will be the same * as getName(), plus the namespace of the module that the * element is contained, if the element name resides in the whole design * tree scope; otherwise we will append the name of the holder where the * element name resides. If the element is existed in the current * module,this method and getName() will return identical * results. * * @return the qualified name of the element. */ public String getQualifiedName( ) { String name = getElement( ).getFullName( ); if ( name == null ) return null; Module rootElement = getModule( ); assert rootElement != null; String namespace = rootElement.getNamespace( ); // if the root is library or other else that is included by other // modules, then it will have a unique namespace return StringUtil.buildQualifiedReference( namespace, name ); } /** * Sets the name of this element. If the name is null, then the * name is cleared if this element does not require a name. * * @param name * the new name * @throws NameException * if the name is duplicate, or if the name is null * and this element requires a name. */ public void setName( String name ) throws NameException { NameCommand cmd = new NameCommand( module, getElement( ) ); cmd.setName( name ); } /** * Returns the unique ID for this object. The ID is valid only within this * one design session. IDs are available only if the application is * configured to use IDs. In general, the web client requires IDs, but the * Eclipse client does not. * * @return the element ID * @see ModuleHandle#getElementByID * @see org.eclipse.birt.report.model.metadata.MetaDataDictionary#enableElementID */ public long getID( ) { return getElement( ).getID( ); } /** * Returns the element factory for creating new report elements. After * creating the element, add it to the design by calling the the * {@link SlotHandle#add(DesignElementHandle ) add} * method of the slot handle that represents the point in the design where * the new element should appear. * * @return a handle to the new element. * @see SlotHandle */ public ElementFactory getElementFactory( ) { return new ElementFactory( module ); } /** * Returns a property handle for a top-level property. A top-level property * is a property that defines on an element. * * @param propName * the name of the property to get * @return The property handle, or null if the no property * exists with the given name. * @see PropertyHandle */ public PropertyHandle getPropertyHandle( String propName ) { if ( propName == null ) return null; DesignElement element = getElement( ); ElementPropertyDefn propDefn = element.getPropertyDefn( propName ); if ( propDefn == null ) return null; // get cached values if ( propDefn.isElementType( ) && !( this instanceof ContentElementHandle ) ) { PropertyHandle propHandle = propHandles.get( propName ); if ( propHandle != null ) return propHandle; else { cachePropertyHandles( ); return propHandles.get( propName ); } } return new PropertyHandle( this, propDefn ); } /** * Returns a user-defined property handle for a top-level property. A * top-level property is a property that defines on an element. * * @param propName * the name of the property to get * @return the user property definition handle, or null if the * no property exists with the given name or it is not a * user-defined property. */ public UserPropertyDefnHandle getUserPropertyDefnHandle( String propName ) { DesignElement element = getElement( ); ElementPropertyDefn propDefn = element.getPropertyDefn( propName ); if ( propDefn == null ) return null; if ( propDefn.isUserProperty( ) ) { return new UserPropertyDefnHandle( this, (UserPropertyDefn) propDefn ); } return null; } /** * Returns a list of user properties defined in this element and somewhere * up the inheritance chain. Each object in the list is instance of * UserPropertyDefn. * * @return The list of user property definitions */ public List getUserProperties( ) { return getElement( ).getUserProperties( ); } /** * Returns a handle for a top-level property for use in preparing the * Factory data structures. This handle follows specialized rules: *

*

    *
  • Optimized to get each property value only once.
  • *
  • Indicates if the value is a style property.
  • *
  • Indicates if a style property is set on the element's private style * or a shared style.
  • *
  • Performs property conversions as needed for the Factory context.
  • *
* * @param propName * the name of the property to get * @return the factory property handle, or null if either 1) no * property exists with the given name or 2) the property is a style * property and is not set in a private style. */ public FactoryPropertyHandle getFactoryPropertyHandle( String propName ) { DesignElement element = getElement( ); ElementPropertyDefn propDefn = element.getPropertyDefn( propName ); if ( propDefn == null ) return null; FactoryPropertyHandle handle = new FactoryPropertyHandle( this, propDefn ); if ( handle.isSet( ) ) return handle; return null; } /** * Returns a handle to the element that contains this element. Every element * except the report design has a container. The container of a parameter, * shared style, data source or data set is the report design itself. The * container of a report item is the section or other report item in which * it appears. * * @return a handle to the container element. */ public DesignElementHandle getContainer( ) { DesignElement element = getElement( ).getContainer( ); if ( element == null ) return null; return element.getHandle( module ); } /** * Moves this element to a new location within the design. * * @param newContainer * the new container element * @param toSlot * the target slot within the new container * @throws ContentException * If the element cannot be placed into the target element or * slot, perhaps because the element is of the wrong type, the * slot is full, or other error. * @see SlotHandle */ public void moveTo( DesignElementHandle newContainer, int toSlot ) throws ContentException { DesignElement element = getElement( ); DesignElement oldContainer = element.getContainer( ); if ( oldContainer == null ) throw new ContentException( element, -1, ContentException.DESIGN_EXCEPTION_HAS_NO_CONTAINER ); ContentCommand cmd = new ContentCommand( module, element .getContainerInfo( ) ); cmd.move( element, new ContainerContext( newContainer.getElement( ), toSlot ) ); } /** * Drops this element from the design. Removes the element from its * container and name space, if any. *

* Note: If this element is referencable, the property referring it will be * set null. * * @throws SemanticException * if this element has no container or the element cannot be * dropped. * @see SlotHandle * @see #drop() */ public void dropAndClear( ) throws SemanticException { DesignElement element = getElement( ); DesignElement container = element.getContainer( ); if ( container == null ) throw new ContentException( element, -1, ContentException.DESIGN_EXCEPTION_HAS_NO_CONTAINER ); ContentCommand cmd = new ContentCommand( module, element .getContainerInfo( ) ); cmd.remove( element ); } /** * Drops this element from the design. Removes the element from its * container and name space, if any. *

* Note: If this element is referencable, the property referring it will be * unresolved. * * @throws SemanticException * if this element has no container or the element cannot be * dropped. * @see SlotHandle * @see #dropAndClear() */ public void drop( ) throws SemanticException { DesignElement element = getElement( ); DesignElement container = element.getContainer( ); if ( container == null ) throw new ContentException( element, -1, ContentException.DESIGN_EXCEPTION_HAS_NO_CONTAINER ); ContentCommand cmd = new ContentCommand( module, element .getContainerInfo( ), false, true ); cmd.remove( element ); } /** * Finds the slot within this element that contains the given element. * * @param content * handle to the content element to find * @return The ID of the slot that contains the element, or * {@link DesignElement#NO_SLOT}if the element is not contained in * this element. */ public int findContentSlot( DesignElementHandle content ) { if ( content.getContainer( ).getElement( ) == getElement( ) ) return content.getElement( ).getContainerInfo( ).getSlotID( ); return IDesignElementModel.NO_SLOT; } /** * Returns the a handle the the container's slot that holds this element. * * @return the slot handle in which this element resides, null * if this element has no container. */ public SlotHandle getContainerSlotHandle( ) { DesignElementHandle containerHandle = getContainer( ); if ( containerHandle == null ) return null; int slotID = containerHandle.findContentSlot( this ); // if not find , return null. if ( slotID == IDesignElementModel.NO_SLOT ) return null; return containerHandle.getSlot( slotID ); } /** * Gets a handle for the container's property what holds this element. * * @return the property handle in which this element resides, * null if this element has no container */ public PropertyHandle getContainerPropertyHandle( ) { DesignElementHandle containerHandle = getContainer( ); if ( containerHandle == null ) return null; return containerHandle.getPropertyHandle( getElement( ) .getContainerInfo( ).getPropertyName( ) ); } /** * Returns a handle to the given slot. If this element has no such slot, * null will be returned. * * @param slotID * the identifier of the slot for which to obtain a handle * @return the handle for the requested slot */ public SlotHandle getSlot( int slotID ) { if ( slotID < 0 || slotHandles == null ) { return null; } int index = getElement( ).getSlotIndex( slotID ); if ( index == -1 ) return null; return slotHandles[index]; } /** * Returns the iterator for slot defined on the element. * * @return the iterator for SlotHandle * */ public Iterator slotsIterator( ) { if ( slotHandles == null ) return Collections. emptyList( ).iterator( ); return Arrays.asList( slotHandles ).iterator( ); } /** * Returns an iterator over the properties of this element. This handle * returns all properties defined on this element, whether or not they are * actually set on this element. * * @return an iterator over the properties. Each call to * getNext( ) returns an object of type * {@link PropertyHandle}. * @see PropertyIterator * @see PropertyHandle * @see UserPropertyDefnHandle */ public Iterator getPropertyIterator( ) { return new PropertyIterator( this ); } /** * Registers a change event listener. A listener receives notifications each * time an element changes. A listener can be registered any number of * times, but will receive each event only once. * * @param obj * the listener to register */ public void addListener( Listener obj ) { getElement( ).addListener( obj ); } /** * Removes a given listener. If the listener registered, then the request is * silently ignored. * * @param obj * the listener to de-register */ public void removeListener( Listener obj ) { getElement( ).removeListener( obj ); } /** * Returns an iterator over the elements that derive from this one. * * @return an iterator over the elements that derive from this one. Each * item returned by the iterator's getNext( ) method is * of type {@link DesignElementHandle}. */ public Iterator derivedIterator( ) { return new DerivedElementIterator( module, this ); } /** * Returns an iterator over the clients of this element. Useful only for * styles. Returns a list of all the elements that use this style. * * @return an iterator over the clients of this element. Each item returned * by the iterator's getNext( ) method is of type * {@link DesignElementHandle}. Nothing will be iterated over an * element that is not ReferenceableElement. */ public Iterator clientsIterator( ) { return new ClientIterator( this ); } /** * Returns a array of valid choices for a property. * * @param propName * the property name * @return a array containing choices for the given property. Return * null, if this property has no choice. */ public IChoice[] getChoices( String propName ) { PropertyHandle propertyHandle = getPropertyHandle( propName ); if ( propertyHandle == null ) return null; return propertyHandle.getChoices( ); } /** * Returns the short display label for this element. * * @return the display label of this element in SHORT_LABEL level. * @see #getDisplayLabel(int ) */ public String getDisplayLabel( ) { return getDisplayLabel( IDesignElementModel.SHORT_LABEL ); } /** * Returns the display label for this element. The display label is the * localized display name to be shown in the UI. The display label is one of * the following: *

*

    *
  • The localized display name of this element, if the display name * resource key is set and the localized string is available
  • *
  • The static display name property text of this element, if set
  • *
  • The name of element, if set
  • *
  • The localized display name of this kind of element, which is defined * in metadata, if set
  • *
  • The name of this kind of element, which is also defined in metadata
  • *
*

* The user can also decide at which detail level the display label should * be returned. The level can be one of the following options: *

*

    *
  • USER_LABEL: Only the first 3 steps are used, if not found, return * null
  • *
  • SHORT_LABEL: All the above steps are used. This will ensure there * will be a return value
  • *
  • FULL_LABEL: Besides the return value of SHORT_LABEL, this option says * we need to return additional information. This information is specific to * each kind of element and my include row and column position, x and y * position and so on. To get this, every child element needs to overwrite * this method
  • *
* * @param level * the display label detail level * @return the display label of this element in a given level */ public String getDisplayLabel( int level ) { assert level == IDesignElementModel.USER_LABEL || level == IDesignElementModel.SHORT_LABEL || level == IDesignElementModel.FULL_LABEL; return getElement( ).getDisplayLabel( module, level ); } /** * Sorts a list of elements by localized display name. * * @param list * the list to sort */ public static void doSort( List list ) { Collections.sort( list, new Comparator( ) { public int compare( DesignElementHandle arg0, DesignElementHandle arg1 ) { DesignElementHandle h1 = arg0; DesignElementHandle h2 = arg1; String s1 = h1.getDisplayLabel( ); String s2 = h2.getDisplayLabel( ); return s1.compareTo( s2 ); } } ); } /** * Returns whether the element is valid or not. An element may be valid even * though it has some semantic errors. * * @return true if this element is valid, otherwise * false. */ public boolean isValid( ) { return getElement( ).isValid( ); } /** * Determines whether to show an error item on the element or not. Show an * error item if the element is invalid or has semantic errors, otherwise * not. * * @return true if the element has semantic error or the element is invalid */ public boolean showError( ) { return hasSemanticError( ) || !isValid( ); } /** * Sets the status that identifies whether the element is valid or not. * * @param isValid * the status to set */ public void setValid( boolean isValid ) { getElement( ).setValid( isValid ); } /** * Justifies whether this element has any semantic error or not. * * @return true if the element has any semantic error, otherwise false */ public boolean hasSemanticError( ) { return !getSemanticErrors( ).isEmpty( ); } /** * Deeply clones the current design element which is wrapped by the handle. * * @return the copy of the design element */ public IDesignElement copy( ) { try { return (DesignElement) getElement( ).clone( ); } catch ( CloneNotSupportedException e ) { assert false; } return null; } /** * Copies all properties to the target element. The following properties * will not be copied. *
    *
  • DesignElement.NAME_PROP *
  • * DesignElement.EXTENDS_PROP *
* * The targetHandle should be in the same report as this * element. And this method should be called in one transaction. * * @param propName * name of the property to copy * @param targetHandle * the target element handle * @throws SemanticException * if the target element type is not as same as this element * type, or property is not defined . * @throws IllegalArgumentException * if the target element is not in the same report as this * element. */ public void copyPropertyTo( String propName, DesignElementHandle targetHandle ) throws SemanticException { assert ( targetHandle.getModule( ) == getModule( ) ); if ( targetHandle.getModule( ) != getModule( ) ) throw new IllegalArgumentException( "The target element should be in the same report !" ); //$NON-NLS-1$ PropertyDefn propDefn = (ElementPropertyDefn) getDefn( ).getProperty( propName ); if ( propDefn == null ) throw new PropertyNameException( getElement( ), propName ); propDefn = (ElementPropertyDefn) targetHandle.getDefn( ).getProperty( propName ); if ( propDefn == null ) throw new PropertyNameException( targetHandle.getElement( ), propName ); Object value = getElement( ).getLocalProperty( module, propDefn.getName( ) ); if ( value == null ) { targetHandle.setProperty( propName, null ); return; } if ( IDesignElementModel.NAME_PROP.equals( propName ) || IDesignElementModel.EXTENDS_PROP.equals( propName ) ) { throw new SemanticError( getElement( ), new String[]{propName}, SemanticError.DESIGN_EXCEPTION_PROPERTY_COPY_FORBIDDEN ); } switch ( propDefn.getTypeCode( ) ) { case IPropertyType.ELEMENT_REF_TYPE : ElementRefValue refValue = (ElementRefValue) value; if ( refValue.isResolved( ) ) targetHandle.setProperty( propDefn.getName( ), refValue .getElement( ) ); else { String name = refValue.getName( ); name = ReferenceValueUtil.needTheNamespacePrefix( (ReferenceValue) value, getModule( ) ); targetHandle.setProperty( propDefn.getName( ), name ); } break; case IPropertyType.STRUCT_REF_TYPE : StructRefValue structRefValue = (StructRefValue) value; if ( structRefValue.isResolved( ) ) targetHandle.setProperty( propDefn.getName( ), structRefValue.getStructure( ) ); else targetHandle.setProperty( propDefn.getName( ), structRefValue.getName( ) ); break; case IPropertyType.STRUCT_TYPE : if ( propDefn.isList( ) ) { PropertyHandle propHandle = targetHandle .getPropertyHandle( propName ); Iterator strcutIter = ( (List) value ) .iterator( ); while ( strcutIter.hasNext( ) ) { Structure struct = strcutIter.next( ); propHandle.addItem( struct.copy( ) ); } } else { IStructure struct = (IStructure) value; targetHandle.setProperty( propName, struct.copy( ) ); } break; case IPropertyType.LIST_TYPE : assert value instanceof List; List valueList = (List) value; PropertyHandle propHandle = targetHandle .getPropertyHandle( propName ); for ( int i = 0; i < valueList.size( ); i++ ) { Object item = valueList.get( i ); if ( propDefn.getSubTypeCode( ) != IPropertyType.ELEMENT_REF_TYPE ) propHandle.addItem( item ); else { assert item instanceof ElementRefValue; refValue = (ElementRefValue) item; if ( refValue.isResolved( ) ) { propHandle.addItem( refValue.getElement( ) ); } else { propHandle.addItem( refValue .getQualifiedReference( ) ); } } } break; default : targetHandle.setProperty( propName, value ); } } /** * Checks this element with semantic rules. * * @return the list of errors, each of which is the ErrorDetail * object. * @see ErrorDetail */ public List semanticCheck( ) { // Validate this element. List exceptionList = getElement( ).validate( module ); List errorDetailList = ErrorDetail.convertExceptionList( exceptionList ); return errorDetailList; } /** * Determines if this element can be dropped from its container. * * @return true if it can be dropped. Returns * false otherwise. */ public boolean canDrop( ) { return getElement( ).canDrop( getModule( ) ); } /** * Determines if this element is editable or not. If the element comes from * a library, it can not be edited in the report design. * * @return true if it can be edited. false if it can't. */ public boolean canEdit( ) { return getElement( ).canEdit( module ); } /** * Determines if the current element can be transformed to a template * element. False will be returned if the element can not be dropped or the * container of the current element can not contain the template element. * * @return true if it can be transformed, otherwise false. */ public boolean canTransformToTemplate( ) { boolean flag = getElement( ).canTransformToTemplate( getModule( ) ); if ( !flag ) return false; return !getModule( ).isReadOnly( ); } /** * Determines if the slot can contain an element with the type of * type. Even return value is true, doesn't mean * the element can be added/moved without exceptions. * * @param slotId * the slot id * @param type * the name of the element type, like "Table", "List", etc. * @return true if the slot can contain the an element with * type type, otherwise false. * * @see #canContain(int, DesignElementHandle) */ public boolean canContain( int slotId, String type ) { if ( StringUtil.isBlank( type ) ) return false; SlotHandle slot = getSlot( slotId ); if ( slot == null ) return false; return new ContainerContext( getElement( ), slotId ).canContain( getModule( ), type ); } /** * Determines if the given slot can contain the content. Even * return value is true, doesn't mean the element can be * added/moved without exceptions. * * @param slotId * the slot id * @param content * the design element handle to check * * @return true if the slot with the given slotId * can contain the content, otherwise * false. * * @see #canContain(int, String) */ public boolean canContain( int slotId, DesignElementHandle content ) { if ( content == null ) return false; SlotHandle slot = getSlot( slotId ); if ( slot == null ) return false; return new ContainerContext( getElement( ), slotId ).canContain( getModule( ), content.getElement( ) ); } /** * Determines if the slot can contain an element with the type of * type. Even return value is true, doesn't mean * the element can be added/moved without exceptions. * * @param propName * name of the property where the type to insert * @param type * the name of the element type, like "Table", "List", etc. * @return true if the slot can contain the an element with * type type, otherwise false. * * @see #canContain(int, DesignElementHandle) */ public boolean canContain( String propName, String type ) { if ( StringUtil.isBlank( type ) || StringUtil.isBlank( propName ) ) return false; IElementPropertyDefn defn = getPropertyDefn( propName ); if ( defn == null ) return false; return new ContainerContext( getElement( ), propName ).canContain( getModule( ), type ); } /** * Determines if the given slot can contain the content. Even * return value is true, doesn't mean the element can be * added/moved without exceptions. * * @param propName * the name of the property where the content to insert * @param content * the design element handle to check * * @return true if the slot with the given slotId * can contain the content, otherwise * false. * * @see #canContain(int, String) */ public boolean canContain( String propName, DesignElementHandle content ) { if ( content == null ) return false; if ( StringUtil.isBlank( propName ) ) return false; IElementPropertyDefn defn = getPropertyDefn( propName ); if ( defn == null ) return false; return new ContainerContext( getElement( ), propName ).canContain( module, content.getElement( ) ); } /** * Returns the semantic error list, each of which is the instance of * ErrorDetail. * * @return the semantic error list. */ public List getSemanticErrors( ) { List exceptionList = getElement( ).getErrors( ); if ( exceptionList == null ) return Collections.EMPTY_LIST; List errorDetailList = ErrorDetail.convertExceptionList( exceptionList ); return ErrorDetail.getSemanticErrors( errorDetailList, DesignFileException.DESIGN_EXCEPTION_SEMANTIC_ERROR ); } /** * Returns the root container of this element. It must be Library or Report * Design. * * @return the handle of the root container. */ public ModuleHandle getRoot( ) { Module module = getElement( ).getRoot( ); if ( module != null ) return (ModuleHandle) module.getHandle( module ); return null; } /** * Returns return the path corresponding to the current position of the * element in the tree. * * This path string helps user locate this element in user interface. It * follows XPath syntax. Each node name indicates the name of the element * definition and the 1-based element position in the slot. The position * information is only available when the element is in the multicardinality * slot. * *

* For example, *

    *
  • /report/Body[1]/Label[3] - The third label element in body slot *
  • /report/Styles[1]/Style[1] - The first style in the styles slot *
  • /report/page-setup[1]/Graphic Master Page - The master page in the * page setup slot. *
*

* Note: the localized name is used for element type and slot name. * * @return the path of this element */ public String getXPath( ) { return XPathUtil.getXPath( this ); } /** * Gets a string that defines the event handle class. * * @return the expression as a string * * @see #setEventHandlerClass(String) */ public String getEventHandlerClass( ) { return getStringProperty( IDesignElementModel.EVENT_HANDLER_CLASS_PROP ); } /** * Sets the group expression. * * @param expr * the expression to set * @throws SemanticException * If the expression is invalid. * * @see #getEventHandlerClass() */ public void setEventHandlerClass( String expr ) throws SemanticException { setProperty( IDesignElementModel.EVENT_HANDLER_CLASS_PROP, expr ); } /** * Gets the newHandlerOnEachEvent property value. This property controls if * the event handler should be created. * * @return the newHandlerOnEachEvent property value. */ public boolean newHandlerOnEachEvent( ) { return getBooleanProperty( NEW_HANDLER_ON_EACH_EVENT_PROP ); } /** * Sets the newHandlerOnEachEvent property value. This property controls if * the event handler should be created. * * @param newHandler * controls if the event handler should be reloaded. * @throws SemanticException */ public void setNewHandlerOnEachEvent( boolean newHandler ) throws SemanticException { setBooleanProperty( NEW_HANDLER_ON_EACH_EVENT_PROP, newHandler ); } /** * Creates a template element handle and transforms the current element * handle to the created template element. * * @param name * the name of created template element handle * @return the template element handle * @throws SemanticException * if the current element can not be transformed to a template * element, current module is not a report design or some * containing contexts don't match */ public TemplateElementHandle createTemplateElement( String name ) throws SemanticException { if ( getRoot( ) == null ) throw new TemplateException( getElement( ), TemplateException.DESIGN_EXCEPTION_CREATE_TEMPLATE_ELEMENT_FORBIDDEN ); TemplateCommand cmd = new TemplateCommand( getModule( ), getElement( ) .getContainerInfo( ) ); TemplateElement template = cmd.createTemplateElement( getElement( ), name ); if ( template == null ) return null; return (TemplateElementHandle) template.getHandle( module ); } /** * Creates a template element handle and transforms the current element * handle to the created template element if the current element is based on * a template parameter definition. * * @param name * the name of created template element handle * @return the template element handle * @throws SemanticException * if the current element can not be transformed to a template * element, current element has no template parameter * definition, current module is not a report design or some * containing contexts don't match */ public TemplateElementHandle revertToTemplate( String name ) throws SemanticException { if ( getRoot( ) == null ) throw new TemplateException( getElement( ), TemplateException.DESIGN_EXCEPTION_CREATE_TEMPLATE_ELEMENT_FORBIDDEN ); TemplateCommand cmd = new TemplateCommand( getModule( ), getElement( ) .getContainerInfo( ) ); TemplateElement template = cmd.revertToTemplate( getElement( ), name ); if ( template == null ) return null; return (TemplateElementHandle) template.getHandle( module ); } /** * if this design element is based on a template definition * {@link #isTemplateParameterValue()},get rid of the template definition ) * * @throws SemanticException */ public void revertToReportItem( ) throws SemanticException { clearProperty( REF_TEMPLATE_PARAMETER_PROP ); } /** * Checks whether this element is based on a template parameter definition * or not. Call this method before calling method * {@link #revertToTemplate(String) }to assure that this element can be * reverted to a template element. If this method returns false, method * revertToTemplate(String) must fail too. * * @return true if this element is based on a template parameter definition, * otherwise false */ public boolean isTemplateParameterValue( ) { return getElement( ).isTemplateParameterValue( getModule( ) ); } /** * Gets the property data for either a system-defined or user-defined * property. * * @param propName * The name of the property to lookup. * @return The property definition, or null, if the property is undefined. */ public IElementPropertyDefn getPropertyDefn( String propName ) { // Look for the property defined on this element. return getElement( ).getPropertyDefn( propName ); } /** * Returns the effective module of the element. If the element is attached * to the design/library, the design/library is returned. Otherwise, the * module cached in the DesignElementHandle is returned. * * @return the effective module of the element. Can be null. */ protected Module getEffectiveModule( ) { return module; } /** * Returns the overridden value of the specified property given its internal * name. * * @param propName * the name of the property to get. Can be a system-defined or * user-defined property name. * * @return the property binding, or null if the overridden value is not set * @deprecated instead use getPropertyBindingExpression( String propName ) */ public String getPropertyBinding( String propName ) { PropertyBinding propBinding = findPropertyBinding( propName ); if ( propBinding != null ) { return propBinding.getValue( ); } return null; } /** * Gets all the defined property bindings for the given element. Each one in * the list is instance of PropertyBinding. * * @return the property binding list defined for the element */ public List getPropertyBindings( ) { List nameList = new ArrayList( ); List resultList = new ArrayList( ); DesignElement element = getElement( ); while ( element != null && element.getRoot( ) != null ) { List propBindings = element.getRoot( ) .getPropertyBindings( element ); resultList.addAll( filterPropertyBindingName( propBindings, nameList ) ); if ( element.isVirtualElement( ) ) { element = element.getVirtualParent( ); } else { element = element.getExtendsElement( ); } } return resultList; } /** * Filters propery binding list.If the same name of property binding is * exist, filter it from result set. * * @param propertyBindings * each item is property binding. * @param nameList * each item is name of property binding. * @return the property binding list. */ private List filterPropertyBindingName( List propertyBindings, List nameList ) { if ( propertyBindings == null ) return Collections.EMPTY_LIST; List resultList = new ArrayList( ); Iterator iterator = propertyBindings.iterator( ); while ( iterator.hasNext( ) ) { PropertyBinding propBinding = iterator.next( ); String name = propBinding.getName( ); if ( !nameList.contains( name ) ) { resultList.add( propBinding ); nameList.add( name ); } } return resultList; } /** * Sets the mask of the specified property. * * @param propName * the property name to get. Can be a system-defined or * user-defined property name. * * @param value * the overridden value * * @throws SemanticException * if the maskValue is not one of the above. * @deprecated instead use setPropertyBinding( String propName, Expression * value ) */ public void setPropertyBinding( String propName, String value ) throws SemanticException { setPropertyBinding( propName, (Object) value ); } /** * Returns externalized message. * * @param textIDProp * the display key property name * @param textProp * the property name * @return externalized message. */ public String getExternalizedValue( String textIDProp, String textProp ) { return ModelUtil.getExternalizedValue( getElement( ), textIDProp, textProp, getModule( ).getLocale( ) ); } /** * Returns externalized message. * * @param textIDProp * the display key property name * @param textProp * the property name * @param locale * the locale to externalize the message * @return externalized message. */ public String getExternalizedValue( String textIDProp, String textProp, ULocale locale ) { return ModelUtil.getExternalizedValue( getElement( ), textIDProp, textProp, locale ); } /** * Returns externalized message. * * @param textIDProp * the display key property name * @param textProp * the property name * @param locale * the locale to externalize the message * @return externalized message. */ public String getExternalizedValue( String textIDProp, String textProp, Locale locale ) { return ModelUtil.getExternalizedValue( getElement( ), textIDProp, textProp, ULocale.forLocale( locale ) ); } /** * Gets the position where this element resides in its container. * * @return the index where this element resides in its container, otherwise * -1 if this element has no container */ public int getIndex( ) { return getElement( ).getIndex( module ); } /** * Adds a report item to the property with the given element handle. The * report item must not be newly created and not yet added to the design. * * @param propName * name of the property where the content to insert * @param content * handle to the newly created element * @throws SemanticException * if the element is not allowed to insert */ public void add( String propName, DesignElementHandle content ) throws SemanticException { if ( content == null ) return; ContentCommand cmd = new ContentCommand( getModule( ), new ContainerContext( getElement( ), propName ) ); cmd.add( content.getElement( ) ); } /** * Adds a report item to this property at the given position. The item must * not be newly created and not yet added to the design. * * @param propName * name of the property where the content to insert * @param content * handle to the newly created element * @param newPos * the position index at which the content to be inserted, * 0-based integer * @throws SemanticException * if the element is not allowed to insert */ public void add( String propName, DesignElementHandle content, int newPos ) throws SemanticException { if ( content == null ) return; ContentCommand cmd = new ContentCommand( getModule( ), new ContainerContext( getElement( ), propName ) ); cmd.add( content.getElement( ), newPos ); } /** * Pastes a report item to this property. The item must be newly created and * not yet added to the design. * * @param propName * name of the property where the content to insert * @param content * the newly created element handle * @return a list containing all errors for the pasted element * @throws SemanticException * if the element is not allowed to paste */ public List paste( String propName, DesignElementHandle content ) throws SemanticException { if ( content == null ) return Collections.emptyList( ); add( propName, content ); return checkPostPasteErrors( content.getElement( ) ); } /** * Pastes a report item to this property. The item must be newly created and * not yet added to the design. * * @param propName * name of the property where the content to insert * @param content * the newly created element * @return a list containing all errors for the pasted element * @throws SemanticException * if the element is not allowed to paste */ public List paste( String propName, IDesignElement content ) throws SemanticException { if ( content == null ) return Collections.emptyList( ); add( propName, content.getHandle( getModule( ) ) ); return checkPostPasteErrors( (DesignElement) content ); } /** * Pastes a report item to the slot. The item must be newly created and not * yet added to the design. * * @param propName * name of the property where the content to insert * @param content * the newly created element handle * @param newPos * the position index at which the content to be inserted. * @return a list containing all errors for the pasted element * @throws SemanticException * if the element is not allowed in the slot */ public List paste( String propName, DesignElementHandle content, int newPos ) throws SemanticException { if ( content == null ) return Collections.emptyList( ); add( propName, content, newPos ); return checkPostPasteErrors( content.getElement( ) ); } /** * Pastes a report item to the property. The item must be newly created and * not yet added to the design. * * @param propName * name of the property where the content to insert * @param content * the newly created element * @param newPos * the position index at which the content to be inserted. * @return a list containing all errors for the pasted element * @throws SemanticException * if the element is not allowed in the property */ public List paste( String propName, IDesignElement content, int newPos ) throws SemanticException { if ( content == null ) return Collections.emptyList( ); add( propName, content.getHandle( getModule( ) ), newPos ); return checkPostPasteErrors( (DesignElement) content ); } /** * Checks the element after the paste action. * * @param content * the pasted element * * @return a list containing parsing errors. Each element in the list is * ErrorDetail. */ List checkPostPasteErrors( DesignElement content ) { Module currentModule = getModule( ); String nameSpace = null; if ( currentModule != null && currentModule instanceof Library ) nameSpace = ( (Library) currentModule ).getNamespace( ); ModelUtil.revisePropertyNameSpace( getModule( ), content, content .getDefn( ).getProperty( IDesignElementModel.EXTENDS_PROP ), nameSpace ); ModelUtil.reviseNameSpace( getModule( ), content, nameSpace ); List exceptionList = content.validateWithContents( getModule( ) ); List errorDetailList = ErrorDetail.convertExceptionList( exceptionList ); return errorDetailList; } /** * Returns the a list with contents.Items are handles to the contents and in * order by position. * * @param propName * name of the property where the contents reside * @return a list with property contents, items of the list are handles to * the contents. */ public List getContents( String propName ) { PropertyHandle propHandle = getPropertyHandle( propName ); return propHandle == null ? Collections.EMPTY_LIST : propHandle .getContents( ); } /** * Returns the number of elements in the property. * * @param propName * name of the property where the contents reside * @return the count of contents in the property */ public int getContentCount( String propName ) { return getContents( propName ).size( ); } /** * Gets a handle to the content element at the given position. * * @param propName * name of the property where the content resides * @param index * the specified position to find * @return the content handle if found, otherwise null */ public DesignElementHandle getContent( String propName, int index ) { if ( index < 0 || index >= getContentCount( propName ) ) return null; return (DesignElementHandle) getContents( propName ).get( index ); } /** * Moves the position of a content element within this container. * * @param propName * name of the property where the content resides * @param content * handle to the content to move * @param toPosn * the new position * @throws SemanticException * if the content is not in the property, or if the to position * is not valid. */ public void shift( String propName, DesignElementHandle content, int toPosn ) throws SemanticException { if ( content == null ) return; ContentCommand cmd = new ContentCommand( getModule( ), new ContainerContext( getElement( ), propName ) ); cmd.movePosition( content.getElement( ), toPosn ); } /** * Moves this element handle to the given position within its container. * * @param posn * the new position to move * @throws SemanticException */ public void moveTo( int posn ) throws SemanticException { DesignElement element = getElement( ); DesignElement oldContainer = element.getContainer( ); if ( oldContainer == null ) throw new ContentException( element, -1, ContentException.DESIGN_EXCEPTION_HAS_NO_CONTAINER ); ContentCommand cmd = new ContentCommand( module, element .getContainerInfo( ) ); cmd.movePosition( element, posn ); } /** * Moves a content element from this element into a property in another * container element. * * @param fromPropName * name of the property where the content originally resides * @param content * a handle to the element to move * @param newContainer * a handle to the new container element * @param toPropName * the target property name where the element will be moved to. * @throws SemanticException * if the content is not in this slot or if the new container is * not, in fact, a container, or if the content cannot go into * the target slot. */ public void move( String fromPropName, DesignElementHandle content, DesignElementHandle newContainer, String toPropName ) throws SemanticException { if ( content == null || newContainer == null ) return; ContentCommand cmd = new ContentCommand( getModule( ), new ContainerContext( getElement( ), fromPropName ) ); cmd.move( content.getElement( ), new ContainerContext( newContainer .getElement( ), toPropName ) ); } /** * Moves this element to a property in another container element. * * @param newContainer * a handle to the new container element * @param toPropName * the target property name where this element will be moved to * @throws SemanticException */ public void moveTo( DesignElementHandle newContainer, String toPropName ) throws SemanticException { DesignElement element = getElement( ); DesignElement oldContainer = element.getContainer( ); if ( oldContainer == null ) throw new ContentException( element, -1, ContentException.DESIGN_EXCEPTION_HAS_NO_CONTAINER ); if ( newContainer == null ) return; ContentCommand cmd = new ContentCommand( getModule( ), element .getContainerInfo( ) ); cmd.move( element, new ContainerContext( newContainer.getElement( ), toPropName ) ); } /** * Moves a content element into a property in another container element at * the specified position. * * @param fromPropName * name of the property where the content originally resides * @param content * a handle to the element to move * @param newContainer * a handle to the new container element * @param toPropName * the target property name where the element will be moved to. * @param newPos * the position to which the content will be moved. If it is * greater than the current content size of the target property, * the content will be appended at the end of the target * property. * @throws SemanticException * if the content is not in this property or if the new * container is not, in fact, a container, or if the content * cannot go into the target property. */ public void move( String fromPropName, DesignElementHandle content, DesignElementHandle newContainer, String toPropName, int newPos ) throws SemanticException { if ( content == null || newContainer == null ) return; ContentCommand cmd = new ContentCommand( getModule( ), new ContainerContext( getElement( ), fromPropName ) ); cmd.move( content.getElement( ), new ContainerContext( newContainer .getElement( ), toPropName ), newPos ); } /** * Moves this element to a property in another container element at the * specified position. * * @param newContainer * a handle to the new container element * @param toPropName * the target property name where this element will be moved to * @param newPos * the position to which this element will be moved. It is a * 0-based integer. If it is greater than the current content * size of the target property, this element will be appended at * the tail * @throws SemanticException */ public void moveTo( DesignElementHandle newContainer, String toPropName, int newPos ) throws SemanticException { DesignElement element = getElement( ); DesignElement oldContainer = element.getContainer( ); if ( oldContainer == null ) throw new ContentException( element, -1, ContentException.DESIGN_EXCEPTION_HAS_NO_CONTAINER ); if ( newContainer == null ) return; ContentCommand cmd = new ContentCommand( getModule( ), element .getContainerInfo( ) ); cmd.move( element, new ContainerContext( newContainer.getElement( ), toPropName ), newPos ); } /** * Drops a content element from the container, and clear any reference * property which refers the element to drop. * * @param propName * name of the property where the content resides * @param content * a handle to the content to drop * @throws SemanticException * if the content is not within the container */ public void dropAndClear( String propName, DesignElementHandle content ) throws SemanticException { if ( content == null ) return; ContentCommand cmd = new ContentCommand( getModule( ), new ContainerContext( getElement( ), propName ) ); cmd.remove( content.getElement( ) ); } /** * Drops a content element from the container, and unresolve any reference * property which refers the element to drop. * * @param propName * name of the property where the content resides * @param content * a handle to the content to drop * @throws SemanticException * if the content is not within the container */ public void drop( String propName, DesignElementHandle content ) throws SemanticException { if ( content == null ) return; ContentCommand cmd = new ContentCommand( getModule( ), new ContainerContext( getElement( ), propName ), false, true ); cmd.remove( content.getElement( ) ); } /** * Drops a content element at the given position from the container, and * clear any reference property which refers the element to drop. * * @param propName * name of the property where the content resides * @param posn * the position of the content to drop * @throws SemanticException * if the position is out of range */ public void dropAndClear( String propName, int posn ) throws SemanticException { PropertyHandle propHandle = getPropertyHandle( propName ); if ( propHandle != null ) { propHandle.dropAndClear( posn ); } } /** * Drops a content element at the given position from the container, and * unresolve any reference property which refers the element to drop. * * @param propName * name of the property where the content resides * @param posn * the position of the content to drop * @throws SemanticException * if the position is out of range */ public void drop( String propName, int posn ) throws SemanticException { PropertyHandle propHandle = getPropertyHandle( propName ); if ( propHandle != null ) { propHandle.drop( posn ); } } /** * Sets the encryption for an encryptable property. Not only this method can * change the encryption ID for a property, but also call * {@link #setProperty(String, Object)} to change the value of the * encryptable property. * * @param propName * @param encryptionID * @throws SemanticException */ public void setEncryption( String propName, String encryptionID ) throws SemanticException { EncryptionCommand cmd = new EncryptionCommand( getModule( ), getElement( ) ); cmd.setEncryption( propName, encryptionID ); } /** * Examines whether the resolved direction of this design element is Right * to Left or not. * * @return true if the direction is RTL, false otherwise * * */ public boolean isDirectionRTL( ) { /* * First check the direction style of this particular design element. If * not set for this element and - inherently - for upper level elements * (the direction style is inheritable), the direction will be decided * based on another property - orientation - of the top-level container. */ String direction = getStringProperty( IStyleModel.TEXT_DIRECTION_PROP ); if ( direction != null ) return DesignChoiceConstants.BIDI_DIRECTION_RTL.equals( direction ); ModuleHandle root = getRoot( ); return root != null && root.isDirectionRTL( ); } /** * Return the direct host element handle for this view element. * * @return null, if the current element is not a sub view. else return * DesignElementHandle which is the direct host element of the * current element view. */ public DesignElementHandle getHostViewHandle( ) { if ( ( !( getElement( ).getContainer( ) instanceof MultiViews ) ) ) return null; return getElement( ).getContainer( ).getContainer( ).getHandle( this.module ); } /** * Checks whether the given element is contained by one of template * parameter definition. * * @return true if the element is in the template parameter * definition. Otherwise, false. */ public boolean isInTemplateParameter( ) { DesignElement element = getElement( ); return element.isInTemplateParameterDefinitionSlot( ); } /** * Gets the factory element handle for this element. The factory element * handle is to retrieve some factory property value and factory styles. * * @return the factory element handle. */ public FactoryElementHandle getFactoryElementHandle( ) { return new FactoryElementHandle( this ); } /** * Returns a handle to work with an expression property. Returns null if the * given property is not defined or cannot be set with expression value. * * @param propName * name of the property. * @return a corresponding ExpressionHandle to with with the expression * property. * * @see ExpressionHandle */ public ExpressionHandle getExpressionProperty( String propName ) { PropertyDefn defn = (PropertyDefn) getPropertyDefn( propName ); if ( defn == null ) return null; if ( defn.allowExpression( ) && !defn.isListType( ) ) return new ExpressionHandle( this, (ElementPropertyDefn) defn ); return null; } /** * Sets the value of a property to an expression. * * @param propName * the property name * @param expression * the value to set * @throws SemanticException */ public void setExpressionProperty( String propName, Expression expression ) throws SemanticException { setProperty( propName, expression ); } /** * Sets the mask of the specified property. * * @param propName * the property name to get. Can be a system-defined or * user-defined property name. * * @param value * the overridden value * * @throws SemanticException * if the maskValue is not one of the above. */ public void setPropertyBinding( String propName, Expression value ) throws SemanticException { setPropertyBinding( propName, (Object) value ); } /** * Returns the overridden value of the specified property given its internal * name. * * @param propName * the name of the property to get. Can be a system-defined or * user-defined property name. * * @return the property binding, or null if the overridden value is not set */ public Expression getPropertyBindingExpression( String propName ) { PropertyBinding propBinding = findPropertyBinding( propName ); if ( propBinding != null ) { return propBinding .getExpressionProperty( PropertyBinding.VALUE_MEMBER ); } return null; } /** * Sets the mask of the specified property. * * @param propName * the property name to get. Can be a system-defined or * user-defined property name. * * @param value * the overridden value * * @throws SemanticException * if the maskValue is not one of the above. */ private void setPropertyBinding( String propName, Object value ) throws SemanticException { // check whether the property is defined on this element ElementPropertyDefn defn = (ElementPropertyDefn) getPropertyDefn( propName ); if ( defn == null ) throw new SemanticError( getElement( ), new String[]{propName}, SemanticError.DESIGN_EXCEPTION_INVALID_PROPERTY_NAME ); if ( IModuleModel.PROPERTY_BINDINGS_PROP.equals( defn.getName( ) ) ) return; // check the element is in the id-map of the root module Module root = getElement( ).getRoot( ); if ( root == null ) throw new SemanticError( getElement( ), SemanticError.DESIGN_EXCEPTION_PROPERTY_BINDING_FORBIDDEN ); assert root.getElementByID( getID( ) ) == getElement( ); ArrayList bindingList = (ArrayList) root.getLocalProperty( root, IModuleModel.PROPERTY_BINDINGS_PROP ); PropertyBinding binding = root.findPropertyBinding( getElement( ), propName ); // if the binding is not set, and the new value is null, returns if ( binding == null && value == null ) return; if ( bindingList == null ) { assert value != null; bindingList = new ArrayList( ); root.setProperty( IModuleModel.PROPERTY_BINDINGS_PROP, bindingList ); } defn = root.getPropertyDefn( IModuleModel.PROPERTY_BINDINGS_PROP ); assert defn != null; if ( value == null && binding != null ) { ComplexPropertyCommand cmd = new ComplexPropertyCommand( module, root ); // maskValue is null, remove the item from the structure list. cmd.removeItem( binding.getContext( ), bindingList .indexOf( binding ) ); } else { /* * If the property has no binding related to, adds a new binding * item into the structure list. */ if ( binding == null ) { binding = new PropertyBinding( ); binding.setName( propName ); binding.setID( getID( ) ); binding.setProperty( PropertyBinding.VALUE_MEMBER, value ); ComplexPropertyCommand cmd = new ComplexPropertyCommand( module, root ); cmd.addItem( new StructureContext( root, defn, null ), binding ); } else { // changes the binding value. PropertyCommand cmd = new PropertyCommand( module, root ); cmd.setMember( new StructureContext( binding, (PropertyDefn) binding.getDefn( ).getMember( PropertyBinding.VALUE_MEMBER ), null ), value ); } } } /** * Returns the specified property with its internal name. * * @param propName * the name of the property to get. Can be a system-defined or * user-defined property name. * * @return the property binding */ private PropertyBinding findPropertyBinding( String propName ) { if ( propName == null ) return null; DesignElement element = getElement( ); while ( element != null && element.getRoot( ) != null ) { PropertyBinding propBinding = element.getRoot( ) .findPropertyBinding( element, propName ); if ( propBinding != null ) return propBinding; if ( element.isVirtualElement( ) ) { element = element.getVirtualParent( ); } else { element = element.getExtendsElement( ); } } return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy