/* * (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.widget; import java.util.Collection; import java.util.Enumeration; import java.util.Iterator; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import org.openflexo.foundation.Inspectors; import org.openflexo.foundation.ie.IEObject; import org.openflexo.foundation.ie.IEWOComponent; import org.openflexo.foundation.ie.IObject; import org.openflexo.foundation.ie.dm.SubsequenceInserted; import org.openflexo.foundation.ie.dm.WidgetAddedToSequence; import org.openflexo.foundation.ie.dm.WidgetRemovedFromSequence; import org.openflexo.foundation.ie.operator.ConditionalOperator; import org.openflexo.foundation.ie.operator.IEOperator; import org.openflexo.foundation.ie.operator.RepetitionOperator; import org.openflexo.foundation.rm.FlexoProject; import org.openflexo.logging.FlexoLogger; import org.openflexo.toolbox.ToolBox; public abstract class IESequence<E extends IWidget> extends IEWidget { private static final Logger logger = FlexoLogger.getLogger(IESequence.class.getPackage().getName()); private Vector<E> _children; private IESequenceOperator _sequenceOperator; private IEOperator operator; public IESequence(IEWOComponent woComponent, IEObject parent, FlexoProject prj) { super(woComponent, parent, prj); _children = new Vector<E>(); if (!(parent instanceof IESequenceOperator)) { _sequenceOperator = new IESequenceOperator(woComponent, this, prj); } } @SuppressWarnings("unchecked") public void simplifySequenceTree() { Enumeration en = ((Vector<E>) _children.clone()).elements(); while (en.hasMoreElements()) { E e = (E) en.nextElement(); if (e.getClass() == this.getClass()) { ((IESequence) e).simplifySequenceTree(); } } if (getOperator() == null && getParent() instanceof IESequence) { int index = ((IESequence) getParent()).indexOf(this); ((IESequence) getParent()).removeFromInnerWidgets(this); while (!_children.isEmpty()) { E w = _children.lastElement(); _children.remove(w); ((IESequence<E>) getParent()).insertElementAt(w, index); } this.delete(); } } @Override public String getNiceName() { String niceName = getCalculatedLabel(); if (niceName != null && niceName.trim().length() > 0) { return ToolBox.getJavaName(niceName); } if (getOperator() != null) { String post = getClass().getSimpleName(); if (post.startsWith("IESequence")) { post = post.substring("IESequence".length()); } return post + getOperator().getWidgetType(); } return getWidgetType(); } @Override public void performOnDeleteOperations() { if (getOperator() != null) { getOperator().delete(); return; } isDeleting = true; Enumeration en = ((Vector) _children.clone()).elements(); while (en.hasMoreElements()) { IWidget w = (IWidget) en.nextElement(); w.delete(); } super.performOnDeleteOperations(); } /** * Returns the number of parents that are of the same class. * * @return the number of parents that are of the same class */ public int getSequenceDepth() { int i = 0; IEObject parent = getParent(); while (parent != null && parent.getClass() == this.getClass()) { i++; parent = ((IESequence) parent).getParent(); } return i; } @Override public String getDefaultInspectorName() { if (isConditional()) { return Inspectors.IE.CONDITIONAL_SEQUENCE_INSPECTOR; } else if (isRepetition()) { return Inspectors.IE.REPETITION_SEQUENCE_INSPECTOR; } else { return null; } } @Override public Vector<IObject> getEmbeddedIEObjects() { Vector<IObject> answer = new Vector<IObject>(); if (getOperator() != null) { answer.add(getOperator()); } answer.addAll(_children); return answer; } @Override public String getFullyQualifiedName() { return null; } public Vector<E> getInnerWidgets() { return _children; } public void setInnerWidgets(Vector<E> v) { _children = v; } /** * Overrides getInspectorName * * @see org.openflexo.foundation.ie.widget.IEWidget#getInspectorName() */ @Override public String getInspectorName() { if (getOperator() != null) { if (isConditional()) { return Inspectors.IE.CONDITIONAL_SEQUENCE_INSPECTOR; } else if (isRepetition()) { return Inspectors.IE.REPETITION_SEQUENCE_INSPECTOR; } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("Unknwown operator-->Cannot return inspector name"); } return null; } } else { return null; } } public void addToInnerWidgets(E w) { if (w instanceof IESequenceOperator) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Tried to add an IESequenceOperator."); } return; } else if (w instanceof IEOperator) { if (getOperator() == null) { setOperator((IEOperator) w); } } else { insertElementAt(w, _children.size()); w.setParent(this); } } public void removeFromInnerWidgets(E w) { removeFromInnerWidgets(w, true); } public void removeFromInnerWidgets(E w, boolean deleteIfEmpty) { if (w instanceof IESequenceOperator || w instanceof IEOperator) { return; } else { _children.remove(w); w.setParent(null); refreshIndexes(); setChanged(); notifyObservers(new WidgetRemovedFromSequence((IEObject) w)); if (w instanceof IESequence) { setChanged(); notifyObservers(new SubsequenceRemoved((IESequence) w)); } if (getOperator() != null) { getOperator().notifyWidgetRemoval(w); } if (deleteIfEmpty && _children.size() == 0 && !isDeleting && isSubsequence()) { isDeleting = true; delete(); } } } private boolean isDeleting = false; public int indexOf(E w) { return _children.indexOf(w); } public int size() { return _children.size(); } public int getWidgetCount() { return size(); } public void insertElementAt(E o, int i) { if (i > _children.size()) { i = _children.size(); } _children.insertElementAt(o, i); o.setParent(this); if (!isDeserializing() && getWOComponent() != null) { // TODO: check that when we duplicate component, all widgets receive this notification o.setWOComponent(getWOComponent()); } refreshIndexes(); setChanged(); if (o instanceof IEWidget) { notifyObservers(new WidgetAddedToSequence((IEWidget) o, ((IEWidget) o).getIndex())); } setChanged(); if (o instanceof IESequence) { notifyObservers(new SubsequenceInserted((IESequence) o)); } if (getOperator() != null) { getOperator().notifyWidgetInsertion(o); } } protected void refreshIndexes() { Enumeration en = elements(); int i = 0; while (en.hasMoreElements()) { ((IEWidget) en.nextElement()).setIndex(i); i++; } } public Enumeration<E> elements() { return _children.elements(); } public Iterator<E> iterator() { return _children.iterator(); } public int length() { return _children.size(); } @Deprecated public IESequenceOperator getSequenceOperator() { return _sequenceOperator; } @Deprecated public void setSequenceOperator(IESequenceOperator op_seq) { _sequenceOperator = op_seq; op_seq.setParent(this); } /** * Overrides getClassNameKey * * @see org.openflexo.foundation.FlexoModelObject#getClassNameKey() */ @Override public String getClassNameKey() { return "sequence"; } public E get(int i) { try { return _children.get(i); } catch (ArrayIndexOutOfBoundsException e) { return null; } } public void setElementAt(E element, int index) { _children.setElementAt(element, index); element.setParent(this); element.setIndex(index); } public static IESequence createASubSequence(IESequence actualParentSequence) { if (actualParentSequence instanceof IESequenceTopComponent) { return new IESequenceTopComponent(actualParentSequence.getWOComponent(), actualParentSequence, actualParentSequence.getProject()); } else if (actualParentSequence instanceof IESequenceTR) { IESequenceTR returned = new IESequenceTR(actualParentSequence.getWOComponent(), actualParentSequence, actualParentSequence.getProject()); returned.constraints.gridwidth = ((IESequenceTR) actualParentSequence).getColCount(); return returned; } else if (actualParentSequence instanceof IESequenceTD) { return new IESequenceTD(actualParentSequence.getWOComponent(), actualParentSequence, actualParentSequence.getProject()); } else if (actualParentSequence instanceof IESequenceWidget) { return new IESequenceWidget(actualParentSequence.getWOComponent(), actualParentSequence, actualParentSequence.getProject()); } else if (actualParentSequence instanceof IESequenceTab) { return new IESequenceTab(actualParentSequence.getWOComponent(), actualParentSequence, actualParentSequence.getProject()); } return null; } public boolean hasOperatorConditional() { return getOperator() != null && getOperator() instanceof ConditionalOperator; } public boolean hasOperatorRepetition() { return getOperator() != null && getOperator() instanceof RepetitionOperator; } public boolean isLast(Object obj) { return _children.lastElement() != null && _children.lastElement().equals(obj); } public boolean isFirst(Object obj) { return _children.size() > 0 && _children.get(0).equals(obj); } public Object getNext(Object obj) { if (!_children.contains(obj)) { return null; } if (isLast(obj)) { return null; } return _children.elementAt(_children.indexOf(obj) + 1); } public Object getPrevious(Object obj) { if (!_children.contains(obj)) { return null; } if (isFirst(obj)) { return null; } return _children.elementAt(_children.indexOf(obj) - 1); } public Object getLast() { if (_children.size() == 0) { return null; } return _children.lastElement(); } public void replaceWidgetByReusable(E oldWidget, E newWidget) { int index = indexOf(oldWidget); removeFromInnerWidgets(oldWidget); insertElementAt(newWidget, index); } public boolean addAll(Collection<? extends E> c) { return _children.addAll(c); } public void clear() { _children.clear(); } public boolean contains(Object o) { return _children.contains(o); } public boolean containsAll(Collection c) { return _children.containsAll(c); } public boolean isEmpty() { return _children.isEmpty(); } public Object[] toArray() { return _children.toArray(); } /** * Overrides toArray * * @see java.util.Collection#toArray(T[]) */ public <T> T[] toArray(T[] a) { return _children.toArray(a); } @SuppressWarnings("unchecked") public void unwrap() { if (isSubsequence()) { int insertionIndex = getIndex(); IESequence<E> parentSequence = (IESequence<E>) getParent(); while (!_children.isEmpty()) { E widget = _children.lastElement(); _children.remove(widget); parentSequence.insertElementAt(widget, insertionIndex); } delete(); } } public void resetOperator() { operator = null; } @Override public Vector<IWidget> getAllNonSequenceWidget() { Vector<IWidget> v = new Vector<IWidget>(); Enumeration<E> en = elements(); while (en.hasMoreElements()) { E element = en.nextElement(); v.addAll(element.getAllNonSequenceWidget()); } return v; } public IEObject getNonSequenceParent() { if (isRoot()) { return getParent(); } else if (getParent() instanceof IESequence) { return ((IESequence<E>) getParent()).getNonSequenceParent(); } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("Not good! This sequence is not the root sequence, but parent is not a sequence"); } return getParent(); } } public abstract boolean isSubsequence(); public boolean isRoot() { return getParent() == null || !getParent().getClass().isAssignableFrom(this.getClass()); } public IEOperator getOperator() { if (!isSubsequence()) { if (_sequenceOperator != null && _sequenceOperator.size() > 0) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Found a sequence of operator but this is not a sub-sequence"); } } return null; } if (operator == null && _sequenceOperator != null && _sequenceOperator.size() > 0) { operator = _sequenceOperator.get(0); operator.setOperatedSequence(this); _sequenceOperator = null; } return operator; } public void setOperator(IEOperator operator) { IEOperator old = this.operator; this.operator = operator; operator.setOperatedSequence(this); setChanged(); notifyObservers(new OperatorChanged(old, operator)); } public boolean isConditional() { return getOperator() != null && getOperator() instanceof ConditionalOperator; } public boolean isRepetition() { return getOperator() != null && getOperator() instanceof RepetitionOperator; } public IWidget lastObject() { if (!(get(size() - 1) instanceof IESequence)) { return get(size() - 1); } else { return ((IESequence) get(size() - 1)).lastObject(); } } public IWidget firstObject() { if (size() == 0) { if (logger.isLoggable(Level.WARNING)) { logger.warning("This is not suppose to happen: an empty sequence is left in the model"); } return null; } if (!(get(0) instanceof IESequence)) { return get(0); } else { return ((IESequence) get(0)).firstObject(); } } @Override public void setWOComponent(IEWOComponent woComponent) { if (noWOChange(woComponent)) { return; } super.setWOComponent(woComponent); if (getOperator() != null) { getOperator().setWOComponent(woComponent); } if (_children != null) {// This call is very important because it will update the WOComponent components cache Enumeration<E> en = elements(); while (en.hasMoreElements()) { E e = en.nextElement(); e.setWOComponent(woComponent); } } } @Override public boolean areComponentInstancesValid() { boolean b = true; Enumeration<E> en = elements(); while (en.hasMoreElements() && b) { E e = en.nextElement(); b &= e.areComponentInstancesValid(); } return b; } @Override public void removeInvalidComponentInstances() { Enumeration<E> en = elements(); while (en.hasMoreElements()) { E e = en.nextElement(); e.removeInvalidComponentInstances(); } } @Override public Vector<IEHyperlinkWidget> getAllButtonInterface() { Vector<IEHyperlinkWidget> v = new Vector<IEHyperlinkWidget>(); Enumeration<? extends IWidget> en = elements(); while (en.hasMoreElements()) { IWidget element = en.nextElement(); v.addAll(element.getAllButtonInterface()); } return v; } }