001: package org.drools.decisiontable.model;
002:
003: /*
004: * Copyright 2005 JBoss Inc
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.io.UnsupportedEncodingException;
020: import java.util.Iterator;
021: import java.util.LinkedList;
022: import java.util.List;
023:
024: /**
025: * @author <a href="mailto:michael.neale@gmail.com"> Michael Neale </a>
026: *
027: * Represents a rule.
028: */
029: public class Rule extends DRLElement implements DRLJavaEmitter {
030:
031: private static final int MAX_ROWS = 65535;
032:
033: private Integer _salience; // Integer as it may be null
034:
035: private String _name;
036:
037: private Duration _duration; // RIK: New variable to the Rule class (Defines
038: // a Duration tag for the rule)
039:
040: private String _description; // RIK: New variable to the Rule class (Set
041: // the description parameter of the rule
042: // tag)
043:
044: private String _noLoop; // RIK: New variable to the Rule class (Set the
045: // no-loop parameter of the rule tag)
046:
047: private String _activationGroup; // RIK: New variable to the Rule class (Set the
048: // activation-group parameter of the rule tag)
049:
050: private String _ruleFlowGroup;
051:
052: private String _agendaGroup; // SJW: New variable to the Rule class (Set the
053: // agenda-group parameter of the rule tag
054:
055: private List _lhs;
056:
057: private List _rhs;
058:
059: private int _spreadsheetRow;
060:
061: /**
062: * Create a new rule. Note that the rule name should be post-fixed with the row number,
063: * as one way of providing tracability for errors back to the originating spreadsheet.
064: * @param name The name of the rule. This may be used to calculate DRL row error
065: * to Spreadsheet row error (just need to keep track of output lines, and map spreadsheetRow to a start
066: * and end range in the rendered output).
067: * @param salience
068: * @param spreadsheetRow The phyical row number from the spreadsheet.
069: */
070: public Rule(final String name, final Integer salience,
071: final int spreadsheetRow) {
072: this ._name = name;
073: this ._salience = salience;
074: this ._description = "";
075:
076: this ._lhs = new LinkedList();
077: this ._rhs = new LinkedList();
078: this ._spreadsheetRow = spreadsheetRow;
079: }
080:
081: public void addCondition(final Condition con) {
082: this ._lhs.add(con);
083: }
084:
085: public void addConsequence(final Consequence con) {
086: this ._rhs.add(con);
087: }
088:
089: public void renderDRL(final DRLOutput out) {
090: if (isCommented()) {
091: out.writeLine("#" + getComment());
092: }
093: out.writeLine("rule " + "\"" + this ._name + "\"");
094: if (this ._description != null) {
095: out.writeLine("\t" + this ._description);
096: }
097: if (this ._salience != null) {
098: out.writeLine("\tsalience " + this ._salience);
099: }
100: if (this ._activationGroup != null) {
101: out.writeLine("\tactivation-group \""
102: + this ._activationGroup + "\"");
103: }
104: if (this ._agendaGroup != null) {
105: out.writeLine("\tagenda-group " + this ._agendaGroup);
106: }
107: if (this ._noLoop != null) {
108: out.writeLine("\tno-loop " + this ._noLoop);
109: }
110: if (this ._duration != null) {
111: out.writeLine("\tduration " + this ._duration);
112: }
113:
114: if (this ._ruleFlowGroup != null) {
115: out.writeLine("\truleflow-group \"" + this ._ruleFlowGroup
116: + "\"");
117: }
118:
119: out.writeLine("\twhen");
120: renderDRL(this ._lhs, out);
121: out.writeLine("\tthen");
122: renderDRL(this ._rhs, out);
123:
124: out.writeLine("end\n");
125: }
126:
127: private void renderDRL(final List list, final DRLOutput out) {
128: for (final Iterator iter = list.iterator(); iter.hasNext();) {
129: final DRLJavaEmitter item = (DRLJavaEmitter) iter.next();
130: item.renderDRL(out);
131: }
132: }
133:
134: public static int calcSalience(final int rowNumber) {
135: if (rowNumber > Rule.MAX_ROWS) {
136: throw new IllegalArgumentException(
137: "That row number is above the max: "
138: + Rule.MAX_ROWS);
139: }
140: return Rule.MAX_ROWS - rowNumber;
141: }
142:
143: /**
144: * @param col -
145: * the column number. Start with zero.
146: * @return The spreadsheet name for this col number, such as "AA" or "AB" or
147: * "A" and such and such.
148: */
149: public static String convertColNumToColName(final int i) {
150:
151: String result;
152: final int div = i / 26;
153: final int mod = i % 26;
154:
155: if (div == 0) {
156: final byte[] c = new byte[1];
157: c[0] = (byte) (mod + 65);
158: result = byteToString(c);
159: } else {
160: final byte[] firstChar = new byte[1];
161: firstChar[0] = (byte) ((div - 1) + 65);
162:
163: final byte[] secondChar = new byte[1];
164: secondChar[0] = (byte) (mod + 65);
165: final String first = byteToString(firstChar);
166: final String second = byteToString(secondChar);
167: result = first + second;
168: }
169: return result;
170:
171: }
172:
173: private static String byteToString(final byte[] secondChar) {
174: try {
175: return new String(secondChar, "UTF-8");
176: } catch (final UnsupportedEncodingException e) {
177: throw new RuntimeException(
178: "Unable to convert char to string.", e);
179: }
180: }
181:
182: public List getConditions() {
183: return this ._lhs;
184: }
185:
186: public List getConsequences() {
187: return this ._rhs;
188: }
189:
190: public void setSalience(final Integer value) // Set the salience of the rule
191: {
192: this ._salience = value;
193: }
194:
195: public Integer getSalience() {
196: return this ._salience;
197: }
198:
199: public void setName(final String value) // Set the name of the rule
200: {
201: this ._name = value;
202: }
203:
204: public String getName() {
205: return this ._name;
206: }
207:
208: public void setDescription(final String value) // Set the description of the
209: // rule
210: {
211: this ._description = value;
212: }
213:
214: public void appendDescription(final String value) // Set the description of the
215: // rule
216: {
217: this ._description += value;
218: }
219:
220: public String getDescription() {
221: return this ._description;
222: }
223:
224: public void setDuration(final Duration value) // Set the duration of the rule
225: {
226: this ._duration = value;
227: }
228:
229: public String getDuration() {
230: return this ._duration.getSnippet();
231: }
232:
233: public void setActivationGroup(final String value) // Set the duration of the rule
234: {
235: this ._activationGroup = value;
236: }
237:
238: public void setRuleFlowGroup(final String value) {
239: this ._ruleFlowGroup = value;
240: }
241:
242: public String getRuleFlowGroup() {
243: return this ._ruleFlowGroup;
244: }
245:
246: public String getActivationGroup() {
247: return this ._activationGroup;
248: }
249:
250: public String getAgendaGroup() {
251: return _agendaGroup;
252: }
253:
254: public void setAgendaGroup(String group) // Set the agenda-group of the rule
255: {
256: _agendaGroup = group;
257: }
258:
259: public void setNoLoop(final String value) // Set the no-loop attribute of the rule
260: {
261: this ._noLoop = value;
262: }
263:
264: /**
265: * @return The row in the spreadsheet this represents.
266: * This can be handy when mapping a line error from Parser back to the rule row.
267: * Will need to have a map of ranges of line numbers that each rule covers.
268: * Then can find out the rule that cause it, and this will give the row number to report.
269: */
270: public int getSpreadsheetRowNumber() {
271: return this._spreadsheetRow;
272: }
273:
274: }
|