001: package org.drools.lang;
002:
003: /*
004: * Author Jayaram C S
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: import java.util.Iterator;
020: import java.util.List;
021:
022: import org.drools.lang.descr.AccumulateDescr;
023: import org.drools.lang.descr.AndDescr;
024: import org.drools.lang.descr.AttributeDescr;
025: import org.drools.lang.descr.CollectDescr;
026: import org.drools.lang.descr.EvalDescr;
027: import org.drools.lang.descr.ExistsDescr;
028: import org.drools.lang.descr.FieldBindingDescr;
029: import org.drools.lang.descr.FieldConstraintDescr;
030: import org.drools.lang.descr.ForallDescr;
031: import org.drools.lang.descr.FromDescr;
032: import org.drools.lang.descr.FunctionDescr;
033: import org.drools.lang.descr.GlobalDescr;
034: import org.drools.lang.descr.ImportDescr;
035: import org.drools.lang.descr.LiteralRestrictionDescr;
036: import org.drools.lang.descr.NotDescr;
037: import org.drools.lang.descr.OrDescr;
038: import org.drools.lang.descr.PackageDescr;
039: import org.drools.lang.descr.PackageDescrDumper;
040: import org.drools.lang.descr.PatternDescr;
041: import org.drools.lang.descr.PredicateDescr;
042: import org.drools.lang.descr.QualifiedIdentifierRestrictionDescr;
043: import org.drools.lang.descr.QueryDescr;
044: import org.drools.lang.descr.RestrictionConnectiveDescr;
045: import org.drools.lang.descr.ReturnValueRestrictionDescr;
046: import org.drools.lang.descr.RuleDescr;
047: import org.drools.lang.descr.VariableRestrictionDescr;
048: import org.drools.util.ReflectiveVisitor;
049:
050: /**
051: *
052: * @author <a href="mailto:jayaramcs@gmail.com">Author Jayaram C S</a>
053: *
054: */
055: public class DrlDumper extends ReflectiveVisitor implements
056: PackageDescrDumper {
057:
058: private StringBuffer drlDump;
059: private static final String eol = System
060: .getProperty("line.separator");
061: private String template;
062: private boolean needsBracket = false;
063:
064: public synchronized String dump(final PackageDescr packageDescr) {
065: this .drlDump = new StringBuffer();
066: visitPackageDescr(packageDescr);
067: return this .drlDump.toString();
068: }
069:
070: public String getTemplate() {
071: return this .template;
072: }
073:
074: public void visitAndDescr(final AndDescr descr) {
075: this .template = new String();
076: if (!descr.getDescrs().isEmpty()) {
077: this .template = processDescrList(descr.getDescrs());
078: } else {
079: this .template = "";
080: }
081: }
082:
083: public void visitAttributeDescr(final AttributeDescr attributeDescr) {
084: this .template = new String();
085: final String name = attributeDescr.getName();
086: String value = null;
087: if (name.equals("agenda-group")
088: || name.equals("activation-group")
089: || name.equals("ruleflow-group")) {
090: // These attributes may need quotes around them, if they have spaces, so add anyway
091: value = "\"" + attributeDescr.getValue() + "\"";
092: } else {
093: value = attributeDescr.getValue();
094: }
095: this .template = "\t " + name + " " + value + DrlDumper.eol;
096: }
097:
098: public void visitFieldConstraintDescr(
099: final FieldConstraintDescr descr) {
100: if (!descr.getRestrictions().isEmpty()) {
101: this .template = descr.getFieldName()
102: + " "
103: + processFieldConstraint(descr.getRestriction(),
104: false);
105: }
106: }
107:
108: public void visitVariableRestrictionDescr(
109: final VariableRestrictionDescr descr) {
110: this .template = new String();
111: this .template = descr.getEvaluator() + " "
112: + descr.getIdentifier();
113: }
114:
115: public void visitPatternDescr(final PatternDescr descr) {
116: StringBuffer buf = new StringBuffer();
117: buf.append("\t\t");
118: if (descr.getIdentifier() != null) {
119: buf.append(descr.getIdentifier());
120: buf.append(" : ");
121:
122: }
123: buf.append(descr.getObjectType());
124: buf.append("( ");
125: if (!descr.getConstraint().getDescrs().isEmpty()) {
126: buf.append(processColoumnConstraintList(descr
127: .getConstraint().getDescrs()));
128: }
129: buf.append(" )");
130: if (descr.getSource() != null) {
131: buf.append(" from ");
132: this .template = buf.toString();
133: visit(descr.getSource());
134: buf.append(this .template);
135: }
136: this .template = buf.toString();
137: }
138:
139: public void visitEvalDescr(final EvalDescr descr) {
140: this .template = new String();
141: this .template = "\t\teval ( " + descr.getContent() + " )"
142: + DrlDumper.eol;
143: }
144:
145: public void visitExistsDescr(final ExistsDescr descr) {
146: this .template = new String();
147: if (!descr.getDescrs().isEmpty()) {
148: this .template = "\t\texists "
149: + processDescrList(descr.getDescrs()) + ";";
150: } else {
151: this .template = "";
152: }
153: }
154:
155: public void visitCollectDescr(final CollectDescr descr) {
156: String tmpstr = new String();
157: tmpstr += " collect (";
158: visitPatternDescr(descr.getInputPattern());
159: tmpstr += this .template.substring(2);
160: this .template = tmpstr + ");";
161: }
162:
163: public void visitAccumulateDescr(final AccumulateDescr descr) {
164: String tmpstr = new String();
165: tmpstr += " accumulate (";
166: visitPatternDescr(descr.getInputPattern());
167: tmpstr += this .template.substring(2);
168:
169: if (descr.isExternalFunction()) {
170: tmpstr += "," + descr.getFunctionIdentifier() + "("
171: + descr.getExpression() + ")";
172: } else {
173: tmpstr += ", init(" + descr.getInitCode() + "), ";
174: tmpstr += "action(" + descr.getActionCode() + "), ";
175: if (descr.getReverseCode() != null) {
176: tmpstr += " reverse(" + descr.getReverseCode() + "), ";
177: }
178: tmpstr += "result(" + descr.getResultCode() + ")";
179: }
180: this .template = tmpstr + ");";
181: }
182:
183: public void visitFromDescr(final FromDescr descr) {
184: this .template = descr.getDataSource().toString();
185: }
186:
187: public void visitForallDescr(final ForallDescr descr) {
188: String localstr = new String();
189: localstr += "\t\tforall ( ";
190: localstr += DrlDumper.eol;
191:
192: for (final Iterator ite = descr.getDescrs().iterator(); ite
193: .hasNext();) {
194: Object obj = ite.next();
195: visit(obj);
196: localstr += this .template + DrlDumper.eol;
197: }
198:
199: this .template = localstr;
200: this .template += "\t\t)";
201: this .template += DrlDumper.eol;
202: }
203:
204: public void visitFieldBindingDescr(final FieldBindingDescr descr) {
205: this .template = new String();
206: this .template = descr.getIdentifier() + " : "
207: + descr.getFieldName();
208: }
209:
210: public void visitFunctionDescr(final FunctionDescr functionDescr) {
211: this .template = new String();
212: final String parameterTemplate = processParameters(
213: functionDescr.getParameterNames(), functionDescr
214: .getParameterTypes());
215:
216: this .template = "function " + functionDescr.getReturnType()
217: + " " + functionDescr.getName() + "("
218: + parameterTemplate + "){" +
219:
220: functionDescr.getText() + DrlDumper.eol + "}"
221: + DrlDumper.eol;
222:
223: }
224:
225: public void visitLiteralRestrictionDescr(
226: final LiteralRestrictionDescr descr) {
227: this .template = "";
228: String text = descr.getText();
229: if (text == null
230: || descr.getType() == LiteralRestrictionDescr.TYPE_NULL) {
231: text = "null";
232: } else if (descr.getType() == LiteralRestrictionDescr.TYPE_NUMBER) {
233: try {
234: Integer.parseInt(text);
235: } catch (final NumberFormatException e) {
236: text = "\"" + text + "\"";
237: }
238: } else if (descr.getType() == LiteralRestrictionDescr.TYPE_STRING) {
239: text = "\"" + text + "\"";
240: }
241: this .template = descr.getEvaluator() + " " + text;
242: }
243:
244: public void visitQualifiedIdentifierRestrictionDescr(
245: final QualifiedIdentifierRestrictionDescr descr) {
246: this .template = descr.getEvaluator() + " " + descr.getText();
247: }
248:
249: public void visitRestrictionConnectiveDescr(
250: final RestrictionConnectiveDescr descr) {
251: String tmp = this .processFieldConstraint(descr, true);
252: this .template = tmp;
253: }
254:
255: public void visitNotDescr(final NotDescr descr) {
256: this .template = new String();
257: if (!descr.getDescrs().isEmpty()) {
258: this .template = "\t not ( "
259: + processDescrList(descr.getDescrs()) + ")";
260: } else {
261: this .template = "";
262: }
263: }
264:
265: public void visitOrDescr(final OrDescr descr) {
266: this .template = new String();
267: if (!descr.getDescrs().isEmpty()) {
268: this .template = processOrDescrList(descr.getDescrs());
269: } else {
270: this .template = " ";
271: }
272: }
273:
274: public void visitPackageDescr(final PackageDescr packageDescr) {
275: final String packageName = packageDescr.getName();
276: final String xmlString = "package " + packageName + ";"
277: + DrlDumper.eol + DrlDumper.eol;
278:
279: appendDrlDump(xmlString);
280: if (packageDescr.getImports() != null) {
281: appendDrlDump(processImportsList(packageDescr.getImports()));
282: }
283: if (packageDescr.getGlobals() != null) {
284: appendDrlDump(processGlobalsList(packageDescr.getGlobals()));
285: }
286: if (packageDescr.getFunctions() != null) {
287: appendDrlDump(processFunctionsList(packageDescr
288: .getFunctions()));
289: }
290: if (packageDescr.getRules() != null) {
291: appendDrlDump(processRules(packageDescr.getRules()));
292: }
293:
294: }
295:
296: public void visitPredicateDescr(final PredicateDescr descr) {
297: this .template = new String();
298: this .template = "eval( " + descr.getContent() + " )";
299:
300: }
301:
302: public void visitReturnValueRestrictionDescr(
303: final ReturnValueRestrictionDescr descr) {
304: this .template = new String();
305: this .template = descr.getEvaluator() + " ( "
306: + descr.getContent() + ")";
307: }
308:
309: public void visitQueryDescr(final QueryDescr descr) {
310: this .template = new String();
311: this .template = "query \"" + descr.getName() + "\""
312: + processDescrList(descr.getLhs().getDescrs()) + "end";
313: }
314:
315: private String processRules(final List rules) {
316: String ruleList = "";
317: Object ruleobj;
318: for (final Iterator iterator = rules.iterator(); iterator
319: .hasNext();) {
320: ruleobj = iterator.next();
321: if (ruleobj instanceof QueryDescr) {
322: visitQueryDescr((QueryDescr) ruleobj);
323: ruleList += this .template;
324: break;
325: }
326:
327: final RuleDescr ruleDescr = (RuleDescr) ruleobj;
328: String rule = "rule \"" + ruleDescr.getName() + "\" "
329: + DrlDumper.eol;
330: final String attribute = processAttribute(ruleDescr
331: .getAttributes());
332: String lhs = "";
333: if (!ruleDescr.getLhs().getDescrs().isEmpty()) {
334: lhs = "\t when"
335: + DrlDumper.eol
336: + processDescrList(ruleDescr.getLhs()
337: .getDescrs()) + DrlDumper.eol;
338: } else {
339:
340: lhs = "\t when";
341: }
342:
343: String rhs = (String) ruleDescr.getConsequence();
344: if (rhs == null) {
345: rhs = "\t then" + DrlDumper.eol + "\t";
346: } else {
347: rhs = "\t then" + DrlDumper.eol
348: + ruleDescr.getConsequence();
349: }
350:
351: rule += attribute;
352: rule += lhs;
353: rule += rhs;
354: rule += "end" + DrlDumper.eol;
355: ruleList += rule;
356: }
357:
358: return ruleList + DrlDumper.eol;
359: }
360:
361: private String processOrDescrList(final List descr) {
362: String descrString = "";
363: for (final Iterator iterator = descr.iterator(); iterator
364: .hasNext();) {
365: visit(iterator.next());
366: descrString += this .template;
367: if (descrString.endsWith(DrlDumper.eol)) {
368: descrString = descrString.substring(0, descrString
369: .indexOf(DrlDumper.eol));
370: }
371: descrString += " || ";
372: }
373: return descrString.substring(0, descrString.length() - 4);
374: }
375:
376: private String processColoumnConstraintList(final List descr) {
377: String descrString = "";
378: Object previous = null;
379: for (final Iterator iterator = descr.iterator(); iterator
380: .hasNext();) {
381:
382: final Object temp = iterator.next();
383: visit(temp);
384:
385: if (previous == null) {
386: descrString += this .template;
387: } else if (previous instanceof FieldBindingDescr
388: && !(temp instanceof FieldBindingDescr)
389: && !(temp instanceof PredicateDescr)) {
390: final FieldConstraintDescr tempDescr = (FieldConstraintDescr) temp;
391: final FieldBindingDescr previousDescr = (FieldBindingDescr) previous;
392: if (tempDescr.getFieldName().equals(
393: previousDescr.getFieldName())) {
394: // as its a binding followed by a field constraint we need to remove
395: // the extra field name
396: descrString += this .template.substring(tempDescr
397: .getFieldName().length() + 1);
398: } else {
399: descrString += " , " + this .template;
400: }
401: } else {
402: descrString += " , " + this .template;
403: }
404:
405: previous = temp;
406:
407: }
408: return descrString.substring(0, descrString.length());
409: }
410:
411: private String processFieldConstraint(
412: final RestrictionConnectiveDescr restriction,
413: boolean addBrackets) {
414: String descrString = "";
415: String connective = "";
416: boolean bracketTmp = this .needsBracket;
417: this .needsBracket = restriction.getRestrictions().size() > 1;
418:
419: if (restriction.getConnective() == RestrictionConnectiveDescr.OR) {
420: connective = " || ";
421: } else {
422: connective = " && ";
423: }
424: if (addBrackets && bracketTmp) {
425: descrString += "( ";
426: }
427: for (final Iterator it = restriction.getRestrictions()
428: .iterator(); it.hasNext();) {
429: final Object temp = it.next();
430: visit(temp);
431: descrString += this .template;
432: if (it.hasNext()) {
433: descrString += connective;
434: }
435: }
436: if (addBrackets && bracketTmp) {
437: descrString += " )";
438: }
439: this .needsBracket = bracketTmp;
440: return descrString;
441: }
442:
443: private String processDescrList(final List descr) {
444: String descrString = "";
445: for (final Iterator ite = descr.iterator(); ite.hasNext();) {
446:
447: Object obj = ite.next();
448:
449: visit(obj);
450: descrString += this .template;
451:
452: if (obj.getClass().equals(PatternDescr.class)
453: || obj.getClass().equals(CollectDescr.class)) {
454: descrString += DrlDumper.eol;
455: } else if (ite.hasNext()) {
456: descrString += " && ";
457: }
458: }
459: return descrString;
460: }
461:
462: private String processFunctionsList(final List functions) {
463: String functionList = "";
464:
465: for (final Iterator it = functions.iterator(); it.hasNext();) {
466: visit(it.next());
467: functionList += this .template;
468: }
469:
470: return functionList + DrlDumper.eol;
471: }
472:
473: private String processAttribute(final List attributes) {
474:
475: String attributeList = "";
476: for (final Iterator it = attributes.iterator(); it.hasNext();) {
477: final AttributeDescr attributeDescr = (AttributeDescr) it
478: .next();
479: visit(attributeDescr);
480: attributeList += this .template;
481: }
482: return attributeList;
483: }
484:
485: private String processParameters(final List parameterNames,
486: final List parameterTypes) {
487: if (parameterNames.isEmpty()) {
488: return "";
489: }
490:
491: String paramList = "";
492: int i = 0;
493: for (final Iterator it = parameterNames.iterator(); it
494: .hasNext(); i++) {
495: final String paramName = (String) it.next();
496: final String paramType = (String) parameterTypes.get(i);
497: final String paramTemplate = paramType + " " + paramName
498: + ",";
499: paramList += paramTemplate;
500: }
501: paramList = paramList.substring(0, paramList.length() - 1);
502: return paramList;
503: }
504:
505: private String processGlobalsList(final List globals) {
506: String globalList = "";
507:
508: for (final Iterator it = globals.iterator(); it.hasNext();) {
509: final GlobalDescr global = (GlobalDescr) it.next();
510: final String identifier = global.getIdentifier();
511: final String type = global.getType();
512: final String globalTemplate = "global " + type + " "
513: + identifier + ";" + DrlDumper.eol;
514: globalList += globalTemplate;
515: }
516:
517: return globalList + DrlDumper.eol;
518: }
519:
520: private String processImportsList(final List imports) {
521: String importList = "";
522:
523: for (final Iterator it = imports.iterator(); it.hasNext();) {
524: final String importString = ((ImportDescr) it.next())
525: .getTarget();
526: final String importTemplate = "import " + importString
527: + ";" + DrlDumper.eol;
528: importList += importTemplate;
529: }
530: return importList + DrlDumper.eol;
531: }
532:
533: private void appendDrlDump(final String temp) {
534: this.drlDump.append(temp);
535: }
536:
537: }
|