f@0: /* f@0: CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool f@0: f@0: Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) f@0: f@0: This program is free software: you can redistribute it and/or modify f@0: it under the terms of the GNU General Public License as published by f@0: the Free Software Foundation, either version 3 of the License, or f@0: (at your option) any later version. f@0: f@0: This program is distributed in the hope that it will be useful, f@0: but WITHOUT ANY WARRANTY; without even the implied warranty of f@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the f@0: GNU General Public License for more details. f@0: f@0: You should have received a copy of the GNU General Public License f@0: along with this program. If not, see . f@0: */ f@0: package uk.ac.qmul.eecs.ccmi.diagrammodel; f@0: f@0: import java.util.List; f@0: import java.util.Set; f@0: f@0: import uk.ac.qmul.eecs.ccmi.diagrammodel.ElementChangedEvent.PropertyChangeArgs; f@0: import uk.ac.qmul.eecs.ccmi.diagrammodel.NodeProperties.Modifiers; f@0: f@0: /** f@0: * This class represents a node in the diagram. f@0: * f@0: */ f@0: @SuppressWarnings("serial") f@0: public abstract class DiagramNode extends DiagramElement { f@0: /** f@0: * Constructor to be called by sub classes f@0: * f@0: * @param type the type of the new node. All nodes with this type will be f@0: * put under the same tree node in the tree representation f@0: * @param properties the properties of this node f@0: */ f@0: public DiagramNode(String type, NodeProperties properties){ f@0: setType(type); f@0: this.properties = properties; f@0: } f@0: f@0: /** f@0: * Returns the properties of this node. Be aware that what is returned is the reference f@0: * to the actual NodeProperties object inside this DiagramNode. Thereforemodifying the returned f@0: * object will affect this node. f@0: * @return the properties of this node f@0: */ f@0: public NodeProperties getProperties(){ f@0: return properties; f@0: } f@0: f@0: /** f@0: * Returns a copy of the properties of this node. The modifying the returned object f@0: * won't affect this Node. f@0: * @return Returns a copy of the properties of this node f@0: */ f@0: public NodeProperties getPropertiesCopy(){ f@0: NodeProperties p = (NodeProperties)properties.clone(); f@0: for(String type : properties.getTypes()){ f@0: Modifiers modifiers = properties.getModifiers(type); f@0: int index = 0; f@0: for(String value : properties.getValues(type)){ f@0: if(properties.getModifiers(type).isNull()) f@0: p.addValue(type, value); f@0: else f@0: p.addValue(type, value, modifiers.getIndexes(index++)); f@0: } f@0: } f@0: return p; f@0: } f@0: f@0: /** f@0: * Set the NodeProperties of this node f@0: * @param properties the properties to set for this node f@0: * @param source the source of the action that triggered this method f@0: */ f@0: public void setProperties(NodeProperties properties, Object source){ f@0: this.properties = properties; f@0: notifyChange(new ElementChangedEvent(this,this.properties,"properties",source)); f@0: } f@0: f@0: /** f@0: * Add a property to the NodeProperties of this node f@0: * @see NodeProperties#addValue(String, String) f@0: * f@0: * @param propertyType the type of the property to add f@0: * @param propertyValue the property to add f@0: * @param source the source of the action that triggered this method f@0: */ f@0: public void addProperty(String propertyType, String propertyValue, Object source){ f@0: getProperties().addValue(propertyType, propertyValue); f@0: int index = getProperties().getValues(propertyType).size() - 1; f@0: notifyChange(new ElementChangedEvent(this,new PropertyChangeArgs(propertyType,index,""),"property.add",source)); f@0: } f@0: f@0: /** f@0: * Removes a property from the NodeProperties of this node f@0: * @see NodeProperties#removeValue(String, int) f@0: * f@0: * @param propertyType the type of the property to add f@0: * @param valueIndex the index of the property to remove f@0: * @param source the source of the action that triggered this method f@0: */ f@0: public void removeProperty(String propertyType, int valueIndex, Object source){ f@0: String oldValue = getProperties().getValues(propertyType).get(valueIndex); f@0: getProperties().removeValue(propertyType, valueIndex); f@0: notifyChange(new ElementChangedEvent(this,new PropertyChangeArgs(propertyType,valueIndex,oldValue),"property.remove",source)); f@0: } f@0: f@0: /** f@0: * Set a property on the NodeProperties of this node to a new value f@0: * @see NodeProperties#setValue(String, int, String) f@0: * f@0: * @param propertyType the type of the property to add f@0: * @param valueIndex the index of the property to remove f@0: * @param newValue the new value for this property f@0: * @param source the source of the action that triggered this method f@0: */ f@0: public void setProperty(String propertyType, int valueIndex, String newValue, Object source){ f@0: String oldValue = getProperties().getValues(propertyType).get(valueIndex); f@0: getProperties().setValue(propertyType, valueIndex, newValue); f@0: notifyChange(new ElementChangedEvent(this,new PropertyChangeArgs(propertyType,valueIndex,oldValue),"property.set",source)); f@0: } f@0: f@0: /** f@0: * Removes all the values in the NodeProperties of this node f@0: * @see NodeProperties#clear() f@0: * f@0: * @param source the source of the action that triggered this method f@0: */ f@0: public void clearProperties(Object source){ f@0: getProperties().clear(); f@0: notifyChange(new ElementChangedEvent(this,this,"properties.clear",source)); f@0: } f@0: f@0: /** f@0: * set the modifier indexes in the NodeProperties of this node f@0: * @see Modifiers#setIndexes(int, Set) f@0: * f@0: * @param propertyType the type of the property to add f@0: * @param propertyValueIndex the index of the property value whose modifiers f@0: * are to be changed f@0: * @param modifierIndexes the new modifiers (identified by their index ) f@0: * for this property value f@0: * @param source the source of the action that triggered this method f@0: */ f@0: public void setModifierIndexes(String propertyType, int propertyValueIndex, Set modifierIndexes,Object source){ f@0: StringBuilder oldIndexes = new StringBuilder(); f@0: List modifierTypes = getProperties().getModifiers(propertyType).getTypes(); f@0: Set indexes = getProperties().getModifiers(propertyType).getIndexes(propertyValueIndex); f@0: for(Integer I : indexes){ f@0: oldIndexes.append(modifierTypes.get(I)).append(' '); f@0: } f@0: getProperties().getModifiers(propertyType).setIndexes(propertyValueIndex, modifierIndexes); f@0: notifyChange(new ElementChangedEvent(this,new PropertyChangeArgs(propertyType,propertyValueIndex,oldIndexes.toString()),"property.modifiers",source)); f@0: } f@0: f@0: /** f@0: * Returns a more detailed description of the node than {@link #spokenText()}. f@0: * the description includes which how many properties the node has and f@0: * how many edges are attached to it. f@0: * f@0: * @return a description of the node f@0: */ f@0: @Override f@0: public String detailedSpokenText(){ f@0: StringBuilder builder = new StringBuilder(getType()); f@0: builder.append(' '); f@0: builder.append(getName()); f@0: builder.append('.').append(' '); f@0: for(int i=0; i 0){ f@0: builder.append(treeNode.getChildCount()) f@0: .append(' ') f@0: .append(treeNode.getName()) f@0: .append(';') f@0: .append(' '); f@0: } f@0: } f@0: return builder.toString(); f@0: } f@0: f@0: /** f@0: * Returns the number of attached edges f@0: * @return the number of attached edges f@0: */ f@0: public abstract int getEdgesNum(); f@0: f@0: /** f@0: * Returns the attached edge at the specified index f@0: * @param index an index into edge's list f@0: * @return the attached edge at the specified index f@0: */ f@0: public abstract DiagramEdge getEdgeAt(int index); f@0: f@0: /** f@0: * add an edge to the attached edges list f@0: * @param e the edge to be added f@0: * f@0: * @return {@code true} if internal collection of edges changed as a result of the call f@0: */ f@0: public abstract boolean addEdge(DiagramEdge e); f@0: f@0: /** f@0: * Removes an edge from the attached edges list f@0: * @param e the edge to be removed f@0: * f@0: * @return {@code true} if internal collection of edges changed as a result of the call f@0: */ f@0: public abstract boolean removeEdge(DiagramEdge e); f@0: f@0: /** f@0: * Gets the node this node is within. f@0: * @return the parent node, or null if the node f@0: * has no parent f@0: */ f@0: public abstract DiagramNode getExternalNode(); f@0: f@0: /** f@0: * Sets the node this node is within. f@0: * @param node the parent node, or null if the node f@0: * has no parent f@0: */ f@0: public abstract void setExternalNode(DiagramNode node); f@0: f@0: /** f@0: * Returns the number of internal nodes f@0: * @return the number of internal nodes f@0: */ f@0: public abstract int getInternalNodesNum(); f@0: f@0: /** f@0: * Gets the internal node at the specified index f@0: * @param index an index into internal nodes list f@0: * @return the internal node at the specified index f@0: */ f@0: public abstract DiagramNode getInternalNodeAt(int index); f@0: f@0: /** f@0: * Adds a node to the internal nodes list. f@0: * @param node the internal node to add f@0: */ f@0: public abstract void addInternalNode(DiagramNode node); f@0: f@0: /** f@0: * Removes a node from the internal nodes list. f@0: * @param node the internal node to remove f@0: */ f@0: public abstract void removeInternalNode(DiagramNode node); f@0: f@0: @Override f@0: public Object clone(){ f@0: DiagramNode clone = (DiagramNode)super.clone(); f@0: clone.properties = (NodeProperties)properties.clone(); f@0: return clone; f@0: } f@0: f@0: private NodeProperties properties; f@0: }