001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.lib.contract;
028:
029: import java.io.FileReader;
030: import java.io.PrintStream;
031:
032: /**
033: * Factory which can <tt>create</tt> <code>Operator</code>s.
034: * <p>
035: * See <tt>main</tt> for sample usage.
036: * <p>
037: * <b>Note:</b> The default implementation of <code>Operator</code>
038: * is currently kept in the utility module as "org.cougaar.lib.contract.lang" --
039: * see the "index.html" file there for language details.
040: * <p>
041: * @see Operator
042: */
043: public abstract class OperatorFactory {
044:
045: /**
046: * System property tags for setting the <tt>default*</tt> values.
047: * <p>
048: * Java usage is "-Dtagname=value"
049: */
050: public static final String PROPERTY_CLASSNAME = "org.cougaar.util.op.name";
051: public static final String PROPERTY_STYLE = "org.cougaar.util.op.style";
052:
053: /**
054: * Default style for <tt>create(Object)</tt>.
055: */
056: private static int defaultStyle;
057:
058: /**
059: * Default classname for <tt>getInstance()</tt>.
060: */
061: private static String defaultClassname;
062:
063: /**
064: * Default instance of <code>OperatorFactory</code>.
065: */
066: private static OperatorFactory defaultOperatorFactory;
067:
068: /**
069: * Set the <tt>default*</tt>s.
070: */
071: static {
072: // overwrite from optional system properties
073: String s;
074: if ((s = System.getProperty(PROPERTY_STYLE)) != null) {
075: if (s.regionMatches(true, 0, "xml", 0, 3)) {
076: defaultStyle = Operator.XML_FLAG;
077: } else if (s.regionMatches(true, 0, "paren", 0, 5)) {
078: defaultStyle = Operator.PAREN_FLAG;
079: } else {
080: System.err.println("Invalid property -D"
081: + PROPERTY_STYLE + "=" + s);
082: }
083: } else {
084: defaultStyle = Operator.DEFAULT_STYLE;
085: }
086: if ((s = System.getProperty(PROPERTY_CLASSNAME)) != null) {
087: defaultClassname = s;
088: } else {
089: defaultClassname = "org.cougaar.lib.contract.lang.OperatorFactoryImpl";
090: }
091: // load the factory
092: defaultOperatorFactory = getInstance(defaultClassname);
093: }
094:
095: /**
096: * Get the default <code>OperatorFactory</code> instance.
097: */
098: public static OperatorFactory getInstance() {
099: return defaultOperatorFactory;
100: }
101:
102: /**
103: * Get the default style for <tt>create(Object)</tt>
104: */
105: public static int getDefaultStyle() {
106: return defaultStyle;
107: }
108:
109: /**
110: * Get the default classname for <tt>getInstance(String)</tt>
111: */
112: public static String getDefaultClassname() {
113: return defaultClassname;
114: }
115:
116: /**
117: * <tt>create</tt> using the <tt>getDefaultStyle()</tt>.
118: * <p>
119: * @see #create
120: */
121: public Operator create(Object inObj) throws Exception {
122: return create(defaultStyle, inObj);
123: }
124:
125: /**
126: * Create an <code>Operator</code>.
127: * <p>
128: * Implementations of the contract language parser must implement
129: * this method.
130: * <p>
131: * @param style either (Operator.XML_FLAG) or (Operator.PAREN_FLAG)
132: * @param inObj an instance of
133: * <code>java.lang.String</code>,
134: * <code>java.io.InputStream</code>,
135: * <code>java.io.Reader</code>, or
136: * <code>org.w3c.dom.Element</code>
137: * @throws Exception if parse failed -- toString will display
138: * useful stack trace
139: */
140: public abstract Operator create(int style, Object inObj)
141: throws Exception;
142:
143: /**
144: * @deprecated See create(int, Object) method to use new symbolic int
145: * flags, e.g. Operator.XML_FLAG or Operator.PAREN_FLAG
146: */
147: public Operator create(boolean isParenStyle, Object inObj)
148: throws Exception {
149: return create((isParenStyle ? Operator.PAREN_FLAG
150: : Operator.XML_FLAG), inObj);
151: }
152:
153: /**
154: * Get an instance of a specific <code>OperatorFactory</code>.
155: */
156: public static OperatorFactory getInstance(final String classname) {
157: try {
158: // load class
159: Class c = Class.forName(classname);
160: return (OperatorFactory) c.newInstance();
161: } catch (Exception e) {
162: // unable to load class!
163: final String errorMsg = e.toString();
164: // create dummy factory that throws an Exception!
165: return new OperatorFactory() {
166: public Operator create(int style, Object inObj)
167: throws Exception {
168: throw new UnsupportedOperationException(
169: "OperatorFactory \"" + classname
170: + "\" not available!\n" + errorMsg);
171: }
172: };
173: }
174: }
175:
176: /**
177: * A testing utility!.
178: * <p>
179: * Try with a ".txt" file, for example:<pre><code>
180: * (and (is:String) (equals "foo"))
181: * </pre></code>
182: */
183: public static void main(String[] args) {
184: System.out.println("Test the operator factory");
185:
186: // get the arguments
187: Object objIn;
188: int style = (Operator.PAREN_FLAG | Operator.PRETTY_FLAG | Operator.VERBOSE_FLAG);
189: if (args.length != 1) {
190: // simple test
191: objIn = "(and (is:String) (equals \"TEST\"))";
192: } else {
193: // read from the input file
194: String filename = args[0];
195: if (filename.regionMatches(true, filename.length() - 4,
196: ".xml", 0, 4)) {
197: // filename ends in ".xml";
198: style = Operator.XML_FLAG;
199: }
200: try {
201: objIn = new FileReader(filename);
202: } catch (Exception e) {
203: System.err.println("Unable to read \"" + filename
204: + "\":");
205: e.printStackTrace();
206: return;
207: }
208: }
209:
210: // get an instance of the default operator factory
211: OperatorFactory operFactory = OperatorFactory.getInstance();
212:
213: // parse the input
214: Operator oper;
215: try {
216: oper = operFactory.create(style, objIn);
217: } catch (Exception e) {
218: System.err.println("Unable to parse: ");
219: e.printStackTrace();
220: return;
221: }
222:
223: // test for null operator
224: if (oper == null) {
225: System.out.println("EMPTY?");
226: return;
227: }
228:
229: // display the parsed operator
230: System.out.println("parsed: \n" + oper);
231:
232: // set optional testing template
233: /************************************************/
234: oper.setConst("foo", "bar");
235: /************************************************/
236:
237: // create a testing object
238: Object testObject;
239: /************************************************/
240: testObject = "TEST";
241: /************************************************/
242: System.out.println("test with: \n " + testObject);
243:
244: // execute the predicate on the test object
245: System.out.println("execute(): ");
246: try {
247: boolean b = oper.execute(testObject);
248: System.out.println(" return value: " + b);
249: } catch (Exception e) {
250: System.err.println(" execute failed: " + e);
251: e.printStackTrace();
252: }
253:
254: // finished the test
255: System.out.println("done.");
256: }
257:
258: }
|