annotate java/src/uk/ac/qmul/eecs/ccmi/simpletemplate/Model.java @ 1:e3935c01cde2 tip

moved license of PdPersistenceManager to the beginning of the file
author Fiore Martin <f.martin@qmul.ac.uk>
date Tue, 08 Jul 2014 19:52:03 +0100
parents 78b7fc5391a2
children
rev   line source
f@0 1 /*
f@0 2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
f@0 3
f@0 4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
f@0 5
f@0 6 This program is free software: you can redistribute it and/or modify
f@0 7 it under the terms of the GNU General Public License as published by
f@0 8 the Free Software Foundation, either version 3 of the License, or
f@0 9 (at your option) any later version.
f@0 10
f@0 11 This program is distributed in the hope that it will be useful,
f@0 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
f@0 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f@0 14 GNU General Public License for more details.
f@0 15
f@0 16 You should have received a copy of the GNU General Public License
f@0 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
f@0 18 */
f@0 19
f@0 20 package uk.ac.qmul.eecs.ccmi.simpletemplate;
f@0 21
f@0 22 import java.util.Collection;
f@0 23 import java.util.LinkedHashMap;
f@0 24 import java.util.Map;
f@0 25 import java.util.ResourceBundle;
f@0 26
f@0 27 /*
f@0 28 * The Wizard Model holds all the data the user enters during the process of creating a diagram template.
f@0 29 * Such data can be re-edited by the user during the same process or if they want to create
f@0 30 * a new diagram template out of an existing one. When the user has entered all the data the model is used
f@0 31 * to create an instance of the {@link Diagram class} which is then used as a prototype diagram.
f@0 32 * Diagram instances that the user will edit are created by cloning the relating prototype diagram.
f@0 33 *
f@0 34 */
f@0 35 class Model {
f@0 36 Model(){
f@0 37 diagramName = new Record();
f@0 38 nodes = new ModelMap<Node>();
f@0 39 edges = new ModelMap<Edge>();
f@0 40 }
f@0 41
f@0 42 @Override
f@0 43 public String toString(){// FIXME need to port the strings to the .properties file
f@0 44 StringBuilder builder = new StringBuilder();
f@0 45 builder.append("Diagram Name is ").append(diagramName.value).append(".\n\n");
f@0 46 builder.append(diagramName.value + " diagram has "+ (nodes.isEmpty() ? "no" : nodes.size()) + " node"+((nodes.size() == 1) ? "" : "s"));
f@0 47 if(!nodes.isEmpty()){
f@0 48 builder.append(": ");
f@0 49 int i = 0;
f@0 50 for(Node n : nodes.values()){
f@0 51 builder.append(n.type.value);
f@0 52 if(nodes.values().size() == 1)
f@0 53 break;
f@0 54 if(i == nodes.values().size() - 2){
f@0 55 builder.append(" and ");
f@0 56 }else if(i < nodes.values().size()-1){
f@0 57 builder.append(", ");
f@0 58 }
f@0 59 i++;
f@0 60 }
f@0 61 }
f@0 62 builder.append(".\n");
f@0 63 for(Node n : nodes.values()){
f@0 64 builder.append(n.type+" node has a ")
f@0 65 .append(n.shape + " shape.\n");
f@0 66 builder.append(n.type+" node has "+ (n.properties.isEmpty() ? "no" : n.properties.size())+((n.properties.size() == 1) ? " property" : " properties"));
f@0 67 if(!n.properties.isEmpty()){
f@0 68 builder.append(": ");
f@0 69 int i = 0;
f@0 70 for(Property p : n.properties.values()){
f@0 71 builder.append(p.type.value);
f@0 72 if(n.properties.size() == 1)
f@0 73 break;
f@0 74 if(i == n.properties.size() - 2){
f@0 75 builder.append(" and ");
f@0 76 }else if(i < n.properties.size()-1){
f@0 77 builder.append(", ");
f@0 78 }
f@0 79 i++;
f@0 80 }
f@0 81 }
f@0 82 builder.append(".\n");
f@0 83 for(Property p : n.properties.values()){
f@0 84 builder.append(p.type+" property has position "+p.position);
f@0 85 if(p.position.value.equals(SimpleShapeNode.Position.Outside.toString()))
f@0 86 builder.append(" and shape "+p.shape+".\n");
f@0 87 else
f@0 88 builder.append(".\n");
f@0 89 builder.append(p.type+" property has "+(p.modifiers.isEmpty() ? "no" : p.modifiers.size())+(p.modifiers.size() == 1 ? " modifier" : " modifiers"));
f@0 90 if(!p.modifiers.isEmpty()){
f@0 91 builder.append(": ");
f@0 92 int i = 0;
f@0 93 for(Modifier m : p.modifiers.values()){
f@0 94 builder.append(m.type.value);
f@0 95 if(p.modifiers.size() == 1)
f@0 96 break;
f@0 97 if(i == p.modifiers.size() - 2){
f@0 98 builder.append(" and ");
f@0 99 }else if(i < p.modifiers.size()-1){
f@0 100 builder.append(", ");
f@0 101 }
f@0 102 i++;
f@0 103 }
f@0 104 }
f@0 105 builder.append(".\n");
f@0 106 for(Modifier m : p.modifiers.values()){
f@0 107 builder.append(m.type+ " modifier ");
f@0 108 if(m.format.values.length > 0)
f@0 109 builder.append("is formatted as "+m.format+".\n");
f@0 110 else
f@0 111 builder.append("\n");
f@0 112 }
f@0 113 }
f@0 114 }
f@0 115 builder.append('\n');
f@0 116 builder.append(diagramName.value + " diagram has "+ (edges.isEmpty() ? "no" : edges.size()) + " edge"+((edges.size() == 1) ? "" : "s"));
f@0 117 if(!edges.isEmpty()){
f@0 118 builder.append(": ");
f@0 119 int i = 0;
f@0 120 for(Edge e : edges.values()){
f@0 121 builder.append(e.type.value);
f@0 122 if(edges.values().size() == 1)
f@0 123 break;
f@0 124 if(i == edges.values().size() - 2){
f@0 125 builder.append(" and ");
f@0 126 }else if(i < edges.values().size()-1){
f@0 127 builder.append(", ");
f@0 128 }
f@0 129 i++;
f@0 130 }
f@0 131 }
f@0 132 builder.append(".\n");
f@0 133 for(Edge e : edges.values()){
f@0 134 builder.append(e.type+ " edge has minimum nodes "+e.minNodes+" and maximum nodes "+e.maxNodes+".\n")
f@0 135 .append(e.type+ " edge has a "+ e.lineStyle+" line style.\n")
f@0 136 .append(e.type+" edge has "+ ((e.arrowHeads.values.length == 0) ? "no harrow heads.\n" : e.arrowHeads.values.length +" harrow heads: "+e.arrowHeads+".\n"));
f@0 137 }
f@0 138 builder.append('\n');
f@0 139 builder.append("Press up and down arrow keys to go through the summary.\n");
f@0 140 return builder.toString();
f@0 141 }
f@0 142
f@0 143 Record diagramName;
f@0 144 /* these are sets as when we edit an already existing node we just add */
f@0 145 /* to the set the new node and it gets replaced */
f@0 146 ModelMap<Node> nodes;
f@0 147 ModelMap<Edge> edges;
f@0 148
f@0 149 static Element copy(Element src, Element dest){
f@0 150 if(src instanceof Node){
f@0 151 copy((Node)src,(Node)dest);
f@0 152 }else if (src instanceof Edge){
f@0 153 copy((Edge)src,(Edge)dest);
f@0 154 }else if(src instanceof Property){
f@0 155 copy((Property)src,(Property)dest);
f@0 156 }else{
f@0 157 copy((Modifier)src,(Modifier)dest);
f@0 158 }
f@0 159 return dest;
f@0 160 }
f@0 161
f@0 162 static void copy(Node src, Node dest){
f@0 163 dest.id = src.id;
f@0 164 dest.type.value = src.type.value;
f@0 165 dest.shape.value = src.shape.value;
f@0 166 dest.properties.clear();
f@0 167 dest.properties.putAll(src.properties);
f@0 168 }
f@0 169
f@0 170 static void copy(Property src, Property dest){
f@0 171 dest.id = src.id;
f@0 172 dest.type.value = src.type.value;
f@0 173 dest.shape.value = src.shape.value;
f@0 174 dest.position.value = src.position.value;
f@0 175 dest.modifiers.clear();
f@0 176 dest.modifiers.putAll(src.modifiers);
f@0 177 }
f@0 178
f@0 179 static void copy(Edge src, Edge dest){
f@0 180 dest.id = src.id;
f@0 181 dest.type.value = src.type.value;
f@0 182 dest.lineStyle.value = src.lineStyle.value;
f@0 183 dest.maxNodes.value = src.maxNodes.value;
f@0 184 dest.minNodes.value = src.minNodes.value;
f@0 185 dest.arrowHeads.values = src.arrowHeads.values;
f@0 186 dest.arrowHeadsDescriptions.values = src.arrowHeadsDescriptions.values;
f@0 187 }
f@0 188
f@0 189 static void copy(Modifier src, Modifier dest){
f@0 190 dest.id = src.id;
f@0 191 dest.type.value = src.type.value;
f@0 192 dest.format.values = src.format.values;
f@0 193 dest.affix.values = src.affix.values;
f@0 194 }
f@0 195
f@0 196 static class Record{
f@0 197 Record(){
f@0 198 value = "";
f@0 199 }
f@0 200 Record(String value){
f@0 201 this.value = value;
f@0 202 }
f@0 203 @Override
f@0 204 public String toString(){
f@0 205 return value;
f@0 206 }
f@0 207 String value;
f@0 208 }
f@0 209
f@0 210 static class StrArrayRecord{
f@0 211 String [] values;
f@0 212 StrArrayRecord(){
f@0 213 values = new String[0];
f@0 214 }
f@0 215
f@0 216 StrArrayRecord(String[] values){
f@0 217 this.values = values;
f@0 218 }
f@0 219
f@0 220 @Override
f@0 221 public String toString(){
f@0 222 StringBuilder builder = new StringBuilder();
f@0 223 for(int i=0; i<values.length; i++){
f@0 224 builder.append(values[i]);
f@0 225 if(values.length == 1)
f@0 226 break;
f@0 227 if(i == values.length - 2)
f@0 228 builder.append(" and ");
f@0 229 else if(i < values.length -1 )
f@0 230 builder.append(", ");
f@0 231 }
f@0 232 return builder.toString();
f@0 233 }
f@0 234 }
f@0 235
f@0 236 private static long uniqueId = 0;
f@0 237 static class Element {
f@0 238 Element(){
f@0 239 type = new Record();
f@0 240 id = uniqueId++;
f@0 241 }
f@0 242
f@0 243 void clear () {
f@0 244 type.value = "";
f@0 245 id = uniqueId++;
f@0 246 }
f@0 247 long id;
f@0 248 Record type;
f@0 249 }
f@0 250
f@0 251 static class Node extends Element{
f@0 252 Node(){
f@0 253 shape = new Record();
f@0 254 properties = new ModelMap<Property>();
f@0 255 }
f@0 256
f@0 257 @Override
f@0 258 void clear(){
f@0 259 super.clear();
f@0 260 shape.value = "";
f@0 261 properties.clear();
f@0 262 }
f@0 263 Record shape;
f@0 264 ModelMap<Property> properties;
f@0 265 }
f@0 266
f@0 267 static class Edge extends Element {
f@0 268 Edge(){
f@0 269 lineStyle = new Record();
f@0 270 minNodes = new Record();
f@0 271 maxNodes = new Record();
f@0 272 arrowHeads = new StrArrayRecord(){
f@0 273 @Override
f@0 274 public String toString(){
f@0 275 StringBuilder builder = new StringBuilder();
f@0 276 for(int i=0; i<values.length; i++){
f@0 277 builder.append(values[i]+" with label "+arrowHeadsDescriptions.values[i]);
f@0 278 if(values.length == 1)
f@0 279 break;
f@0 280 if(i == values.length - 2)
f@0 281 builder.append(" and ");
f@0 282 else if(i < values.length -1 )
f@0 283 builder.append(", ");
f@0 284 }
f@0 285 return builder.toString();
f@0 286 }
f@0 287 };
f@0 288 arrowHeadsDescriptions = new StrArrayRecord();
f@0 289 }
f@0 290 @Override
f@0 291 public void clear(){
f@0 292 super.clear();
f@0 293 lineStyle.value = "";
f@0 294 minNodes.value = "";
f@0 295 maxNodes.value = "";
f@0 296 arrowHeads.values = new String[0];
f@0 297 arrowHeadsDescriptions.values = new String[0];
f@0 298 }
f@0 299 Record lineStyle;
f@0 300 Record minNodes;
f@0 301 Record maxNodes;
f@0 302 StrArrayRecord arrowHeads;
f@0 303 StrArrayRecord arrowHeadsDescriptions;
f@0 304 }
f@0 305
f@0 306 static class Property extends Element{
f@0 307 Property(){
f@0 308 position = new Model.Record();
f@0 309 shape = new Model.Record();
f@0 310 modifiers = new ModelMap<Modifier>();
f@0 311 }
f@0 312 Record position;
f@0 313 Record shape;
f@0 314 ModelMap<Modifier> modifiers;
f@0 315
f@0 316 @Override
f@0 317 void clear(){
f@0 318 super.clear();
f@0 319 modifiers.clear();
f@0 320 position.value = "";
f@0 321 shape.value = "";
f@0 322 }
f@0 323 }
f@0 324
f@0 325 static class Modifier extends Element {
f@0 326 StrArrayRecord format;
f@0 327 StrArrayRecord affix;
f@0 328
f@0 329 Modifier(){
f@0 330 affix = new StrArrayRecord();
f@0 331 format = new StrArrayRecord(){
f@0 332 @Override
f@0 333 public String toString(){
f@0 334 ResourceBundle resources = ResourceBundle.getBundle(SpeechWizardDialog.class.getName());
f@0 335 StringBuilder builder = new StringBuilder();
f@0 336 for(int i=0; i<values.length; i++){
f@0 337 builder.append(values[i]);
f@0 338 if(values[i].equals(resources.getString("modifier.format.prefix")) && !affix.values[0].isEmpty()){
f@0 339 builder.append(' ').append(affix.values[0]);
f@0 340 }
f@0 341 if(values[i].equals(resources.getString("modifier.format.suffix")) && !affix.values[1].isEmpty()){
f@0 342 builder.append(' ').append(affix.values[1]);
f@0 343 }
f@0 344
f@0 345 if(values.length == 1)
f@0 346 break;
f@0 347 if(i == values.length - 2)
f@0 348 builder.append(" and ");
f@0 349 else if(i < values.length -1 )
f@0 350 builder.append(", ");
f@0 351 }
f@0 352 return builder.toString();
f@0 353 }
f@0 354 };
f@0 355
f@0 356 /* affix is always length = 2 as it only contains prefix and suffix string */
f@0 357 /* eventually it contains empty strings but its length is not variable */
f@0 358 affix.values = new String[2];
f@0 359 }
f@0 360
f@0 361 @Override
f@0 362 void clear(){
f@0 363 super.clear();
f@0 364 format.values = new String[0];
f@0 365 affix.values = new String[2];
f@0 366 }
f@0 367 }
f@0 368 }
f@0 369
f@0 370
f@0 371 @SuppressWarnings("serial")
f@0 372 class ModelMap<T extends Model.Element> extends LinkedHashMap<Long,T> {
f@0 373 public ModelMap(){
f@0 374 namesMap = new LinkedHashMap<Long,String>();
f@0 375 }
f@0 376
f@0 377 @Override
f@0 378 public void clear(){
f@0 379 namesMap.clear();
f@0 380 super.clear();
f@0 381 }
f@0 382
f@0 383 public T put(Long key, T value){
f@0 384 namesMap.put(key, value.type.value);
f@0 385 return super.put(key, value);
f@0 386 }
f@0 387
f@0 388 public void putAll(Map<? extends Long,? extends T> m){
f@0 389 for(Map.Entry<? extends Long,? extends T> entry : m.entrySet()){
f@0 390 namesMap.put(entry.getKey(), entry.getValue().type.value);
f@0 391 }
f@0 392 super.putAll(m);
f@0 393 }
f@0 394
f@0 395 public T remove(Object key){
f@0 396 namesMap.remove(key);
f@0 397 return super.remove(key);
f@0 398 }
f@0 399
f@0 400 public Collection<String> getNames(){
f@0 401 return namesMap.values();
f@0 402 }
f@0 403
f@0 404 private Map<Long,String> namesMap;
f@0 405 }