001: package biz.hammurapi.rules.jsr94.admin;
002:
003: import java.util.ArrayList;
004: import java.util.Collections;
005: import java.util.HashMap;
006: import java.util.List;
007: import java.util.Map;
008:
009: import javax.rules.admin.Rule;
010: import javax.xml.transform.TransformerException;
011:
012: import org.apache.xpath.XPathAPI;
013: import org.w3c.dom.Element;
014: import org.w3c.dom.Node;
015: import org.w3c.dom.traversal.NodeIterator;
016:
017: import biz.hammurapi.config.ConfigurationException;
018: import biz.hammurapi.config.RuntimeConfigurationException;
019: import biz.hammurapi.xml.dom.AbstractDomObject;
020: import biz.hammurapi.xml.dom.DOMUtils;
021:
022: class RuleExecutionSet implements javax.rules.admin.RuleExecutionSet {
023: /**
024: * Generated ID.
025: */
026: private static final long serialVersionUID = 6333369438749221375L;
027:
028: private Element holder;
029:
030: Element getHolder() {
031: return holder;
032: // Handle properties?
033: }
034:
035: Map getProperties() {
036: return properties;
037: }
038:
039: private String uri;
040:
041: String getUri() {
042: return uri;
043: }
044:
045: private List rules;
046: private String description;
047: private String name;
048: private boolean modified;
049:
050: boolean isModified() {
051: return modified;
052: }
053:
054: /**
055: * Constructs rule execution set from XML definition.
056: * The definition shall contain nested elements <code>name</code>, <code>description</code>, and <code>rules</code>.
057: * Rules are defined as nested <code>rule</code> elements of <code>rules</code> element.
058: * @param holder
059: * @throws ConfigurationException
060: * @throws TransformerException
061: */
062: public RuleExecutionSet(Element holder, Map properties)
063: throws ConfigurationException, TransformerException {
064: this .holder = holder;
065: name = DOMUtils.getSingleElementText(holder, "name");
066: description = DOMUtils.getSingleElementText(holder,
067: "description");
068: List rl = new ArrayList();
069: NodeIterator nit = XPathAPI.selectNodeIterator(holder,
070: "rules/rule");
071: Node n;
072: while ((n = nit.nextNode()) != null) {
073: final Element ruleElement = (Element) n;
074: final String name = DOMUtils.getSingleNonBlankElementText(
075: ruleElement, "name");
076: final String description = DOMUtils
077: .getSingleNonBlankElementText(ruleElement,
078: "description");
079:
080: Rule rule = new Rule() {
081:
082: public String getName() {
083: return name;
084: }
085:
086: public String getDescription() {
087: return description;
088: }
089:
090: // property cache.
091: Map properties = new HashMap();
092:
093: public Object getProperty(Object key) {
094: // Properties set at runtime
095: if (properties.containsKey(key)) {
096: return properties.get(key);
097: } else if (key instanceof String) { // Properties defined in XML.
098: try {
099: return DOMUtils.getSingleElementText(
100: ruleElement, (String) key);
101: } catch (ConfigurationException e) {
102: throw new RuntimeConfigurationException(
103: "Could not read property '" + key
104: + "': " + e, e);
105: } catch (TransformerException e) {
106: throw new RuntimeConfigurationException(
107: "Could not read property '" + key
108: + "': " + e, e);
109: }
110: }
111:
112: return null;
113: }
114:
115: public void setProperty(Object key, Object value) {
116: properties.put(key, value); // cache properties set at runtime.
117:
118: if (key instanceof String) {
119: if ("name".equals(key)) {
120: throw new IllegalArgumentException(
121: "'name' property corresponds to rule name and is readonly");
122: }
123: if ("description".equals(key)) {
124: throw new IllegalArgumentException(
125: "'description' property corresponds to rule description and is readonly");
126: }
127: try {
128: modified = true;
129: Element propertyElement = (Element) XPathAPI
130: .selectSingleNode(ruleElement,
131: (String) key);
132: if (propertyElement != null) {
133: ruleElement
134: .removeChild(propertyElement);
135: }
136:
137: if (value != null) {
138: DOMUtils.toDom(value, AbstractDomObject
139: .addElement(ruleElement,
140: (String) key));
141: }
142: } catch (TransformerException e) {
143: throw new RuntimeConfigurationException(
144: "Could not set property " + key
145: + "=" + value + ": " + e, e);
146: }
147: } else {
148: throw new IllegalArgumentException(
149: "Properties shall have keys of type String");
150: }
151: }
152:
153: };
154:
155: rl.add(rule);
156: }
157:
158: rules = Collections.unmodifiableList(rl);
159:
160: if (properties != null) {
161: this .properties.putAll(properties);
162: }
163: }
164:
165: /**
166: * Constructs rules execution set from XML definition.
167: * @param uri URI of the definition. Used to store rule sets by reference.
168: * @param holder Parent XML element.
169: * @throws ConfigurationException
170: * @throws TransformerException
171: */
172: public RuleExecutionSet(String uri, Element holder, Map properties)
173: throws ConfigurationException, TransformerException {
174: this (holder, properties);
175: this .uri = uri;
176: }
177:
178: /**
179: * @return Rule set name.
180: */
181: public String getName() {
182: return name;
183: }
184:
185: /**
186: * @return Rule set description.
187: */
188: public String getDescription() {
189: return description;
190: }
191:
192: private Map properties = new HashMap();
193:
194: /**
195: * @return Runtime property. These properties are not stored in the rule set definition.
196: */
197: public Object getProperty(Object key) {
198: return properties.get(key);
199: }
200:
201: /**
202: * Sets runtime property
203: */
204: public void setProperty(Object key, Object value) {
205: properties.put(key, value);
206: }
207:
208: /**
209: * Sets default object filter.
210: */
211: public void setDefaultObjectFilter(String type) {
212: try {
213: modified = true;
214: Element objectFilterElement = (Element) XPathAPI
215: .selectSingleNode(holder, "object-filter");
216: if (objectFilterElement != null) {
217: holder.removeChild(objectFilterElement);
218: }
219:
220: if (type != null) {
221: objectFilterElement = AbstractDomObject.addElement(
222: holder, "object-filter");
223: objectFilterElement.setAttribute("type", type);
224: }
225: } catch (TransformerException e) {
226: throw new RuntimeConfigurationException(
227: "Could not set object filter: " + e, e);
228: }
229: }
230:
231: /**
232: * @return Default object filter class.
233: */
234: public String getDefaultObjectFilter() {
235: try {
236: Element objectFilterElement = (Element) XPathAPI
237: .selectSingleNode(holder, "object-filter");
238: return objectFilterElement == null ? null
239: : objectFilterElement.getAttribute("type");
240: } catch (TransformerException e) {
241: throw new RuntimeConfigurationException(
242: "Could not set object filter: " + e, e);
243: }
244: }
245:
246: /**
247: * Returns rules.
248: */
249: public List getRules() {
250: return rules;
251: }
252: }
|