001: package org.drools.spi;
002:
003: import java.util.HashMap;
004: import java.util.Map;
005: import java.util.Stack;
006:
007: import org.drools.rule.Pattern;
008: import org.drools.rule.Declaration;
009: import org.drools.rule.GroupElement;
010: import org.drools.rule.RuleConditionElement;
011:
012: /**
013: * A class capable of resolving a declaration in the current build context
014: *
015: * @author etirelli
016: */
017: public class DeclarationScopeResolver {
018: private static final Stack EMPTY_STACK = new Stack();
019: private Map[] maps;
020: private Stack buildStack;
021:
022: public DeclarationScopeResolver(final Map[] maps) {
023: this (maps, EMPTY_STACK);
024: }
025:
026: public DeclarationScopeResolver(final Map[] maps,
027: final Stack buildStack) {
028: this .maps = maps;
029: if (buildStack == null) {
030: this .buildStack = EMPTY_STACK;
031: } else {
032: this .buildStack = buildStack;
033: }
034: }
035:
036: public Class getType(final String name) {
037: for (int i = this .buildStack.size() - 1; i >= 0; i--) {
038: final Declaration declaration = (Declaration) ((RuleConditionElement) this .buildStack
039: .get(i)).getInnerDeclarations().get(name);
040: if (declaration != null) {
041: return declaration.getExtractor().getExtractToClass();
042: }
043: }
044: for (int i = 0, length = this .maps.length; i < length; i++) {
045: final Object object = this .maps[i].get(name);
046: if (object != null) {
047: if (object instanceof Declaration) {
048: return ((Declaration) object).getExtractor()
049: .getExtractToClass();
050: } else {
051: return (Class) object;
052: }
053: }
054: }
055: return null;
056: }
057:
058: public Declaration getDeclaration(final String name) {
059: // it may be a local bound variable
060: for (int i = this .buildStack.size() - 1; i >= 0; i--) {
061: final Declaration declaration = (Declaration) ((RuleConditionElement) this .buildStack
062: .get(i)).getInnerDeclarations().get(name);
063: if (declaration != null) {
064: return declaration;
065: }
066: }
067: // it may be a global or something
068: for (int i = 0, length = this .maps.length; i < length; i++) {
069: if (this .maps[i].containsKey((name))) {
070: final GlobalExtractor global = new GlobalExtractor(
071: name, this .maps[i]);
072: final Pattern dummy = new Pattern(0, global
073: .getObjectType());
074: final Declaration declaration = new Declaration(name,
075: global, dummy);
076: return declaration;
077: }
078: }
079: return null;
080: }
081:
082: public boolean available(final String name) {
083: for (int i = this .buildStack.size() - 1; i >= 0; i--) {
084: final Declaration declaration = (Declaration) ((RuleConditionElement) this .buildStack
085: .get(i)).getInnerDeclarations().get(name);
086: if (declaration != null) {
087: return true;
088: }
089: }
090: for (int i = 0, length = this .maps.length; i < length; i++) {
091: if (this .maps[i].containsKey((name))) {
092: return true;
093: }
094: }
095: return false;
096: }
097:
098: public boolean isDuplicated(final String name) {
099: for (int i = 0, length = this .maps.length; i < length; i++) {
100: if (this .maps[i].containsKey((name))) {
101: return true;
102: }
103: }
104: for (int i = this .buildStack.size() - 1; i >= 0; i--) {
105: final RuleConditionElement rce = (RuleConditionElement) this .buildStack
106: .get(i);
107: final Declaration declaration = (Declaration) rce
108: .getInnerDeclarations().get(name);
109: if (declaration != null) {
110: if ((rce instanceof GroupElement)
111: && ((GroupElement) rce).isOr()) {
112: // if it is an OR and it is duplicated, we can stop looking for duplication now
113: // as it is a separate logical branch
114: return false;
115: }
116: return true;
117: }
118: }
119: return false;
120: }
121:
122: /**
123: * Return all declarations scoped to the current
124: * RuleConditionElement in the build stack
125: *
126: * @return
127: */
128: public Map getDeclarations() {
129: final Map declarations = new HashMap();
130: for (int i = 0; i < this .buildStack.size(); i++) {
131: // this may be optimized in the future to only re-add elements at
132: // scope breaks, like "NOT" and "EXISTS"
133: declarations.putAll(((RuleConditionElement) this.buildStack
134: .get(i)).getInnerDeclarations());
135: }
136: return declarations;
137: }
138: }
|