/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.foundation.ie; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.InvalidNameException; import org.apache.commons.collections.BidiMap; import org.apache.commons.collections.bidimap.DualHashBidiMap; import org.openflexo.foundation.FlexoException; import org.openflexo.foundation.FlexoModelObject; import org.openflexo.foundation.bindings.Bindable; import org.openflexo.foundation.bindings.BindingModel; import org.openflexo.foundation.bindings.BindingValue; import org.openflexo.foundation.dm.ComponentDMEntity; import org.openflexo.foundation.dm.DMObject; import org.openflexo.foundation.dm.DuplicateClassNameException; import org.openflexo.foundation.ie.cl.ComponentDefinition; import org.openflexo.foundation.ie.cl.TabComponentDefinition; import org.openflexo.foundation.ie.dm.ComponentDeleteRequest; import org.openflexo.foundation.ie.dm.ComponentDeleted; import org.openflexo.foundation.ie.dm.ComponentNameChanged; import org.openflexo.foundation.ie.dm.TopWidgetInserted; import org.openflexo.foundation.ie.dm.TopWidgetRemoved; import org.openflexo.foundation.ie.operator.ConditionalOperator; import org.openflexo.foundation.ie.operator.RepetitionOperator; import org.openflexo.foundation.ie.widget.IEBlocWidget; import org.openflexo.foundation.ie.widget.IEBrowserWidget; import org.openflexo.foundation.ie.widget.IEButtonWidget; import org.openflexo.foundation.ie.widget.IECheckBoxWidget; import org.openflexo.foundation.ie.widget.IEControlWidget; import org.openflexo.foundation.ie.widget.IEDropDownWidget; import org.openflexo.foundation.ie.widget.IEHTMLTableWidget; import org.openflexo.foundation.ie.widget.IEHyperlinkWidget; import org.openflexo.foundation.ie.widget.IELabelWidget; import org.openflexo.foundation.ie.widget.IERadioButtonWidget; import org.openflexo.foundation.ie.widget.IEReusableWidget; import org.openflexo.foundation.ie.widget.IESequence; import org.openflexo.foundation.ie.widget.IESequenceTab; import org.openflexo.foundation.ie.widget.IESequenceTopComponent; import org.openflexo.foundation.ie.widget.IESequenceWidget; import org.openflexo.foundation.ie.widget.IEStringWidget; import org.openflexo.foundation.ie.widget.IETabWidget; import org.openflexo.foundation.ie.widget.IETextAreaWidget; import org.openflexo.foundation.ie.widget.IETextFieldWidget; import org.openflexo.foundation.ie.widget.IEWidget; import org.openflexo.foundation.ie.widget.ITabWidget; import org.openflexo.foundation.ie.widget.ITableRow; import org.openflexo.foundation.ie.widget.IWidget; import org.openflexo.foundation.rm.DuplicateResourceException; import org.openflexo.foundation.rm.FlexoComponentResource; import org.openflexo.foundation.rm.FlexoProject; import org.openflexo.foundation.rm.FlexoResource; import org.openflexo.foundation.rm.FlexoXMLStorageResource; import org.openflexo.foundation.rm.RMNotification; import org.openflexo.foundation.rm.SaveResourceException; import org.openflexo.foundation.rm.XMLStorageResourceData; import org.openflexo.foundation.utils.FlexoRadioManager; import org.openflexo.foundation.validation.FixProposal; import org.openflexo.foundation.validation.Validable; import org.openflexo.foundation.validation.ValidationError; import org.openflexo.foundation.validation.ValidationIssue; import org.openflexo.foundation.validation.ValidationModel; import org.openflexo.foundation.validation.ValidationReport; import org.openflexo.foundation.validation.ValidationRule; import org.openflexo.foundation.xml.FlexoComponentBuilder; import org.openflexo.inspector.InspectableObject; import org.openflexo.toolbox.ReservedKeyword; import org.openflexo.toolbox.ToolBox; /** * Represents an abstract WOComponent * * @author bmangez, sguerin */ public abstract class IEWOComponent extends IEObject implements XMLStorageResourceData, InspectableObject, Validable, Bindable { private static final Logger logger = Logger.getLogger(IEWOComponent.class.getPackage().getName()); // ========================================================================== // ============================= Variables // ================================== // ========================================================================== private FlexoComponentResource _resource; private String _helpText; public static final String WOCOMPONENT_NAME_ATTRIBUTENAME = "woComponentName"; private ComponentDefinition _componentDefinition; private Vector<RepetitionOperator> repetitions; private Vector<IESequenceTab> tabContainers; private FlexoRadioManager radioButtonManager = new FlexoRadioManager(this); /* Key: String, Value: FlexoModelObject */ private BidiMap nameForWidgetMap = new DualHashBidiMap(); private IESequenceWidget rootSequence; private Date lastUpdate; public IEWOComponent(FlexoComponentBuilder builder) { this(builder.componentDefinition, builder.getProject()); builder.woComponent = this; _resource = builder.resource; } /** * @param model * */ public IEWOComponent(ComponentDefinition model, FlexoProject project) { super(project); if (project == null) { new Exception("No project at all, this is going to kill me!").printStackTrace(); } setRootSequence(new IESequenceWidget(this, this, project)); _componentDefinition = model; tabContainers = new Vector<IESequenceTab>(); if (model != null) { model.addObserver(this); } } @Override public void initializeDeserialization(Object builder) { super.initializeDeserialization(builder); if (getProject() != null) { getProject().getBindingValueConverter().setPreProcessor(new BindingValue.DecodingPreProcessor() { @Override public String preProcessString(String aString) { if (!aString.startsWith("component.") && !aString.startsWith("$")) { return "component." + aString; } return aString; } }); } } /** * */ @Override public void finalizeDeserialization(Object builder) { if (rootSequence.getOperator() != null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("There is an operator on the root sequence. This is not allowed, I will remove it."); } rootSequence.resetOperator(); } rootSequence.simplifySequenceTree(); super.finalizeDeserialization(builder); Iterator<IESequenceTab> i = tabContainers.iterator(); while (i.hasNext()) { IESequenceTab tab = i.next(); if (tab.isSubsequence()) { i.remove(); } } if (getProject() != null) { getProject().getBindingValueConverter().setPreProcessor(null); } getComponentDefinition().setHasTabContainer(hasTabContainer()); } /** * Overrides delete * * @see org.openflexo.foundation.FlexoModelObject#delete() */ @Override public void delete() { delete(true); } public void delete(boolean deleteDefinition) { if (getFlexoResource() != null) { getFlexoResource().delete(); _resource = null; if (_componentDefinition != null) { if (deleteDefinition) { ComponentDefinition cd = _componentDefinition; _componentDefinition = null; cd.delete(); } else { _componentDefinition = null; } } super.delete(); nameForWidgetMap.clear(); nameForWidgetMap = null; } } @Override public IEObject getParent() { return null;// WOComponents have no father! } @Override public synchronized void setIsModified() { if (ignoreNotifications()) { return; } if (nameForWidgetMap != null) { nameForWidgetMap.clear();// Any modification is capable of modify the names of the objects. } lastUpdate = null; super.setIsModified(); // lastUpdate = lastMemoryUpdate(); } /** * This date is use to perform fine tuning resource dependancies computing * * @return */ @Override public Date getLastUpdate() { if (lastUpdate == null) { lastUpdate = lastMemoryUpdate(); } if (lastUpdate == null) { lastUpdate = super.getLastUpdate(); } return lastUpdate; } public void setLastUpdate(Date lastUpdate) { this.lastUpdate = lastUpdate; } /** * Returns reference to the main object in which this XML-serializable object is contained relating to storing scheme: here it's the * WOComponent itself * * @return this */ @Override public XMLStorageResourceData getXMLResourceData() { return this; } public ComponentDefinition getComponentDefinition() { if (_componentDefinition == null) { if (getProject() == null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("No component def and no project for :" + getName()); } } _componentDefinition = getProject().getFlexoComponentLibrary().getComponentNamed(getName()); } return _componentDefinition; } @Override public Vector<IObject> getEmbeddedIEObjects() { Vector<IObject> v = new Vector<IObject>(); v.add(getComponentDefinition()); v.add(this); v.add(rootSequence); return v; } public FlexoRadioManager getRadioButtonManager() { return radioButtonManager; } public String getNameRegexp() { return IERegExp.JAVA_CLASS_NAME_REGEXP; } public ComponentDMEntity getComponentDMEntity() { if (getComponentDefinition() != null) { return getComponentDefinition().getComponentDMEntity(); } return null; } @Override public BindingModel getBindingModel() { if (getComponentDefinition() != null) { return getComponentDefinition().getBindingModel(); } return null; } @Override public String getDescription() { if (getComponentDefinition() != null && !isSerializing()) { if (getComponentDefinition().getDescription() == null || getComponentDefinition().getDescription().trim().length() == 0) { return getRootSequence().getDescription(); } else { return getComponentDefinition().getDescription(); } } return null; } @Override public void setDescription(String text) { if (getComponentDefinition() != null && !isDeserializing()) { getComponentDefinition().setDescription(text); } } @Override public boolean getHasSpecificDescriptions() { if (getComponentDefinition() != null && !isSerializing()) { return getComponentDefinition().getHasSpecificDescriptions(); } return false; } @Override public void setHasSpecificDescriptions(boolean hasSpecificDescription) { if (getComponentDefinition() != null && !isDeserializing()) { getComponentDefinition().setHasSpecificDescriptions(hasSpecificDescription); } } @Override public Map<String, String> getSpecificDescriptions() { if (getComponentDefinition() != null && !isSerializing()) { return getComponentDefinition().getSpecificDescriptions(); } return null; } @Override public void setSpecificDescriptions(Map<String, String> desc) { if (getComponentDefinition() != null && !isDeserializing()) { getComponentDefinition().setSpecificDescriptions(desc); } } @Override public String getSpecificDescriptionForKey(String key) { if (getComponentDefinition() != null && !isSerializing()) { return getComponentDefinition().getSpecificDescriptionForKey(key); } return null; } @Override public void setSpecificDescriptionsForKey(String description, String key) { if (getComponentDefinition() != null && !isDeserializing()) { getComponentDefinition().setSpecificDescriptionsForKey(description, key); } } @Override public String getName() { if (_componentDefinition != null) { return _componentDefinition.getName(); } return null; } @Override public void setName(String name) throws DuplicateResourceException, DuplicateClassNameException, InvalidNameException { if (getComponentDefinition() != null) { getComponentDefinition().setName(name); } } @Override public String getHelpText() { return _helpText; } public void setHelpText(String text) { _helpText = text; setChanged(); notifyModification("helpText", null, _helpText); } /** * Return a Vector of all ComponentInstance objects involved in the definition of that component * * @return a newly created Vector of ComponentInstance objects */ public Vector<ComponentInstance> getAllComponentInstances() { Vector allIEObjects = getAllEmbeddedIEObjects(); Vector<ComponentInstance> returned = new Vector<ComponentInstance>(); for (FlexoResource r : getFlexoResource().getDependentResources()) { if (r instanceof FlexoComponentResource) { for (ComponentInstance ci : ((FlexoComponentResource) r).getComponentDefinition().getComponentInstances()) { if (ci.getXMLResourceData() == this) { } } } } for (Enumeration en = allIEObjects.elements(); en.hasMoreElements();) { IEObject next = (IEObject) en.nextElement(); if (next instanceof ComponentInstance) { returned.add((ComponentInstance) next); } } return returned; } public boolean isTopComponent() { Enumeration<IWidget> en = getRootSequence().getAllNonSequenceWidget().elements(); boolean isTopComponent = en.hasMoreElements();// If root sequence is empty then this component is not a top component while (en.hasMoreElements()) { IEWidget widget = (IEWidget) en.nextElement(); if (!widget.isTopComponent()) { return false; } } return isTopComponent; } public boolean isASingleHTMLTable() { Vector<IEWidget> v = getRootSequence().getInnerWidgets(); return v.size() == 1 && v.firstElement() instanceof IEHTMLTableWidget; } public boolean isAListOfTableRows() { Enumeration en = getRootSequence().getInnerWidgets().elements(); if (!en.hasMoreElements()) { return false; } while (en.hasMoreElements()) { IEWidget w = (IEWidget) en.nextElement(); if (!(w instanceof ITableRow)) { return false; } } return true; } @Override public FlexoComponentResource getFlexoResource() { return _resource; } @Override public void setFlexoResource(FlexoResource resource) { _resource = (FlexoComponentResource) resource; } @Override public FlexoXMLStorageResource getFlexoXMLFileResource() { return _resource; } /** * Save this object using ResourceManager scheme * * Overrides * * @see org.openflexo.foundation.rm.FlexoResourceData#save() * @see org.openflexo.foundation.rm.FlexoResourceData#save() */ @Override public void save() throws SaveResourceException { _resource.saveResourceData(); } /** * Implements * * @see org.openflexo.foundation.rm.FlexoResourceData#receiveRMNotification(org.openflexo.foundation.rm.RMNotification) Receive a * notification that has been propagated by the ResourceManager scheme and coming from a modification on an other resource * * Handles ComponentNameChanged notifications * * @see org.openflexo.foundation.rm.FlexoResourceData#receiveRMNotification(org.openflexo.foundation.rm.RMNotification) */ @Override public void receiveRMNotification(RMNotification aNotification) throws FlexoException { if (aNotification instanceof ComponentNameChanged) { ComponentNameChanged notification = (ComponentNameChanged) aNotification; Vector instances = getAllComponentInstances(); for (Enumeration en = instances.elements(); en.hasMoreElements();) { ComponentInstance ci = (ComponentInstance) en.nextElement(); if (ci.getComponentName().equals(notification.oldValue())) { ci.notifyComponentNameChanged(notification.component); } } } if (aNotification instanceof ComponentDeleteRequest) { ComponentDeleteRequest notification = (ComponentDeleteRequest) aNotification; for (Enumeration en = getAllComponentInstances().elements(); en.hasMoreElements();) { ComponentInstance ci = (ComponentInstance) en.nextElement(); if (ci.getComponentName().equals(notification.component.getComponentName())) { notification.addToWarnings(notification.component.getComponentName() + " is used by " + getName()); } } } if (aNotification instanceof ComponentDeleted) { ComponentDeleted notification = (ComponentDeleted) aNotification; for (Enumeration en = getAllComponentInstances().elements(); en.hasMoreElements();) { ComponentInstance ci = (ComponentInstance) en.nextElement(); if (ci.getComponentName().equals(notification.component.getComponentName())) { IEReusableWidget[] reusable = findReusableWidgetForComponentInstance(ci); for (int i = 0; i < reusable.length; i++) { reusable[i].delete(); } IEHyperlinkWidget[] hyperlink = findHyperlinksForComponentInstance(ci); for (int i = 0; i < hyperlink.length; i++) { hyperlink[i].setPopupComponentDefinition(null); } } } } } private IEReusableWidget[] findReusableWidgetForComponentInstance(ComponentInstance ci) { Vector allIEObjects = getAllEmbeddedIEObjects(); Vector<IEReusableWidget> returned = new Vector<IEReusableWidget>(); for (Enumeration en = allIEObjects.elements(); en.hasMoreElements();) { IEObject next = (IEObject) en.nextElement(); if (next instanceof IEReusableWidget) { if (((IEReusableWidget) next).getReusableComponentInstance().equals(ci)) { returned.add((IEReusableWidget) next); } } } IEReusableWidget[] answer = new IEReusableWidget[returned.size()]; int i = 0; Enumeration en = returned.elements(); while (en.hasMoreElements()) { answer[i] = (IEReusableWidget) en.nextElement(); i++; } return answer; } private IEHyperlinkWidget[] findHyperlinksForComponentInstance(ComponentInstance ci) { Vector allIEObjects = getAllEmbeddedIEObjects(); Vector<IEHyperlinkWidget> returned = new Vector<IEHyperlinkWidget>(); for (Enumeration en = allIEObjects.elements(); en.hasMoreElements();) { IEObject next = (IEObject) en.nextElement(); if (next instanceof IEHyperlinkWidget) { if (((IEHyperlinkWidget) next).getPopupComponentDefinition() != null && ((IEHyperlinkWidget) next).getPopupComponentDefinition().equals(ci.getComponentDefinition())) { returned.add((IEHyperlinkWidget) next); } } } IEHyperlinkWidget[] answer = new IEHyperlinkWidget[returned.size()]; int i = 0; Enumeration en = returned.elements(); while (en.hasMoreElements()) { answer[i] = (IEHyperlinkWidget) en.nextElement(); i++; } return answer; } public Vector<IEHyperlinkWidget> getAllButtonInterface() { return rootSequence.getAllButtonInterface(); } public Vector<RepetitionOperator> getAllRepetitionOperator() { Vector<RepetitionOperator> reply = new Vector<RepetitionOperator>(); Enumeration en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IEObject widget = (IEObject) en.nextElement(); if (widget instanceof IESequence && ((IESequence) widget).getOperator() != null && ((IESequence) widget).getOperator() instanceof RepetitionOperator) { reply.add((RepetitionOperator) ((IESequence) widget).getOperator()); } } return reply; } public Vector<RepetitionOperator> getAllList() { if (repetitions == null) { repetitions = new Vector<RepetitionOperator>(); Enumeration en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IObject o = (IObject) en.nextElement(); if (o instanceof RepetitionOperator) { repetitions.add((RepetitionOperator) o); } } } return repetitions; } public Vector<IEHyperlinkWidget> getAvailableFlexoActions() { if (logger.isLoggable(Level.FINEST)) { logger.finest("getAvailableFlexoActions"); } Vector<IEHyperlinkWidget> v = new Vector<IEHyperlinkWidget>(); Enumeration en = getAllButtonInterface().elements(); while (en.hasMoreElements()) { IEHyperlinkWidget w = (IEHyperlinkWidget) en.nextElement(); if (w.getIsFlexoAction()) { v.add(w); } } return v; } public Vector<IEHyperlinkWidget> getAvailableDisplayActions() { if (logger.isLoggable(Level.FINEST)) { logger.finest("getAvailableFlexoActions"); } Vector<IEHyperlinkWidget> v = new Vector<IEHyperlinkWidget>(); Enumeration en = getAllButtonInterface().elements(); while (en.hasMoreElements()) { IEHyperlinkWidget w = (IEHyperlinkWidget) en.nextElement(); if (w.getIsDisplayAction()) { v.add(w); } } return v; } public String getInput() { if (_componentDefinition != null) { return _componentDefinition.getInput(); } else { return null; } } public void setInput(String s) { if (_componentDefinition != null) { _componentDefinition.setInput(s); } } public String getBehavior() { if (_componentDefinition != null) { return _componentDefinition.getBehavior(); } else { return null; } } public void setBehavior(String s) { if (_componentDefinition != null) { _componentDefinition.setBehavior(s); } } /** * Returns a flag indicating if this object is valid according to default validation model * * @return boolean */ @Override public boolean isValid() { return isValid(getDefaultValidationModel()); } /** * Returns a flag indicating if this object is valid according to specified validation model * * @return boolean */ @Override public boolean isValid(ValidationModel validationModel) { return validationModel.isValid(this); } /** * Validates this object by building new ValidationReport object Default validation model is used to perform this validation. */ @Override public ValidationReport validate() { return validate(getDefaultValidationModel()); } /** * Validates this object by building new ValidationReport object Supplied validation model is used to perform this validation. */ @Override public ValidationReport validate(ValidationModel validationModel) { return validationModel.validate(this); } /** * Validates this object by appending eventual issues to supplied ValidationReport. Default validation model is used to perform this * validation. * * @param report * , a ValidationReport object on which found issues are appened */ @Override public void validate(ValidationReport report) { validate(report, getDefaultValidationModel()); } /** * Validates this object by appending eventual issues to supplied ValidationReport. Supplied validation model is used to perform this * validation. * * @param report * , a ValidationReport object on which found issues are appened */ @Override public void validate(ValidationReport report, ValidationModel validationModel) { validationModel.validate(this, report); } /** * @param _widget * @return */ public Vector<IETextFieldWidget> getAllDateTextfields() { return rootSequence.getAllDateTextfields(); } public void getAllDateTexfields(IETopComponent top, Vector<IETextFieldWidget> v) { if (top instanceof IEBlocWidget) { IEBlocWidget block = (IEBlocWidget) top; v.addAll(block.getAllDateTextfields()); } else if (top instanceof IEHTMLTableWidget) { v.addAll(((IEHTMLTableWidget) top).getAllDateTextfields()); } else if (top instanceof IESequenceTopComponent) { Iterator<IETopComponent> i = ((IESequenceTopComponent) top).iterator(); while (i.hasNext()) { IETopComponent obj = i.next(); getAllDateTexfields(obj, v); } } } public boolean hasTabContainer() { return tabContainers != null && tabContainers.size() > 0; } public Vector<IESequenceTab> getTabContainers() { return tabContainers; } public Vector<IETabWidget> getAllTabWidget() { Vector<IETabWidget> v = new Vector<IETabWidget>(); for (IESequenceTab tab : getTabContainers()) { for (IWidget w : tab.getAllNonSequenceWidget()) { v.add((IETabWidget) w); } } return v; } /** * @return */ public static final String getTypeName() { return "WOComponent"; } @Override public String toString() { return "IEWOComponent:" + getName(); } public Vector<IEControlWidget> getFilterWidgetsForRepetition(RepetitionOperator rep) { Vector<IEControlWidget> v = new Vector<IEControlWidget>(); Enumeration en = getAllEmbeddedIEObjects().elements(); while (en.hasMoreElements()) { IEObject o = (IEObject) en.nextElement(); if (o instanceof IEControlWidget && ((IEControlWidget) o).getIsFilterForRepetition() == rep) { v.add((IEControlWidget) o); } } return v; } public boolean hasHelpText() { return getHelpText() != null && getHelpText().trim().length() > 0; } public static class ComponentCannotHaveTwoListWithSameName extends ValidationRule<ComponentCannotHaveTwoListWithSameName, IEWOComponent> { public ComponentCannotHaveTwoListWithSameName() { super(IEWOComponent.class, "list_name_must_be_unique_in_a_component"); } @Override public ValidationIssue<ComponentCannotHaveTwoListWithSameName, IEWOComponent> applyValidation(IEWOComponent wo) { Vector<RepetitionOperator> allList = wo.getAllList(); if (allList.size() < 2) { return null; } Hashtable<String, RepetitionOperator> h = new Hashtable<String, RepetitionOperator>(); Enumeration<RepetitionOperator> en = allList.elements(); while (en.hasMoreElements()) { RepetitionOperator rep = en.nextElement(); if (rep.getName() != null && h.get(rep.getName()) == null) { h.put(rep.getName(), rep); } else { ValidationError<ComponentCannotHaveTwoListWithSameName, IEWOComponent> error = new ValidationError<ComponentCannotHaveTwoListWithSameName, IEWOComponent>( this, wo, "list_name_must_be_unique_in_a_component"); error.addToFixProposals(new ChangeListName(rep)); return error; } } return null; } } public static class ChangeListName extends FixProposal<ComponentCannotHaveTwoListWithSameName, IEWOComponent> { public RepetitionOperator repetition; public ChangeListName(RepetitionOperator rep) { super("append_flexoID_to_current_list_name"); repetition = rep; } @Override protected void fixAction() { repetition.setName(repetition.getName() + repetition.getFlexoID()); } } public String getFirstTabContainerTitle() { IESequenceTab obj = null; Enumeration<IESequenceTab> en = getAllTabContainers().elements(); while (en.hasMoreElements()) { obj = en.nextElement(); return obj.getWOComponent().getName() + obj.getFlexoID() + "Tabs"; } return null; } public IETabWidget findTab(TabComponentDefinition tabComponentDefinition) { Enumeration en = getAllEmbeddedIEObjects().elements(); Object o = null; while (en.hasMoreElements()) { o = en.nextElement(); if (o instanceof IETabWidget) { if (((IETabWidget) o).getTabComponentDefinition().equals(tabComponentDefinition)) { return (IETabWidget) o; } } } return null; } public Vector<IEHyperlinkWidget> getAllAbstractButtonWidgetInterface() { return getAllButtonInterface(); } public Vector<IESequenceTab> getAllTabContainers() { Vector<IESequenceTab> reply = new Vector<IESequenceTab>(); Enumeration en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IEObject top = (IEObject) en.nextElement(); if (top instanceof IESequenceTab && ((IESequenceTab) top).isTabContainer()) { reply.add((IESequenceTab) top); } } return reply; } public Vector<TabComponentDefinition> getAllTabComponents(Vector<TabComponentDefinition> reply) { for (IESequenceTab container : getAllTabContainers()) { for (ITabWidget itab : container.getInnerWidgets()) { for (IETabWidget tab : itab.getAllTabs()) { TabComponentDefinition tabcd = tab.getTabComponentDefinition(); if (!reply.contains(tabcd)) { reply.add(tabcd); // tabcd.getWOComponent().getAllTabComponents(reply); } } } } return reply; } public Vector<IETabWidget> getAllTabWidget(Vector<IETabWidget> reply) { for (IESequenceTab container : getAllTabContainers()) { for (ITabWidget itab : container.getInnerWidgets()) { for (IETabWidget tab : itab.getAllTabs()) { if (!reply.contains(tab)) { reply.add(tab); tab.getTabComponentDefinition().getWOComponent().getAllTabWidget(reply); } } } } return reply; } public IETabWidget getTabWidgetForTabComponent(TabComponentDefinition component) { Iterator<IESequenceTab> i = tabContainers.iterator(); while (i.hasNext()) { IESequenceTab st = i.next(); Iterator<IWidget> j = st.getAllNonSequenceWidget().iterator(); while (j.hasNext()) { IETabWidget w = (IETabWidget) j.next(); if (w.getTabComponentDefinition() == component) { return w; } } } return null; } public IESequenceTab getSequenceTabForTabComponent(TabComponentDefinition component) { IETabWidget tabWidget = getTabWidgetForTabComponent(component); if (tabWidget != null) { return tabWidget.getRootParent(); } return null; } public void notifyWidgetAdded(IEWidget widget) { if (widget instanceof RepetitionOperator) { repetitions = null; } else if (widget instanceof IESequenceTab) { if (!((IESequenceTab) widget).isSubsequence() && !tabContainers.contains(widget)) { tabContainers.add((IESequenceTab) widget); } getComponentDefinition().setHasTabContainer(hasTabContainer()); } } public void notifyWidgetRemoved(IEWidget widget) { if (widget instanceof RepetitionOperator) { repetitions = null; } else if (widget instanceof IESequenceTab) { if (!((IESequenceTab) widget).isSubsequence()) { tabContainers.remove(widget); } getComponentDefinition().setHasTabContainer(hasTabContainer()); } } /** * Returns all the strings ({@link IEStringWidget}) of this WOComponent. You should not use directly this method but instead implement a * cache mechanism and use the benefits of the methods notifyWidgetAdded and notifyWidgetRemoved. This method is intended to be used to * preserve the order of this component when presenting this to a user. * * @return all the strings contained in this component. */ @Override public Vector<IEStringWidget> getStrings() { Vector<IEStringWidget> v = new Vector<IEStringWidget>(); Enumeration<IObject> en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IObject o = en.nextElement(); if (o instanceof IEStringWidget) { v.add((IEStringWidget) o); } } return v; } /** * Returns all the textfields ({@link IETextFieldWidget}) of this WOComponent. You should not use directly this method but instead * implement a cache mechanism and use the benefits of the methods notifyWidgetAdded and notifyWidgetRemoved. This method is intended to * be used to preserve the order of this component when presenting this to a user. * * @return all the textfields contained in this component. */ @Override public Vector<IETextFieldWidget> getTextfields() { Vector<IETextFieldWidget> v = new Vector<IETextFieldWidget>(); Enumeration<IObject> en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IObject o = en.nextElement(); if (o instanceof IETextFieldWidget) { v.add((IETextFieldWidget) o); } } return v; } /** * Returns all the textareas ({@link IETextAreaWidget}) of this WOComponent. You should not use directly this method but instead * implement a cache mechanism and use the benefits of the methods notifyWidgetAdded and notifyWidgetRemoved. This method is intended to * be used to preserve the order of this component when presenting this to a user. * * @return all the textareas contained in this component. */ @Override public Vector<IETextAreaWidget> getTextareas() { Vector<IETextAreaWidget> v = new Vector<IETextAreaWidget>(); Enumeration<IObject> en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IObject o = en.nextElement(); if (o instanceof IETextAreaWidget) { v.add((IETextAreaWidget) o); } } return v; } /** * Returns all the dropdowns ({@link IEDropDownWidget}) of this WOComponent. You should not use directly this method but instead * implement a cache mechanism and use the benefits of the methods notifyWidgetAdded and notifyWidgetRemoved. This method is intended to * be used to preserve the order of this component when presenting this to a user. * * @return all the dropdowns contained in this component. */ @Override public Vector<IEDropDownWidget> getDropdowns() { Vector<IEDropDownWidget> v = new Vector<IEDropDownWidget>(); Enumeration<IObject> en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IObject o = en.nextElement(); if (o instanceof IEDropDownWidget) { v.add((IEDropDownWidget) o); } } return v; } /** * Returns all the browsers ({@link IEBrowserWidget}) of this WOComponent. You should not use directly this method but instead implement * a cache mechanism and use the benefits of the methods notifyWidgetAdded and notifyWidgetRemoved. This method is intended to be used * to preserve the order of this component when presenting this to a user. * * @return all the browsers contained in this component. */ @Override public Vector<IEBrowserWidget> getBrowsers() { Vector<IEBrowserWidget> v = new Vector<IEBrowserWidget>(); Enumeration<IObject> en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IObject o = en.nextElement(); if (o instanceof IEBrowserWidget) { v.add((IEBrowserWidget) o); } } return v; } /** * Returns all the checkboxes ({@link IECheckBoxWidget}) of this WOComponent. You should not use directly this method but instead * implement a cache mechanism and use the benefits of the methods notifyWidgetAdded and notifyWidgetRemoved. This method is intended to * be used to preserve the order of this component when presenting this to a user. * * @return all the checkboxes contained in this component. */ @Override public Vector<IECheckBoxWidget> getCheckboxes() { Vector<IECheckBoxWidget> v = new Vector<IECheckBoxWidget>(); Enumeration<IObject> en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IObject o = en.nextElement(); if (o instanceof IECheckBoxWidget) { v.add((IECheckBoxWidget) o); } } return v; } /** * Returns all the radio buttons ({@link IERadioButtonWidget}) of this WOComponent. You should not use directly this method but instead * implement a cache mechanism and use the benefits of the methods notifyWidgetAdded and notifyWidgetRemoved. This method is intended to * be used to preserve the order of this component when presenting this to a user. * * @return all the radio buttons contained in this component. */ @Override public Vector<IERadioButtonWidget> getRadios() { Vector<IERadioButtonWidget> v = new Vector<IERadioButtonWidget>(); Enumeration<IObject> en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IObject o = en.nextElement(); if (o instanceof IERadioButtonWidget) { v.add((IERadioButtonWidget) o); } } return v; } /** * Returns all the buttons ({@link IEButtonWidget}) of this WOComponent. You should not use directly this method but instead implement a * cache mechanism and use the benefits of the methods notifyWidgetAdded and notifyWidgetRemoved. This method is intended to be used to * preserve the order of this component when presenting this to a user. * * @return all the buttons contained in this component. */ public Vector<IEButtonWidget> getButtons() { Vector<IEButtonWidget> v = new Vector<IEButtonWidget>(); Enumeration<IObject> en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IObject o = en.nextElement(); if (o.getClass() == IEButtonWidget.class) { v.add((IEButtonWidget) o); } } return v; } /** * Returns all the hyperlinks ({@link IEHyperlinkWidget}) of this WOComponent. You should not use directly this method but instead * implement a cache mechanism and use the benefits of the methods notifyWidgetAdded and notifyWidgetRemoved. This method is intended to * be used to preserve the order of this component when presenting this to a user. * * @return all the hyperlinks contained in this component. */ @Override public Vector<IEHyperlinkWidget> getHyperlinks() { Vector<IEHyperlinkWidget> v = new Vector<IEHyperlinkWidget>(); Enumeration<IObject> en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IObject o = en.nextElement(); if (o instanceof IEHyperlinkWidget) { v.add((IEHyperlinkWidget) o); } } return v; } public Hashtable<IEObject, Hashtable<String, String>> getLocalizableObjects() { Hashtable<IEObject, Hashtable<String, String>> reply = new Hashtable<IEObject, Hashtable<String, String>>(); Enumeration<IObject> en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IObject object = en.nextElement(); if (object instanceof IEWidget) { Hashtable<String, String> props = ((IEWidget) object).getLocalizedProperties(); if (props.size() > 0) { reply.put((IEWidget) object, props); } } } return reply; } public synchronized BidiMap getNameForWidgetMap() { if (nameForWidgetMap.size() == 0) { buildNameForWidgetMap(); } return nameForWidgetMap; } public synchronized String getUniqueNameForWidget(IEWidget widget) { if (getNameForWidgetMap().getKey(widget) != null) { return (String) getNameForWidgetMap().getKey(widget); } if (logger.isLoggable(Level.WARNING)) { logger.warning("Widget " + widget + " had no computed name meaning that it was probably not properly embedded in the WOComponent." + "I will compute its name now, but this can be source of instability in the names of the widgets. You should try to find why that widget was not embedded."); } return computeAndStoreNameForWidget(widget); } private synchronized String computeAndStoreNameForWidget(IEWidget widget) { String base = ToolBox.uncapitalize(widget.getNiceName()); String attempt = base; if (nameForWidgetMap.get(attempt) != null || widget instanceof IELabelWidget || ReservedKeyword.contains(attempt)) { String widgetType = widget.getWidgetType(); if (widget instanceof IESequence && ((IESequence<?>) widget).getOperator() != null) { widgetType = ((IESequence<?>) widget).getOperator().getWidgetType(); } if (base.toLowerCase().indexOf(widgetType.toLowerCase()) == -1) { base = base + widgetType; } base = ToolBox.uncapitalize(base); int i = 1; attempt = base; while (nameForWidgetMap.get(attempt) != null || ReservedKeyword.contains(attempt)) { i++; attempt = base + String.valueOf(i); } } nameForWidgetMap.put(attempt, widget); return attempt; } private void buildNameForWidgetMap() { Vector<IEWidget> widgets = new Vector<IEWidget>(); Enumeration<IObject> en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IObject object = en.nextElement(); if (object instanceof IEWidget) { IEWidget widget = (IEWidget) object; widgets.add(widget); } } Collections.sort(widgets, new Comparator<FlexoModelObject>() { @Override public int compare(FlexoModelObject o1, FlexoModelObject o2) { return o1.compareTo(o2); } }); for (DMObject obj : getComponentDMEntity().getOrderedChildren()) { nameForWidgetMap.put(ToolBox.uncapitalize(obj.getName()), obj); } for (IEWidget widget : widgets) { computeAndStoreNameForWidget(widget); } } public IESequenceWidget getRootSequence() { return rootSequence; } public void setRootSequence(IESequenceWidget rootSequence) { if (this.rootSequence != null) { this.rootSequence.setParent(null); } this.rootSequence = rootSequence; if (this.rootSequence != null) { this.rootSequence.setParent(this); } } public boolean hasAtLeastOneTabDefined() { return getAvailableTabs().size() > 0; } public Vector<TabComponentDefinition> getAvailableTabs() { return getAllTabComponents(new Vector<TabComponentDefinition>()); } public Vector<IEHyperlinkWidget> getAllAbstractButtonNeedingAWorkflowConditional() { Vector<IEHyperlinkWidget> reply = new Vector<IEHyperlinkWidget>(); Enumeration en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IEObject widget = (IEObject) en.nextElement(); if (widget instanceof IEHyperlinkWidget && ((IEHyperlinkWidget) widget).needAWorkflowConditional()) { reply.add((IEHyperlinkWidget) widget); } } return reply; } public void removeTopWidget(IEWidget widget) { rootSequence.removeFromInnerWidgets(widget); setChanged(); notifyObservers(new TopWidgetRemoved(widget)); } public int indexOfTopWidget(IEWidget topWidget) { return rootSequence.indexOf(topWidget); } public void replaceWidgetByReusable(IEWidget oldWidget, IEReusableWidget newWidget) { int index = rootSequence.indexOf(oldWidget); newWidget.setIndex(index); removeTopWidget(oldWidget); insertTopWidgetAtIndex(newWidget, index); } public Enumeration<IEWidget> topComponents() { return rootSequence.elements(); } public Iterator<IEWidget> iterator() { return rootSequence.iterator(); } public int length() { return rootSequence.getWidgetCount(); } public void addToTopWidgetList(IEWidget widget) { rootSequence.addToInnerWidgets(widget); widget.setParent(rootSequence); } public void removeFromTopWidgetList(IEWidget topWidget) { rootSequence.removeFromInnerWidgets(topWidget); } public void insertTopWidgetAtIndex(IEWidget topWidget, int index) { rootSequence.insertElementAt(topWidget, Math.min(rootSequence.getWidgetCount(), index)); topWidget.setParent(this); topWidget.setWOComponent(this); } public void notifyTopWidgetInserted(TopWidgetInserted tci) { setChanged(); notifyObservers(tci); } public void notifyTopComponentRemoved(TopWidgetRemoved tcr) { setChanged(); notifyObservers(tcr); } public Iterator getRealTopComponents() { return rootSequence.getAllNonSequenceWidget().iterator(); } public Vector<IESequence> getAllSequenceWithConditionalOperators() { Vector<IESequence> reply = new Vector<IESequence>(); Enumeration en = getAllEmbeddedIEObjects(true).elements(); while (en.hasMoreElements()) { IEObject widget = (IEObject) en.nextElement(); if (widget instanceof IESequence && ((IESequence) widget).getOperator() != null && ((IESequence) widget).getOperator() instanceof ConditionalOperator) { reply.add((IESequence) widget); } } return reply; } }