001: package org.drools.brms.client.modeldriven.brl;
002:
003: import java.util.ArrayList;
004: import java.util.List;
005:
006: public class RuleModel implements PortableObject {
007:
008: /**
009: * This name is generally not used - the asset name or the
010: * file name is preferred (ie it could get out of sync with the name of the file it is in).
011: */
012: public String name;
013: public String modelVersion = "1.0";
014:
015: public RuleAttribute[] attributes = new RuleAttribute[0];
016:
017: public IPattern[] lhs = new IPattern[0];
018: public IAction[] rhs = new IAction[0];
019:
020: /**
021: * This will return the fact pattern that a variable is bound to.
022: *
023: * @param var The bound fact variable (NOT bound field).
024: * @return null or the FactPattern found.
025: */
026: public FactPattern getBoundFact(final String var) {
027: if (this .lhs == null) {
028: return null;
029: }
030: for (int i = 0; i < this .lhs.length; i++) {
031:
032: if (this .lhs[i] instanceof FactPattern) {
033: final FactPattern p = (FactPattern) this .lhs[i];
034: if (p.boundName != null && var.equals(p.boundName)) {
035: return p;
036: }
037: }
038: }
039: return null;
040: }
041:
042: /**
043: * @return A list of bound facts (String). Or empty list if none are found.
044: */
045: public List getBoundFacts() {
046: if (this .lhs == null) {
047: return null;
048: }
049: final List list = new ArrayList();
050: for (int i = 0; i < this .lhs.length; i++) {
051: if (this .lhs[i] instanceof FactPattern) {
052: final FactPattern p = (FactPattern) this .lhs[i];
053: if (p.boundName != null) {
054: list.add(p.boundName);
055: }
056: }
057: }
058: return list;
059:
060: }
061:
062: /**
063: *
064: * @param idx Remove this index from the LHS.
065: * @param Returns false if it was NOT allowed to remove this item (ie
066: * it is used on the RHS).
067: */
068: public boolean removeLhsItem(final int idx) {
069:
070: final IPattern[] newList = new IPattern[this .lhs.length - 1];
071: int newIdx = 0;
072: for (int i = 0; i < this .lhs.length; i++) {
073:
074: if (i != idx) {
075: newList[newIdx] = this .lhs[i];
076: newIdx++;
077: } else {
078: if (this .lhs[i] instanceof FactPattern) {
079: final FactPattern p = (FactPattern) this .lhs[i];
080: if (p.boundName != null
081: && isBoundFactUsed(p.boundName)) {
082: return false;
083: }
084: }
085:
086: }
087:
088: }
089: this .lhs = newList;
090: return true;
091: }
092:
093: /**
094: * @param binding The name of the LHS fact binding.
095: * @return Returns true if the specified binding is used on the RHS.
096: */
097: public boolean isBoundFactUsed(final String binding) {
098: if (this .rhs == null) {
099: return false;
100: }
101: for (int i = 0; i < this .rhs.length; i++) {
102: if (this .rhs[i] instanceof ActionSetField) {
103: final ActionSetField set = (ActionSetField) this .rhs[i];
104: if (set.variable.equals(binding)) {
105: return true;
106: }
107: } else if (this .rhs[i] instanceof ActionRetractFact) {
108: final ActionRetractFact ret = (ActionRetractFact) this .rhs[i];
109: if (ret.variableName.equals(binding)) {
110: return true;
111: }
112: }
113: }
114: return false;
115: }
116:
117: public void addLhsItem(final IPattern pat) {
118: if (this .lhs == null) {
119: this .lhs = new IPattern[0];
120: }
121:
122: final IPattern[] list = this .lhs;
123: final IPattern[] newList = new IPattern[list.length + 1];
124:
125: for (int i = 0; i < list.length; i++) {
126: newList[i] = list[i];
127: }
128: newList[list.length] = pat;
129:
130: this .lhs = newList;
131: }
132:
133: public void addRhsItem(final IAction action) {
134: if (this .rhs == null) {
135: this .rhs = new IAction[0];
136: }
137:
138: final IAction[] list = this .rhs;
139: final IAction[] newList = new IAction[list.length + 1];
140:
141: for (int i = 0; i < list.length; i++) {
142: newList[i] = list[i];
143: }
144: newList[list.length] = action;
145:
146: this .rhs = newList;
147: }
148:
149: public void removeRhsItem(final int idx) {
150: final IAction[] newList = new IAction[this .rhs.length - 1];
151: int newIdx = 0;
152: for (int i = 0; i < this .rhs.length; i++) {
153:
154: if (i != idx) {
155: newList[newIdx] = this .rhs[i];
156: newIdx++;
157: }
158:
159: }
160: this .rhs = newList;
161: }
162:
163: public void addAttribute(final RuleAttribute attribute) {
164:
165: final RuleAttribute[] list = this .attributes;
166: final RuleAttribute[] newList = new RuleAttribute[list.length + 1];
167:
168: for (int i = 0; i < list.length; i++) {
169: newList[i] = list[i];
170: }
171: newList[list.length] = attribute;
172:
173: this .attributes = newList;
174:
175: }
176:
177: public void removeAttribute(final int idx) {
178: final RuleAttribute[] newList = new RuleAttribute[this .attributes.length - 1];
179: int newIdx = 0;
180: for (int i = 0; i < this .attributes.length; i++) {
181:
182: if (i != idx) {
183: newList[newIdx] = this .attributes[i];
184: newIdx++;
185: }
186:
187: }
188: this .attributes = newList;
189:
190: }
191:
192: /**
193: * This uses a deceptively simple algorithm to determine
194: * what bound variables are in scope for a given constraint (including connectives).
195: * Does not take into account globals.
196: */
197: public List getBoundVariablesInScope(
198: final ISingleFieldConstraint con) {
199: final List result = new ArrayList();
200: for (int i = 0; i < this .lhs.length; i++) {
201: final IPattern pat = this .lhs[i];
202: if (pat instanceof FactPattern) {
203: final FactPattern fact = (FactPattern) pat;
204:
205: if (fact.constraintList != null) {
206: final FieldConstraint[] cons = fact.constraintList.constraints;
207: if (cons != null) {
208: for (int k = 0; k < cons.length; k++) {
209: FieldConstraint fc = cons[k];
210: if (fc instanceof SingleFieldConstraint) {
211: final SingleFieldConstraint c = (SingleFieldConstraint) fc;
212: if (c == con) {
213: return result;
214: }
215: if (c.connectives != null) {
216: for (int j = 0; j < c.connectives.length; j++) {
217: if (con == c.connectives[j]) {
218: return result;
219: }
220: }
221: }
222: if (c.isBound()) {
223: result.add(c.fieldBinding);
224: }
225: }
226: }
227: }
228: if (fact.isBound()) {
229: result.add(fact.boundName);
230: }
231: } else {
232: if (fact.isBound()) {
233: result.add(fact.boundName);
234: }
235: }
236:
237: }
238: }
239: return result;
240: }
241:
242: /**
243: * This will get a list of all bound variables, including bound fields.
244: */
245: public List getAllVariables() {
246: List result = new ArrayList();
247: for (int i = 0; i < this .lhs.length; i++) {
248: IPattern pat = this .lhs[i];
249: if (pat instanceof FactPattern) {
250: FactPattern fact = (FactPattern) pat;
251: if (fact.isBound()) {
252: result.add(fact.boundName);
253: }
254:
255: for (int j = 0; j < fact.getFieldConstraints().length; j++) {
256: FieldConstraint fc = fact.getFieldConstraints()[j];
257: if (fc instanceof SingleFieldConstraint) {
258: SingleFieldConstraint con = (SingleFieldConstraint) fc;
259: if (con.isBound()) {
260: result.add(con.fieldBinding);
261: }
262: }
263: }
264: }
265: }
266: return result;
267: }
268:
269: /**
270: * Checks to see if a variable is used or not, includes fields
271: * as well as facts.
272: */
273: public boolean isVariableNameUsed(String s) {
274: return getAllVariables().contains(s);
275: }
276:
277: /**
278: * Returns true if any DSLSentences are used.
279: */
280: public boolean hasDSLSentences() {
281:
282: if (this .lhs != null) {
283: for (int i = 0; i < this .lhs.length; i++) {
284: if (lhs[i] instanceof DSLSentence) {
285: return true;
286: }
287: }
288: }
289:
290: if (this .rhs != null) {
291: for (int i = 0; i < this .rhs.length; i++) {
292: if (rhs[i] instanceof DSLSentence) {
293: return true;
294: }
295: }
296: }
297:
298: return false;
299: }
300:
301: }
|