/* * 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.model; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Vector; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.emf.ecore.EObject; import org.eclipse.swt.graphics.Image; import org.teiid.designer.diagram.ui.DiagramUiConstants; import org.teiid.designer.diagram.ui.connection.NodeConnectionModel; import org.teiid.designer.diagram.ui.editor.DiagramEditorUtil; import org.teiid.designer.diagram.ui.util.DiagramEntityAdapter; import org.teiid.designer.diagram.ui.util.DiagramEntityManager; import org.teiid.designer.diagram.ui.util.DiagramUiUtilities; import org.teiid.designer.metamodels.diagram.Diagram; import org.teiid.designer.metamodels.diagram.DiagramEntity; import org.teiid.designer.ui.viewsupport.ModelUtilities; /** * * @since 8.0 */ abstract public class AbstractDiagramModelNode implements DiagramModelNode, DiagramUiConstants { private boolean layoutState = false; private Vector m_sourceConnections = new Vector(); private Vector m_targetConnections = new Vector(); private DiagramEntity diagramEntity; private EObject modelObject; private List children = null; private DiagramModelNode parent; private Diagram diagram; private Dimension thisSize; private Point thisPosition; private boolean needsDiagramEntity = true; protected boolean errorState = false; protected boolean warningState = false; private Image firstOverlayImage; private String editorID = null; private Image secondOverlayImage; private boolean readOnly = false; private boolean hideLocationValue = false; private boolean heightFixed = false; private int fixedHeight = DEFAULT_FIXED_HEIGHT; /** * Constructor */ public AbstractDiagramModelNode( Diagram diagramModelObject, EObject modelObject ) { this.modelObject = modelObject; this.diagram = diagramModelObject; this.thisPosition = new Point(0, 0); thisSize = new Dimension(100, 15); initialize(diagramModelObject, null); setErrorState(); } /** * Constructor */ public AbstractDiagramModelNode( Diagram diagramModelObject, EObject modelObject, Object secondObject ) { this.modelObject = modelObject; this.diagram = diagramModelObject; this.thisPosition = new Point(0, 0); thisSize = new Dimension(100, 15); initialize(diagramModelObject, secondObject); setErrorState(); } /** * Constructor */ public AbstractDiagramModelNode( EObject modelObject ) { this.modelObject = modelObject; this.needsDiagramEntity = false; this.thisPosition = new Point(0, 0); thisSize = new Dimension(100, 15); initialize(null, null); setErrorState(); } /** * Constructor */ public AbstractDiagramModelNode( Diagram diagramModelObject, EObject modelObject, boolean needsDiagramEntity ) { this.modelObject = modelObject; this.diagram = diagramModelObject; this.needsDiagramEntity = needsDiagramEntity; this.thisPosition = new Point(0, 0); thisSize = new Dimension(100, 15); initialize(diagramModelObject, null); setErrorState(); } /** * Constructor */ public AbstractDiagramModelNode( Diagram diagramModelObject, EObject modelObject, Object secondObject, boolean needsDiagramEntity ) { this.modelObject = modelObject; this.diagram = diagramModelObject; this.thisPosition = new Point(0, 0); thisSize = new Dimension(100, 15); initialize(diagramModelObject, secondObject); setErrorState(); } protected void initialize( Diagram diagramModelObject, Object secondObject ) { setReadOnly(DiagramUiUtilities.getReadOnlyState(diagramModelObject)); if (needsDiagramEntity) { // If diagramModelObject == null, then we assume that the diagramEntity needs to be "transient". // In otherwords, have no parent... diagramEntity = findDiagramEntity(diagramModelObject, null); if (diagramEntity != null) { setLayoutState(DiagramModelNode.LAYOUT_TRUE); this.thisPosition.x = DiagramEntityAdapter.getXPosition(diagramEntity); this.thisPosition.y = DiagramEntityAdapter.getYPosition(diagramEntity); thisSize.width = DiagramEntityAdapter.getWidth(diagramEntity); thisSize.height = DiagramEntityAdapter.getHeight(diagramEntity); } else if (!isReadOnly()) { // Need to create a new diagram entity here. diagramEntity = DiagramUiUtilities.getDiagramEntity(getModelObject(), diagramModelObject); } } } @Override public Diagram getDiagram() { return this.diagram; } protected DiagramEntity findDiagramEntity( Diagram diagram, Object secondaryObject ) { DiagramEntity de = (DiagramEntity)DiagramEntityManager.getEntity(diagram, getModelObject());// null; return de; } public void setErrorState() { int state = DiagramUiConstants.NO_ERRORS; errorState = false; warningState = false; if (getModelObject() != null) { state = DiagramEditorUtil.getErrorState(getModelObject()); if (state == DiagramUiConstants.HAS_ERROR) errorState = true; else if (state == DiagramUiConstants.HAS_WARNING) warningState = true; } } /* * (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#recoverObjectProperties() */ @Override public void recoverObjectProperties() { setInitialSize(); setInitialPosition(); } /** * Set the Model Object */ @Override public void setModelObject( EObject object ) { modelObject = object; } /** * Set the Diagram Model Object */ @Override public void setDiagramModelObject( DiagramEntity object ) { diagramEntity = object; } /** * Get the Model Object */ @Override public EObject getModelObject() { return modelObject; } /** * Get the Diagram Model Object */ @Override public DiagramEntity getDiagramModelObject() { return diagramEntity; } /** * Add a Child */ @Override public void addChild( DiagramModelNode child ) { if (children == null) { children = new ArrayList(); } child.setParent(this); children.add(child); fireStructureChange(DiagramNodeProperties.CHILDREN, child); } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#addChildren(java.util.List) */ @Override public void addChildren( List newChildren ) { if (newChildren != null && !newChildren.isEmpty()) { if (children == null) { children = new ArrayList(); } DiagramModelNode nextChild = null; Iterator iter = newChildren.iterator(); while (iter.hasNext()) { nextChild = (DiagramModelNode)iter.next(); nextChild.setParent(this); children.add(nextChild); } fireStructureChange(DiagramNodeProperties.CHILDREN, this); } } /** * Remove a Child */ @Override public void removeChild( DiagramModelNode child, boolean deleteDiagramEntity ) { if (children == null) { return; } children.remove(child); fireStructureChange(DiagramNodeProperties.CHILDREN, child); } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#removeChildren(java.util.List) */ @Override public void removeChildren( List oldChildren, boolean deleteDiagramEntities ) { if (oldChildren != null && !oldChildren.isEmpty()) { if (children == null) { return; } DiagramModelNode nextChild = null; Iterator iter = oldChildren.iterator(); while (iter.hasNext()) { nextChild = (DiagramModelNode)iter.next(); children.remove(nextChild); } fireStructureChange(DiagramNodeProperties.CHILDREN, this); } } @Override public void updateForChild( boolean isMove ) { fireStructureChange(DiagramNodeProperties.CHILDREN, "EMPTY"); //$NON-NLS-1$ } /** * Set the List of Children */ @Override public void setChildren( List childList ) { children = childList; } /** * Get the List of Children */ @Override public List getChildren() { if (children == null || children.isEmpty()) { return Collections.EMPTY_LIST; } return children; } /** * Get the number of Children */ public int getNumberOfChildren() { if (children == null || children.isEmpty()) { return 0; } return children.size(); } @Override public void setParent( DiagramModelNode parent ) { this.parent = parent; } @Override public DiagramModelNode getParent() { return this.parent; } /* * (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#setPosition(org.eclipse.draw2d.geometry.Point) */ @Override public void setPosition( Point position ) { if (position.x != thisPosition.x || position.y != thisPosition.y) { if (isWritableDiagramEntity(diagramEntity)) { DiagramEntityAdapter.setPosition(diagramEntity, position.x, position.y); } this.thisPosition.x = position.x; this.thisPosition.y = position.y; firePropertyChange(DiagramNodeProperties.LOCATION, null, position); } } /* * Private method to fire a position changed property event when the diagram component properties * are refreshed from the DiagramEntity */ private void setInitialPosition() { if (diagramEntity != null) { this.thisPosition.x = DiagramEntityAdapter.getXPosition(diagramEntity); this.thisPosition.y = DiagramEntityAdapter.getYPosition(diagramEntity); } firePropertyChange(DiagramNodeProperties.LOCATION, null, getPosition()); } @Override public void setCenterXY( int newCenterX, int newCenterY ) { int newX = newCenterX - this.getWidth() / 2; int newY = newCenterY - this.getHeight() / 2; if (newX != thisPosition.x || newY != thisPosition.y) { if (isWritableDiagramEntity(diagramEntity)) { DiagramEntityAdapter.setXPosition(diagramEntity, newX); DiagramEntityAdapter.setYPosition(diagramEntity, newY); } this.thisPosition.x = newX; this.thisPosition.y = newY; firePropertyChange(DiagramNodeProperties.LOCATION, null, thisPosition); } } @Override public void setCenterX( int newCenterX ) { int newX = newCenterX - this.getWidth() / 2; if (newX != thisPosition.x) { if (isWritableDiagramEntity(diagramEntity)) { DiagramEntityAdapter.setXPosition(diagramEntity, newX); } this.thisPosition.x = newX; firePropertyChange(DiagramNodeProperties.LOCATION, null, thisPosition); } } @Override public void setCenterY( int newCenterY ) { int newY = newCenterY - this.getHeight() / 2; if (newY != thisPosition.y) { if (isWritableDiagramEntity(diagramEntity)) { DiagramEntityAdapter.setYPosition(diagramEntity, newY); } this.thisPosition.y = newY; firePropertyChange(DiagramNodeProperties.LOCATION, null, thisPosition); } } @Override public Point getPosition() { return this.thisPosition; // new Point(this.thisPosition); } @Override public void setSize( Dimension dimension ) { if (dimension.height != thisSize.height || dimension.width != thisSize.width) { thisSize.width = dimension.width; thisSize.height = dimension.height; firePropertyChange(DiagramNodeProperties.SIZE, null, dimension); } } /* * method to fire a size changed property event when the diagram component properties * are refreshed from the DiagramEntity */ public void setInitialSize() { firePropertyChange(DiagramNodeProperties.SIZE, null, thisSize); } @Override public Dimension getSize() { return thisSize; } transient protected PropertyChangeSupport listeners = new PropertyChangeSupport(this); @Override public void addPropertyChangeListener( PropertyChangeListener l ) { listeners.addPropertyChangeListener(l); } @Override public void removePropertyChangeListener( PropertyChangeListener l ) { listeners.removePropertyChangeListener(l); } @Override public void firePropertyChange( String prop, Object old, Object newValue ) { listeners.firePropertyChange(prop, old, newValue); } // Used to alert the Edit Part that the children have been modified // and a refreshChildren() is needed. public void fireStructureChange( String prop, Object child ) { listeners.firePropertyChange(prop, null, child); } public Object getEditableValue() { return this; } @Override public void update() { firePropertyChange(DiagramNodeProperties.PROPERTIES, null, null); } @Override public void update( String property ) { firePropertyChange(property, null, null); } @Override public void update( String prop, String oldValue, String newValue ) { firePropertyChange(prop, oldValue, newValue); } @Override public void setName( String name ) { if (isWritableDiagramEntity(diagramEntity)) { String oldName = "xxxXxxx"; //$NON-NLS-1$ DiagramEntityAdapter.setName(diagramEntity, name); firePropertyChange(DiagramNodeProperties.NAME, oldName, name); } } @Override public String getName() { if (diagramEntity != null) return DiagramEntityAdapter.getName(diagramEntity); return null; } @Override public String getDisplayString() { return getName(); } public String getPath() { return "Path"; //$NON-NLS-1$ } public int getXPosition() { return this.thisPosition.x; } public int getYPosition() { return this.thisPosition.y; } @Override public int getX() { return this.thisPosition.x; } @Override public int getY() { return this.thisPosition.y; } @Override public int getCenterX() { return (this.thisPosition.x + thisSize.width / 2); } @Override public int getCenterY() { return (this.thisPosition.y + thisSize.height / 2); } @Override public int getWidth() { return thisSize.width; } @Override public int getHeight() { return thisSize.height; } @Override public String toString() { StringBuffer result = new StringBuffer(super.toString()); result.append(" (name: "); //$NON-NLS-1$ result.append(getName()); result.append(", path: "); //$NON-NLS-1$ result.append(getPath()); result.append(", xPosition: "); //$NON-NLS-1$ result.append(getXPosition()); result.append(", yPosition: "); //$NON-NLS-1$ result.append(getYPosition()); result.append(", height: "); //$NON-NLS-1$ result.append(getHeight()); result.append(", width: "); //$NON-NLS-1$ result.append(getWidth()); result.append(')'); return result.toString(); } @Override public Vector getSourceConnections() { return m_sourceConnections; } @Override public Vector getTargetConnections() { return m_targetConnections; } @Override public void addSourceConnection( NodeConnectionModel iConnection ) { m_sourceConnections.addElement(iConnection); } @Override public void addTargetConnection( NodeConnectionModel iConnection ) { m_targetConnections.addElement(iConnection); } @Override public void removeSourceConnection( NodeConnectionModel iConnection ) { m_sourceConnections.removeElement(iConnection); } @Override public void removeTargetConnection( NodeConnectionModel iConnection ) { m_targetConnections.removeElement(iConnection); } @Override public List getAssociations( HashMap nodeMap ) { return Collections.EMPTY_LIST; } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#updateAssociations() */ @Override public void updateAssociations() { firePropertyChange(DiagramNodeProperties.CONNECTION, null, null); } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#hasErrors() */ @Override public boolean hasErrors() { return errorState; } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#hasWarnings() */ @Override public boolean hasWarnings() { return warningState; } /* * (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#wasLayedOut() */ @Override public boolean wasLayedOut() { return layoutState; } private void setLayoutState( boolean newState ) { this.layoutState = newState; } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#getDependencies() */ @Override public List getDependencies() { return Collections.EMPTY_LIST; } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#getFirstOverlayImage() */ @Override public Image getFirstOverlayImage() { return firstOverlayImage; } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#setFirstOverlayImage(org.eclipse.swt.graphics.Image) */ @Override public void setFirstOverlayImage( Image image, String editorID ) { this.firstOverlayImage = image; this.editorID = editorID; } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#getSecondOverlayImage() */ @Override public Image getSecondOverlayImage() { return secondOverlayImage; } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#setSecondOverlayImage(org.eclipse.swt.graphics.Image) */ @Override public void setSecondOverlayImage( Image image, int positionIndex ) { this.secondOverlayImage = image; } @Override public boolean isReadOnly() { return readOnly || ModelUtilities.isModelDiagramLocked(getDiagram().getTarget()); } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#updateForErrorsAndWarnings() */ @Override public void updateForErrorsAndWarnings() { setErrorState(); firePropertyChange(DiagramNodeProperties.ERRORS, null, null); } private boolean isWritableDiagramEntity( DiagramEntity de ) { boolean isOK = false; if (de != null) { if (getModelObject() != null && !isReadOnly()) { isOK = true; } } return isOK; } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelNode#setReadOnly(boolean) */ @Override public void setReadOnly( boolean readOnly ) { this.readOnly = readOnly; } /** * @see org.teiid.designer.diagram.ui.model.DiagramModelNode#hideLocation() * @since 4.2 */ @Override public boolean hideLocation() { return hideLocationValue; } /** * @see org.teiid.designer.diagram.ui.model.DiagramModelNode#setHideLocation(boolean) * @since 4.2 */ @Override public void setHideLocation( boolean hideLocation ) { hideLocationValue = hideLocation; } @Override public String getEditorID() { return this.editorID; } public void setEditorID( String editorID ) { this.editorID = editorID; } @Override public int getFixedHeight() { return this.fixedHeight; } @Override public void setFixedHeight( int theFixedHeight ) { this.fixedHeight = theFixedHeight; if (children != null && !children.isEmpty()) { for (Iterator iter = children.iterator(); iter.hasNext();) { DiagramModelNode nextChildNode = (DiagramModelNode)iter.next(); nextChildNode.setFixedHeight(theFixedHeight); } } } @Override public boolean isHeightFixed() { return this.heightFixed; } @Override public void setHeightFixed( boolean theHeightFixed ) { this.heightFixed = theHeightFixed; if (children != null && !children.isEmpty()) { for (Iterator iter = children.iterator(); iter.hasNext();) { DiagramModelNode nextChildNode = (DiagramModelNode)iter.next(); nextChildNode.setHeightFixed(theHeightFixed); } } } }