View Javadoc
1   /**
2    * Copyright 2004-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.student.remote.impl.mojo;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  import org.kuali.student.contract.model.Service;
21  
22  import org.kuali.student.contract.model.ServiceContractModel;
23  import org.kuali.student.contract.model.ServiceMethod;
24  import org.kuali.student.contract.model.ServiceMethodError;
25  import org.kuali.student.contract.model.ServiceMethodParameter;
26  import org.kuali.student.contract.model.XmlType;
27  import org.kuali.student.contract.model.util.ModelFinder;
28  import org.kuali.student.contract.writer.JavaClassWriter;
29  import org.kuali.student.contract.writer.service.GetterSetterNameCalculator;
30  import org.kuali.student.contract.writer.service.MessageStructureTypeCalculator;
31  import org.kuali.student.contract.writer.service.ServiceExceptionWriter;
32  
33  /**
34   *
35   * @author nwright
36   */
37  public class RemoteImplServiceWriter extends JavaClassWriter {
38  
39      private ServiceContractModel model;
40      private ModelFinder finder;
41      private String directory;
42      private String rootPackage;
43      private String servKey;
44      private List<ServiceMethod> methods;
45  
46      public RemoteImplServiceWriter(ServiceContractModel model,
47              String directory,
48              String rootPackage,
49              String servKey,
50              List<ServiceMethod> methods) {
51          super(directory + "/main/java", calcPackage(servKey, rootPackage), calcClassName(servKey));
52          this.model = model;
53          this.finder = new ModelFinder(model);
54          this.directory = directory;
55          this.rootPackage = rootPackage;
56          this.servKey = servKey;
57          this.methods = methods;
58      }
59  
60      public static String calcPackage(String servKey, String rootPackage) {
61  //        String pack = rootPackage + "." + servKey.toLowerCase() + ".";
62  //  StringBuffer buf = new StringBuffer (service.getVersion ().length ());
63  //  for (int i = 0; i < service.getVersion ().length (); i ++)
64  //  {
65  //   char c = service.getVersion ().charAt (i);
66  //   c = Character.toLowerCase (c);
67  //   if (Character.isLetter (c))
68  //   {
69  //    buf.append (c);
70  //    continue;
71  //   }
72  //   if (Character.isDigit (c))
73  //   {
74  //    buf.append (c);
75  //   }
76  //  }
77  //  pack = pack + buf.toString ();
78  //        pack = pack + "service.decorators";
79  //        return pack;
80          return rootPackage;
81      }
82  
83      public static String calcClassName(String servKey) {
84          String name = GetterSetterNameCalculator.calcInitUpper(servKey + "ServiceRemoteImpl");
85          if (name.startsWith("RICE.")) {
86              name = name.substring("RICE.".length());
87          }
88          return name;
89      }
90  
91      public static String calcDecoratorClassName(String servKey) {
92          String name = GetterSetterNameCalculator.calcInitUpper(servKey + "ServiceDecorator");
93          if (name.startsWith("RICE.")) {
94              name = name.substring("RICE.".length());
95          }
96          return name;
97      }
98  
99      private static enum MethodType {
100 
101         VALIDATE, CREATE, UPDATE
102     };
103 
104     private MethodType calcMethodType(ServiceMethod method) {
105         if (method.getName().startsWith("validate")) {
106             return MethodType.VALIDATE;
107         }
108         if (method.getName().startsWith("create")) {
109             return MethodType.CREATE;
110         }
111         if (method.getName().startsWith("update")) {
112             return MethodType.UPDATE;
113         }
114         return null;
115     }
116 
117     /**
118      * Write out the entire file
119      *
120      * @param out
121      */
122     public void write() {
123         indentPrint("public class " + calcClassName(servKey));
124         println(" extends " + calcDecoratorClassName(servKey));
125         // TODO: figure out how to add import for the decorator
126         openBrace();
127         writeBiolerPlate();
128         indentPrintln("//");
129         indentPrintln("// Have to override and check each method that returns a list for null");
130         indentPrintln("// This is because SOAP/JAXB renders and empty list as null ");
131         indentPrintln("// but our contract standard says we ALWAYS return an empty list");
132         indentPrintln("//");
133         for (ServiceMethod method : methods) {
134             if (!method.getReturnValue().getType().endsWith("List")) {
135                 continue;
136             }
137 
138             indentPrintln("");
139 //            indentPrintln("/**");
140 //            indentPrintWrappedComment(method.getDescription());
141 //            indentPrintln("* ");
142 //            for (ServiceMethodParameter param : method.getParameters()) {
143 //                indentPrintWrappedComment("@param " + param.getName() + " - "
144 //                        + param.getType() + " - "
145 //                        + param.getDescription());
146 //            }
147 //            indentPrintWrappedComment("@return " + method.getReturnValue().
148 //                    getDescription());
149 //            indentPrintln("*/");
150             indentPrintln("@Override");
151             String type = method.getReturnValue().getType();
152             String realType = stripList(type);
153             indentPrint("public " + calcType(type, realType) + " " + method.getName()
154                     + "(");
155             // now do parameters
156             String comma = "";
157             for (ServiceMethodParameter param : method.getParameters()) {
158                 type = param.getType();
159                 realType = stripList(type);
160                 print(comma);
161                 print(calcType(type, realType));
162                 print(" ");
163                 print(param.getName());
164                 comma = ", ";
165             }
166             println(")");
167             // now do exceptions
168             comma = "throws ";
169             incrementIndent();
170             for (ServiceMethodError error : method.getErrors()) {
171                 indentPrint(comma);
172                 String exceptionClassName = calcExceptionClassName(error);
173                 String exceptionPackageName = this.calcExceptionPackageName(error);
174                 println(exceptionClassName);
175                 this.importsAdd(exceptionPackageName + "." + exceptionClassName);
176                 comma = "      ,";
177             }
178             decrementIndent();
179             openBrace();
180             type = method.getReturnValue().getType();
181             realType = stripList(type);
182             XmlType retValXmlType = finder.findXmlType(realType);
183             importsAdd(retValXmlType.getJavaPackage() + "." + retValXmlType.getName());
184             indentPrint("List<" + retValXmlType.getName() + "> list = this.getNextDecorator ()." + method.getName() + "(");
185             comma = "";
186             for (ServiceMethodParameter param : method.getParameters()) {
187                 type = param.getType();
188                 realType = stripList(type);
189                 print(comma);
190                 print(param.getName());
191                 comma = ", ";
192             }
193             println(");");
194             indentPrintln("if (list == null)");
195             openBrace();
196             importsAdd(ArrayList.class.getName());
197             indentPrintln("return new ArrayList<" + retValXmlType.getName() + "> ();");
198             closeBrace();
199             indentPrintln("return list;");
200             closeBrace();
201         }
202         closeBrace();
203 
204         this.writeJavaClassAndImportsOutToFile();
205         this.getOut().close();
206     }
207 
208     private String calcType(String type, String realType) {
209         XmlType t = finder.findXmlType(this.stripList(type));
210         return MessageStructureTypeCalculator.calculate(this, model, type, realType,
211                 t.getJavaPackage());
212     }
213 
214     private String stripList(String str) {
215         return GetterSetterNameCalculator.stripList(str);
216     }
217 
218     private String calcExceptionClassName(ServiceMethodError error) {
219         if (error.getClassName() == null) {
220             return ServiceExceptionWriter.calcClassName(error.getType());
221         }
222         return error.getClassName();
223     }
224 
225     private String calcExceptionPackageName(ServiceMethodError error) {
226         if (error.getClassName() == null) {
227             return ServiceExceptionWriter.calcPackage(rootPackage);
228         }
229         return error.getPackageName();
230     }
231 
232     private void writeBiolerPlate() {
233 
234         String initUpperServKey = GetterSetterNameCalculator.calcInitUpper(servKey);
235         if (initUpperServKey.startsWith("RICE.")) {
236             initUpperServKey = initUpperServKey.substring("RICE.".length());
237         }
238 
239         // TODO: figure out how to add import for the service constants
240         importsAdd("java.net.MalformedURLException");
241         importsAdd("java.net.URL");
242         importsAdd("javax.xml.namespace.QName");
243         importsAdd("javax.xml.ws.Service");
244         Service service = finder.findService(servKey);
245         importsAdd(service.getImplProject() + "." + service.getName());
246 
247         indentPrintln("private String hostUrl = null;");
248         indentPrintln("private String servicesUrlFragment = \"/services/\";");
249         indentPrintln("private String serviceNameLocalPart = " + initUpperServKey + "ServiceConstants.SERVICE_NAME_LOCAL_PART;");
250         indentPrintln("private String namespace = " + initUpperServKey + "ServiceConstants.NAMESPACE;");
251         indentPrintln("private URL wsdlUrl = null;");
252         println("");
253         indentPrintln("public String getHostUrl() {");
254         indentPrintln("    // check if explicitly configured, manually for testing or via spring");
255         indentPrintln("    if (this.hostUrl != null) {");
256         indentPrintln("        return hostUrl;");
257         indentPrintln("    }");
258         indentPrintln("    // check for a specific url for this service (not all services may be hosted from the same place)");
259         indentPrintln("    Properties config = ConfigContext.getCurrentContextConfig().getProperties();");
260         indentPrintln("    this.hostUrl = config.getProperty(\"remote.service.host.url." + servKey.toLowerCase() + "\");");
261         indentPrintln("    if (this.hostUrl != null) {");
262         indentPrintln("        return this.hostUrl;");
263         indentPrintln("    }");
264         indentPrintln("    // check for the default for all remote services");
265         indentPrintln("    this.hostUrl = config.getProperty(\"remote.service.host.url\");");
266         indentPrintln("    if (this.hostUrl != null) {");
267         indentPrintln("        return this.hostUrl;");
268         indentPrintln("    }");
269         indentPrintln("    throw new IllegalArgumentException(\"No host url configured\");");
270         indentPrintln("}");
271         println("");
272         indentPrintln("public void setHostUrl(String hostUrl) {");
273         indentPrintln("    this.hostUrl = hostUrl;");
274         indentPrintln("}");
275         println("");
276         indentPrintln("public URL getWsdlUrl() {");
277         indentPrintln("    if (this.wsdlUrl == null) {");
278         indentPrintln("        String urlString = this.getHostUrl() + this.getServicesUrlFragment() + this.getServiceNameLocalPart() + \"?wsdl\";");
279         indentPrintln("        try {");
280         indentPrintln("            this.wsdlUrl = new URL(urlString);");
281         indentPrintln("        } catch (MalformedURLException ex) {");
282         indentPrintln("            throw new IllegalArgumentException(urlString, ex);");
283         indentPrintln("        }");
284         indentPrintln("    }");
285         indentPrintln("    return wsdlUrl;");
286         indentPrintln("}");
287         println("");
288         indentPrintln("public void setWsdlUrl(URL wsdlUrl) {");
289         indentPrintln("    this.wsdlUrl = wsdlUrl;");
290         indentPrintln("}");
291         println("");
292         indentPrintln("public String getServiceNameLocalPart() {");
293         indentPrintln("    return serviceNameLocalPart;");
294         indentPrintln("}");
295         println("");
296         indentPrintln("public void setServiceNameLocalPart(String serviceNameLocalPart) {");
297         indentPrintln("    this.serviceNameLocalPart = serviceNameLocalPart;");
298         indentPrintln("}");
299         println("");
300         indentPrintln("public String getServicesUrlFragment() {");
301         indentPrintln("    return servicesUrlFragment;");
302         indentPrintln("}");
303         println("");
304         indentPrintln("public void setServicesUrlFragment(String servicesUrlFragment) {");
305         indentPrintln("    this.servicesUrlFragment = servicesUrlFragment;");
306         indentPrintln("}");
307         println("");
308         indentPrintln("public String getNamespace() {");
309         indentPrintln("    return namespace;");
310         indentPrintln("}");
311         println("");
312         indentPrintln("public void setNamespace(String namespace) {");
313         indentPrintln("    this.namespace = namespace;");
314         indentPrintln("}");
315         println("");
316         indentPrintln("public void init() {");
317         indentPrintln("    QName qname = new QName(this.getNamespace(), this.getServiceNameLocalPart());");
318         indentPrintln("    Service factory = Service.create(this.getWsdlUrl(), qname);");
319         indentPrintln("    " + initUpperServKey + "Service port = factory.getPort(" + initUpperServKey + "Service.class);");
320         indentPrintln("    this.setNextDecorator(port);");
321         indentPrintln("}");
322         println("");
323         indentPrintln("private boolean hasBeenIntialized = false;");
324         println("");
325         indentPrintln("@Override");
326         indentPrintln("public " + initUpperServKey + "Service getNextDecorator() throws OperationFailedException {");
327         indentPrintln("    if (!this.hasBeenIntialized) {");
328         indentPrintln("        this.hasBeenIntialized = true;");
329         indentPrintln("        this.init();");
330         indentPrintln("    }");
331         indentPrintln("    return super.getNextDecorator();");
332         indentPrintln("}");
333         println("");
334 
335     }
336 }