001: /*
002: * Copyright 2007 Dan Shellman
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.iscreen.mvel;
017:
018: import java.util.Iterator;
019: import java.util.Set;
020:
021: import org.iscreen.ConfigurationException;
022: import org.iscreen.impl.ConfiguredResource;
023: import org.iscreen.impl.xml.XmlConfigConstraint;
024: import org.iscreen.impl.xml.XmlConfigFailure;
025: import org.iscreen.impl.xml.XmlConfigLabel;
026: import org.iscreen.impl.xml.XmlConfigMapping;
027: import org.iscreen.impl.xml.XmlServiceFactory;
028: import org.iscreen.impl.DefaultValidationService;
029: import org.iscreen.impl.xml.XmlConfigDoc;
030:
031: /**
032: * This factory constructs a ValidationService based upon an XML
033: * configuration (via file or String, etc.). This ValidationFactory
034: * supports XML files that use MVEL.
035: *
036: * @author Shellman, Dan
037: */
038: public class MvelXmlServiceFactory extends XmlServiceFactory {
039: /**
040: * Default constructor.
041: */
042: public MvelXmlServiceFactory() {
043: } //end MvelXmlServiceFactory()
044:
045: /**
046: * Registers an individual Validator configuration. This will create
047: * a configured Validator that can be referenced by other Validators or
048: * by adding a Validator to a Validation Set.
049: *
050: * @param globalDefaultResource The resource id, when all else fails.
051: * @param id The unique id of the Validator
052: * @param ref The unique id of the Validator this Validator references.
053: * This can be null and is optional.
054: * @param className The class name of the Validator (optional, but if
055: * there MUST be a valid ref).
056: * @param defaultResource The resource id if no id is defined locally.
057: * @param label The Label for the Validator. This is optional.
058: * @param doc Documentation for this use of the validator.
059: * @param mappings The Set of mappings (can't be null, but can be empty).
060: * @param constraints The Set of constraints (can't be null, but can be empty).
061: * @param failures The Set of failures (can't be null, but can be empty).
062: */
063: public void registerValidator(String globalDefaultResource,
064: String id, String ref, String className,
065: String defaultResource, XmlConfigLabel label,
066: XmlConfigDoc doc, Set mappings, Set constraints,
067: Set failures) {
068: MvelConfiguredValidator validator;
069:
070: if (id == null || id.trim().equals("")) {
071: throw new ConfigurationException(
072: "Invalid definition of a Validator. The id is missing. All validators must have a unique id.");
073: }
074:
075: if ((className == null || className.trim().equals(""))
076: && (ref == null || ref.trim().equals(""))) {
077: throw new ConfigurationException(
078: "Invalid definition of a Validator. Either the ref or the class name must be valid.");
079: }
080:
081: validator = getValidator(id);
082: validator.setId(id);
083: validator.setClassName(className);
084: if (ref != null && !ref.trim().equals("")) {
085: validator.setRef(getValidator(ref));
086: }
087:
088: configureValidator(validator, globalDefaultResource,
089: defaultResource, label, doc, mappings, constraints,
090: failures);
091: } //end registerValidator()
092:
093: /**
094: * Registers a Validation Set.
095: *
096: * @param id The validation set's unique id.
097: */
098: public void registerValidationSet(String id) {
099: DefaultValidationService service;
100:
101: if (id == null || id.trim().equals("")) {
102: throw new ConfigurationException(
103: "Invalid unique id for validation set. All validation sets must have a non-empty, unique id.");
104: }
105:
106: //Check to see if it exists
107: if (setMap.get(id) == null) {
108: service = new DefaultValidationService(id,
109: getDefaultLocale());
110: setMap.put(id, service);
111: }
112: } //end registerValidationSet()
113:
114: /**
115: * Adds a 'use-validator' to a Validation Set. The 'use-validator' must
116: * reference a Validator.
117: *
118: * @param setId The Validation Set id.
119: * @param globalDefaultResource The configuration file's default resource
120: * (can be null/empty).
121: * @param defaultResource The Validation Set's default resource (optional).
122: * @param validatorRef The reference to a Validator (required).
123: * @param failFastFlag Whether to stop validations if this validator fails.
124: * @param label The label for this validator.
125: * @param doc Documentation for this use of the validator.
126: * @param mappings The mappings for this validator.
127: * @param constraints The constraints for this validator.
128: * @param failures The failures for this validator.
129: */
130: public void addValidatorToSet(String setId,
131: String globalDefaultResource, String defaultResource,
132: String validatorRef, boolean failFastFlag,
133: String validatorName, XmlConfigLabel label,
134: XmlConfigDoc doc, Set mappings, Set constraints,
135: Set failures) {
136: MvelConfiguredValidator validator;
137: DefaultValidationService service;
138:
139: if (validatorRef == null || validatorRef.trim().equals("")) {
140: throw new ConfigurationException(
141: "Invalid reference to a Validator. The 'ref' attribute must be set and must point to a Validator.");
142: }
143:
144: validator = new MvelConfiguredValidator();
145: validator.setRef(getValidator(validatorRef));
146:
147: configureValidator(validator, globalDefaultResource,
148: defaultResource, label, doc, mappings, constraints,
149: failures);
150:
151: validator.setFailFast(failFastFlag);
152: validator.setName(validatorName);
153:
154: service = (DefaultValidationService) setMap.get(setId);
155: service.addValidatorWrapper(validator);
156: validator.setValidationService(service);
157: } //end addValidatorToSet()
158:
159: /**
160: * Adds a validation set reference call to a validation set.
161: *
162: * @param setId The id of the containing Validation Set.
163: * @param setRefId The id of the Validation Set being referenced.
164: * @param failFastFlag Whether to continue validations if the set
165: * reports a failure.
166: * @param ifExp Whether to execute the validations in the referenced set.
167: * @param iterateExp Whether to iterate over the objects being mapped
168: * and validate each one.
169: * @param mapExp The mapping expression.
170: */
171: public void addValidationSetToSet(String setId, String setRefId,
172: boolean failFastFlag, String name, String ifExp,
173: String iterateExp, String mapExp) {
174: DefaultValidationService service;
175: DefaultValidationService referencedService;
176: MvelValidationServiceValidator serviceWrapper;
177:
178: //Grab the referenced service. If it doesn't exist, then create it.
179: referencedService = (DefaultValidationService) setMap
180: .get(setRefId);
181: if (referencedService == null) {
182: referencedService = new DefaultValidationService(setRefId,
183: getDefaultLocale());
184: setMap.put(setRefId, referencedService);
185: }
186:
187: //Configure the service "wrapper"
188: serviceWrapper = new MvelValidationServiceValidator(
189: referencedService);
190:
191: serviceWrapper.setFailFast(failFastFlag);
192: serviceWrapper.setIfExpression(ifExp);
193: serviceWrapper.setIterateExpression(iterateExp);
194: serviceWrapper.setMapExpression(mapExp);
195: serviceWrapper.setName(name);
196:
197: //This will never be null, since the registerValidationSet() will have
198: //been called before this method.
199: service = (DefaultValidationService) setMap.get(setId);
200: service.addValidatorWrapper(serviceWrapper);
201: } //end addValidationSetToSet()
202:
203: /**
204: * Retrieves a MvelConfiguredValidator with the given id. If one has not
205: * been previously registered, then create a blank one.
206: *
207: *
208: * @param id The Validator's id.
209: * @return Returns a Validator with the given id.
210: */
211: public MvelConfiguredValidator getValidator(String id) {
212: MvelConfiguredValidator validator;
213:
214: validator = (MvelConfiguredValidator) validatorMap.get(id);
215: if (validator == null) {
216: validator = new MvelConfiguredValidator();
217: validator.setId(id);
218: validatorMap.put(id, validator);
219: }
220:
221: return validator;
222: } //end getValidator()
223:
224: /**
225: * Registers a service with the factory. This service can then be
226: * referenced by validators via configuration.
227: *
228: * @param serviceId The service id
229: * @param service The service
230: */
231: public void registerService(String serviceId, Object service) {
232: serviceMap.put(serviceId, service);
233: } //end registerService()
234:
235: // ***
236: // Protected methods
237: // ***
238:
239: /**
240: * Handles the actual configuration of a Validator, whether via registration
241: * or by adding one to a Validation Set.
242: */
243: protected void configureValidator(
244: MvelConfiguredValidator validator,
245: String globalDefaultResource, String defaultResource,
246: XmlConfigLabel label, XmlConfigDoc doc, Set mappings,
247: Set constraints, Set failures) {
248: Iterator it;
249:
250: //Configure the constraints.
251: it = constraints.iterator();
252: while (it.hasNext()) {
253: XmlConfigConstraint constraint;
254:
255: constraint = (XmlConfigConstraint) it.next();
256: if (constraint.getServiceId() == null
257: || constraint.getServiceId().trim().equals("")) {
258: validator.addStaticProperty(constraint.getProperty(),
259: constraint.getValue());
260: } else {
261: validator.addStaticProperty(constraint.getProperty(),
262: serviceMap.get(constraint.getServiceId()));
263: }
264: }
265:
266: //Configure the failure objects.
267: it = failures.iterator();
268: while (it.hasNext()) {
269: XmlConfigFailure failure;
270:
271: failure = (XmlConfigFailure) it.next();
272: if (failure.getMessage() == null) {
273: ConfiguredResource resource;
274:
275: resource = getResource(failure.getResource(),
276: defaultResource, globalDefaultResource);
277: validator.addStaticProperty(failure.getProperty(),
278: new MvelResourceMessage(resource, failure
279: .getKey()));
280: } else {
281: validator.addStaticProperty(failure.getProperty(),
282: new MvelMessage(failure.getMessage()));
283: }
284: }
285:
286: //Configure mappings
287: it = mappings.iterator();
288: while (it.hasNext()) {
289: XmlConfigMapping mapping;
290:
291: mapping = (XmlConfigMapping) it.next();
292: validator.addMapping(mapping.getFrom(), mapping.getTo());
293: }
294:
295: //TODO: this needs to be done better.
296: if (label != null) {
297: if (label.getValue() != null) {
298: validator.setLabel(label.getValue());
299: } else {
300: validator.setLabel(getResource(label.getResourceId(),
301: defaultResource, globalDefaultResource), label
302: .getResourceKey());
303: }
304: }
305: } //end configureValidator()
306: } //end MvelXmlServiceFactory
|