001: /*
002: * Copyright 2002-2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package info.jtrac.domain;
018:
019: import info.jtrac.util.XmlUtils;
020:
021: import java.util.HashSet;
022:
023: import static info.jtrac.Constants.*;
024:
025: import java.io.Serializable;
026: import java.util.Collection;
027: import java.util.HashMap;
028: import java.util.Map;
029: import java.util.Set;
030: import org.dom4j.Element;
031:
032: /**
033: * State as in "State Transition"
034: * holds a set of possible future states to transition to
035: * also holds a map of [ field name = integer "mask" ]
036: * to represent permissions (view or edit) that the role owning this state
037: * has for each field for an item which is in this particular state
038: *
039: * For example, consider a state FOO and a role BAR.
040: * When a user with role BAR views an item that is having the status FOO:
041: * ie. when item.status == FOO.status, the fields that can be viewed on screen
042: * will be the entries in FOO.fields where the value == MASK_READONLY (or 1)
043: */
044: public class State implements Serializable {
045:
046: private int status;
047: private Set<Integer> transitions = new HashSet<Integer>();
048: private Map<Field.Name, Integer> fields = new HashMap<Field.Name, Integer>();
049:
050: public static final int NEW = 0;
051: public static final int OPEN = 1;
052: public static final int CLOSED = 99;
053:
054: public static final int MASK_HIDDEN = 0;
055: public static final int MASK_READONLY = 1;
056: public static final int MASK_OPTIONAL = 2;
057: public static final int MASK_MANDATORY = 3;
058:
059: public State() {
060: // zero arg constructor
061: }
062:
063: public State(int s) {
064: this .status = s;
065: }
066:
067: public State(Element e) {
068: this .status = Integer.parseInt(e.attributeValue(STATUS));
069: for (Object o : e.elements(TRANSITION)) {
070: Element t = (Element) o;
071: transitions.add(new Integer(t.attributeValue(STATUS)));
072: }
073: for (Object o : e.elements(FIELD)) {
074: Element f = (Element) o;
075: String fieldName = f.attributeValue(NAME);
076: fields.put(Field.convertToName(fieldName), new Integer(f
077: .attributeValue(MASK)));
078: }
079: }
080:
081: /* append this object onto an existing XML document */
082: public void addAsChildOf(Element parent) {
083: Element e = parent.addElement(STATE);
084: copyTo(e);
085: }
086:
087: /* marshal this object into a fresh new XML Element */
088: public Element getAsElement() {
089: Element e = XmlUtils.getNewElement(STATE);
090: copyTo(e);
091: return e;
092: }
093:
094: /* copy object values into an existing XML Element */
095: private void copyTo(Element e) {
096: // appending empty strings to create new objects for "clone" support
097: e.addAttribute(STATUS, status + "");
098: for (Integer toStatus : transitions) {
099: Element t = e.addElement(TRANSITION);
100: t.addAttribute(STATUS, toStatus + "");
101: }
102: for (Map.Entry<Field.Name, Integer> entry : fields.entrySet()) {
103: Element f = e.addElement(FIELD);
104: f.addAttribute(NAME, entry.getKey() + "");
105: f.addAttribute(MASK, entry.getValue() + "");
106: }
107: }
108:
109: //=======================================================================
110:
111: public void add(Collection<Field.Name> fieldNames) {
112: for (Field.Name fieldName : fieldNames) {
113: add(fieldName);
114: }
115: }
116:
117: public void add(Field.Name fieldName) {
118: int mask = MASK_READONLY;
119: // for NEW states, normally all Fields on the Item are editable
120: if (status == NEW) {
121: mask = MASK_MANDATORY;
122: }
123: fields.put(fieldName, mask);
124: }
125:
126: public void remove(Field.Name fieldName) {
127: fields.remove(fieldName);
128: }
129:
130: public void addTransition(int toStatus) {
131: transitions.add(toStatus);
132: }
133:
134: public void removeTransition(int toStatus) {
135: transitions.remove(toStatus);
136: }
137:
138: //=======================================================================
139:
140: public Map<Field.Name, Integer> getFields() {
141: return fields;
142: }
143:
144: public void setFields(Map<Field.Name, Integer> fields) {
145: this .fields = fields;
146: }
147:
148: public int getStatus() {
149: return status;
150: }
151:
152: public void setStatus(int status) {
153: this .status = status;
154: }
155:
156: public Set<Integer> getTransitions() {
157: return transitions;
158: }
159:
160: public void setTransitions(Set<Integer> transitions) {
161: this .transitions = transitions;
162: }
163:
164: @Override
165: public String toString() {
166: StringBuffer sb = new StringBuffer();
167: sb.append("status [").append(status);
168: sb.append("]; transitions [").append(transitions);
169: sb.append("]; fields [").append(fields);
170: sb.append("]");
171: return sb.toString();
172: }
173:
174: }
|