diff java/src/uk/ac/qmul/eecs/ccmi/simpletemplate/Model.java @ 0:78b7fc5391a2

first import, outcome of NIME 2014 hackaton
author Fiore Martin <f.martin@qmul.ac.uk>
date Tue, 08 Jul 2014 16:28:59 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/uk/ac/qmul/eecs/ccmi/simpletemplate/Model.java	Tue Jul 08 16:28:59 2014 +0100
@@ -0,0 +1,405 @@
+/*  
+ CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
+  
+ Copyright (C) 2011  Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
+
+ This program 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.
+
+ This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+*/  
+
+package uk.ac.qmul.eecs.ccmi.simpletemplate;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+/*
+ * The Wizard Model holds all the data the user enters during the process of creating a diagram template. 
+ * Such data can be re-edited by the user during the same process or if they want to create
+ * a new diagram template out of an existing one. When the user has entered all the data the model is used 
+ * to create an instance of the {@link Diagram class} which is then used as a prototype diagram. 
+ * Diagram instances that the user will edit are created by cloning the relating prototype diagram.  
+ *
+ */
+class Model {
+	Model(){
+		diagramName = new Record();
+		nodes = new ModelMap<Node>();
+		edges = new ModelMap<Edge>();
+	}
+	
+	@Override
+	public String toString(){// FIXME need to port the strings to the .properties file
+		StringBuilder builder = new StringBuilder();
+		builder.append("Diagram Name is ").append(diagramName.value).append(".\n\n");
+		builder.append(diagramName.value + " diagram has "+ (nodes.isEmpty() ? "no" : nodes.size()) + " node"+((nodes.size() == 1) ? "" : "s"));
+		if(!nodes.isEmpty()){
+			builder.append(": ");
+			int i = 0;
+			for(Node n : nodes.values()){
+				builder.append(n.type.value);
+				if(nodes.values().size() == 1)
+					break;
+				if(i == nodes.values().size() - 2){
+					builder.append(" and ");
+				}else if(i < nodes.values().size()-1){
+					builder.append(", ");
+				}
+				i++;
+			}
+		}
+		builder.append(".\n");
+		for(Node n : nodes.values()){
+			builder.append(n.type+" node has a ")
+				.append(n.shape + " shape.\n");
+			builder.append(n.type+" node has "+ (n.properties.isEmpty() ? "no" : n.properties.size())+((n.properties.size() == 1) ? " property" : " properties"));
+			if(!n.properties.isEmpty()){
+				builder.append(": ");
+				int i = 0;
+				for(Property p : n.properties.values()){
+					builder.append(p.type.value);
+					if(n.properties.size() == 1)
+						break;
+					if(i == n.properties.size() - 2){
+						builder.append(" and ");
+					}else if(i < n.properties.size()-1){
+						builder.append(", ");
+					}
+					i++;
+				}
+			}
+			builder.append(".\n");
+			for(Property p : n.properties.values()){
+				builder.append(p.type+" property has position "+p.position);
+				if(p.position.value.equals(SimpleShapeNode.Position.Outside.toString()))
+					builder.append(" and shape "+p.shape+".\n");
+				else
+					builder.append(".\n");
+				builder.append(p.type+" property has "+(p.modifiers.isEmpty() ? "no" : p.modifiers.size())+(p.modifiers.size() == 1 ? " modifier" : " modifiers"));
+				if(!p.modifiers.isEmpty()){
+					builder.append(": ");
+					int i = 0;
+					for(Modifier m : p.modifiers.values()){
+						builder.append(m.type.value);
+						if(p.modifiers.size() == 1)
+							break;
+						if(i == p.modifiers.size() - 2){
+							builder.append(" and ");
+						}else if(i < p.modifiers.size()-1){
+							builder.append(", ");
+						}
+						i++;
+					}
+				}
+				builder.append(".\n");
+				for(Modifier m : p.modifiers.values()){
+					builder.append(m.type+ " modifier ");
+					if(m.format.values.length > 0)
+						builder.append("is formatted as "+m.format+".\n");
+					else
+						builder.append("\n");
+				}
+			}
+		}
+		builder.append('\n');
+		builder.append(diagramName.value + " diagram has "+ (edges.isEmpty() ? "no" : edges.size()) + " edge"+((edges.size() == 1) ? "" : "s"));
+		if(!edges.isEmpty()){
+			builder.append(": ");
+			int i = 0;
+			for(Edge e : edges.values()){
+				builder.append(e.type.value);
+				if(edges.values().size() == 1)
+					break;
+				if(i == edges.values().size() - 2){
+					builder.append(" and ");
+				}else if(i < edges.values().size()-1){
+					builder.append(", ");
+				}
+				i++;
+			}
+		}
+		builder.append(".\n");
+		for(Edge e : edges.values()){
+			builder.append(e.type+ " edge has minimum nodes "+e.minNodes+" and maximum nodes "+e.maxNodes+".\n")
+			 .append(e.type+ " edge has a "+ e.lineStyle+" line style.\n")
+			 .append(e.type+" edge has "+ ((e.arrowHeads.values.length == 0) ? "no harrow heads.\n" : e.arrowHeads.values.length +" harrow heads: "+e.arrowHeads+".\n"));
+		}
+		builder.append('\n');
+		builder.append("Press up and down arrow keys to go through the summary.\n");
+		return builder.toString();
+	}
+
+	Record diagramName;
+	/* these are sets as when we edit an already existing node we just add */   
+	/* to the set the new node and it gets replaced                        */
+	ModelMap<Node> nodes;
+	ModelMap<Edge> edges;
+	
+	static Element copy(Element src, Element dest){
+		if(src instanceof Node){
+			copy((Node)src,(Node)dest);
+		}else if (src instanceof Edge){
+			copy((Edge)src,(Edge)dest);
+		}else if(src instanceof Property){
+			copy((Property)src,(Property)dest);
+		}else{
+			copy((Modifier)src,(Modifier)dest);
+		}
+		return dest;
+	}
+	
+	static void copy(Node src, Node dest){
+		dest.id = src.id;
+		dest.type.value = src.type.value;
+		dest.shape.value = src.shape.value;
+		dest.properties.clear(); 
+		dest.properties.putAll(src.properties);
+	}
+	
+	static void copy(Property src, Property dest){
+		dest.id = src.id;
+		dest.type.value = src.type.value;
+		dest.shape.value = src.shape.value;
+		dest.position.value = src.position.value;
+		dest.modifiers.clear();
+		dest.modifiers.putAll(src.modifiers);
+	}
+	
+	static void copy(Edge src, Edge dest){
+		dest.id = src.id;
+		dest.type.value = src.type.value;
+		dest.lineStyle.value = src.lineStyle.value;
+		dest.maxNodes.value = src.maxNodes.value;
+		dest.minNodes.value = src.minNodes.value;
+		dest.arrowHeads.values = src.arrowHeads.values;
+		dest.arrowHeadsDescriptions.values = src.arrowHeadsDescriptions.values;
+	}
+	
+	static void copy(Modifier src, Modifier dest){
+		dest.id = src.id;
+		dest.type.value = src.type.value;
+		dest.format.values = src.format.values;
+		dest.affix.values = src.affix.values;
+	}
+	
+	static class Record{
+		Record(){
+			value = "";
+		}
+		Record(String value){
+			this.value = value;
+		}
+		@Override
+		public String toString(){
+			return value;
+		}
+		String value;
+	}
+	
+	static class StrArrayRecord{
+		String [] values;
+		StrArrayRecord(){
+			values = new String[0];
+		}
+		
+		StrArrayRecord(String[] values){
+			this.values = values;
+		}
+		
+		@Override
+		public String toString(){
+			StringBuilder builder = new StringBuilder();
+			for(int i=0; i<values.length; i++){
+				builder.append(values[i]);
+				if(values.length == 1)
+					break;
+				if(i == values.length - 2)
+					builder.append(" and ");
+				else if(i < values.length -1 )
+					builder.append(", ");
+			}
+			return builder.toString();
+		}
+	}
+	
+	private static long uniqueId = 0;
+	static class Element {
+		Element(){
+			type = new Record();
+			id = uniqueId++;
+		}
+
+		void clear () {
+			type.value = "";
+			id = uniqueId++;
+		}
+		long id;
+		Record type;
+	}
+	
+	static class Node extends Element{
+		Node(){
+			shape = new Record();	
+			properties = new ModelMap<Property>();
+		}
+		
+		@Override
+		void clear(){
+			super.clear();
+			shape.value = "";
+			properties.clear();
+		}
+		Record shape;
+		ModelMap<Property> properties;
+	}
+	
+	static class Edge extends Element {
+		Edge(){
+			lineStyle = new Record();
+			minNodes = new Record();
+			maxNodes = new Record();
+			arrowHeads = new StrArrayRecord(){
+				@Override
+				public String toString(){
+					StringBuilder builder = new StringBuilder();
+					for(int i=0; i<values.length; i++){
+						builder.append(values[i]+" with label "+arrowHeadsDescriptions.values[i]);
+						if(values.length == 1)
+							break;
+						if(i == values.length - 2)
+							builder.append(" and ");
+						else if(i < values.length -1 )
+							builder.append(", ");
+					}
+					return builder.toString();
+				}
+			};
+			arrowHeadsDescriptions = new StrArrayRecord();
+		}
+		@Override
+		public void clear(){
+			super.clear();
+			lineStyle.value = "";
+			minNodes.value = "";
+			maxNodes.value = "";
+			arrowHeads.values = new String[0];
+			arrowHeadsDescriptions.values = new String[0];
+		}
+		Record lineStyle;
+		Record minNodes;
+		Record maxNodes;
+		StrArrayRecord arrowHeads;
+		StrArrayRecord arrowHeadsDescriptions;
+	}
+	
+	static class Property extends Element{
+		Property(){
+			position = new Model.Record();
+			shape = new Model.Record();
+			modifiers = new ModelMap<Modifier>();
+		}
+		Record position;
+		Record shape;
+		ModelMap<Modifier> modifiers;
+		
+		@Override
+		void clear(){
+			super.clear();
+			modifiers.clear();
+			position.value = "";
+			shape.value = "";
+		}
+	}
+	
+	static class Modifier extends Element {
+		StrArrayRecord format;
+		StrArrayRecord affix;
+		
+		Modifier(){
+			affix = new StrArrayRecord();
+			format = new StrArrayRecord(){
+				@Override
+				public String toString(){
+					ResourceBundle resources = ResourceBundle.getBundle(SpeechWizardDialog.class.getName());
+					StringBuilder builder = new StringBuilder();
+					for(int i=0; i<values.length; i++){
+						builder.append(values[i]);
+						if(values[i].equals(resources.getString("modifier.format.prefix")) && !affix.values[0].isEmpty()){
+							builder.append(' ').append(affix.values[0]);
+						}
+						if(values[i].equals(resources.getString("modifier.format.suffix")) && !affix.values[1].isEmpty()){
+							builder.append(' ').append(affix.values[1]);
+						}
+
+						if(values.length == 1)
+							break;
+						if(i == values.length - 2)
+							builder.append(" and ");
+						else if(i < values.length -1 )
+							builder.append(", ");
+					}
+					return builder.toString();
+				}
+			};
+				
+			/* affix is always length = 2 as it only contains prefix and suffix string */
+			/* eventually it contains empty strings but its length is not variable     */
+			affix.values = new String[2];
+		}
+		
+		@Override
+		void clear(){
+			super.clear();
+			format.values = new String[0];
+			affix.values =  new String[2];
+		}
+	}
+}
+
+
+@SuppressWarnings("serial")
+class ModelMap<T extends Model.Element> extends LinkedHashMap<Long,T> {
+	public ModelMap(){
+		namesMap = new LinkedHashMap<Long,String>();
+	}
+	
+	@Override
+	public void clear(){
+		namesMap.clear();
+		super.clear();
+	}
+	
+	public T put(Long key, T value){
+		namesMap.put(key, value.type.value);
+		return super.put(key, value);
+	}
+	
+	public void putAll(Map<? extends Long,? extends T> m){
+		for(Map.Entry<? extends Long,? extends T> entry : m.entrySet()){
+			namesMap.put(entry.getKey(), entry.getValue().type.value);
+		}
+		super.putAll(m);
+	}
+	
+	public T remove(Object key){
+		namesMap.remove(key);
+		return super.remove(key);
+	}
+	
+	public Collection<String> getNames(){
+		return namesMap.values();
+	}
+	
+	private Map<Long,String> namesMap;
+}