/* * 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.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.preference.IPreferenceStore; 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.PluginConstants; import org.teiid.designer.diagram.ui.connection.BinaryAssociation; import org.teiid.designer.diagram.ui.connection.DiagramUmlAssociation; import org.teiid.designer.diagram.ui.connection.NodeConnectionModel; import org.teiid.designer.diagram.ui.connection.UmlRelationshipFactory; import org.teiid.designer.diagram.ui.model.DiagramModelNode; import org.teiid.designer.diagram.ui.model.ExpandableNode; import org.teiid.designer.diagram.ui.part.ExpandableDiagram; import org.teiid.designer.diagram.ui.util.DiagramEntityAdapter; import org.teiid.designer.diagram.ui.util.DiagramUiUtilities; import org.teiid.designer.metamodels.diagram.Diagram; import org.teiid.designer.ui.viewsupport.ModelObjectUtilities; /** * @author mdrilling Model Node for UML Classifier. * * @since 8.0 */ public class UmlClassifierNode extends UmlModelNode implements ExpandableNode { boolean expandedState = false; private UmlClassifierContainerNode attributesContainer; private UmlClassifierContainerNode associationsContainer; private UmlClassifierContainerNode operationsContainer; private UmlClassifierContainerNode classifiersContainer; public UmlClassifierNode( Diagram diagram, EObject modelObject, UmlClassifier aspect ) { super(diagram, modelObject, aspect); reconcile(); } public UmlClassifierNode( Diagram diagram, EObject modelObject, UmlClassifier aspect, boolean isNested ) { super(diagram, modelObject, aspect, isNested); reconcile(); } public boolean showInnerClasses( EObject eObj, Diagram diagram ) { boolean show = false; IClassifierContentAdapter classAdapter = DiagramUiPlugin.getDiagramTypeManager().getDiagram(diagram.getType()).getClassifierContentAdapter(); if (classAdapter != null) show = classAdapter.showInnerClasses(eObj, diagram); return show; } /** * Helper method to get the UmlAspect given an EObject */ public MetamodelAspect getUmlAspect( EObject eObject ) { return DiagramUiPlugin.getDiagramAspectManager().getUmlAspect(eObject); } @Override public String getName() { return aspect.getSignature(getRealModelObject(), UmlClassifier.SIGNATURE_NAME); } @Override public String getPath() { String somePath = null; if (getDiagramModelObject() != null) { Diagram theDiagram = getDiagramModelObject().getDiagram(); somePath = DiagramUiPlugin.getDiagramTypeManager().getDisplayedPath(theDiagram, getRealModelObject()); } return somePath; } public void refreshForNameChange() { String oldName = "xxxXxxx"; //$NON-NLS-1$ if (getDiagramModelObject() != null && !isReadOnly()) { DiagramEntityAdapter.setName(getDiagramModelObject(), getName()); } firePropertyChange(DiagramNodeProperties.NAME, oldName, getName()); } public void refreshForPathChange() { update(DiagramNodeProperties.PATH); } @Override public void setName( String name ) { // aspect.setSignature(getModelObject(),name); ModelObjectUtilities.rename(getRealModelObject(), name, this); // super.setName(name); } public void setSignature( String signature ) { aspect.setSignature(getRealModelObject(), signature); } // public String getPath() { // return aspect.getSignature(getModelObject(),UmlClassifier.SIGNATURE_NAME); // } @Override public String toString() { return "UmlClassifierNode(" + getName() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } public List getAttributes() { if (attributesContainer != null) return attributesContainer.getChildren(); return Collections.EMPTY_LIST; } public DiagramModelNode getAttributesContainer() { return attributesContainer; } @Override public List getAssociations( HashMap nodeMap ) { IPreferenceStore store = DiagramUiPlugin.getDefault().getPreferenceStore(); boolean showRoles = store.getBoolean(PluginConstants.Prefs.SHOW_FK_NAME); boolean showMulti = store.getBoolean(PluginConstants.Prefs.SHOW_FK_MULTIPLICITY); MetamodelAspect classifierAspect = getUmlAspect(getRealModelObject()); if (classifierAspect instanceof UmlClassifier) { List returnAssociations = new ArrayList(); DiagramModelNode diagramRootModelObject = this.getParent(); Collection relationships = ((UmlClassifier)classifierAspect).getRelationships(getRealModelObject()); Collection superTypes = ((UmlClassifier)classifierAspect).getSupertypes(getRealModelObject()); List allAssociations = new ArrayList(); if (relationships != null && !relationships.isEmpty()) { Iterator iter = relationships.iterator(); Object nextObject = null; while (iter.hasNext()) { nextObject = iter.next(); if (!allAssociations.contains(nextObject)) allAssociations.add(nextObject); } } if (superTypes != null && !superTypes.isEmpty()) { Iterator iter = superTypes.iterator(); Object nextObject = null; while (iter.hasNext()) { nextObject = iter.next(); if (!allAssociations.contains(nextObject)) allAssociations.add(nextObject); } } List allBasses = UmlRelationshipFactory.getBinaryAssociations(allAssociations, getRealModelObject()); // allAssociations will be a list of BinaryAssociations..... Iterator iter = allBasses.iterator(); BinaryAssociation nextBass = null; NodeConnectionModel newConnectionModel = null; while (iter.hasNext()) { nextBass = (BinaryAssociation)iter.next(); newConnectionModel = UmlRelationshipFactory.getConnectionModel(nextBass, diagramRootModelObject, nodeMap); if (newConnectionModel instanceof DiagramUmlAssociation) { ((DiagramUmlAssociation)newConnectionModel).setShowRoles(showRoles); ((DiagramUmlAssociation)newConnectionModel).setShowMultiplicity(showMulti); } if (newConnectionModel != null) { returnAssociations.add(newConnectionModel); } } if (returnAssociations.isEmpty()) return Collections.EMPTY_LIST; return returnAssociations; } return Collections.EMPTY_LIST; } /** * This method provides a consistent way for the classifier node to keep in synch with it's eObject. The reconcile() method * will insure that the attributes of the classifier (all containers) are consistent with the model provider and in the right * order. * * @param eObj * @return */ public DiagramModelNode addChild( EObject eObj ) { reconcile(); DiagramModelNode newNode = getChild(eObj); if (newNode != null) updateForChild(true); return newNode; } public void removeChild( DiagramModelNode childNode ) { // Check containers and if any child's modelObject == eObj, then then // tell the container's modelObject to removeChild(node); if (attributesContainer != null && attributesContainer.getChildren().contains(childNode)) { attributesContainer.removeChild(childNode, false); if (attributesContainer.getChildren() == null || attributesContainer.getChildren().isEmpty()) { super.removeChild(attributesContainer, false); attributesContainer = null; } } else if (associationsContainer != null && associationsContainer.getChildren().contains(childNode)) { associationsContainer.removeChild(childNode, false); if (associationsContainer.getChildren() == null || associationsContainer.getChildren().isEmpty()) { super.removeChild(associationsContainer, false); associationsContainer = null; } } else if (operationsContainer != null && operationsContainer.getChildren().contains(childNode)) { operationsContainer.removeChild(childNode, false); if (operationsContainer.getChildren() == null || operationsContainer.getChildren().isEmpty()) { super.removeChild(operationsContainer, false); operationsContainer = null; } } else if (classifiersContainer != null && classifiersContainer.getChildren().contains(childNode)) { classifiersContainer.removeChild(childNode, false); if (classifiersContainer.getChildren() == null || classifiersContainer.getChildren().isEmpty()) { super.removeChild(classifiersContainer, false); classifiersContainer = null; } } updateForChild(false); } @Override public void updateForChild( boolean isMove ) { if (isMove) { reorderChildren(); if (attributesContainer != null) attributesContainer.updateForChild(false); if (associationsContainer != null) associationsContainer.updateForChild(false); if (operationsContainer != null) operationsContainer.updateForChild(false); if (classifiersContainer != null) classifiersContainer.updateForChild(false); super.updateForChild(false); } else super.updateForChild(isMove); } public void reorderChildren() { // Find the diagram. Diagram diagram = null; if (getDiagramModelObject() == null) { DiagramModelNode diagramNode = DiagramUiUtilities.getTopClassifierParentNode(this); Object mo = diagramNode.getDiagram(); if (mo instanceof Diagram) { diagram = (Diagram)mo; } else { // We shouldn't get here... String message = " UmlClassifierNode.reorderChildren(): modelObject NOT Diagram. Object = " + mo + " for DiagramModelNode = " + diagramNode; //$NON-NLS-1$ //$NON-NLS-2$ DiagramUiConstants.Util.log(IStatus.ERROR, message); } } else { diagram = (Diagram)getDiagramModelObject().eContainer(); } if (diagram != null) { EObject modelObject = getRealModelObject(); boolean showInnerClasses = showInnerClasses(modelObject, diagram); // This method reconciles the children of each container with the children of the Classifier. List list = getChildren(getRealModelObject()); Iterator iter = list.iterator(); // Gather up each type separately List newAttributeList = new ArrayList(); List newAssociationList = new ArrayList(); List newOperationList = new ArrayList(); List newClassifiersList = new ArrayList(); // Iterate while (iter.hasNext()) { EObject eObj = (EObject)iter.next(); MetamodelAspect mmAspect = getUmlAspect(eObj); if (mmAspect instanceof UmlProperty) { newAttributeList.add(eObj); } else if (mmAspect instanceof UmlAssociation) { newAssociationList.add(eObj); } else if (mmAspect instanceof UmlOperation) { newOperationList.add(eObj); } else if (mmAspect instanceof UmlClassifier && showInnerClasses) { newClassifiersList.add(eObj); } } // Now add the appropriate container children to this Classifier if (!newAttributeList.isEmpty() && attributesContainer != null) { attributesContainer.reorderChildren(newAttributeList); } if (!newAssociationList.isEmpty() && associationsContainer != null) { associationsContainer.reorderChildren(newAssociationList); } if (!newOperationList.isEmpty() && operationsContainer != null) { operationsContainer.reorderChildren(newOperationList); } if (!newClassifiersList.isEmpty() && classifiersContainer != null) { classifiersContainer.reorderChildren(newClassifiersList); } } } protected List getChildren( EObject parent ) { return DiagramUiPlugin.getDiagramAspectManager().getChildren(parent); } private DiagramModelNode getChild( EObject eObj ) { DiagramModelNode childNode = null; // Walk through the containers and ask for a child // Now add the appropriate container children to this Classifier if (attributesContainer != null) { childNode = attributesContainer.getChild(eObj); } if (childNode == null && associationsContainer != null) { childNode = associationsContainer.getChild(eObj); } if (childNode == null && operationsContainer != null) { childNode = operationsContainer.getChild(eObj); } if (childNode == null && classifiersContainer != null) { childNode = classifiersContainer.getChild(eObj); } return childNode; } public void reconcile() { if (getRealModelObject() != null) { boolean showInnerClasses = showInnerClasses(getRealModelObject(), getDiagram()); // Get the EObject Contents (children) - create appropriate ModelNodes List list = getChildren(getRealModelObject()); Iterator iter = list.iterator(); // Gather up each type separately List attributeList = new ArrayList(); List associationList = new ArrayList(); List operationList = new ArrayList(); List classifiersList = new ArrayList(); // Iterate while (iter.hasNext()) { EObject eObj = (EObject)iter.next(); MetamodelAspect mmAspect = getUmlAspect(eObj); if (mmAspect instanceof UmlProperty) { attributeList.add(eObj); } else if (mmAspect instanceof UmlAssociation) { associationList.add(eObj); } else if (mmAspect instanceof UmlOperation) { operationList.add(eObj); } else if (mmAspect instanceof UmlClassifier && showInnerClasses) { classifiersList.add(eObj); } } // Now add the appropriate container children to this Classifier if (!attributeList.isEmpty()) { if (attributesContainer == null) { attributesContainer = new UmlClassifierContainerNode(UmlClassifierContainerNode.ATTRIBUTES, attributeList, getDiagram()); attributesContainer.setParent(this); super.addChild(attributesContainer); } else { attributesContainer.reconcile(attributeList, getDiagram()); } } else { if (attributesContainer != null) { super.removeChild(attributesContainer, false); attributesContainer = null; } } if (!associationList.isEmpty()) { if (associationsContainer == null) { associationsContainer = new UmlClassifierContainerNode(UmlClassifierContainerNode.ASSOCIATIONS, associationList, getDiagram()); associationsContainer.setParent(this); super.addChild(associationsContainer); } else { associationsContainer.reconcile(associationList, getDiagram()); } } else { if (associationsContainer != null) { super.removeChild(associationsContainer, false); associationsContainer = null; } } if (!operationList.isEmpty()) { if (operationsContainer == null) { operationsContainer = new UmlClassifierContainerNode(UmlClassifierContainerNode.ASSOCIATIONS, operationList, getDiagram()); operationsContainer.setParent(this); super.addChild(operationsContainer); } else { operationsContainer.reconcile(operationList, getDiagram()); } } else { if (operationsContainer != null) { super.removeChild(operationsContainer, false); operationsContainer = null; } } if (!classifiersList.isEmpty()) { if (classifiersContainer == null) { classifiersContainer = new UmlClassifierContainerNode(UmlClassifierContainerNode.CLASSIFIERS, classifiersList, getDiagram()); classifiersContainer.setParent(this); super.addChild(classifiersContainer); } else { classifiersContainer.reconcile(classifiersList, getDiagram()); } } else { if (classifiersContainer != null) { super.removeChild(classifiersContainer, false); classifiersContainer = null; } } setErrorState(); reorderChildren(); } } public boolean isAbstract() { return ((UmlClassifier)getUmlAspect()).isAbstract(getRealModelObject()); } /** * @see org.teiid.designer.diagram.ui.model.AbstractDiagramModelNode#setErrorState() * @since 4.2 */ @Override public void setErrorState() { super.setErrorState(); if (!hasWarnings() && !hasErrors()) { // Need to check children for errors. int errorValue = childErrorState(); if (errorValue == DiagramUiConstants.HAS_ERROR) { errorState = true; } else if (errorValue == DiagramUiConstants.HAS_WARNING) { warningState = true; } } else if (hasWarnings()) { // Need to check children for errors. int errorValue = childErrorState(); if (errorValue == DiagramUiConstants.HAS_ERROR) { errorState = true; warningState = false; } } } private int childErrorState() { int state = DiagramUiConstants.NO_ERRORS; // NO ERRORS Iterator iter = null; DiagramModelNode nextNode = null; if (attributesContainer != null && attributesContainer.getChildren() != null && !attributesContainer.getChildren().isEmpty()) { iter = attributesContainer.getChildren().iterator(); while (iter.hasNext() && state < 2) { nextNode = (DiagramModelNode)iter.next(); if (nextNode.hasWarnings()) state = DiagramUiConstants.HAS_WARNING; if (nextNode.hasErrors()) state = DiagramUiConstants.HAS_ERROR; } } if (state < 2 && associationsContainer != null && associationsContainer.getChildren() != null && !associationsContainer.getChildren().isEmpty()) { iter = associationsContainer.getChildren().iterator(); while (iter.hasNext() && state < 2) { nextNode = (DiagramModelNode)iter.next(); if (nextNode.hasWarnings()) state = DiagramUiConstants.HAS_WARNING; if (nextNode.hasErrors()) state = DiagramUiConstants.HAS_ERROR; } } if (state < 2 && operationsContainer != null && operationsContainer.getChildren() != null && !operationsContainer.getChildren().isEmpty()) { iter = operationsContainer.getChildren().iterator(); while (iter.hasNext() && state < 2) { nextNode = (DiagramModelNode)iter.next(); if (nextNode.hasWarnings()) state = DiagramUiConstants.HAS_WARNING; if (nextNode.hasErrors()) state = DiagramUiConstants.HAS_ERROR; } } if (state < 2 && classifiersContainer != null && classifiersContainer.getChildren() != null && !classifiersContainer.getChildren().isEmpty()) { iter = classifiersContainer.getChildren().iterator(); while (iter.hasNext() && state < 2) { nextNode = (DiagramModelNode)iter.next(); if (nextNode.hasWarnings()) state = DiagramUiConstants.HAS_WARNING; if (nextNode.hasErrors()) state = DiagramUiConstants.HAS_ERROR; } } return state; } protected EObject getRealModelObject() { return getModelObject(); } private boolean canExpand() { return (this.getParent() instanceof ExpandableDiagram && ((ExpandableDiagram)this.getParent()).canExpand()); } public void setExpandedState( boolean b ) { this.expandedState = b; } @Override public boolean isExpanded() { // If classifier is contained on an expandable diagram // return the expanded state. if (canExpand()) return expandedState; // Else return TRUE always return true; } @Override public void expand() { if (canExpand()) { expandedState = true; firePropertyChange(DiagramNodeProperties.EXPAND, null, null); getParent().firePropertyChange(DiagramNodeProperties.EXPAND, null, null); } } @Override public void collapse() { if (canExpand()) { expandedState = false; firePropertyChange(DiagramNodeProperties.COLLAPSE, null, null); getParent().firePropertyChange(DiagramNodeProperties.EXPAND, null, null); } } @Override public List getChildren() { if (isExpanded()) return super.getChildren(); return Collections.EMPTY_LIST; } }