/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.diagram.ui.notation.uml.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.emf.ecore.EObject;
import org.teiid.designer.core.metamodel.aspect.MetamodelAspect;
import org.teiid.designer.core.metamodel.aspect.uml.UmlAssociation;
import org.teiid.designer.core.metamodel.aspect.uml.UmlClassifier;
import org.teiid.designer.core.metamodel.aspect.uml.UmlOperation;
import org.teiid.designer.core.metamodel.aspect.uml.UmlProperty;
import org.teiid.designer.diagram.ui.DiagramUiConstants;
import org.teiid.designer.diagram.ui.DiagramUiPlugin;
import org.teiid.designer.diagram.ui.model.AbstractDiagramModelNode;
import org.teiid.designer.diagram.ui.model.AbstractLocalDiagramModelNode;
import org.teiid.designer.diagram.ui.model.DiagramModelNode;
import org.teiid.designer.metamodels.diagram.Diagram;
/**
* @author mdrilling
*
* Model Node for UML Classifier Container
*
* @since 8.0
*/
public class UmlClassifierContainerNode extends AbstractLocalDiagramModelNode {
public static final int ATTRIBUTES = 0;
public static final int ASSOCIATIONS = 1;
public static final int OPERATIONS = 2;
public static final int CLASSIFIERS = 3;
public int type = -1;
/**
* Construct an instance of UmlClassifierContainerNode.
*/
public UmlClassifierContainerNode( int containerType ) {
super( null, "ClassifierContainer" ); //$NON-NLS-1$
this.type = containerType;
}
/**
* Construct an instance of UmlClassifierContainerNode.
*/
public UmlClassifierContainerNode( int containerType , List containedItems ) {
super( null, "ClassifierContainer" ); //$NON-NLS-1$
this.type = containerType;
setParentOfChildren(containedItems);
setChildren(containedItems);
}
public UmlClassifierContainerNode( EObject modelObject, List containedItems ) {
super( modelObject, "ClassifierContainer"); //$NON-NLS-1$
setParentOfChildren(containedItems);
setChildren(containedItems);
}
/**
* This constructor is designed to take a list of EObjects and construct a list of
* appropriate attributes whose type is based on "aspects"
*/
public UmlClassifierContainerNode( int containerType, List eObjectList, Diagram diagram ) {
super( null, "ClassifierContainer"); //$NON-NLS-1$
this.type = containerType;
// call createChildren() - private method (make sure you set the parent of the node
setChildren(createChildren(eObjectList, diagram));
}
public DiagramModelNode getChild(EObject eObject ) {
DiagramModelNode childNode = null;
List currentChildren = new ArrayList( getChildren() );
Iterator iter = currentChildren.iterator();
DiagramModelNode nextNode = null;
while( iter.hasNext() && childNode == null ) {
nextNode = (DiagramModelNode)iter.next();
if( nextNode != null && nextNode.getModelObject() != null &&
nextNode.getModelObject().equals(eObject)) {
childNode = nextNode;
}
}
return childNode;
}
public int getType() {
return this.type;
}
private void setParentOfChildren(List children) {
if( !children.isEmpty() ) {
DiagramModelNode nextNode = null;
Iterator iter = children.iterator();
while( iter.hasNext() ) {
nextNode = (DiagramModelNode)iter.next();
nextNode.setParent(this);
}
}
}
public void reorderChildren(List reorderedChildren) {
List newChildList = new ArrayList(getChildren().size());
Iterator iter = reorderedChildren.iterator();
EObject nextChild = null;
DiagramModelNode nextChildNode = null;
while( iter.hasNext() ) {
nextChild = (EObject)iter.next();
nextChildNode = getChild(nextChild);
if( nextChildNode != null )
newChildList.add(nextChildNode);
}
if( !newChildList.isEmpty() ) {
setChildren(newChildList);
}
}
public List getEObjectChildren() {
List eObjectList = Collections.EMPTY_LIST;
if( getChildren() != null && !getChildren().isEmpty() ) {
Iterator iter = null;
DiagramModelNode nextNode = null;
eObjectList = new ArrayList(getChildren().size());
iter = getChildren().iterator();
while( iter.hasNext() ) {
nextNode = (DiagramModelNode)iter.next();
eObjectList.add(nextNode.getModelObject());
}
}
return eObjectList;
}
public boolean isEmpty() {
if( getChildren() == null || getChildren().isEmpty() )
return true;
return false;
}
/**
* This private method allows the constructor to create a set of attributes
* for this container. The container is in charge of knowing what type
* of attributes to construct.
* @param eObjectList
* @param diagram
* @return
*/
private List createChildren(List eObjectList, Diagram diagram) {
if( eObjectList != null && !eObjectList.isEmpty() ) {
List modelNodeList = new ArrayList(eObjectList.size());
Iterator iter = eObjectList.iterator();
while(iter.hasNext()) {
EObject eObj = (EObject)iter.next();
MetamodelAspect mmAspect = getUmlAspect(eObj);
if(mmAspect instanceof UmlProperty) {
DiagramModelNode attributeNode = new UmlAttributeNode(eObj, (UmlProperty)mmAspect);
attributeNode.setParent(this);
modelNodeList.add(attributeNode);
} else if(mmAspect instanceof UmlAssociation) {
DiagramModelNode associationNode = new UmlAssociationNode(eObj, (UmlAssociation)mmAspect);
associationNode.setParent(this);
modelNodeList.add(associationNode);
} else if(mmAspect instanceof UmlOperation) {
DiagramModelNode operationNode = new UmlOperationNode(eObj, (UmlOperation)mmAspect);
operationNode.setParent(this);
modelNodeList.add(operationNode);
} else if(mmAspect instanceof UmlClassifier) {
DiagramModelNode classifierNode = new UmlClassifierNode(diagram, eObj, (UmlClassifier)mmAspect, true);
classifierNode.setParent(this);
modelNodeList.add(classifierNode);
}
}
return modelNodeList;
}
return Collections.EMPTY_LIST;
}
/** this method is designed to add/remove any model objects that conflict with
* the list of eObjects in the input list.
*/
public void reconcile(List newEObjectList, Diagram diagram) {
if( newEObjectList != null && !newEObjectList.isEmpty() ) {
Iterator iter = newEObjectList.iterator();
// BML 9/14/06 - Changed this method to use addChildren() & removeChildren() (rather than one at a time) to minimize
// the amount of property change events being fired. Simple and safe fix.
List newChildNodes = new ArrayList();
while(iter.hasNext()) {
EObject eObj = (EObject)iter.next();
DiagramModelNode someModelNode = getChild(eObj);
if( someModelNode == null ) {
MetamodelAspect mmAspect = getUmlAspect(eObj);
if(mmAspect instanceof UmlProperty) {
DiagramModelNode attributeNode = new UmlAttributeNode(eObj, (UmlProperty)mmAspect);
attributeNode.setParent(this);
newChildNodes.add(attributeNode);
} else if(mmAspect instanceof UmlAssociation) {
DiagramModelNode associationNode = new UmlAssociationNode(eObj, (UmlAssociation)mmAspect);
associationNode.setParent(this);
newChildNodes.add(associationNode);
} else if(mmAspect instanceof UmlOperation) {
DiagramModelNode operationNode = new UmlOperationNode(eObj, (UmlOperation)mmAspect);
operationNode.setParent(this);
newChildNodes.add(operationNode);
} else if(mmAspect instanceof UmlClassifier) {
DiagramModelNode classifierNode = new UmlClassifierNode(diagram, eObj, (UmlClassifier)mmAspect);
classifierNode.setParent(this);
newChildNodes.add(classifierNode);
}
}
}
if( ! newChildNodes.isEmpty() ) {
addChildren(newChildNodes);
}
// Now we need to walk through the current list and find any objects that don't belong
List currentEObjectList = new ArrayList(getEObjectChildren());
Iterator currentIter = currentEObjectList.iterator();
List oldChildNodes = new ArrayList();
EObject nextEObj = null;
DiagramModelNode nextNode = null;
while( currentIter.hasNext() ) {
nextEObj = (EObject)currentIter.next();
if( ! newEObjectList.contains(nextEObj) ) {
nextNode = getChild(nextEObj);
if( nextNode != null ) {
oldChildNodes.add(nextNode);
}
}
}
if( ! oldChildNodes.isEmpty() ) {
removeChildren(oldChildNodes, false);
}
reorderChildren(newEObjectList);
} else {
// make sure that we remove all children here.
List currentChildren = new ArrayList(getChildren());
removeChildren(currentChildren, false);
}
}
/**
* Helper method to get the UmlAspect given an EObject
*/
private MetamodelAspect getUmlAspect(EObject eObject) {
return DiagramUiPlugin.getDiagramAspectManager().getUmlAspect( eObject );
}
// Used to alert the Edit Part that the children have been modified
// and a refreshChildren() is needed.
@Override
public void fireStructureChange(String prop, Object child) {
super.fireStructureChange(prop, child);
// Now we need to tell the parent classifier that it children has changed...
((AbstractDiagramModelNode)getParent()).fireStructureChange(prop,null);
}
@Override
public void setSize(Dimension theDimension) {
int newHeight = height;
int newWidth = width;
if( isHeightFixed() ) {
newHeight = getFixedHeight(); //DiagramModelNode.DEFAULT_FIXED_HEIGHT;
} else {
newHeight = theDimension.height;
}
newWidth = theDimension.width;
if( newWidth != width || newHeight != height ) {
width = newWidth;
height = newHeight;
firePropertyChange(DiagramUiConstants.DiagramNodeProperties.SIZE, null, theDimension);
}
}
}