KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > service > ModelService


1 /*
2  * $Id: ModelService.java 6582 2006-01-25 20:23:59Z jonesde $
3  *
4  * Copyright (c) 2001-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  */

25 package org.ofbiz.service;
26
27 import java.util.*;
28 import java.lang.reflect.Method JavaDoc;
29 import java.io.Serializable JavaDoc;
30
31 import javax.wsdl.*;
32 import javax.wsdl.extensions.soap.SOAPBinding;
33 import javax.wsdl.extensions.soap.SOAPBody;
34 import javax.wsdl.extensions.soap.SOAPOperation;
35 import javax.wsdl.extensions.soap.SOAPAddress;
36 import javax.wsdl.factory.WSDLFactory;
37 import javax.xml.namespace.QName JavaDoc;
38
39 import javolution.util.FastList;
40 import javolution.util.FastMap;
41
42 import com.ibm.wsdl.extensions.soap.SOAPBindingImpl;
43 import com.ibm.wsdl.extensions.soap.SOAPBodyImpl;
44 import com.ibm.wsdl.extensions.soap.SOAPOperationImpl;
45 import com.ibm.wsdl.extensions.soap.SOAPAddressImpl;
46
47 import org.ofbiz.base.util.Debug;
48 import org.ofbiz.base.util.GeneralException;
49 import org.ofbiz.base.util.ObjectType;
50 import org.ofbiz.base.util.UtilProperties;
51 import org.ofbiz.base.util.UtilValidate;
52 import org.ofbiz.base.util.UtilMisc;
53 import org.ofbiz.base.util.collections.OrderedSet;
54 import org.ofbiz.entity.GenericValue;
55 import org.ofbiz.security.Security;
56 import org.ofbiz.service.group.GroupModel;
57 import org.ofbiz.service.group.GroupServiceModel;
58 import org.ofbiz.service.group.ServiceGroupReader;
59
60 import org.apache.commons.collections.set.ListOrderedSet;
61 import org.w3c.dom.Document JavaDoc;
62
63 /**
64  * Generic Service Model Class
65  *
66  * @author <a HREF="mailto:jaz@ofbiz.org">Andy Zeneski</a>
67  * @author <a HREF="mailto:jonesde@ofbiz.org">David E. Jones</a>
68  * @version $Rev: 6582 $
69  * @since 2.0
70  */

71 public class ModelService implements Serializable JavaDoc {
72
73     public static final String JavaDoc module = ModelService.class.getName();
74
75     public static final String JavaDoc XSD = "http://www.w3.org/2001/XMLSchema";
76     public static final String JavaDoc TNS = "http://www.ofbiz.org/service/";
77     public static final String JavaDoc OUT_PARAM = "OUT";
78     public static final String JavaDoc IN_PARAM = "IN";
79
80     public static final String JavaDoc RESPONSE_MESSAGE = "responseMessage";
81     public static final String JavaDoc RESPOND_SUCCESS = "success";
82     public static final String JavaDoc RESPOND_ERROR = "error";
83     public static final String JavaDoc RESPOND_FAIL = "fail";
84     public static final String JavaDoc ERROR_MESSAGE = "errorMessage";
85     public static final String JavaDoc ERROR_MESSAGE_LIST = "errorMessageList";
86     public static final String JavaDoc ERROR_MESSAGE_MAP = "errorMessageMap";
87     public static final String JavaDoc SUCCESS_MESSAGE = "successMessage";
88     public static final String JavaDoc SUCCESS_MESSAGE_LIST = "successMessageList";
89
90     public static final String JavaDoc resource = "ServiceErrorUiLabels";
91
92     /** The name of this service */
93     public String JavaDoc name;
94
95     /** The description of this service */
96     public String JavaDoc description;
97
98     /** The name of the service engine */
99     public String JavaDoc engineName;
100
101     /** The namespace of this service */
102     public String JavaDoc nameSpace;
103
104     /** The package name or location of this service */
105     public String JavaDoc location;
106
107     /** The method or function to invoke for this service */
108     public String JavaDoc invoke;
109
110     /** The default Entity to use for auto-attributes */
111     public String JavaDoc defaultEntityName;
112
113     /** Does this service require authorization */
114     public boolean auth;
115
116     /** Can this service be exported via RPC, RMI, SOAP, etc */
117     public boolean export;
118
119     /** Enable verbose debugging when calling this service */
120     public boolean debug;
121
122     /** Validate the context info for this service */
123     public boolean validate;
124
125     /** Create a transaction for this service (if one is not already in place...)? */
126     public boolean useTransaction;
127
128     /** Require a new transaction for this service */
129     public boolean requireNewTransaction;
130
131     /** Override the default transaction timeout, only works if we start the transaction */
132     public int transactionTimeout;
133
134     /** Sets the max number of times this service will retry when failed (persisted async only) */
135     public int maxRetry = -1;
136
137     /** Set of services this service implements */
138     public Set implServices = new ListOrderedSet();
139
140     /** Set of override parameters */
141     public Set overrideParameters = new ListOrderedSet();
142
143     /** List of permission groups for service invocation */
144     public List permissionGroups = FastList.newInstance();
145
146     /** Context Information, a Map of parameters used by the service, contains ModelParam objects */
147     protected Map contextInfo = FastMap.newInstance();
148
149     /** Context Information, a List of parameters used by the service, contains ModelParam objects */
150     protected List contextParamList = FastList.newInstance();
151
152     /** Flag to say if we have pulled in our addition parameters from our implemented service(s) */
153     protected boolean inheritedParameters = false;
154
155     public ModelService() {}
156
157     public ModelService(ModelService model) {
158         this.name = model.name;
159         this.description = model.description;
160         this.engineName = model.engineName;
161         this.nameSpace = model.nameSpace;
162         this.location = model.location;
163         this.invoke = model.invoke;
164         this.defaultEntityName = model.defaultEntityName;
165         this.auth = model.auth;
166         this.export = model.export;
167         this.validate = model.validate;
168         this.useTransaction = model.useTransaction || true;
169         this.requireNewTransaction = model.requireNewTransaction || false;
170         this.transactionTimeout = model.transactionTimeout;
171         this.implServices = model.implServices;
172         this.overrideParameters = model.overrideParameters;
173         this.inheritedParameters = model.inheritedParameters();
174
175         List modelParamList = model.getModelParamList();
176         Iterator i = modelParamList.iterator();
177         while (i.hasNext()) {
178             this.addParamClone((ModelParam) i.next());
179         }
180     }
181
182     public String JavaDoc toString() {
183         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
184         buf.append(name).append("::");
185         buf.append(description + "::");
186         buf.append(engineName + "::");
187         buf.append(nameSpace + "::");
188         buf.append(location + "::");
189         buf.append(invoke + "::");
190         buf.append(defaultEntityName + "::");
191         buf.append(auth + "::");
192         buf.append(export + "::");
193         buf.append(validate + "::");
194         buf.append(useTransaction + "::");
195         buf.append(requireNewTransaction + "::");
196         buf.append(transactionTimeout + "::");
197         buf.append(implServices + "::");
198         buf.append(overrideParameters + "::");
199         buf.append(contextInfo + "::");
200         buf.append(contextParamList + "::");
201         buf.append(inheritedParameters + "::");
202         return buf.toString();
203     }
204
205     public String JavaDoc debugInfo() {
206         if (debug || Debug.verboseOn()) {
207             return " [" + this.toString() + "]";
208         }
209         return "";
210     }
211
212     /**
213      * Test if we have already inherited our interface parameters
214      * @return boolean
215      */

216     public boolean inheritedParameters() {
217         return this.inheritedParameters;
218     }
219
220     /**
221      * Gets the ModelParam by name
222      * @param name The name of the parameter to get
223      * @return ModelParam object with the specified name
224      */

225     public ModelParam getParam(String JavaDoc name) {
226         return (ModelParam) contextInfo.get(name);
227     }
228
229     /**
230      * Adds a parameter definition to this service; puts on list in order added
231      * then sorts by order if specified.
232      */

233     public void addParam(ModelParam param) {
234         if (param != null) {
235             contextInfo.put(param.name, param);
236             contextParamList.add(param);
237         }
238     }
239
240     /* DEJ20060125 This is private but not used locally, so just commenting it out for now... may remove later
241     private void copyParams(Collection params) {
242         if (params != null) {
243             Iterator i = params.iterator();
244             while (i.hasNext()) {
245                 ModelParam param = (ModelParam) i.next();
246                 addParam(param);
247             }
248         }
249     }
250     */

251
252     /**
253      * Adds a clone of a parameter definition to this service
254      */

255     public void addParamClone(ModelParam param) {
256         if (param != null) {
257             ModelParam newParam = new ModelParam(param);
258             addParam(newParam);
259         }
260     }
261
262     public Set getAllParamNames() {
263         Set nameList = new OrderedSet();
264         Iterator i = this.contextParamList.iterator();
265
266         while (i.hasNext()) {
267             ModelParam p = (ModelParam) i.next();
268             nameList.add(p.name);
269         }
270         return nameList;
271     }
272
273     public Set getInParamNames() {
274         Set nameList = new OrderedSet();
275         Iterator i = this.contextParamList.iterator();
276
277         while (i.hasNext()) {
278             ModelParam p = (ModelParam) i.next();
279             // don't include OUT parameters in this list, only IN and INOUT
280
if ("OUT".equals(p.mode)) continue;
281             nameList.add(p.name);
282         }
283         return nameList;
284     }
285
286     public Set getOutParamNames() {
287         Set nameList = new OrderedSet();
288         Iterator i = this.contextParamList.iterator();
289
290         while (i.hasNext()) {
291             ModelParam p = (ModelParam) i.next();
292             // don't include IN parameters in this list, only OUT and INOUT
293
if ("IN".equals(p.mode)) continue;
294             nameList.add(p.name);
295         }
296         return nameList;
297     }
298
299     /**
300      * Validates a Map against the IN or OUT parameter information
301      * @param test The Map object to test
302      * @param mode Test either mode IN or mode OUT
303      */

304     public void validate(Map test, String JavaDoc mode, Locale locale) throws ServiceValidationException {
305         Map requiredInfo = FastMap.newInstance();
306         Map optionalInfo = FastMap.newInstance();
307         boolean verboseOn = Debug.verboseOn();
308
309         if (verboseOn) Debug.logVerbose("[ModelService.validate] : {" + this.name + "} : Validating context - " + test, module);
310
311         // do not validate results with errors
312
if (mode.equals(OUT_PARAM) && test != null && test.containsKey(RESPONSE_MESSAGE)) {
313             if (RESPOND_ERROR.equals(test.get(RESPONSE_MESSAGE)) || RESPOND_FAIL.equals(test.get(RESPONSE_MESSAGE))) {
314                 if (verboseOn) Debug.logVerbose("[ModelService.validate] : {" + this.name + "} : response was an error, not validating.", module);
315                 return;
316             }
317         }
318
319         // get the info values
320
Iterator contextParamIter = this.contextParamList.iterator();
321         while (contextParamIter.hasNext()) {
322             ModelParam modelParam = (ModelParam) contextParamIter.next();
323             // Debug.logInfo("In ModelService.validate preparing parameter [" + modelParam.name + (modelParam.optional?"(optional):":"(required):") + modelParam.mode + "] for service [" + this.name + "]", module);
324
if ("INOUT".equals(modelParam.mode) || mode.equals(modelParam.mode)) {
325                 if (modelParam.optional) {
326                     optionalInfo.put(modelParam.name, modelParam.type);
327                 } else {
328                     requiredInfo.put(modelParam.name, modelParam.type);
329                 }
330             }
331         }
332
333         // get the test values
334
Map requiredTest = FastMap.newInstance();
335         Map optionalTest = FastMap.newInstance();
336
337         if (test == null) test = FastMap.newInstance();
338         requiredTest.putAll(test);
339
340         List requiredButNull = FastList.newInstance();
341         if (requiredTest != null) {
342             List keyList = FastList.newInstance();
343             keyList.addAll(requiredTest.keySet());
344             Iterator t = keyList.iterator();
345
346             while (t.hasNext()) {
347                 Object JavaDoc key = t.next();
348                 Object JavaDoc value = requiredTest.get(key);
349
350                 if (!requiredInfo.containsKey(key)) {
351                     requiredTest.remove(key);
352                     optionalTest.put(key, value);
353                 } else if (value == null) {
354                     requiredButNull.add(key);
355                 }
356             }
357         }
358
359         // check for requiredButNull fields and return an error since null values are not allowed for required fields
360
if (requiredButNull.size() > 0) {
361             List missingMsg = FastList.newInstance();
362             Iterator rbni = requiredButNull.iterator();
363             while (rbni.hasNext()) {
364                 String JavaDoc missingKey = (String JavaDoc) rbni.next();
365                 String JavaDoc message = this.getParam(missingKey).getPrimaryFailMessage(locale);
366                 if (message == null) {
367                     String JavaDoc errMsg = UtilProperties.getMessage(ServiceUtil.resource, "ModelService.following_required_parameter_missing", locale);
368                     message = errMsg + " [" + this.name + "." + missingKey + "]";
369                 }
370                 missingMsg.add(message);
371             }
372             throw new ServiceValidationException(missingMsg, this, requiredButNull, null, mode);
373         }
374
375         if (verboseOn) {
376             String JavaDoc requiredNames = "";
377             Iterator requiredIter = requiredInfo.keySet().iterator();
378             while (requiredIter.hasNext()) {
379                 requiredNames = requiredNames + requiredIter.next();
380                 if (requiredIter.hasNext()) {
381                     requiredNames = requiredNames + ", ";
382                 }
383             }
384             Debug.logVerbose("[ModelService.validate] : required fields - " + requiredNames, module);
385
386             Debug.logVerbose("[ModelService.validate] : {" + name + "} : (" + mode + ") Required - " +
387                 requiredTest.size() + " / " + requiredInfo.size(), module);
388             Debug.logVerbose("[ModelService.validate] : {" + name + "} : (" + mode + ") Optional - " +
389                 optionalTest.size() + " / " + optionalInfo.size(), module);
390         }
391
392         try {
393             validate(requiredInfo, requiredTest, true, this, mode, locale);
394             validate(optionalInfo, optionalTest, false, this, mode, locale);
395         } catch (ServiceValidationException e) {
396             Debug.logError("[ModelService.validate] : {" + name + "} : (" + mode + ") Required test error: " + e.toString(), module);
397             throw e;
398         }
399     }
400
401     /**
402      * Validates a map of name, object types to a map of name, objects
403      * @param info The map of name, object types
404      * @param test The map to test its value types.
405      * @param reverse Test the maps in reverse.
406      */

407     public static void validate(Map info, Map test, boolean reverse, ModelService model, String JavaDoc mode, Locale locale) throws ServiceValidationException {
408         if (info == null || test == null) {
409             throw new ServiceValidationException("Cannot validate NULL maps", model);
410         }
411
412         // * Validate keys first
413
Set testSet = test.keySet();
414         Set keySet = info.keySet();
415
416         // Quick check for sizes
417
if (info.size() == 0 && test.size() == 0) return;
418         // This is to see if the test set contains all from the info set (reverse)
419
if (reverse && !testSet.containsAll(keySet)) {
420             Set missing = new TreeSet(keySet);
421
422             missing.removeAll(testSet);
423             List missingMsgs = FastList.newInstance();
424
425             Iterator iter = missing.iterator();
426             while (iter.hasNext()) {
427                 String JavaDoc key = (String JavaDoc) iter.next();
428                 String JavaDoc msg = model.getParam(key).getPrimaryFailMessage(locale);
429                 if (msg == null) {
430                     String JavaDoc errMsg = UtilProperties.getMessage(ServiceUtil.resource, "ModelService.following_required_parameter_missing", locale) ;
431                     msg = errMsg + " [" + model.name + "." + key + "]";
432                 }
433                 missingMsgs.add(msg);
434             }
435             
436             List missingCopy = FastList.newInstance();
437             missingCopy.addAll(missing);
438             throw new ServiceValidationException(missingMsgs, model, missingCopy, null, mode);
439         }
440
441         // This is to see if the info set contains all from the test set
442
if (!keySet.containsAll(testSet)) {
443             Set extra = new TreeSet(testSet);
444
445             extra.removeAll(keySet);
446             List extraMsgs = FastList.newInstance();
447
448             Iterator iter = extra.iterator();
449             while (iter.hasNext()) {
450                 String JavaDoc key = (String JavaDoc) iter.next();
451                 ModelParam param = model.getParam(key);
452                 String JavaDoc msg = null;
453                 if (param != null) {
454                     msg = param.getPrimaryFailMessage(locale);
455                 }
456                 if (msg == null) {
457                     msg = "Unknown parameter found: [" + model.name + "." + key + "]";
458                 }
459                 extraMsgs.add(msg);
460             }
461
462             List extraCopy = FastList.newInstance();
463             extraCopy.addAll(extra);
464             throw new ServiceValidationException(extraMsgs, model, null, extraCopy, mode);
465         }
466
467         // * Validate types next
468
List typeFailMsgs = FastList.newInstance();
469         Iterator i = testSet.iterator();
470         while (i.hasNext()) {
471             String JavaDoc key = (String JavaDoc) i.next();
472             ModelParam param = model.getParam(key);
473
474             Object JavaDoc testObject = test.get(key);
475             String JavaDoc infoType = (String JavaDoc) info.get(key);
476
477             if (param.validators != null && param.validators.size() > 0) {
478                 Iterator vali = param.validators.iterator();
479                 while (vali.hasNext()) {
480                     ModelParam.ModelParamValidator val = (ModelParam.ModelParamValidator) vali.next();
481                     if (UtilValidate.isNotEmpty(val.getMethodName())) {
482                         try {
483                             if (!typeValidate(val, testObject)) {
484                                 String JavaDoc msg = val.getFailMessage(locale);
485                                 if (msg == null) {
486                                     msg = "The following parameter failed validation: [" + model.name + "." + key + "]";
487                                 }
488                                 typeFailMsgs.add(msg);
489                             }
490                         } catch (GeneralException e) {
491                             Debug.logError(e, module);
492                             String JavaDoc msg = param.getPrimaryFailMessage(locale);
493                             if (msg == null) {
494                                 msg = "The following parameter failed validation: [" + model.name + "." + key + "]";
495                             }
496                             typeFailMsgs.add(msg);
497                         }
498                     } else {
499                         if (!ObjectType.instanceOf(testObject, infoType, null)) {
500                             String JavaDoc msg = val.getFailMessage(locale);
501                             if (msg == null) {
502                                 msg = "The following parameter failed validation: [" + model.name + "." + key + "]";
503                             }
504                             typeFailMsgs.add(msg);
505                         }
506                     }
507                 }
508             } else {
509                 if (!ObjectType.instanceOf(testObject, infoType, null)) {
510                     String JavaDoc testType = testObject == null ? "null" : testObject.getClass().getName();
511                     String JavaDoc msg = "Type check failed for field [" + model.name + "." + key + "]; expected type is [" + infoType + "]; actual type is [" + testType + "]";
512                     typeFailMsgs.add(msg);
513                 }
514             }
515         }
516
517         if (typeFailMsgs.size() > 0) {
518             throw new ServiceValidationException(typeFailMsgs, model, mode);
519         }
520     }
521
522     public static boolean typeValidate(ModelParam.ModelParamValidator vali, Object JavaDoc testValue) throws GeneralException {
523         // find the validator class
524
Class JavaDoc validatorClass = null;
525         try {
526             validatorClass = ObjectType.loadClass(vali.getClassName());
527         } catch (ClassNotFoundException JavaDoc e) {
528         }
529
530         if (validatorClass == null) {
531             throw new GeneralException("Unable to load validation class [" + vali.getClassName() + "]");
532         }
533
534         boolean foundObjectParam = true;
535         Class JavaDoc[] stringParam = new Class JavaDoc[] { String JavaDoc.class };
536         Class JavaDoc[] objectParam = new Class JavaDoc[] { Object JavaDoc.class };
537
538         Method JavaDoc validatorMethod = null;
539         try {
540             // try object type first
541
validatorMethod = validatorClass.getMethod(vali.getMethodName(), objectParam);
542         } catch (NoSuchMethodException JavaDoc e) {
543             foundObjectParam = false;
544             // next try string type
545
try {
546                 validatorMethod = validatorClass.getMethod(vali.getMethodName(), stringParam);
547             } catch (NoSuchMethodException JavaDoc e2) {
548             }
549         }
550
551         if (validatorMethod == null) {
552             throw new GeneralException("Unable to find validation method [" + vali.getMethodName() + "] in class [" + vali.getClassName() + "]");
553         }
554
555         Object JavaDoc[] params;
556         if (!foundObjectParam) {
557             // convert to string
558
String JavaDoc converted = null;
559             try {
560                 converted = (String JavaDoc) ObjectType.simpleTypeConvert(testValue, "String", null, null);
561             } catch (GeneralException e) {
562                 throw new GeneralException("Unable to convert parameter to String");
563             }
564             params = new Object JavaDoc[] { converted };
565         } else {
566             // use plain object
567
params = new Object JavaDoc[] { testValue };
568         }
569
570         // run the validator
571
Boolean JavaDoc resultBool = Boolean.FALSE;
572         try {
573             resultBool = (Boolean JavaDoc) validatorMethod.invoke(null, params);
574         } catch (ClassCastException JavaDoc e) {
575             throw new GeneralException("Validation method [" + vali.getMethodName() + "] in class [" + vali.getClassName() + "] did not return expected Boolean");
576         } catch (Exception JavaDoc e) {
577             throw new GeneralException("Unable to run validation method [" + vali.getMethodName() + "] in class [" + vali.getClassName() + "]");
578         }
579
580         return resultBool.booleanValue();
581     }
582
583     /**
584      * Gets the parameter names of the specified mode (IN/OUT/INOUT). The
585      * parameters will be returned in the order specified in the file.
586      * Note: IN and OUT will also contains INOUT parameters.
587      * @param mode The mode (IN/OUT/INOUT)
588      * @param optional True if to include optional parameters
589      * @param internal True to include internal parameters
590      * @return List of parameter names
591      */

592     public List getParameterNames(String JavaDoc mode, boolean optional, boolean internal) {
593         List names = FastList.newInstance();
594
595         if (!"IN".equals(mode) && !"OUT".equals(mode) && !"INOUT".equals(mode)) {
596             return names;
597         }
598         if (contextInfo.size() == 0) {
599             return names;
600         }
601         Iterator i = contextParamList.iterator();
602
603         while (i.hasNext()) {
604             ModelParam param = (ModelParam) i.next();
605
606             if (param.mode.equals("INOUT") || param.mode.equals(mode)) {
607                 if (optional || (!optional && !param.optional)) {
608                     if (internal || (!internal && !param.internal)) {
609                         names.add(param.name);
610                     }
611                 }
612             }
613         }
614         return names;
615     }
616
617     public List getParameterNames(String JavaDoc mode, boolean optional) {
618         return this.getParameterNames(mode, optional, true);
619     }
620
621     /**
622      * Creates a new Map based from an existing map with just valid parameters.
623      * Tries to convert parameters to required type.
624      * @param source The source map
625      * @param mode The mode which to build the new map
626      */

627     public Map makeValid(Map source, String JavaDoc mode) {
628         return makeValid(source, mode, true, null, null);
629     }
630
631     /**
632      * Creates a new Map based from an existing map with just valid parameters.
633      * Tries to convert parameters to required type.
634      * @param source The source map
635      * @param mode The mode which to build the new map
636      * @param includeInternal When false will exclude internal fields
637      */

638     public Map makeValid(Map source, String JavaDoc mode, boolean includeInternal, List errorMessages) {
639         return makeValid(source, mode, includeInternal, errorMessages, null);
640     }
641
642     /**
643      * Creates a new Map based from an existing map with just valid parameters.
644      * Tries to convert parameters to required type.
645      * @param source The source map
646      * @param mode The mode which to build the new map
647      * @param includeInternal When false will exclude internal fields
648      * @param locale locale to use to do some type conversion
649      */

650     public Map makeValid(Map source, String JavaDoc mode, boolean includeInternal, List errorMessages, Locale locale) {
651         Map target = new HashMap();
652
653         if (source == null) {
654             return target;
655         }
656         if (!"IN".equals(mode) && !"OUT".equals(mode) && !"INOUT".equals(mode)) {
657             return target;
658         }
659         if (contextInfo.size() == 0) {
660             return target;
661         }
662         Iterator i = contextParamList.iterator();
663
664         while (i.hasNext()) {
665             ModelParam param = (ModelParam) i.next();
666             //boolean internalParam = param.internal;
667

668             if (param.mode.equals("INOUT") || param.mode.equals(mode)) {
669                 Object JavaDoc key = param.name;
670
671                 // internal map of strings
672
if (param.stringMapPrefix != null && param.stringMapPrefix.length() > 0 && !source.containsKey(key)) {
673                     Map paramMap = this.makePrefixMap(source, param);
674                     if (paramMap != null && paramMap.size() > 0) {
675                         target.put(key, paramMap);
676                     }
677                 // internal list of strings
678
} else if (param.stringListSuffix != null && param.stringListSuffix.length() > 0 && !source.containsKey(key)) {
679                     List paramList = this.makeSuffixList(source, param);
680                     if (paramList != null && paramList.size() > 0) {
681                         target.put(key, paramList);
682                     }
683                 // other attributes
684
} else {
685                     if (source.containsKey(key)) {
686                         if ((param.internal && includeInternal) || (!param.internal)) {
687                             Object JavaDoc value = source.get(key);
688
689                             try {
690                                 // no need to fail on type conversion; the validator will catch this
691
value = ObjectType.simpleTypeConvert(value, param.type, null, locale, false);
692                             } catch (GeneralException e) {
693                                 String JavaDoc errMsg = "Type conversion of field [" + key + "] to type [" + param.type + "] failed for value \"" + value + "\": " + e.toString();
694                                 Debug.logWarning("[ModelService.makeValid] : " + errMsg, module);
695                                 if (errorMessages != null) {
696                                     errorMessages.add(errMsg);
697                                 }
698                             }
699                             target.put(key, value);
700                         }
701                     }
702                 }
703             }
704         }
705         return target;
706     }
707
708     private Map makePrefixMap(Map source, ModelParam param) {
709         Map paramMap = new HashMap();
710         Set sourceSet = source.keySet();
711         Iterator i = sourceSet.iterator();
712         while (i.hasNext()) {
713             String JavaDoc key = (String JavaDoc) i.next();
714             if (key.startsWith(param.stringMapPrefix)) {
715                 paramMap.put(key, source.get(key));
716             }
717         }
718         return paramMap;
719     }
720
721     private List makeSuffixList(Map source, ModelParam param) {
722         List paramList = FastList.newInstance();
723         Set sourceSet = source.keySet();
724         Iterator i = sourceSet.iterator();
725         while (i.hasNext()) {
726             String JavaDoc key = (String JavaDoc) i.next();
727             if (key.endsWith(param.stringListSuffix)) {
728                 paramList.add(source.get(key));
729             }
730         }
731         return paramList;
732     }
733
734     public boolean containsPermissions() {
735         if (this.permissionGroups != null && this.permissionGroups.size() > 0) {
736             return true;
737         }
738         return false;
739     }
740
741     /**
742      * Evaluates permissions for a service.
743      * @param security The security object to use for permission checking
744      * @param userLogin The logged in user's value object
745      * @return true if all permissions evaluate true.
746      */

747     public boolean evalPermissions(Security security, GenericValue userLogin) {
748         if (this.containsPermissions()) {
749             Iterator i = this.permissionGroups.iterator();
750             while (i.hasNext()) {
751                 ModelPermGroup group = (ModelPermGroup) i.next();
752                 if (!group.evalPermissions(security, userLogin)) {
753                     return false;
754                 }
755             }
756             return true;
757         } else {
758             return true;
759         }
760     }
761
762     /**
763      * Gets a list of required IN parameters in sequence.
764      * @return A list of required IN parameters in the order which they were defined.
765      */

766     public List getInParameterSequence(Map source) {
767         List target = FastList.newInstance();
768         if (source == null) {
769             return target;
770         }
771         if (contextInfo == null || contextInfo.size() == 0) {
772             return target;
773         }
774         Iterator contextParamIter = this.contextParamList.iterator();
775         while (contextParamIter.hasNext()) {
776             ModelParam modelParam = (ModelParam) contextParamIter.next();
777
778             // don't include OUT parameters in this list, only IN and INOUT
779
if ("OUT".equals(modelParam.mode)) continue;
780
781             Object JavaDoc srcObject = source.get(modelParam.name);
782             if (srcObject != null) {
783                 target.add(srcObject);
784             }
785         }
786         return target;
787     }
788
789     /**
790      * Returns a list of ModelParam objects in the order they were defined when
791      * the service was created.
792      */

793     public List getModelParamList() {
794         List newList = FastList.newInstance();
795         newList.addAll(this.contextParamList);
796         return newList;
797     }
798
799     /**
800      * Returns a list of ModelParam objects in the order they were defined when
801      * the service was created.
802      */

803     public List getInModelParamList() {
804         List inList = FastList.newInstance();
805         Iterator contactParamIter = this.contextParamList.iterator();
806         while (contactParamIter.hasNext()) {
807             ModelParam modelParam = (ModelParam) contactParamIter.next();
808             
809             // don't include OUT parameters in this list, only IN and INOUT
810
if ("OUT".equals(modelParam.mode)) continue;
811             
812             inList.add(modelParam);
813         }
814         return inList;
815     }
816
817     /**
818      * Run the interface update and inherit all interface parameters
819      * @param dctx The DispatchContext to use for service lookups
820      */

821     public synchronized void interfaceUpdate(DispatchContext dctx) throws GenericServiceException {
822         if (!inheritedParameters) {
823             // services w/ engine 'group' auto-implement the grouped services
824
if (this.engineName.equals("group") && implServices.size() == 0) {
825                 GroupModel group = ServiceGroupReader.getGroupModel(this.location);
826                 if (group != null) {
827                     List groupedServices = group.getServices();
828                     Iterator i = groupedServices.iterator();
829                     while (i.hasNext()) {
830                         GroupServiceModel sm = (GroupServiceModel) i.next();
831                         implServices.add(sm.getName());
832                         if (Debug.verboseOn()) Debug.logVerbose("Adding service [" + sm.getName() + "] as interface of: [" + this.name + "]", module);
833                     }
834                 }
835             }
836
837             // handle interfaces
838
if (implServices != null && implServices.size() > 0 && dctx != null) {
839                 Iterator implIter = implServices.iterator();
840                 while (implIter.hasNext()) {
841                     String JavaDoc serviceName = (String JavaDoc) implIter.next();
842                     ModelService model = dctx.getModelService(serviceName);
843                     if (model != null) {
844                         Iterator contextParamIter = model.contextParamList.iterator();
845                         while (contextParamIter.hasNext()) {
846                             ModelParam newParam = (ModelParam) contextParamIter.next();
847                             ModelParam existingParam = (ModelParam) this.contextInfo.get(newParam.name);
848                             if (existingParam != null) {
849                                 // if the existing param is not INOUT and the newParam.mode is different from existingParam.mode, make the existing param optional and INOUT
850
// TODO: this is another case where having different optional/required settings for IN and OUT would be quite valuable...
851
if (!"INOUT".equals(existingParam.mode) && !existingParam.mode.equals(newParam.mode)) {
852                                     existingParam.mode = "INOUT";
853                                     existingParam.optional = true;
854                                 }
855                             } else {
856                                 // instead of calling: addParamClone(param), do it here because we want to make the inputs optional and such because earlier services in a group may create the parameters for later
857
ModelParam newParamClone = new ModelParam(newParam);
858                                 newParamClone.optional = true;
859                                 this.addParam(newParamClone);
860                             }
861                         }
862                     } else {
863                         Debug.logWarning("Inherited model [" + serviceName + "] not found for [" + this.name + "]", module);
864                     }
865                 }
866             }
867
868             // handle any override parameters
869
if (overrideParameters != null && overrideParameters.size() > 0) {
870                 Iterator keySetIter = overrideParameters.iterator();
871                 while (keySetIter.hasNext()) {
872                     ModelParam overrideParam = (ModelParam) keySetIter.next();
873                     ModelParam existingParam = (ModelParam) contextInfo.get(overrideParam.name);
874
875                     // keep the list clean, remove it then add it back
876
contextParamList.remove(existingParam);
877
878                     if (existingParam != null) {
879                         // now re-write the parameters
880
if (overrideParam.type != null && overrideParam.type.length() > 0) {
881                             existingParam.type = overrideParam.type;
882                         }
883                         if (overrideParam.mode != null && overrideParam.mode.length() > 0) {
884                             existingParam.mode = overrideParam.mode;
885                         }
886                         if (overrideParam.entityName != null && overrideParam.entityName.length() > 0) {
887                             existingParam.entityName = overrideParam.entityName;
888                         }
889                         if (overrideParam.fieldName != null && overrideParam.fieldName.length() > 0) {
890                             existingParam.fieldName = overrideParam.fieldName;
891                         }
892                         if (overrideParam.formLabel != null && overrideParam.formLabel.length() > 0) {
893                             existingParam.formLabel = overrideParam.formLabel;
894                         }
895                         if (overrideParam.overrideFormDisplay) {
896                             existingParam.formDisplay = overrideParam.formDisplay;
897                         }
898                         if (overrideParam.overrideOptional) {
899                             existingParam.optional = overrideParam.optional;
900                         }
901                         addParam(existingParam);
902                     } else {
903                         Debug.logWarning("Override param found but no parameter existing; ignoring: " + overrideParam.name, module);
904                     }
905                 }
906             }
907
908             // set the flag so we don't do this again
909
this.inheritedParameters = true;
910         }
911     }
912
913     public Document JavaDoc toWSDL(String JavaDoc locationURI) throws WSDLException {
914         WSDLFactory factory = WSDLFactory.newInstance();
915         Definition def = factory.newDefinition();
916         def.setTargetNamespace(TNS);
917         def.addNamespace("xsd", XSD);
918         def.addNamespace("tns", TNS);
919         def.addNamespace("soap", "http://schemas.xmlsoap.org/wsdl/soap/");
920         this.getWSDL(def, locationURI);
921         return factory.newWSDLWriter().getDocument(def);
922 }
923
924     public void getWSDL(Definition def, String JavaDoc locationURI) throws WSDLException {
925         // set the IN parameters
926
Input input = def.createInput();
927         List inParam = this.getParameterNames(IN_PARAM, true, false);
928         if (inParam != null) {
929             Message inMessage = def.createMessage();
930             inMessage.setQName(new QName JavaDoc(TNS, this.name + "Request"));
931             inMessage.setUndefined(false);
932             Iterator i = inParam.iterator();
933             while (i.hasNext()) {
934                 String JavaDoc paramName = (String JavaDoc) i.next();
935                 ModelParam param = this.getParam(paramName);
936                 if (!param.internal) {
937                     inMessage.addPart(param.getWSDLPart(def));
938                 }
939             }
940             def.addMessage(inMessage);
941             input.setMessage(inMessage);
942         }
943
944         // set the OUT parameters
945
Output output = def.createOutput();
946         List outParam = this.getParameterNames(OUT_PARAM, true, false);
947         if (outParam != null) {
948             Message outMessage = def.createMessage();
949             outMessage.setQName(new QName JavaDoc(TNS, this.name + "Response"));
950             outMessage.setUndefined(false);
951             Iterator i = outParam.iterator();
952             while (i.hasNext()) {
953                 String JavaDoc paramName = (String JavaDoc) i.next();
954                 ModelParam param = this.getParam(paramName);
955                 if (!param.internal) {
956                     outMessage.addPart(param.getWSDLPart(def));
957                 }
958             }
959             def.addMessage(outMessage);
960             output.setMessage(outMessage);
961         }
962
963         // set port type
964
Operation operation = def.createOperation();
965         operation.setName(this.name);
966         operation.setUndefined(false);
967         operation.setOutput(output);
968         operation.setInput(input);
969
970         PortType portType = def.createPortType();
971         portType.setQName(new QName JavaDoc(TNS, this.name + "PortType"));
972         portType.addOperation(operation);
973         portType.setUndefined(false);
974         def.addPortType(portType);
975
976         // SOAP binding
977
SOAPBinding soapBinding = new SOAPBindingImpl();
978         soapBinding.setStyle("document");
979         soapBinding.setTransportURI("http://schemas.xmlsoap.org/soap/http");
980
981         Binding binding = def.createBinding();
982         binding.setQName(new QName JavaDoc(TNS, this.name + "SoapBinding"));
983         binding.setPortType(portType);
984         binding.setUndefined(false);
985         binding.addExtensibilityElement(soapBinding);
986
987         BindingOperation bindingOperation = def.createBindingOperation();
988         bindingOperation.setName(operation.getName());
989         bindingOperation.setOperation(operation);
990
991         SOAPBody soapBody = new SOAPBodyImpl();
992         soapBody.setUse("literal");
993         soapBody.setNamespaceURI(TNS);
994         soapBody.setEncodingStyles(UtilMisc.toList("http://schemas.xmlsoap.org/soap/encoding/"));
995
996         BindingOutput bindingOutput = def.createBindingOutput();
997         bindingOutput.addExtensibilityElement(soapBody);
998         bindingOperation.setBindingOutput(bindingOutput);
999
1000        BindingInput bindingInput = def.createBindingInput();
1001        bindingInput.addExtensibilityElement(soapBody);
1002        bindingOperation.setBindingInput(bindingInput);
1003
1004        SOAPOperation soapOperation = new SOAPOperationImpl();
1005        soapOperation.setSoapActionURI(""); // ?
1006
bindingOperation.addExtensibilityElement(soapOperation);
1007
1008        binding.addBindingOperation(bindingOperation);
1009        def.addBinding(binding);
1010
1011        // Service port
1012
Port port = def.createPort();
1013        port.setBinding(binding);
1014        port.setName(this.name + "Port");
1015
1016        if (locationURI != null) {
1017            SOAPAddress soapAddress = new SOAPAddressImpl();
1018            soapAddress.setLocationURI(locationURI);
1019            port.addExtensibilityElement(soapAddress);
1020        }
1021
1022        Service service = def.createService();
1023        service.setQName(new QName JavaDoc(TNS, this.name));
1024        service.addPort(port);
1025        def.addService(service);
1026    }
1027}
1028
Popular Tags