001: package org.obe.xpdl.model.misc;
002:
003: import org.obe.XMLException;
004: import org.obe.xpdl.XPDLNames;
005: import org.obe.xpdl.model.activity.Activity;
006: import org.obe.xpdl.model.activity.BlockActivity;
007: import org.obe.xpdl.model.data.XMLFragment;
008: import org.obe.xpdl.model.ext.AssignmentStrategyDef;
009: import org.obe.xpdl.model.ext.Event;
010: import org.obe.xpdl.model.ext.Loop;
011: import org.obe.xpdl.model.pkg.XPDLPackage;
012: import org.obe.xpdl.model.transition.Transition;
013: import org.obe.xpdl.model.workflow.WorkflowProcess;
014: import org.w3c.dom.*;
015:
016: import java.util.Collections;
017: import java.util.HashMap;
018: import java.util.Iterator;
019: import java.util.Map;
020:
021: /**
022: * Holds 3rd party extended attributes as XML text. The text must include the
023: * <ExtendedAttributes> parent element, correctly declared in the XPDL
024: * namespace.
025: * <p/>
026: * <em>N.B. DO NOT USE THIS CLASS FOR STORING OBE EXTENDED ATTRIBUTES!</em>
027: *
028: * @author Adrian Price
029: * @see XPDLNames#XPDL_NS_PREFIX
030: * @see XPDLNames#XPDL_NS_URI
031: * @see XPDLPackage#setAssignmentStrategy(AssignmentStrategyDef)
032: * @see WorkflowProcess#setAssignmentStrategy(AssignmentStrategyDef)
033: * @see Activity#setAssignmentStrategy(AssignmentStrategyDef)
034: * @see XPDLPackage#setCompletionStrategy(String)
035: * @see WorkflowProcess#setCompletionStrategy(String)
036: * @see Activity#setCompletionStrategy(String)
037: * @see XPDLPackage#setCalendar(String)
038: * @see WorkflowProcess#setCalendar(String)
039: * @see Activity#setCalendar(String)
040: * @see Transition#setExecutionType(ExecutionType)
041: * @see Transition#setEvent(Event)
042: * @see BlockActivity#setLoop(Loop)
043: */
044: public final class ExtendedAttributes extends XMLFragment {
045: private static final long serialVersionUID = 6285607010686717240L;
046: private transient Map _map;
047:
048: public ExtendedAttributes() {
049: }
050:
051: public ExtendedAttributes(String text) throws XMLException {
052: super (text);
053: }
054:
055: public ExtendedAttributes(Document document) throws XMLException {
056: super (document);
057: }
058:
059: public ExtendedAttributes(Map map) throws XMLException {
060: setMap(map);
061: }
062:
063: protected String getDocumentElementName() {
064: return XPDLNames.EXTENDED_ATTRIBUTES;
065: }
066:
067: protected String getDocumentElementNamespaceURI() {
068: return XPDLNames.XPDL_NS_URI;
069: }
070:
071: public void clear() throws XMLException {
072: setMap(null);
073: }
074:
075: public String get(String key) throws XMLException {
076: return (String) getMap().get(key);
077: }
078:
079: public void put(String key, Object value) throws XMLException {
080: getMap();
081: _map.put(key, value == null ? null : value.toString());
082: setMap(_map);
083: }
084:
085: public void remove(String key) throws XMLException {
086: getMap();
087: _map.remove(key);
088: setMap(_map);
089: }
090:
091: /**
092: * Returns an unmodifiable map of name:value pairs. The map representation
093: * is only suitable for simple extended attributes with values that can be
094: * represented as strings.
095: *
096: * @return A map of simple name:value pairs.
097: * @throws XMLException
098: */
099: public Map getMap() throws XMLException {
100: Map map = _map;
101: if (map == null) {
102: _map = map = new HashMap();
103: Document document = getDocument();
104: if (document != null) {
105: Element docElem = document.getDocumentElement();
106: NodeList nodes = docElem.getChildNodes();
107: for (int i = 0, m = nodes.getLength(); i < m; i++) {
108: Node node = nodes.item(i);
109: if (node.getNodeType() == Node.ELEMENT_NODE
110: && node.getNodeName().endsWith(
111: XPDLNames.EXTENDED_ATTRIBUTE)) {
112:
113: Element elem = (Element) node;
114: NamedNodeMap attrs = elem.getAttributes();
115: Node nameAttr = attrs
116: .getNamedItem(XPDLNames.NAME);
117: Node valueAttr = attrs
118: .getNamedItem(XPDLNames.VALUE);
119: String value;
120: if (valueAttr == null) {
121: if (elem.hasChildNodes()) {
122: StringBuffer sb = new StringBuffer();
123: elem.normalize();
124: NodeList children = elem
125: .getChildNodes();
126: for (int j = 0, n = children
127: .getLength(); j < n; j++)
128: sb.append(children.item(j)
129: .getNodeValue());
130: value = sb.toString();
131: } else {
132: value = null;
133: }
134: } else {
135: value = valueAttr.getNodeValue();
136: }
137: map.put(nameAttr.getNodeValue(),
138: value == null ? null : value.trim());
139: }
140: }
141: }
142: }
143: return Collections.unmodifiableMap(map);
144: }
145:
146: /**
147: * Sets extended attributes as map of name:value pairs. The map
148: * representation is only suitable for simple extended attributes with
149: * values that can be represented as strings. Complex extended attributes
150: * must be set either as XML text or as a DOM document; in either case the
151: * document element must be <code>ExtendedAttributes</code>, in the XPDL
152: * namspace URI <code>http://www.wfmc.org/2002/XPDL1.0</code>.
153: *
154: * @param map Map of name:value pairs.
155: * @throws XMLException
156: */
157: public void setMap(Map map) throws XMLException {
158: if (map == null) {
159: setText(null);
160: } else {
161: StringBuffer buf = new StringBuffer();
162: buf
163: .append("<ExtendedAttributes xmlns=\"http://www.wfmc.org/2002/XPDL1.0\">\n");
164: for (Iterator iter = map.entrySet().iterator(); iter
165: .hasNext();) {
166: Map.Entry entry = (Map.Entry) iter.next();
167: Object key = entry.getKey();
168: if (key == null) {
169: throw new XMLException(
170: new IllegalArgumentException(
171: "Map key cannot be null"));
172: }
173: buf.append(" <ExtendedAttribute Name=\"").append(key)
174: .append('\"');
175: Object value = entry.getValue();
176: if (value != null) {
177: // If the string representation of the extended attribute's
178: // value contains any XML markup or symbols, we must store
179: // it in a CDATA section.
180: String str = value.toString().trim();
181: if (str.indexOf('<') != -1
182: || str.indexOf('>') != -1
183: || str.indexOf('&') != -1) {
184:
185: buf.append(">\n <![CDATA[\n").append(str)
186: .append("\n ]]>\n");
187: buf.append(" </ExtendedAttribute>\n");
188: } else {
189: // Otherwise, a simple attribute will suffice.
190: buf.append(" Value=\"").append(value).append(
191: "\"/>\n");
192: }
193: } else {
194: buf.append("/>\n");
195: }
196: }
197: buf.append("</ExtendedAttributes>\n");
198: setText(buf.toString());
199: }
200: _map = new HashMap(map);
201: }
202: }
|