annotate java/src/uk/ac/qmul/eecs/ccmi/diagrammodel/NodeProperties.java @ 8:ea7885bd9bff tip

fixed bug : render solid line as dotted/dashed when moving the stylus from dotted/dashed to solid
author ccmi-guest
date Thu, 03 Jul 2014 16:12:20 +0100
parents d66dd5880081
children
rev   line source
fiore@0 1 /*
fiore@0 2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
fiore@0 3
fiore@0 4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
fiore@0 5
fiore@0 6 This program is free software: you can redistribute it and/or modify
fiore@0 7 it under the terms of the GNU General Public License as published by
fiore@0 8 the Free Software Foundation, either version 3 of the License, or
fiore@0 9 (at your option) any later version.
fiore@0 10
fiore@0 11 This program is distributed in the hope that it will be useful,
fiore@0 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
fiore@0 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
fiore@0 14 GNU General Public License for more details.
fiore@0 15
fiore@0 16 You should have received a copy of the GNU General Public License
fiore@0 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
fiore@0 18 */
fiore@0 19 package uk.ac.qmul.eecs.ccmi.diagrammodel;
fiore@0 20
fiore@0 21 import java.util.ArrayList;
fiore@0 22 import java.util.Collections;
fiore@0 23 import java.util.LinkedHashMap;
fiore@0 24 import java.util.LinkedHashSet;
fiore@0 25 import java.util.List;
fiore@0 26 import java.util.Map;
fiore@0 27 import java.util.Set;
fiore@0 28
fiore@0 29 /**
fiore@0 30 * This class represents the internal properties of a node. Internal properties can be seen as
fiore@0 31 * attributes that each single nodes owns and that, in a visual diagram, would normally be displayed inside
fiore@0 32 * or in the neighbourhood of the node itself. This is a very high abstraction of the concept of properties
fiore@0 33 * of a node as the user can define their own type of properties through the property type definition object
fiore@0 34 * passed as argument in the constructor.
fiore@0 35 * An example of properties is <i>attributes</i> and <i>methods</i> of a class diagram in the UML language or just the
fiore@0 36 * <i>attributes</i> of entities in an ER diagram.
fiore@0 37 *
fiore@0 38 */
fiore@0 39 public final class NodeProperties implements Cloneable {
fiore@0 40
fiore@0 41 /**
fiore@0 42 * Creates a diagram element property data structure out of a property type specification. In a UML
fiore@0 43 * diagram the NodeProperties for a class node would be constructed passing as arguments a linked hash
fiore@0 44 * map containing the strings "attributes" and "properties" and the strings "public", "protected", "private",
fiore@0 45 * "static" as value for both the keys. "attributes" and "methods" would be the types of the NodeProperties,
fiore@0 46 * that is, all the values inserted in the object such as values would fall under either type. For example
fiore@0 47 * if a UML diagram class has the methods getX() and getY(), these would be inserted in the NodeProperties
fiore@0 48 * object with a type "methods".
fiore@0 49 *
fiore@0 50 * @param typeDefinition a linked Hash Map holding the properties types as keys
fiore@0 51 * and the modifiers type definition of each property as values
fiore@0 52 */
fiore@0 53
fiore@0 54 public NodeProperties(LinkedHashMap<String,Set<String>> typeDefinition){
fiore@0 55 if(typeDefinition == null)
fiore@0 56 this.typeDefinition = EMPTY_PROPERTY_TYPE_DEFINITION;
fiore@0 57 else
fiore@0 58 this.typeDefinition = typeDefinition;
fiore@0 59 /* create the type collection out of the typeDefinition keyset */
fiore@0 60 types = Collections.unmodifiableList(new ArrayList<String>(this.typeDefinition.keySet()));
fiore@0 61 properties = new LinkedHashMap<String,Entry>();
fiore@0 62 for(String s : types){
fiore@0 63 Entry q = new Entry();
fiore@0 64 q.values = new ArrayList<String>(); // property values to be filled by user + modifiers
fiore@0 65 q.indexes = new ArrayList<Set<Integer>>();
fiore@0 66 q.view = null;
fiore@0 67 Set<String> modifierTypeDefinition = this.typeDefinition.get(s);
fiore@0 68 if(modifierTypeDefinition == null)
fiore@0 69 /* null modifiers for this property */
fiore@0 70 q.modifiers = new Modifiers(EMPTY_MODIFIER_TYPE_DEFINITION,q.indexes);
fiore@0 71 else if(modifierTypeDefinition.size() == 0)
fiore@0 72 /* null modifiers for this property */
fiore@0 73 q.modifiers = new Modifiers(EMPTY_MODIFIER_TYPE_DEFINITION,q.indexes);
fiore@0 74 else
fiore@0 75 q.modifiers = new Modifiers(modifierTypeDefinition, q.indexes);
fiore@0 76 properties.put(s, q);
fiore@0 77 }
fiore@0 78 }
fiore@0 79
fiore@0 80 /**
fiore@0 81 * Returns the type definition argument of the constructor this object has been created through.
fiore@0 82 *
fiore@0 83 * @return the type definition
fiore@0 84 */
fiore@0 85 public Map<String,Set<String>> getTypeDefinition(){
fiore@0 86 return typeDefinition;
fiore@0 87 }
fiore@0 88
fiore@0 89 /**
fiore@0 90 * Returns the types of properties.
fiore@3 91 *
fiore@3 92 * @return a list of strings holding types of properties
fiore@0 93 */
fiore@0 94 public List<String> getTypes(){
fiore@0 95 return types;
fiore@0 96 }
fiore@0 97
fiore@0 98 /**
fiore@3 99 * @param propertyType the property type we want to get the values of.
fiore@0 100 * @return an array of string with the different properties set by the user or
fiore@3 101 * {@code null} if the specified type does not exist.
fiore@0 102 */
fiore@0 103 public List<String> getValues(String propertyType){
fiore@0 104 Entry e = properties.get(propertyType);
fiore@0 105 if(e == null)
fiore@0 106 throw new IllegalArgumentException(ILLEGAL_TYPE_MSG+propertyType);
fiore@0 107 return new ArrayList<String>(e.values);
fiore@0 108 }
fiore@0 109
fiore@0 110 /**
fiore@0 111 * Returns the view object associated with a property type in this NodeProperties instance. A view object is
fiore@0 112 * defined by the client of this class and it holds the information needed for a visual representation
fiore@3 113 * of the property.
fiore@3 114 *
fiore@0 115 * @param type the property type the returned view is associated with
fiore@0 116 * @return the View object or null if non has been set previously
fiore@0 117 */
fiore@0 118 public Object getView(String type){
fiore@0 119 Entry e = properties.get(type);
fiore@0 120 if(e == null)
fiore@0 121 throw new IllegalArgumentException(ILLEGAL_TYPE_MSG+type);
fiore@0 122 return e.view;
fiore@0 123 }
fiore@0 124
fiore@0 125 /**
fiore@0 126 * Sets the View object for the a type of properties. The NodeProperties only works
fiore@0 127 * as a holder as for the view objects. The client code of this class has to define
fiore@3 128 * its own view.
fiore@3 129 *
fiore@0 130 * @param type the type of property the view is associated with.
fiore@0 131 * @param o an object defined by user
fiore@0 132 * @see #getView(String)
fiore@0 133 */
fiore@0 134 public void setView(String type, Object o){
fiore@0 135 Entry e = properties.get(type);
fiore@0 136 if(e == null)
fiore@0 137 throw new IllegalArgumentException(ILLEGAL_TYPE_MSG+type);
fiore@0 138 e.view = o;
fiore@0 139 }
fiore@0 140
fiore@0 141 /**
fiore@0 142 * Returns a reference to the modifier object associated with a property type. Changes to the returned
fiore@0 143 * reference will affect the internal state of the NodeProperty object.
fiore@0 144 *
fiore@0 145 * @param propertyType a property type
fiore@0 146 * @return the modifiers of the specified property type or null if either
fiore@0 147 * the property type is null or it was not listed in the property type definition
fiore@0 148 * passed to the constructor
fiore@0 149 */
fiore@0 150 public Modifiers getModifiers(String propertyType){
fiore@0 151 Entry e = properties.get(propertyType);
fiore@0 152 if(e == null)
fiore@0 153 throw new IllegalArgumentException(ILLEGAL_TYPE_MSG+propertyType);
fiore@0 154 return e.modifiers;
fiore@0 155 }
fiore@0 156
fiore@0 157 /**
fiore@3 158 * Adds a value of the type passed as argument.
fiore@3 159 *
fiore@0 160 * @param propertyType a property type defined in the property type definition passed as argument to the constructor
fiore@0 161 * @param propertyValue the value to add to the property type
fiore@0 162 */
fiore@0 163 public void addValue(String propertyType, String propertyValue){
fiore@0 164 Entry e = properties.get(propertyType);
fiore@0 165 /* no such property type exists */
fiore@0 166 if(e == null)
fiore@0 167 throw new IllegalArgumentException(ILLEGAL_TYPE_MSG+propertyType);
fiore@0 168 e.values.add(propertyValue);
fiore@0 169 e.indexes.add(new LinkedHashSet<Integer>());
fiore@0 170 }
fiore@0 171
fiore@0 172 /**
fiore@0 173 * Adds a value of the type passed as argument and sets the modifier indexes for it as for
fiore@3 174 * {@link Modifiers#setIndexes(int, Set)}.
fiore@3 175 *
fiore@0 176 * @param propertyType a property type
fiore@0 177 * @param propertyValue a property value
fiore@0 178 * @param modifierIndexes the modifier set of indexes
fiore@0 179 *
fiore@0 180 * @throws IllegalArgumentException if propertyType
fiore@0 181 * is not among the ones in the type definition passed as argument to the constructor
fiore@0 182 */
fiore@0 183 public void addValue(String propertyType, String propertyValue, Set<Integer> modifierIndexes){
fiore@0 184 for(Integer i : modifierIndexes)
fiore@0 185 if((i < 0)||(i >= getModifiers(propertyType).getTypes().size()))
fiore@0 186 throw new ArrayIndexOutOfBoundsException("Index "+ i +
fiore@0 187 " corresponds to no Modifier type (modifierType size = "+
fiore@0 188 getModifiers(propertyType).getTypes().size()+")" );
fiore@0 189
fiore@0 190 Entry e = properties.get(propertyType);
fiore@0 191 if(e == null)
fiore@0 192 throw new IllegalArgumentException(ILLEGAL_TYPE_MSG+propertyType);
fiore@0 193 e.values.add(propertyValue);
fiore@0 194 e.indexes.add(modifierIndexes);
fiore@0 195 }
fiore@0 196
fiore@0 197 /**
fiore@3 198 * Removes the value at the specified index for the specified property type.
fiore@3 199 *
fiore@0 200 * @param propertyType a property type
fiore@0 201 * @param valueIndex the index of the value to remove
fiore@0 202 * @return the removed value
fiore@0 203 * @throws IllegalArgumentException if propertyType
fiore@0 204 * is not among the ones in the type definition passed as argument to the constructor
fiore@0 205 */
fiore@0 206 public String removeValue(String propertyType, int valueIndex){
fiore@0 207 Entry e = properties.get(propertyType);
fiore@0 208 if(e == null)
fiore@0 209 throw new IllegalArgumentException(ILLEGAL_TYPE_MSG+propertyType);
fiore@0 210 e.indexes.remove(valueIndex);
fiore@0 211 return e.values.remove(valueIndex);
fiore@0 212 }
fiore@0 213
fiore@0 214 /**
fiore@3 215 * Sets the value of a property type at the specified index to a new value.
fiore@3 216 *
fiore@0 217 * @param propertyType a property type
fiore@0 218 * @param valueIndex the index of the value which must be replaced
fiore@0 219 * @param newValue the new value for the specified index
fiore@3 220 * @throws IllegalArgumentException if propertyType
fiore@0 221 * is not among the ones in the type definition passed as argument to the constructor
fiore@0 222 */
fiore@0 223 public void setValue(String propertyType, int valueIndex, String newValue){
fiore@0 224 Entry e = properties.get(propertyType);
fiore@0 225 if(e == null)
fiore@0 226 throw new IllegalArgumentException(ILLEGAL_TYPE_MSG+propertyType);
fiore@0 227 e.values.set(valueIndex, newValue);
fiore@0 228 }
fiore@0 229
fiore@0 230 /**
fiore@3 231 * Removes all the values and modifiers for a specific type.
fiore@3 232 *
fiore@0 233 * @param propertyType the type whose property and modifiers must be removed
fiore@0 234 * @throws IllegalArgumentException if propertyType
fiore@0 235 * is not among the ones in the type definition passed as argument to the constructor
fiore@0 236 */
fiore@0 237 public void clear(String propertyType){
fiore@0 238 Entry e = properties.get(propertyType);
fiore@0 239 if(e == null)
fiore@0 240 throw new IllegalArgumentException(ILLEGAL_TYPE_MSG+propertyType);
fiore@0 241 e.values.clear();
fiore@0 242 e.indexes.clear();
fiore@0 243 }
fiore@0 244
fiore@0 245 /**
fiore@0 246 * Removes all the values and modifiers of this object.
fiore@0 247 */
fiore@0 248 public void clear(){
fiore@0 249 for(String type : types){
fiore@0 250 clear(type);
fiore@0 251 }
fiore@0 252 }
fiore@0 253
fiore@0 254 /**
fiore@3 255 * Returns true if this NodeProperties contains no values.
fiore@3 256 *
fiore@0 257 * @return true if this NodeProperties contains no values
fiore@0 258 */
fiore@0 259 public boolean isEmpty(){
fiore@0 260 boolean empty = true;
fiore@0 261 for(String type : types)
fiore@0 262 if(!properties.get(type).values.isEmpty()){
fiore@0 263 empty = false;
fiore@0 264 break;
fiore@0 265 }
fiore@0 266 return empty;
fiore@0 267 }
fiore@0 268
fiore@0 269 /**
fiore@3 270 * Returns true if there are no values for the specified type in this NodeProperties instance.
fiore@3 271 *
fiore@5 272 * @param propertyType the property type to be checked for value presence
fiore@0 273 * @return true if there are no values for the specified type in this NodeProperties instance
fiore@0 274 */
fiore@0 275 public boolean typeIsEmpty(String propertyType){
fiore@0 276 Entry e = properties.get(propertyType);
fiore@0 277 if(e == null)
fiore@0 278 throw new IllegalArgumentException(ILLEGAL_TYPE_MSG+propertyType);
fiore@0 279 return e.values.isEmpty();
fiore@0 280 }
fiore@0 281
fiore@0 282 /**
fiore@0 283 * true if this NodeProperties object has no types. This can happen if the constructor
fiore@3 284 * has been called with an empty or null property type definition.
fiore@3 285 *
fiore@0 286 * @return true if this NodeProperties object has no types
fiore@0 287 */
fiore@0 288 public boolean isNull(){
fiore@0 289 return types.isEmpty();
fiore@0 290 }
fiore@0 291
fiore@0 292 /**
fiore@0 293 * Returns a string representation of types, value and modifiers of this property. Such a
fiore@3 294 * representation can be passed as argument to {@link #fill(String)} to populate a NodeProperties
fiore@0 295 * object. Such NodeProperties object though must have the same type and modifier definition of
fiore@0 296 * the object this method is called on.
fiore@0 297 *
fiore@0 298 * @return a string representation of the values and modifiers of this object
fiore@0 299 */
fiore@0 300 @Override
fiore@0 301 public String toString(){
fiore@0 302 StringBuilder builder = new StringBuilder();
fiore@0 303 for(String type : types){
fiore@0 304 builder.append(TYPE_ENTRY_SEPARATOR).append(type);
fiore@0 305 int propertyValueIndex = 0;
fiore@0 306 for(String value : properties.get(type).values){
fiore@0 307 builder.append(VALUE_ENTRY_SEPARATOR);
fiore@0 308 builder.append(value);
fiore@0 309 for(int modifierIndex : getModifiers(type).getIndexes(propertyValueIndex)){
fiore@0 310 builder.append(MODIFIER_ENTRY_SEPARATOR);
fiore@0 311 builder.append(modifierIndex);
fiore@0 312 }
fiore@0 313 propertyValueIndex++;
fiore@0 314 }
fiore@0 315 }
fiore@0 316 return builder.toString();
fiore@0 317 }
fiore@0 318
fiore@0 319 /**
fiore@0 320 * Fills up the this property according to the string passed as arguments
fiore@3 321 * The string must be generated by calling toString on a NodeProperty instance
fiore@0 322 * holding the same property types as type, otherwise an IllegalArgumentException
fiore@0 323 * is likely to be thrown.
fiore@0 324 *
fiore@0 325 * @param s the string representation of the property values, such as the one returned
fiore@0 326 * by toString()
fiore@0 327 * @throws IllegalArgumentException if s contains property types which
fiore@0 328 * are not among the ones in the type definition passed as argument to the constructor
fiore@0 329 */
fiore@3 330 public void fill(String s){
fiore@0 331 /* clear up previous values */
fiore@0 332 clear();
fiore@0 333
fiore@0 334 /* a property entry is a string with the type of the property followed by value *
fiore@0 335 * entries of that type. all value entries begin with the VALUE_SEPARATOR. *
fiore@0 336 * a value entry is a property value followed by its modifiers entries, a modifier entry *
fiore@0 337 * is a modifier beginning with the MODIFIER_SEPARATOR */
fiore@0 338 String propertyEntries[] = s.split(TYPE_ENTRY_SEPARATOR);
fiore@0 339 for(String propertyEntry : propertyEntries){
fiore@0 340 String[] typeEntries = propertyEntry.split(VALUE_ENTRY_SEPARATOR);
fiore@0 341 String type = typeEntries[0];
fiore@0 342 for(int i=1;i<typeEntries.length;i++){
fiore@0 343 Entry e = properties.get(type);
fiore@0 344 if(e == null)
fiore@0 345 throw new IllegalArgumentException(ILLEGAL_TYPE_MSG+type);
fiore@0 346 String valueEntries[] = typeEntries[i].split(MODIFIER_ENTRY_SEPARATOR);
fiore@0 347 String value = valueEntries[0];
fiore@0 348 LinkedHashSet<Integer> modifiers = new LinkedHashSet<Integer>();
fiore@0 349 for(int j=1;j<valueEntries.length;j++){
fiore@0 350 modifiers.add(Integer.valueOf(valueEntries[j]));
fiore@0 351 }
fiore@0 352 addValue(type,value,modifiers);
fiore@0 353 }
fiore@0 354 }
fiore@0 355 }
fiore@0 356
fiore@0 357 @Override
fiore@0 358 @SuppressWarnings(value = "unchecked")
fiore@0 359 public Object clone(){
fiore@0 360 NodeProperties p = null;
fiore@0 361 try {
fiore@0 362 p = (NodeProperties)super.clone();
fiore@0 363 } catch (CloneNotSupportedException e) {
fiore@0 364 e.printStackTrace();
fiore@0 365 }
fiore@0 366 p.properties = (LinkedHashMap<String,Entry>)properties.clone();
fiore@0 367 for(String key : p.properties.keySet()){
fiore@0 368 Entry old = p.properties.get(key);
fiore@0 369 Entry q = new Entry();
fiore@0 370 q.values = new ArrayList<String>();
fiore@0 371 q.indexes = new ArrayList<Set<Integer>>();
fiore@0 372 q.view = old.view;
fiore@0 373 if(old.modifiers != null){
fiore@0 374 q.modifiers = new Modifiers(old.modifiers.modifierTypes, q.indexes);
fiore@0 375 for(String modifierType : q.modifiers.getTypes())
fiore@0 376 q.modifiers.setView(modifierType, old.modifiers.getView(modifierType));
fiore@0 377 }
fiore@0 378 p.properties.put(key, q);
fiore@0 379 }
fiore@0 380 return p;
fiore@0 381 }
fiore@0 382
fiore@0 383 private class Entry{
fiore@0 384 List<String> values;
fiore@0 385 List<Set<Integer>> indexes;
fiore@0 386 Modifiers modifiers;
fiore@0 387 Object view;
fiore@0 388 }
fiore@0 389
fiore@0 390 /**
fiore@0 391 * A modifier is a label peculiar of a certain subset of properties. For example in
fiore@0 392 * a UML class diagram one or more methods can be labelled as <i>public</i>, <i>private</i> or <i>protected</i>.
fiore@0 393 * Had a NodeProperties instance been used to represent the methods of a class node, there would be then
fiore@0 394 * one modifier for each label: one for <i>public</i>, one for <i>private</i>, and one for <i>protected</i>. To each modifier
fiore@0 395 * a view-object can be associated, which describes how these labels would be rendered visually.
fiore@0 396 * Following on from the UML example, a view-object would be used with the protected modifier
fiore@0 397 * to hold the information that the properties which are assigned such a modifier must be prefixed
fiore@0 398 * with the '#' sign.
fiore@0 399 */
fiore@0 400 public class Modifiers{
fiore@0 401 private Modifiers(Set<String> modifierTypes, List<Set<Integer>> indexes){
fiore@0 402 views = new LinkedHashMap<String,Object>();
fiore@0 403 indexesRef = indexes;
fiore@0 404 this.modifierTypes = Collections.unmodifiableList(new ArrayList<String>(modifierTypes));
fiore@0 405 for(String modifierType : modifierTypes){
fiore@0 406 views.put(modifierType,null);
fiore@0 407 }
fiore@0 408 }
fiore@0 409
fiore@0 410 /* only used by NodeProperties.clone() method */
fiore@0 411 private Modifiers(List<String> modifierTypes, List<Set<Integer>> indexes){
fiore@0 412 views = new LinkedHashMap<String,Object>();
fiore@0 413 indexesRef = indexes;
fiore@0 414 this.modifierTypes = modifierTypes;
fiore@0 415 for(String modifierType : modifierTypes){
fiore@0 416 views.put(modifierType,null);
fiore@0 417 }
fiore@0 418 }
fiore@0 419
fiore@0 420 /**
fiore@0 421 * Returns the list of modifier types, as per the type definition passed as argument to the NodeProperties
fiore@0 422 * constructor.
fiore@3 423 *
fiore@0 424 * @return a list of modifier types
fiore@0 425 * @see NodeProperties#NodeProperties(LinkedHashMap)
fiore@0 426 */
fiore@0 427 public List<String> getTypes(){
fiore@0 428 return modifierTypes;
fiore@0 429 }
fiore@0 430
fiore@0 431 /**
fiore@0 432 * Returns the view object associated with a modifier type in this Modifier instance. A view object is
fiore@0 433 * defined by the client of this class and it holds the information needed for a visual representation
fiore@0 434 * of the modifier.
fiore@3 435 *
fiore@3 436 * @param modifierType the property type the returned view is associated with
fiore@0 437 * @return the View object or null if non has been set previously
fiore@0 438 */
fiore@0 439 public Object getView(String modifierType){
fiore@0 440 return views.get(modifierType);
fiore@0 441 }
fiore@0 442
fiore@0 443 /**
fiore@0 444 * Sets the View object for the a type of modifier. The NodeProperties only works
fiore@0 445 * as a holder as for the view objects. The client code of this class has to define
fiore@0 446 * its own view, which will then be used by the client itself to visualise the modifier
fiore@3 447 *
fiore@3 448 * @param modifierType the type of modifier the view is associated with.
fiore@5 449 * @param view an object defined by user defining how this property looks like
fiore@0 450 * @see #getView(String)
fiore@0 451 * @throws IllegalArgumentException if modifierType
fiore@0 452 * is not among the ones in the type definition passed as argument to the constructor
fiore@0 453 */
fiore@0 454 public void setView(String modifierType, Object view){
fiore@0 455 if(!views.containsKey(modifierType))
fiore@0 456 throw new IllegalArgumentException(ILLEGAL_TYPE_MSG+modifierType);
fiore@0 457 views.put(modifierType,view);
fiore@0 458 }
fiore@0 459
fiore@0 460 /**
fiore@0 461 * Returns the modifier indexes for the specified property value. Each property type can be associated
fiore@0 462 * with one or more modifier type and each property value can be assigned one or more modifier. The
fiore@0 463 * integer set returned by this method tells the client code to which modifiers the property value at the index
fiore@0 464 * passed as argument is assigned. The returned indexes refer to the modifier list returned by {@link #getTypes()}
fiore@0 465 *
fiore@5 466 * @param propertyValueIndex the index of the property value for which the set of modifier indexes
fiore@5 467 * is being queried
fiore@5 468 * @return a set of indexes of the modifier types the property value at the index passed as argument
fiore@0 469 * is assigned to
fiore@0 470 */
fiore@0 471 public Set<Integer> getIndexes(int propertyValueIndex){
fiore@0 472 Set<Integer> set = indexesRef.get(propertyValueIndex);
fiore@0 473 return (new LinkedHashSet<Integer>(set));
fiore@0 474 }
fiore@0 475
fiore@0 476 /**
fiore@0 477 * Set the modifier indexes for the property value at the index passed as argument
fiore@3 478 *
fiore@0 479 * @param propertyValueIndex the index of the property value
fiore@0 480 * @param modifierIndexes a set of indexes which refer to the list returned by {@link #getTypes()}
fiore@0 481 * @throws ArrayIndexOutOfBoundsException if one or more of the indexes in modifierIndexes are lower than 0 or greater
fiore@0 482 * or equal to the size of the modifier type list returned by {@link #getTypes()}. The same exception is also thrown
fiore@0 483 * if propertyValueIndex is lower than 0 or greater or equal to the property values list returned by {@link NodeProperties#getValues(String)}
fiore@0 484 * passing as argument the same property type passed to {@link NodeProperties#getModifiers(String)} to obtain
fiore@0 485 * this Modifiers instance.
fiore@0 486 * @see #getIndexes(int)
fiore@0 487 */
fiore@0 488 public void setIndexes(int propertyValueIndex, Set<Integer> modifierIndexes){
fiore@0 489 for(Integer i : modifierIndexes)
fiore@0 490 if((i < 0)||(i >= getTypes().size()))
fiore@0 491 throw new ArrayIndexOutOfBoundsException("Index "+ i + " corresponds to no Modifier Type (modifierType size = "+getTypes().size()+")" );
fiore@0 492
fiore@0 493 Set<Integer> m = indexesRef.get(propertyValueIndex);
fiore@0 494 m.clear();
fiore@0 495 m.addAll(modifierIndexes);
fiore@0 496 }
fiore@0 497
fiore@0 498 /**
fiore@3 499 * Removes all the modifier indexes for a property value at the specified index.
fiore@3 500 *
fiore@0 501 * @param propertyValueIndex the index of the property value
fiore@0 502 */
fiore@0 503 public void clear(int propertyValueIndex){
fiore@0 504 Set<Integer> m = indexesRef.get(propertyValueIndex);
fiore@0 505 m.clear();
fiore@0 506 }
fiore@0 507
fiore@0 508 /**
fiore@0 509 * true if this Modifiers object has no types. This can happen if the constructor
fiore@0 510 * has been called with an empty or null modifier in the type definition passed as argument
fiore@3 511 * to the constructor of the NodeProperties object holding this Modifiers object.
fiore@3 512 *
fiore@0 513 * @return true if this Modifiers object has no types
fiore@0 514 */
fiore@0 515 public boolean isNull(){
fiore@0 516 return modifierTypes.isEmpty();
fiore@0 517 }
fiore@0 518
fiore@0 519 private LinkedHashMap<String,Object> views;
fiore@0 520 private final List<String> modifierTypes;
fiore@0 521 private List<Set<Integer>> indexesRef;
fiore@0 522 }
fiore@0 523
fiore@0 524 /* for each property (key) I associate a Couple (value) made out of *
fiore@0 525 * a list of the property values plus a list of possible modifiers */
fiore@0 526 private LinkedHashMap<String,Entry> properties;
fiore@0 527 private final List<String> types;
fiore@0 528 private Map<String,Set<String>> typeDefinition;
fiore@0 529
fiore@0 530 private static final LinkedHashMap<String,Set<String>> EMPTY_PROPERTY_TYPE_DEFINITION = new LinkedHashMap<String,Set<String>>();
fiore@0 531 private static final Set<String> EMPTY_MODIFIER_TYPE_DEFINITION = Collections.emptySet();
fiore@0 532 private static final String ILLEGAL_TYPE_MSG = "argument must be in type definition list: ";
fiore@0 533 /**
fiore@0 534 * A special static instance of the class corresponding to the null NodeProperties. A null NodeProperties instance will have isNull() returning true,
fiore@0 535 * which means it has no property types associated.
fiore@3 536 * @see #isNull()
fiore@0 537 */
fiore@0 538 public static final NodeProperties NULL_PROPERTIES = new NodeProperties(EMPTY_PROPERTY_TYPE_DEFINITION);
fiore@0 539
fiore@0 540 private final static String TYPE_ENTRY_SEPARATOR = "\n:";
fiore@0 541 private final static String VALUE_ENTRY_SEPARATOR = "\n;";
fiore@0 542 private final static String MODIFIER_ENTRY_SEPARATOR = "\n,";
fiore@0 543 }