001: /*******************************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. 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,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *******************************************************************************/package org.ofbiz.widget.tree;
019:
020: import java.lang.reflect.Method;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.Map;
024:
025: import javolution.util.FastList;
026:
027: import org.ofbiz.base.util.Debug;
028: import org.ofbiz.base.util.GeneralException;
029: import org.ofbiz.base.util.ObjectType;
030: import org.ofbiz.base.util.UtilXml;
031: import org.ofbiz.base.util.collections.FlexibleMapAccessor;
032: import org.ofbiz.base.util.string.FlexibleStringExpander;
033: import org.ofbiz.entity.GenericValue;
034: import org.ofbiz.entityext.permission.EntityPermissionChecker;
035: import org.ofbiz.minilang.operation.BaseCompare;
036: import org.ofbiz.security.Security;
037:
038: import org.apache.oro.text.regex.MalformedPatternException;
039: import org.apache.oro.text.regex.Pattern;
040: import org.apache.oro.text.regex.PatternCompiler;
041: import org.apache.oro.text.regex.PatternMatcher;
042: import org.apache.oro.text.regex.Perl5Compiler;
043: import org.apache.oro.text.regex.Perl5Matcher;
044: import org.w3c.dom.Element;
045:
046: /**
047: * Widget Library - Screen model condition class
048: */
049: public class ModelTreeCondition {
050: public static final String module = ModelTreeCondition.class
051: .getName();
052:
053: protected ModelTree modelTree;
054: protected TreeCondition rootCondition;
055:
056: public ModelTreeCondition(ModelTree modelTree,
057: Element conditionElement) {
058: this .modelTree = modelTree;
059: Element firstChildElement = UtilXml
060: .firstChildElement(conditionElement);
061: this .rootCondition = readCondition(modelTree, firstChildElement);
062: }
063:
064: public boolean eval(Map context) {
065: if (rootCondition == null) {
066: return true;
067: }
068: return rootCondition.eval(context);
069: }
070:
071: public static abstract class TreeCondition {
072: protected ModelTree modelTree;
073:
074: public TreeCondition(ModelTree modelTree,
075: Element conditionElement) {
076: this .modelTree = modelTree;
077: }
078:
079: public abstract boolean eval(Map context);
080: }
081:
082: public static List readSubConditions(ModelTree modelTree,
083: Element conditionElement) {
084: List condList = FastList.newInstance();
085: List subElementList = UtilXml
086: .childElementList(conditionElement);
087: Iterator subElementIter = subElementList.iterator();
088: while (subElementIter.hasNext()) {
089: Element subElement = (Element) subElementIter.next();
090: condList.add(readCondition(modelTree, subElement));
091: }
092: return condList;
093: }
094:
095: public static TreeCondition readCondition(ModelTree modelTree,
096: Element conditionElement) {
097: if (conditionElement == null) {
098: return null;
099: }
100: if ("and".equals(conditionElement.getNodeName())) {
101: return new And(modelTree, conditionElement);
102: } else if ("xor".equals(conditionElement.getNodeName())) {
103: return new Xor(modelTree, conditionElement);
104: } else if ("or".equals(conditionElement.getNodeName())) {
105: return new Or(modelTree, conditionElement);
106: } else if ("not".equals(conditionElement.getNodeName())) {
107: return new Not(modelTree, conditionElement);
108: } else if ("if-has-permission".equals(conditionElement
109: .getNodeName())) {
110: return new IfHasPermission(modelTree, conditionElement);
111: } else if ("if-validate-method".equals(conditionElement
112: .getNodeName())) {
113: return new IfValidateMethod(modelTree, conditionElement);
114: } else if ("if-compare".equals(conditionElement.getNodeName())) {
115: return new IfCompare(modelTree, conditionElement);
116: } else if ("if-compare-field".equals(conditionElement
117: .getNodeName())) {
118: return new IfCompareField(modelTree, conditionElement);
119: } else if ("if-regexp".equals(conditionElement.getNodeName())) {
120: return new IfRegexp(modelTree, conditionElement);
121: } else if ("if-empty".equals(conditionElement.getNodeName())) {
122: return new IfEmpty(modelTree, conditionElement);
123: } else if ("if-entity-permission".equals(conditionElement
124: .getNodeName())) {
125: return new IfEntityPermission(modelTree, conditionElement);
126: } else {
127: throw new IllegalArgumentException(
128: "Condition element not supported with name: "
129: + conditionElement.getNodeName());
130: }
131: }
132:
133: public static class And extends TreeCondition {
134: protected List subConditions;
135:
136: public And(ModelTree modelTree, Element condElement) {
137: super (modelTree, condElement);
138: this .subConditions = readSubConditions(modelTree,
139: condElement);
140: }
141:
142: public boolean eval(Map context) {
143: // return false for the first one in the list that is false, basic and algo
144: Iterator subConditionIter = this .subConditions.iterator();
145: while (subConditionIter.hasNext()) {
146: TreeCondition subCondition = (TreeCondition) subConditionIter
147: .next();
148: if (!subCondition.eval(context)) {
149: return false;
150: }
151: }
152: return true;
153: }
154: }
155:
156: public static class Xor extends TreeCondition {
157: protected List subConditions;
158:
159: public Xor(ModelTree modelTree, Element condElement) {
160: super (modelTree, condElement);
161: this .subConditions = readSubConditions(modelTree,
162: condElement);
163: }
164:
165: public boolean eval(Map context) {
166: // if more than one is true stop immediately and return false; if all are false return false; if only one is true return true
167: boolean foundOneTrue = false;
168: Iterator subConditionIter = this .subConditions.iterator();
169: while (subConditionIter.hasNext()) {
170: TreeCondition subCondition = (TreeCondition) subConditionIter
171: .next();
172: if (subCondition.eval(context)) {
173: if (foundOneTrue) {
174: // now found two true, so return false
175: return false;
176: } else {
177: foundOneTrue = true;
178: }
179: }
180: }
181: return foundOneTrue;
182: }
183: }
184:
185: public static class Or extends TreeCondition {
186: protected List subConditions;
187:
188: public Or(ModelTree modelTree, Element condElement) {
189: super (modelTree, condElement);
190: this .subConditions = readSubConditions(modelTree,
191: condElement);
192: }
193:
194: public boolean eval(Map context) {
195: // return true for the first one in the list that is true, basic or algo
196: Iterator subConditionIter = this .subConditions.iterator();
197: while (subConditionIter.hasNext()) {
198: TreeCondition subCondition = (TreeCondition) subConditionIter
199: .next();
200: if (subCondition.eval(context)) {
201: return true;
202: }
203: }
204: return false;
205: }
206: }
207:
208: public static class Not extends TreeCondition {
209: protected TreeCondition subCondition;
210:
211: public Not(ModelTree modelTree, Element condElement) {
212: super (modelTree, condElement);
213: Element firstChildElement = UtilXml
214: .firstChildElement(condElement);
215: this .subCondition = readCondition(modelTree,
216: firstChildElement);
217: }
218:
219: public boolean eval(Map context) {
220: return !this .subCondition.eval(context);
221: }
222: }
223:
224: public static class IfHasPermission extends TreeCondition {
225: protected FlexibleStringExpander permissionExdr;
226: protected FlexibleStringExpander actionExdr;
227:
228: public IfHasPermission(ModelTree modelTree, Element condElement) {
229: super (modelTree, condElement);
230: this .permissionExdr = new FlexibleStringExpander(
231: condElement.getAttribute("permission"));
232: this .actionExdr = new FlexibleStringExpander(condElement
233: .getAttribute("action"));
234: }
235:
236: public boolean eval(Map context) {
237: // if no user is logged in, treat as if the user does not have permission
238: GenericValue userLogin = (GenericValue) context
239: .get("userLogin");
240: if (userLogin != null) {
241: String permission = permissionExdr
242: .expandString(context);
243: String action = actionExdr.expandString(context);
244:
245: Security security = (Security) context.get("security");
246: if (action != null && action.length() > 0) {
247: // run hasEntityPermission
248: if (security.hasEntityPermission(permission,
249: action, userLogin)) {
250: return true;
251: }
252: } else {
253: // run hasPermission
254: if (security.hasPermission(permission, userLogin)) {
255: return true;
256: }
257: }
258: }
259: return false;
260: }
261: }
262:
263: public static class IfValidateMethod extends TreeCondition {
264: protected FlexibleMapAccessor fieldAcsr;
265: protected FlexibleStringExpander methodExdr;
266: protected FlexibleStringExpander classExdr;
267:
268: public IfValidateMethod(ModelTree modelTree, Element condElement) {
269: super (modelTree, condElement);
270: this .fieldAcsr = new FlexibleMapAccessor(condElement
271: .getAttribute("field-name"));
272: this .methodExdr = new FlexibleStringExpander(condElement
273: .getAttribute("method"));
274: this .classExdr = new FlexibleStringExpander(condElement
275: .getAttribute("class"));
276: }
277:
278: public boolean eval(Map context) {
279: String methodName = this .methodExdr.expandString(context);
280: String className = this .classExdr.expandString(context);
281:
282: Object fieldVal = this .fieldAcsr.get(context);
283: String fieldString = null;
284: if (fieldVal != null) {
285: try {
286: fieldString = (String) ObjectType
287: .simpleTypeConvert(fieldVal, "String",
288: null, null);
289: } catch (GeneralException e) {
290: Debug
291: .logError(
292: e,
293: "Could not convert object to String, using empty String",
294: module);
295: }
296: }
297:
298: // always use an empty string by default
299: if (fieldString == null)
300: fieldString = "";
301:
302: Class[] paramTypes = new Class[] { String.class };
303: Object[] params = new Object[] { fieldString };
304:
305: Class valClass;
306: try {
307: valClass = ObjectType.loadClass(className);
308: } catch (ClassNotFoundException cnfe) {
309: Debug.logError("Could not find validation class: "
310: + className, module);
311: return false;
312: }
313:
314: Method valMethod;
315: try {
316: valMethod = valClass.getMethod(methodName, paramTypes);
317: } catch (NoSuchMethodException cnfe) {
318: Debug
319: .logError(
320: "Could not find validation method: "
321: + methodName + " of class "
322: + className, module);
323: return false;
324: }
325:
326: Boolean resultBool = Boolean.FALSE;
327: try {
328: resultBool = (Boolean) valMethod.invoke(null, params);
329: } catch (Exception e) {
330: Debug.logError(e, "Error in IfValidationMethod "
331: + methodName + " of class " + className
332: + ", defaulting to false ", module);
333: }
334:
335: return resultBool.booleanValue();
336: }
337: }
338:
339: public static class IfCompare extends TreeCondition {
340: protected FlexibleMapAccessor fieldAcsr;
341: protected FlexibleStringExpander valueExdr;
342:
343: protected String operator;
344: protected String type;
345: protected FlexibleStringExpander formatExdr;
346:
347: public IfCompare(ModelTree modelTree, Element condElement) {
348: super (modelTree, condElement);
349: this .fieldAcsr = new FlexibleMapAccessor(condElement
350: .getAttribute("field-name"));
351: this .valueExdr = new FlexibleStringExpander(condElement
352: .getAttribute("value"));
353:
354: this .operator = condElement.getAttribute("operator");
355: this .type = condElement.getAttribute("type");
356:
357: this .formatExdr = new FlexibleStringExpander(condElement
358: .getAttribute("format"));
359: }
360:
361: public boolean eval(Map context) {
362: String value = this .valueExdr.expandString(context);
363: String format = this .formatExdr.expandString(context);
364:
365: Object fieldVal = this .fieldAcsr.get(context);
366:
367: // always use an empty string by default
368: if (fieldVal == null) {
369: fieldVal = "";
370: }
371:
372: List messages = FastList.newInstance();
373: Boolean resultBool = BaseCompare.doRealCompare(fieldVal,
374: value, operator, type, format, messages, null,
375: null, true);
376: if (messages.size() > 0) {
377: messages.add(0,
378: "Error with comparison in if-compare between field ["
379: + fieldAcsr.toString()
380: + "] with value [" + fieldVal
381: + "] and value [" + value
382: + "] with operator [" + operator
383: + "] and type [" + type + "]: ");
384:
385: StringBuffer fullString = new StringBuffer();
386: Iterator miter = messages.iterator();
387: while (miter.hasNext()) {
388: fullString.append((String) miter.next());
389: }
390: Debug.logWarning(fullString.toString(), module);
391:
392: throw new IllegalArgumentException(fullString
393: .toString());
394: }
395:
396: return resultBool.booleanValue();
397: }
398: }
399:
400: public static class IfCompareField extends TreeCondition {
401: protected FlexibleMapAccessor fieldAcsr;
402: protected FlexibleMapAccessor toFieldAcsr;
403:
404: protected String operator;
405: protected String type;
406: protected FlexibleStringExpander formatExdr;
407:
408: public IfCompareField(ModelTree modelTree, Element condElement) {
409: super (modelTree, condElement);
410: this .fieldAcsr = new FlexibleMapAccessor(condElement
411: .getAttribute("field-name"));
412: this .toFieldAcsr = new FlexibleMapAccessor(condElement
413: .getAttribute("to-field-name"));
414:
415: this .operator = condElement.getAttribute("operator");
416: this .type = condElement.getAttribute("type");
417:
418: this .formatExdr = new FlexibleStringExpander(condElement
419: .getAttribute("format"));
420: }
421:
422: public boolean eval(Map context) {
423: String format = this .formatExdr.expandString(context);
424:
425: Object fieldVal = this .fieldAcsr.get(context);
426: Object toFieldVal = this .toFieldAcsr.get(context);
427:
428: // always use an empty string by default
429: if (fieldVal == null) {
430: fieldVal = "";
431: }
432:
433: List messages = FastList.newInstance();
434: Boolean resultBool = BaseCompare.doRealCompare(fieldVal,
435: toFieldVal, operator, type, format, messages, null,
436: null, false);
437: if (messages.size() > 0) {
438: messages.add(0,
439: "Error with comparison in if-compare-field between field ["
440: + fieldAcsr.toString()
441: + "] with value [" + fieldVal
442: + "] and to-field ["
443: + toFieldVal.toString()
444: + "] with value [" + toFieldVal
445: + "] with operator [" + operator
446: + "] and type [" + type + "]: ");
447:
448: StringBuffer fullString = new StringBuffer();
449: Iterator miter = messages.iterator();
450: while (miter.hasNext()) {
451: fullString.append((String) miter.next());
452: }
453: Debug.logWarning(fullString.toString(), module);
454:
455: throw new IllegalArgumentException(fullString
456: .toString());
457: }
458:
459: return resultBool.booleanValue();
460: }
461: }
462:
463: public static class IfRegexp extends TreeCondition {
464: static PatternMatcher matcher = new Perl5Matcher();
465: static PatternCompiler compiler = new Perl5Compiler();
466:
467: protected FlexibleMapAccessor fieldAcsr;
468: protected FlexibleStringExpander exprExdr;
469:
470: public IfRegexp(ModelTree modelTree, Element condElement) {
471: super (modelTree, condElement);
472: this .fieldAcsr = new FlexibleMapAccessor(condElement
473: .getAttribute("field-name"));
474: this .exprExdr = new FlexibleStringExpander(condElement
475: .getAttribute("expr"));
476: }
477:
478: public boolean eval(Map context) {
479: Object fieldVal = this .fieldAcsr.get(context);
480: String expr = this .exprExdr.expandString(context);
481: Pattern pattern = null;
482: try {
483: pattern = compiler.compile(expr);
484: } catch (MalformedPatternException e) {
485: String errMsg = "Error in evaluation in if-regexp in screen: "
486: + e.toString();
487: Debug.logError(e, errMsg, module);
488: throw new IllegalArgumentException(errMsg);
489: }
490:
491: String fieldString = null;
492: try {
493: fieldString = (String) ObjectType.simpleTypeConvert(
494: fieldVal, "String", null, null);
495: } catch (GeneralException e) {
496: Debug
497: .logError(
498: e,
499: "Could not convert object to String, using empty String",
500: module);
501: }
502: // always use an empty string by default
503: if (fieldString == null)
504: fieldString = "";
505:
506: return matcher.matches(fieldString, pattern);
507: }
508: }
509:
510: public static class IfEmpty extends TreeCondition {
511: protected FlexibleMapAccessor fieldAcsr;
512:
513: public IfEmpty(ModelTree modelTree, Element condElement) {
514: super (modelTree, condElement);
515: this .fieldAcsr = new FlexibleMapAccessor(condElement
516: .getAttribute("field-name"));
517: }
518:
519: public boolean eval(Map context) {
520: Object fieldVal = this .fieldAcsr.get(context);
521: return ObjectType.isEmpty(fieldVal);
522: }
523: }
524:
525: public static class IfEntityPermission extends TreeCondition {
526: protected EntityPermissionChecker permissionChecker;
527:
528: public IfEntityPermission(ModelTree modelTree,
529: Element condElement) {
530: super (modelTree, condElement);
531: this .permissionChecker = new EntityPermissionChecker(
532: condElement);
533: }
534:
535: public boolean eval(Map context) {
536:
537: boolean passed = permissionChecker
538: .runPermissionCheck(context);
539: return passed;
540: }
541: }
542: }
|