001: package org.drools.decisiontable.parser;
002:
003: import java.util.ArrayList;
004: import java.util.HashMap;
005: import java.util.HashSet;
006: import java.util.Iterator;
007: import java.util.List;
008: import java.util.Map;
009: import java.util.Set;
010:
011: import org.drools.decisiontable.model.SnippetBuilder;
012:
013: /**
014: * This utility will build up a list of constraints for a column.
015: * For instance, the column has been spanned across multiple cells, and the cells below
016: * contain the constraints.
017: * @author Michael Neale
018: *
019: */
020: public class LhsBuilder implements SourceBuilder {
021:
022: private String column;
023: private Map constraints;
024: private List values;
025: private boolean hasValues;
026: private static Set operators;
027:
028: static {
029: operators = new HashSet();
030: operators.add("==");
031: operators.add("=");
032: operators.add("!=");
033: operators.add("<");
034: operators.add(">");
035: operators.add("<=");
036: operators.add(">=");
037: operators.add("contains");
038: operators.add("matches");
039: }
040:
041: /**
042: * @param colDefinition The initial column definition that is shared via merged cells.
043: */
044: public LhsBuilder(String colDefinition) {
045: this .column = colDefinition == null ? "" : colDefinition;
046: this .constraints = new HashMap();
047: this .values = new ArrayList();
048: }
049:
050: public void addTemplate(int column, String content) {
051: Integer key = new Integer(column);
052: content = content.trim();
053: if (constraints.containsKey(key)) {
054: throw new IllegalArgumentException(
055: "Internal error: Can't have a constraint added twice to one spreadsheet col.");
056: }
057:
058: //we can wrap all values in quotes, it all works
059: FieldType fieldType = calcFieldType(content);
060: if (fieldType == FieldType.NORMAL_FIELD
061: || !isMultipleConstraints()) {
062: constraints.put(key, content);
063: } else if (fieldType == FieldType.SINGLE_FIELD) {
064: constraints.put(key, content + " == \"$param\"");
065: } else if (fieldType == FieldType.OPERATOR_FIELD) {
066: constraints.put(key, content + " \"$param\"");
067: }
068:
069: }
070:
071: public void clearValues() {
072: this .hasValues = false;
073: this .values.clear();
074: }
075:
076: public void addCellValue(int col, String value) {
077: this .hasValues = true;
078: Integer key = new Integer(col);
079: String content = (String) this .constraints.get(key);
080:
081: SnippetBuilder snip = new SnippetBuilder(content);
082: String result = snip.build(value);
083: this .values.add(result);
084:
085: }
086:
087: public String getResult() {
088: StringBuffer buf = new StringBuffer();
089: if (!isMultipleConstraints()) {
090: for (Iterator iter = values.iterator(); iter.hasNext();) {
091: String content = (String) iter.next();
092: buf.append(content);
093: if (iter.hasNext()) {
094: buf.append('\n');
095: }
096: }
097: return buf.toString();
098: } else {
099: buf.append(this .column);
100: buf.append('(');
101: for (Iterator iter = values.iterator(); iter.hasNext();) {
102: buf.append(iter.next());
103: if (iter.hasNext()) {
104: buf.append(", ");
105: }
106:
107: }
108: buf.append(')');
109: return buf.toString();
110: }
111: }
112:
113: /** Returns true if this is building up multiple constraints as in:
114: * Foo(a ==b, c == d) etc...
115: * If not, then it it really just like the "classic" style DTs.
116: */
117: boolean isMultipleConstraints() {
118: if ("".equals(column)) {
119: return false;
120: } else {
121: if (column.endsWith(")")) {
122: return false;
123: } else {
124: return true;
125: }
126: }
127: }
128:
129: /**
130: * Work out the type of "field" that is being specified,
131: * as in :
132: * age
133: * age <
134: * age == $param
135: *
136: * etc. as we treat them all differently.
137: */
138: public FieldType calcFieldType(String content) {
139: if (content.indexOf("$param") != -1
140: || content.indexOf("$1") != -1) {
141: return FieldType.NORMAL_FIELD;
142: }
143: for (Iterator iter = operators.iterator(); iter.hasNext();) {
144: String op = (String) iter.next();
145: if (content.endsWith(op)) {
146: return FieldType.OPERATOR_FIELD;
147: }
148: }
149: return FieldType.SINGLE_FIELD;
150: }
151:
152: static class FieldType {
153: public static final FieldType SINGLE_FIELD = new FieldType();
154: public static final FieldType OPERATOR_FIELD = new FieldType();
155: public static final FieldType NORMAL_FIELD = new FieldType();
156: }
157:
158: public boolean hasValues() {
159: return hasValues;
160:
161: }
162:
163: }
|