001: package org.drools.rule;
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.util.ArrayList;
020: import java.util.Collections;
021: import java.util.HashMap;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Map;
025:
026: import org.drools.spi.PatternExtractor;
027: import org.drools.spi.Constraint;
028: import org.drools.spi.Extractor;
029: import org.drools.spi.ObjectType;
030:
031: public class Pattern implements RuleConditionElement {
032: /**
033: *
034: */
035: private static final long serialVersionUID = 400L;
036: private final ObjectType objectType;
037: private List constraints = Collections.EMPTY_LIST;
038: final Declaration declaration;
039: private Map declarations;
040: private final int index;
041: private PatternSource source;
042:
043: // this is the offset of the related fact inside a tuple. i.e:
044: // the position of the related fact inside the tuple;
045: private int offset;
046:
047: public Pattern(final int index, final ObjectType objectType) {
048: this (index, index, objectType, null);
049: }
050:
051: public Pattern(final int index, final ObjectType objectType,
052: final String identifier) {
053: this (index, index, objectType, identifier);
054: }
055:
056: public Pattern(final int index, final int offset,
057: final ObjectType objectType, final String identifier) {
058: this (index, offset, objectType, identifier, false);
059: }
060:
061: public Pattern(final int index, final int offset,
062: final ObjectType objectType, final String identifier,
063: final boolean isInternalFact) {
064: this .index = index;
065: this .offset = offset;
066: this .objectType = objectType;
067: if (identifier != null && (!identifier.equals(""))) {
068: this .declaration = new Declaration(identifier,
069: new PatternExtractor(objectType), this ,
070: isInternalFact);
071: this .declarations = new HashMap(2); // default to avoid immediate resize
072: this .declarations.put(this .declaration.getIdentifier(),
073: this .declaration);
074: } else {
075: this .declaration = null;
076: }
077: }
078:
079: public Object clone() {
080: final String identifier = (this .declaration != null) ? this .declaration
081: .getIdentifier()
082: : null;
083: final Pattern clone = new Pattern(this .index, this .objectType,
084: identifier);
085:
086: for (final Iterator it = this .constraints.iterator(); it
087: .hasNext();) {
088: final Object constr = it.next();
089: if (constr instanceof Declaration) {
090: final Declaration decl = (Declaration) constr;
091: clone.addDeclaration(decl.getIdentifier(), decl
092: .getExtractor());
093: } else {
094: clone.addConstraint((Constraint) constr);
095: }
096: }
097: return clone;
098: }
099:
100: public ObjectType getObjectType() {
101: return this .objectType;
102: }
103:
104: public PatternSource getSource() {
105: return source;
106: }
107:
108: public void setSource(PatternSource source) {
109: this .source = source;
110: }
111:
112: public List getConstraints() {
113: return Collections.unmodifiableList(this .constraints);
114: }
115:
116: public void addConstraint(final Constraint constraint) {
117: if (this .constraints == Collections.EMPTY_LIST) {
118: this .constraints = new ArrayList(1);
119: }
120: this .constraints.add(constraint);
121: }
122:
123: public Declaration addDeclaration(final String identifier,
124: final Extractor extractor) {
125: if (this .constraints == Collections.EMPTY_LIST) {
126: this .constraints = new ArrayList(1);
127: }
128: final Declaration declaration = new Declaration(identifier,
129: extractor, this );
130: this .constraints.add(declaration);
131: if (this .declarations == null) {
132: this .declarations = new HashMap(2); // default to avoid immediate resize
133: }
134: this .declarations.put(declaration.getIdentifier(), declaration);
135: return declaration;
136:
137: }
138:
139: public boolean isBound() {
140: return (this .declaration != null);
141: }
142:
143: public Declaration getDeclaration() {
144: return this .declaration;
145: }
146:
147: public int getIndex() {
148: return this .index;
149: }
150:
151: /**
152: * The offset of the fact related to this pattern
153: * inside the tuple
154: *
155: * @return the offset
156: */
157: public int getOffset() {
158: return this .offset;
159: }
160:
161: public void setOffset(final int offset) {
162: this .offset = offset;
163: }
164:
165: public Map getInnerDeclarations() {
166: return (this .declarations != null) ? this .declarations
167: : Collections.EMPTY_MAP;
168: }
169:
170: public Map getOuterDeclarations() {
171: return (this .declarations != null) ? this .declarations
172: : Collections.EMPTY_MAP;
173: }
174:
175: public Declaration resolveDeclaration(final String identifier) {
176: return (this .declarations != null) ? (Declaration) this .declarations
177: .get(identifier)
178: : null;
179: }
180:
181: public String toString() {
182: return "Pattern type='"
183: + ((this .objectType == null) ? "null" : this .objectType
184: .toString())
185: + "', index='"
186: + this .index
187: + "', offset='"
188: + this .getOffset()
189: + "', identifer='"
190: + ((this .declaration == null) ? "" : this .declaration
191: .toString()) + "'";
192: }
193:
194: public int hashCode() {
195: final int PRIME = 31;
196: int result = 1;
197: result = PRIME * result + this .constraints.hashCode();
198: result = PRIME
199: * result
200: + ((this .declaration == null) ? 0 : this .declaration
201: .hashCode());
202: result = PRIME * result + this .index;
203: result = PRIME
204: * result
205: + ((this .objectType == null) ? 0 : this .objectType
206: .hashCode());
207: result = PRIME * result + this .offset;
208: result = PRIME * result
209: + ((this .source == null) ? 0 : this .source.hashCode());
210: return result;
211: }
212:
213: public boolean equals(final Object object) {
214: if (this == object) {
215: return true;
216: }
217:
218: if (object == null || getClass() != object.getClass()) {
219: return false;
220: }
221:
222: final Pattern other = (Pattern) object;
223:
224: if (!this .constraints.equals(other.constraints)) {
225: return false;
226: }
227:
228: if (this .declaration == null) {
229: if (other.declaration != null) {
230: return false;
231: }
232: } else if (!this .declaration.equals(other.declaration)) {
233: return false;
234: }
235:
236: if (this .index != other.index) {
237: return false;
238: }
239:
240: if (!this .objectType.equals(other.objectType)) {
241: return false;
242: }
243: if (this .offset != other.offset) {
244: return false;
245: }
246: return (this.source == null) ? other.source == null
247: : this.source.equals(other.source);
248: }
249:
250: }
|