001: package org.drools.brms.client.modeldriven;
002:
003: import java.util.HashMap;
004: import java.util.Iterator;
005: import java.util.Map;
006: import java.util.Set;
007:
008: import org.drools.brms.client.modeldriven.brl.DSLSentence;
009: import org.drools.brms.client.modeldriven.brl.PortableObject;
010:
011: /**
012: * An suggestion completion processor. This should be usable in both GWT/Web and the IDE.
013: * The data for this can be loaded into this from simple string lists.
014: *
015: * @author Michael Neale
016: */
017: public class SuggestionCompletionEngine implements PortableObject {
018:
019: /** These are the explicit types supported */
020: public static final String TYPE_COLLECTION = "Collection";
021: public static final String TYPE_COMPARABLE = "Comparable";
022: public static final String TYPE_STRING = "String";
023: public static final String TYPE_NUMERIC = "Numeric";
024:
025: /**
026: * The operators that are used at different times (based on type).
027: */
028: private static final String[] STANDARD_CONNECTIVES = new String[] {
029: "|| ==", "|| !=", "&& !=" };
030: private static final String[] STRING_CONNECTIVES = new String[] {
031: "|| ==", "|| !=", "&& !=", "&& matches", "|| matches" };
032: private static final String[] COMPARABLE_CONNECTIVES = new String[] {
033: "|| ==", "|| !=", "&& !=", "&& >", "&& <", "|| >", "|| <",
034: "&& >=", "&& <=", "|| <=", "|| >=" };
035: private static final String[] COLLECTION_CONNECTIVES = new String[] {
036: "|| ==", "|| !=", "&& !=", "|| contains", "&& contains",
037: "|| excludes", "&& excludes" };
038:
039: private static final String[] STANDARD_OPERATORS = new String[] {
040: "==", "!=" };
041: private static final String[] COMPARABLE_OPERATORS = new String[] {
042: "==", "!=", "<", ">", "<=", ">=" };
043: private static final String[] STRING_OPERATORS = new String[] {
044: "==", "!=", "matches" };
045: private static final String[] COLLECTION_OPERATORS = new String[] {
046: "contains", "excludes", "==", "!=" };
047:
048: /** The top level conditional elements (first order logic) */
049: private static final String[] CONDITIONAL_ELEMENTS = new String[] {
050: "not", "exists", "or" };
051:
052: /**
053: * A list of fact types (never fully qualified).
054: */
055: public String[] factTypes;
056:
057: /**
058: * A map of types to the fields. key is type, value is (String[] of fields)
059: *
060: * @gwt.typeArgs <java.lang.String, java.lang.String[]>
061: */
062: public Map fieldsForType;
063:
064: /**
065: * A map of the Fields to their types, needed for operator completions,
066: * as well as other things like rendering strings, dates etc.
067: * This is in the format of: { 'Type.field' => 'typename' }.
068: * Should not be the exact type, perhaps just a high level interface, eg "Comparable".
069: *
070: * @gwt.typeArgs <java.lang.String, java.lang.String>
071: */
072: public Map fieldTypes;
073:
074: /**
075: * Contains a map of globals (name is key) and their type (value).
076: * @gwt.typeArgs <java.lang.String, java.lang.String>
077: */
078: public Map globalTypes = new HashMap();
079:
080: /**
081: * Contains a map of { TypeName.field : String[] } - where a list is
082: * valid values to display in a drop down for a given Type.field combination.
083: * @gwt.typeArgs <java.lang.String, java.lang.String[]>
084: */
085: public Map dataEnumLists = new HashMap();
086:
087: /** Operators (from the grammar):
088: * op=( '=='
089: | '>'
090: | '>='
091: | '<'
092: | '<='
093: | '!='
094: | 'contains'
095: | 'matches'
096: | 'excludes'
097: )
098: * Connectives add "&" and "|" to this.
099: */
100:
101: /**
102: * DSL language extensions, if needed, if provided by the package.
103: */
104: public DSLSentence[] conditionDSLSentences = new DSLSentence[0];
105: public DSLSentence[] actionDSLSentences = new DSLSentence[0];
106:
107: // /**
108: // * For bulk loading up the data (from a previous rule save)
109: // *
110: // * @param factToFields A map of "FactType" (key - String) to String[] (value)
111: // * @param factFieldToOperator A map of "FactType.field" (key - String) to String[] operators
112: // * @param factFieldToConnectiveOperator A map of "FactType.field" (key -String) to String[] operators
113: // * that are valid CONNECTIVE operators.
114: // *
115: // * @param globals A map of global variable name to its fields (String[]).
116: // * @param boundFacts A map of bound facts to types.
117: // * @param conditionDSLs a list of DSLSentence suggestions for the LHS
118: // * @param actionDSLs a list of DSLSentence suggestions for the RHS
119: // *
120: // */
121: // public void load(
122: // Map factToFields,
123: // Map factFieldToOperator,
124: // Map factFieldToConnectiveOperator,
125: // Map globals,
126: // List conditionDSLs,
127: // List actionDSLs
128: // ) {
129: // this.factToFields = factToFields;
130: // this.factFieldToOperator = factFieldToOperator;
131: // this.factFieldToConnectiveOperator = factFieldToConnectiveOperator;
132: // this.actionDSLSentences = actionDSLs;
133: // this.conditionDSLSentences = conditionDSLs;
134: // this.globals = globals;
135: //
136: // }
137:
138: public SuggestionCompletionEngine() {
139:
140: }
141:
142: public String[] getConditionalElements() {
143: return CONDITIONAL_ELEMENTS;
144: }
145:
146: public DSLSentence[] getDSLConditions() {
147: return this .conditionDSLSentences;
148: }
149:
150: public DSLSentence[] getDSLActions() {
151: return this .actionDSLSentences;
152: }
153:
154: public String[] getConnectiveOperatorCompletions(
155: final String factType, final String fieldName) {
156: final String type = (String) this .fieldTypes.get(factType + "."
157: + fieldName);
158: if (type == null) {
159: return STANDARD_CONNECTIVES;
160: } else if (type.equals(TYPE_STRING)) {
161: return STRING_CONNECTIVES;
162: } else if (type.equals(TYPE_COMPARABLE)
163: || type.equals(TYPE_NUMERIC)) {
164: return COMPARABLE_CONNECTIVES;
165: } else if (type.equals(TYPE_COLLECTION)) {
166: return COLLECTION_CONNECTIVES;
167: } else {
168: return STANDARD_CONNECTIVES;
169: }
170:
171: }
172:
173: public String[] getFactTypes() {
174: return this .factTypes;
175: }
176:
177: public String[] getFieldCompletions(final String factType) {
178: return (String[]) this .fieldsForType.get(factType);
179:
180: }
181:
182: public String[] getOperatorCompletions(final String factType,
183: final String fieldName) {
184: final String type = (String) this .fieldTypes.get(factType + "."
185: + fieldName);
186: if (type == null) {
187: return STANDARD_OPERATORS;
188: } else if (type.equals(TYPE_STRING)) {
189: return STRING_OPERATORS;
190: } else if (type.equals(TYPE_COMPARABLE)
191: || type.equals(TYPE_NUMERIC)) {
192: return COMPARABLE_OPERATORS;
193: } else if (type.equals(TYPE_COLLECTION)) {
194: return COLLECTION_OPERATORS;
195: } else {
196: return STANDARD_OPERATORS;
197: }
198:
199: }
200:
201: public String getFieldType(final String factType,
202: final String fieldName) {
203: return (String) this .fieldTypes.get(factType + "." + fieldName);
204: }
205:
206: public boolean isGlobalVariable(final String variable) {
207: return this .globalTypes.containsKey(variable);
208: }
209:
210: public String[] getFieldCompletionsForGlobalVariable(
211: final String varName) {
212: final String type = (String) this .globalTypes.get(varName);
213: return (String[]) this .fieldsForType.get(type);
214: }
215:
216: private String[] toStringArray(final Set set) {
217: final String[] f = new String[set.size()];
218: int i = 0;
219: for (final Iterator iter = set.iterator(); iter.hasNext();) {
220: f[i] = (String) iter.next();
221: i++;
222: }
223: return f;
224: }
225:
226: public String[] getGlobalVariables() {
227: return toStringArray(this.globalTypes.keySet());
228: }
229:
230: }
|