001: /*
002: * Created on 12 Sep 2007
003: */
004: package uk.org.ponder.springutil.validator.support;
005:
006: import java.util.Arrays;
007: import java.util.Comparator;
008: import java.util.HashMap;
009: import java.util.List;
010: import java.util.Map;
011:
012: import org.springframework.validation.Errors;
013: import org.springframework.validation.Validator;
014:
015: import uk.org.ponder.beanutil.BeanModelAlterer;
016: import uk.org.ponder.springutil.validator.ValidatorArgReporter;
017: import uk.org.ponder.springutil.validator.ValidatorCodeReceiver;
018: import uk.org.ponder.springutil.validator.ValidatorCompostor;
019: import uk.org.ponder.springutil.validator.ValidatorFactory;
020: import uk.org.ponder.stringutil.StringUtil;
021:
022: /**
023: * Parses validators out of a primitive String specification into a concrete
024: * implementation (currently) as a Spring validator.
025: *
026: * @author Antranig Basman (antranig@caret.cam.ac.uk)
027: */
028:
029: public class ValidatorCompostorImpl implements ValidatorCompostor {
030: private List validators;
031: private Map nametoval = new HashMap();
032:
033: public void setBeanModelAlterer(BeanModelAlterer beanModelAlterer) {
034: this .beanModelAlterer = beanModelAlterer;
035: }
036:
037: public void setValidators(List validators) {
038: this .validators = validators;
039: }
040:
041: private BeanModelAlterer beanModelAlterer;
042:
043: public void init() {
044: for (int i = 0; i < validators.size(); ++i) {
045: ValidatorFactory vf = (ValidatorFactory) validators.get(i);
046: String name = vf.getName();
047: nametoval.put(name, vf);
048: }
049: }
050:
051: private void sortValidators(ValidatorBase[] vals) {
052: Arrays.sort(vals, new Comparator() {
053:
054: public int compare(Object arg0, Object arg1) {
055: ValidatorBase val1 = (ValidatorBase) arg0;
056: ValidatorBase val2 = (ValidatorBase) arg1;
057: return val1.getPriority() - val2.getPriority();
058: }
059: });
060: }
061:
062: public Validator parseValidator(String spec) {
063: int colpos = spec.indexOf(':');
064: String offset = null;
065: if (colpos != -1) {
066: offset = spec.substring(0, colpos);
067: spec = spec.substring(colpos + 1);
068: }
069: String[] segments = StringUtil.parseArray(spec);
070: final ValidatorBase[] vals = new ValidatorBase[segments.length];
071: for (int i = 0; i < segments.length; ++i) {
072: ValidatorBase val = parseSingleValidator(segments[i]);
073: val.setOffsetPath(offset);
074: vals[i] = val;
075: }
076: sortValidators(vals);
077: return new Validator() {
078: public boolean supports(Class clazz) {
079: return true;
080: }
081:
082: public void validate(Object obj, Errors errors) {
083: boolean failed = false;
084: for (int i = 0; i < vals.length; ++i) {
085: if (i > 0
086: && failed
087: && vals[i].getPriority() > vals[i - 1]
088: .getPriority()) {
089: break;
090: }
091: String offsetpath = vals[i].getOffsetPath();
092: if (offsetpath != null) {
093: Object offset = beanModelAlterer.getBeanValue(
094: offsetpath, obj, null);
095: errors.pushNestedPath(offsetpath);
096: try {
097: int oldcount = errors.getErrorCount();
098: vals[i].validate(offset, errors);
099: boolean this fail = errors.getErrorCount() > oldcount;
100: failed = failed | this fail;
101: } finally {
102: errors.popNestedPath();
103: }
104: } else {
105: vals[i].validate(obj, errors);
106: }
107: }
108: }
109: };
110: }
111:
112: private ValidatorBase parseSingleValidator(String spec) {
113: int brackpos = spec.indexOf('(');
114: String name = spec.trim();
115: String[] args = new String[] {};
116: if (brackpos != -1) {
117: name = spec.substring(0, brackpos);
118: int lastbrackpos = spec.lastIndexOf(')');
119: args = StringUtil.parseArray((spec.substring(brackpos + 1,
120: lastbrackpos)));
121: }
122: ValidatorFactory vnr = (ValidatorFactory) nametoval.get(name);
123: Object validator = vnr.getValidator();
124: int setterargs = 0;
125: if (vnr instanceof ValidatorArgReporter) {
126: String setterspec = ((ValidatorArgReporter) vnr)
127: .getValidatorArgMethods();
128: String[] setters = StringUtil.parseArray(setterspec);
129: setterargs = setters.length;
130: for (int i = 0; i < setters.length; ++i) {
131: beanModelAlterer.setBeanValue(setters[i], validator,
132: args[i], null, true);
133: }
134: }
135: if (validator instanceof ValidatorCodeReceiver) {
136: ValidatorCodeReceiver vcr = (ValidatorCodeReceiver) validator;
137: if (args.length > setterargs) {
138: vcr.setMessageCode(args[args.length - 1]);
139: }
140: vcr.setMessageArgs(args);
141: }
142: if (validator instanceof ValidatorBase) {
143: ValidatorBase base = (ValidatorBase) validator;
144: base.setPriority(vnr.getPriority());
145: }
146: // Currently only supports Spring validators
147: return (ValidatorBase) validator;
148: }
149: }
|