1 16 17 package info.jtrac.domain; 18 19 import static info.jtrac.Constants.*; 20 21 import info.jtrac.util.XmlUtils; 22 23 import java.io.Serializable ; 24 import java.util.ArrayList ; 25 import java.util.Collection ; 26 import java.util.EnumMap ; 27 import java.util.EnumSet ; 28 import java.util.HashMap ; 29 import java.util.HashSet ; 30 import java.util.LinkedHashMap ; 31 import java.util.LinkedList ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.Set ; 35 import java.util.TreeMap ; 36 37 38 import org.dom4j.Document; 39 import org.dom4j.Element; 40 41 73 public class Metadata implements Serializable { 74 75 private long id; 76 private int version; 77 private Integer type; 78 private String name; 79 private String description; 80 private Metadata parent; 81 82 private Map <Field.Name, Field> fields; 83 private Map <String , Role> roles; 84 private Map <Integer , String > states; 85 private List <Field.Name> fieldOrder; 86 87 public Metadata() { 88 init(); 89 } 90 91 private void init() { 92 fields = new EnumMap <Field.Name, Field>(Field.Name.class); 93 roles = new HashMap <String , Role>(); 94 states = new TreeMap <Integer , String >(); 95 fieldOrder = new LinkedList <Field.Name>(); 96 } 97 98 99 public void setXmlString(String xmlString) { 100 init(); 101 if (xmlString == null) { 102 return; 103 } 104 Document document = XmlUtils.parse(xmlString); 105 for (Element e : (List <Element>) document.selectNodes(FIELD_XPATH)) { 106 Field field = new Field(e); 107 fields.put(field.getName(), field); 108 } 109 for (Element e : (List <Element>) document.selectNodes(ROLE_XPATH)) { 110 Role role = new Role(e); 111 roles.put(role.getName(), role); 112 } 113 for (Element e : (List <Element>) document.selectNodes(STATE_XPATH)) { 114 String key = e.attributeValue(STATUS); 115 String value = e.attributeValue(LABEL); 116 states.put(Integer.parseInt(key), value); 117 } 118 for (Element e : (List <Element>) document.selectNodes(FIELD_ORDER_XPATH)) { 119 String fieldName = e.attributeValue(NAME); 120 fieldOrder.add(Field.convertToName(fieldName)); 121 } 122 } 123 124 125 public String getXmlString() { 126 Document d = XmlUtils.getNewDocument(METADATA); 127 Element root = d.getRootElement(); 128 Element fs = root.addElement(FIELDS); 129 for (Field field : fields.values()) { 130 field.addAsChildOf(fs); 131 } 132 Element rs = root.addElement(ROLES); 133 for (Role role : roles.values()) { 134 role.addAsChildOf(rs); 135 } 136 Element ss = root.addElement(STATES); 137 for (Map.Entry <Integer , String > entry : states.entrySet()) { 138 Element e = ss.addElement(STATE); 139 e.addAttribute(STATUS, entry.getKey() + ""); 140 e.addAttribute(LABEL, entry.getValue()); 141 } 142 Element fo = fs.addElement(FIELD_ORDER); 143 for (Field.Name f : fieldOrder) { 144 Element e = fo.addElement(FIELD); 145 e.addAttribute(NAME, f.toString()); 146 } 147 return d.asXML(); 148 } 149 150 public String getPrettyXml() { 151 return XmlUtils.getAsPrettyXml(getXmlString()); 152 } 153 154 156 public void initRoles() { 157 states.put(State.NEW, "New"); 159 states.put(State.OPEN, "Open"); 160 states.put(State.CLOSED, "Closed"); 161 addRole("DEFAULT"); 162 toggleTransition("DEFAULT", State.NEW, State.OPEN); 163 toggleTransition("DEFAULT",State.OPEN, State.OPEN); 164 toggleTransition("DEFAULT", State.OPEN, State.CLOSED); 165 toggleTransition("DEFAULT", State.CLOSED, State.OPEN); 166 } 167 168 public Field getField(String name) { 169 return fields.get(Field.convertToName(name)); 170 } 171 172 public void add(Field field) { 173 fields.put(field.getName(), field); if (!fieldOrder.contains(field.getName())) { fieldOrder.add(field.getName()); 176 } 177 for (Role role : roles.values()) { 178 for (State state : role.getStates().values()) { 179 state.add(field.getName()); 180 } 181 } 182 } 183 184 public void removeField(String fieldName) { 185 Field.Name name = Field.convertToName(fieldName); 186 fields.remove(name); 187 fieldOrder.remove(name); 188 for (Role role : roles.values()) { 189 for (State state : role.getStates().values()) { 190 state.remove(name); 191 } 192 } 193 } 194 195 public void addState(String name) { 196 int maxStatus = 0; 198 for (int status : states.keySet()) { 199 if (status > maxStatus && status != State.CLOSED) { 200 maxStatus = status; 201 } 202 } 203 int newStatus = maxStatus + 1; 204 states.put(newStatus, name); 205 for (Role role : roles.values()) { 207 State state = new State(newStatus); 208 state.add(fields.keySet()); 209 role.add(state); 210 } 211 } 212 213 public void removeState(int stateId) { 214 states.remove(stateId); 215 for (Role role : roles.values()) { 216 role.removeState(stateId); 217 } 218 219 } 220 221 public void addRole(String name) { 222 Role role = new Role(name); 223 for (Map.Entry <Integer , String > entry : states.entrySet()) { 224 State state = new State(entry.getKey()); 225 state.add(fields.keySet()); 226 role.add(state); 227 } 228 roles.put(role.getName(), role); 229 } 230 231 public void renameRole(String oldRole, String newRole) { 232 Role role = roles.get(oldRole); 234 if (role == null) { 235 return; } 237 role.setName(newRole); 238 roles.remove(oldRole); 239 roles.put(newRole, role); 240 } 241 242 public void removeRole(String name) { 243 roles.remove(name); 245 } 246 247 public Set <Field.Name> getUnusedFieldNames() { 248 EnumSet <Field.Name> allFieldNames = EnumSet.allOf(Field.Name.class); 249 for (Field f : getFields().values()) { 250 allFieldNames.remove(f.getName()); 251 } 252 return allFieldNames; 253 } 254 255 public Map <String , String > getAvailableFieldTypes() { 256 Map <String , String > fieldTypes = new LinkedHashMap <String , String >(); 257 for (Field.Name fieldName : getUnusedFieldNames()) { 258 fieldTypes.put(fieldName.getType() + "", fieldName.getDescription()); 259 } 260 return fieldTypes; 261 } 262 263 public Field getNextAvailableField(int type) { 264 for (Field.Name fieldName : getUnusedFieldNames()) { 265 if (fieldName.getType() == type) { 266 return new Field(fieldName + ""); 267 } 268 } 269 throw new RuntimeException ("No field available of type " + type); 270 } 271 272 public Map <Field.Name, Field> getFields() { 274 Map <Field.Name, Field> map = fields; 275 if (parent != null) { 276 map.putAll(parent.getFields()); 277 } 278 return map; 279 } 280 281 public Collection <Role> getRoleList() { 283 return roles.values(); 284 } 285 286 public List <Field> getFieldList() { 287 Map <Field.Name, Field> map = getFields(); 288 List <Field> list = new ArrayList <Field>(fields.size()); 289 for (Field.Name fieldName : getFieldOrder()) { 290 list.add(fields.get(fieldName)); 291 } 292 return list; 293 } 294 295 public String getCustomValue(Field.Name fieldName, Integer key) { 296 return getCustomValue(fieldName, key + ""); 297 } 298 299 public String getCustomValue(Field.Name fieldName, String key) { 300 Field field = fields.get(fieldName); 301 if (field != null) { 302 return field.getCustomValue(key); 303 } 304 if (parent != null) { 305 return parent.getCustomValue(fieldName, key); 306 } 307 return ""; 308 } 309 310 public String getStatusValue(Integer key) { 311 if (key == null) { 312 return ""; 313 } 314 String s = states.get(key); 315 if (s == null) { 316 return ""; 317 } 318 return s; 319 } 320 321 public int getRoleCount() { 322 return roles.size(); 323 } 324 325 public int getFieldCount() { 326 return getFields().size(); 327 } 328 329 public int getStateCount() { 330 return states.size(); 331 } 332 333 340 public Map <Integer , String > getPermittedTransitions(List <String > roleKeys, int status) { 341 Map <Integer , String > map = new LinkedHashMap <Integer , String >(); 342 for(String roleKey : roleKeys) { 343 Role role = roles.get(roleKey); 344 if (role != null) { 345 State state = role.getStates().get(status); 346 if (state != null) { 347 for(int transition : state.getTransitions()) { 348 map.put(transition, this.states.get(transition)); 349 } 350 } 351 } 352 } 353 return map; 354 } 355 356 public Map <String , Boolean > getRolesAbleToTransition(int fromStatus, int toStatus) { 358 Map <String , Boolean > map = new HashMap <String , Boolean >(roles.size()); 359 for(Role role : roles.values()) { 360 State s = role.getStates().get(fromStatus); 361 if(s.getTransitions().contains(toStatus)) { 362 map.put(role.getName(), true); 363 } 364 } 365 return map; 366 } 367 368 public Set <String > getRolesAbleToTransitionFrom(int state) { 369 Set <String > set = new HashSet <String >(roles.size()); 370 for(Role role : roles.values()) { 371 State s = role.getStates().get(state); 372 if(s.getTransitions().size() > 0) { 373 set.add(role.getName()); 374 } 375 } 376 return set; 377 } 378 379 private State getRoleState(String roleKey, int stateKey) { 380 Role role = roles.get(roleKey); 381 return role.getStates().get(stateKey); 382 } 383 384 public void toggleTransition(String roleKey, int fromState, int toState) { 385 State state = getRoleState(roleKey, fromState); 386 if (state.getTransitions().contains(toState)) { 387 state.getTransitions().remove(toState); 388 } else { 389 state.getTransitions().add(toState); 390 } 391 } 392 393 public void switchMask(int stateKey, String roleKey, String fieldName) { 394 State state = getRoleState(roleKey, stateKey); 395 Field.Name name = Field.convertToName(fieldName); 396 Integer mask = state.getFields().get(name); 397 switch(mask) { 398 case State.MASK_VIEW: state.getFields().put(name, State.MASK_EDIT); return; 400 case State.MASK_EDIT: state.getFields().put(name, State.MASK_VIEW); return; 401 } 402 } 403 404 public List <Field> getEditableFields(Collection <String > roleKeys, Collection <Integer > ss) { 405 Set <Field> fs = new HashSet <Field>(); 406 for(String roleKey : roleKeys) { 407 if (roleKey.startsWith("ROLE_")) { 408 continue; 409 } 410 for(Integer status : ss) { 411 if (status == State.NEW) { 412 continue; } 414 State state = getRoleState(roleKey, status); 415 for(Map.Entry <Field.Name, Integer > entry : state.getFields().entrySet()) { 416 if (entry.getValue() == State.MASK_EDIT) { 417 fs.add(fields.get(entry.getKey())); 418 } 419 } 420 } 421 } 422 List <Field> result = getFieldList(); 423 result.retainAll(fs); return result; 425 } 426 427 public List <Field> getEditableFields() { 428 return getEditableFields(roles.keySet(), states.keySet()); 429 } 430 431 433 public int getVersion() { 434 return version; 435 } 436 437 public void setVersion(int version) { 438 this.version = version; 439 } 440 441 public String getName() { 442 return name; 443 } 444 445 public void setName(String name) { 446 this.name = name; 447 } 448 449 public String getDescription() { 450 return description; 451 } 452 453 public void setDescription(String description) { 454 this.description = description; 455 } 456 457 public long getId() { 458 return id; 459 } 460 461 public void setId(long id) { 462 this.id = id; 463 } 464 465 public Integer getType() { 466 return type; 467 } 468 469 public void setType(Integer type) { 470 this.type = type; 471 } 472 473 public Metadata getParent() { 474 return parent; 475 } 476 477 public void setParent(Metadata parent) { 478 this.parent = parent; 479 } 480 481 484 public Map <String , Role> getRoles() { 485 return roles; 486 } 487 488 public Map <Integer , String > getStates() { 489 return states; 490 } 491 492 public List <Field.Name> getFieldOrder() { 493 return fieldOrder; 494 } 495 496 @Override 497 public String toString() { 498 StringBuffer sb = new StringBuffer (); 499 sb.append("id [").append(id); 500 sb.append("]; parent [").append(parent); 501 sb.append("]; fields [").append(fields); 502 sb.append("]; roles [").append(roles); 503 sb.append("]; states [").append(states); 504 sb.append("]; fieldOrder [").append(fieldOrder); 505 sb.append("]"); 506 return sb.toString(); 507 } 508 509 } 510 | Popular Tags |