/*
* (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.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Observable;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.foundation.DataFlexoObserver;
import org.openflexo.foundation.DataModification;
import org.openflexo.foundation.FlexoModelObject;
import org.openflexo.foundation.FlexoObservable;
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.IEDropDownWidget;
import org.openflexo.foundation.ie.widget.IEHyperlinkWidget;
import org.openflexo.foundation.ie.widget.IERadioButtonWidget;
import org.openflexo.foundation.ie.widget.IEStringWidget;
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.rm.FlexoProject;
import org.openflexo.foundation.validation.Validable;
import org.openflexo.foundation.validation.ValidationModel;
import org.openflexo.toolbox.EmptyVector;
import org.openflexo.xmlcode.InvalidObjectSpecificationException;
/**
* Superclass for all model classes. Holds all attributes for a model class. Notify observers when some attribute change (i.e. when put is
* called), giving the modified key as notification argument. TODO: currently implements Serializable: don't know why: remove this interface
* ???
*
* @author bmangez
*
*/
public abstract class IEObject extends FlexoModelObject implements DataFlexoObserver, IObject {
private static final Logger logger = Logger.getLogger(IEObject.class.getPackage().getName());
protected static final Vector<IObject> EMPTY_IOBJECT_VECTOR = EmptyVector.EMPTY_VECTOR(IObject.class);
/**
* This consrtuctor should never be called anywhre by anyone
*/
public IEObject(FlexoProject project) {
super(project);
}
@Override
public void update(Observable observable, Object obj) {
// Do nothing, since Observer interface is no more used
// See FlexoObserver
}
@Override
public void update(FlexoObservable observable, DataModification obj) {
// Ignored at this level: implements it in sub-classes
}
protected void notifyModification(String key, Object oldValue, Object newValue) {
notifyModification(key, oldValue, newValue, false);
}
protected void notifyModification(String key, Object oldValue, Object newValue, boolean isReentrant) {
setChanged();
DataModification dataModification = new DataModification(key, oldValue, newValue);
if (isReentrant) {
dataModification.setReentrant(isReentrant);
}
notifyObservers(dataModification);
}
@Override
public Class getTypeForKey(String key) {
if (logger.isLoggable(Level.FINE)) {
logger.finer("getTypeForKey for " + key);
}
try {
return super.getTypeForKey(key);
} catch (InvalidObjectSpecificationException e) {
if (logger.isLoggable(Level.FINE)) {
logger.finer("OK, lets use the dynamic attributes !");
}
return String.class;
}
}
@Override
public ValidationModel getDefaultValidationModel() {
if (getProject() != null) {
return getProject().getIEValidationModel();
} else {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not access to project !");
}
}
return null;
}
private void processToAdditionOfEmbedded(IEObject object, Collection<IObject> queue) {
queue.add(object);
if (object.getEmbeddedIEObjects() != null) {
Enumeration en = object.getEmbeddedIEObjects().elements();
Object candidate = null;
while (en.hasMoreElements()) {
candidate = en.nextElement();
if (candidate == null) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Object of class " + object.getClass().getName()
+ " returned IEObjects null in its method getEmbeddedIEObjects");
}
continue;
}
if (!queue.contains(candidate)) {
if (candidate instanceof IObject) {
processToAdditionOfEmbedded((IEObject) candidate, queue);
} else {
if (logger.isLoggable(Level.SEVERE)) {
logger.severe("Object of class " + object.getClass().getName()
+ " returned non IEObjects in its method getEmbeddedIEObjects");
}
}
}
}
}
}
public boolean checkWidgetDoesNotEmbedWOComponent(IEReusableComponent wo) {
Vector<IObject> v = getAllEmbeddedIEObjects();
for (IObject o : v) {
if (o instanceof PartialComponentInstance) {
if (((PartialComponentInstance) o).getComponentDefinition() == wo.getComponentDefinition()) {
return true;
} else {
boolean res = ((PartialComponentInstance) o).getComponentDefinition().getWOComponent()
.checkWidgetDoesNotEmbedWOComponent(wo);
if (res) {
return true;
}
}
}
}
return false;
}
public abstract IEObject getParent();
/**
* Return a Vector of all embedded IEObjects: recursive method (Note must include itself in this vector)
*
* @return a Vector of IEObject instances
*/
@Override
public Vector<IObject> getAllEmbeddedIEObjects() {
return getAllEmbeddedIEObjects(false);
}
/**
* Return a Vector of all embedded IEObjects: recursive method (Note must include itself in this vector)
*
* @param maintainNaturalOrder
* wheter the natural order (e.g., in a table from left to right and top to bottom) should be maintained or not. This impacts
* directly the performance.
* @return a Vector of IEObject instances
*/
public Vector<IObject> getAllEmbeddedIEObjects(boolean maintainNaturalOrder) {
Collection<IObject> returned;
if (maintainNaturalOrder) {
returned = new Vector<IObject>();
} else {
returned = new HashSet<IObject>();
}
processToAdditionOfEmbedded(this, returned);
return new Vector<IObject>(returned);
}
/**
* Return a Vector of all embedded IEWidget matching the classe specified: recursive method (Note must include itself in this vector)
*
* @param classeToMatch
* @return a Vector of all embedded IEWidget matching the classe specified: recursive method (Note must include itself in this vector)
*/
public <T extends IEWidget> Vector<T> getAllEmbeddedIEWidgets(Class<T> classeToMatch) {
Vector<T> reply = new Vector<T>();
Enumeration en = getAllEmbeddedIEObjects(true).elements();
while (en.hasMoreElements()) {
IEObject widget = (IEObject) en.nextElement();
if (classeToMatch.isAssignableFrom(widget.getClass())) {
reply.add((T) widget);
}
}
return reply;
}
/**
* Return a Vector of embedded IEObjects at this level. NOTE that this is NOT a recursive method
*
* @return a Vector of IEObject instances
*/
@Override
public abstract Vector<IObject> getEmbeddedIEObjects();
@Override
public Vector<Validable> getAllEmbeddedValidableObjects() {
return new Vector<Validable>(getAllEmbeddedIEObjects());
}
/**
* Returns all the strings ({@link IEStringWidget}) of this object. 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 object when presenting this to a user.
*
* @return all the strings contained in this component.
*/
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 object. 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 object when presenting this to a user.
*
* @return all the textfields contained in this component.
*/
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 object. 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 object when presenting this to a user.
*
* @return all the textareas contained in this component.
*/
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 object. 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 object when presenting this to a user.
*
* @return all the dropdowns contained in this component.
*/
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 object. 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 object when presenting this to a user.
*
* @return all the browsers contained in this component.
*/
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 object. 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 object when presenting this to a user.
*
* @return all the checkboxes contained in this component.
*/
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 object. 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 object when presenting this to a user.
*
* @return all the radio buttons contained in this component.
*/
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 object. 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 object when presenting this to a user.
*
* @return all the buttons contained in this component.
*/
public Vector<IEButtonWidget> getIEButtons() {
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 object. 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 object when presenting this to a user.
*
* @return all the hyperlinks contained in this component.
*/
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;
}
}