001    /*
002     * Copyright 2009 The Kuali Foundation
003     *
004     * Licensed under the Educational Community 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.osedu.org/licenses/ECL-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.kuali.student.remote.impl.mojo;
017    
018    import java.util.ArrayList;
019    import java.util.List;
020    import org.kuali.student.contract.model.Service;
021    
022    import org.kuali.student.contract.model.ServiceContractModel;
023    import org.kuali.student.contract.model.ServiceMethod;
024    import org.kuali.student.contract.model.ServiceMethodError;
025    import org.kuali.student.contract.model.ServiceMethodParameter;
026    import org.kuali.student.contract.model.XmlType;
027    import org.kuali.student.contract.model.util.ModelFinder;
028    import org.kuali.student.contract.writer.JavaClassWriter;
029    import org.kuali.student.contract.writer.service.GetterSetterNameCalculator;
030    import org.kuali.student.contract.writer.service.MessageStructureTypeCalculator;
031    import org.kuali.student.contract.writer.service.ServiceExceptionWriter;
032    
033    /**
034     *
035     * @author nwright
036     */
037    public class RemoteImplServiceWriter extends JavaClassWriter {
038    
039        private ServiceContractModel model;
040        private ModelFinder finder;
041        private String directory;
042        private String rootPackage;
043        private String servKey;
044        private List<ServiceMethod> methods;
045    
046        public RemoteImplServiceWriter(ServiceContractModel model,
047                String directory,
048                String rootPackage,
049                String servKey,
050                List<ServiceMethod> methods) {
051            super(directory + "/main/java", calcPackage(servKey, rootPackage), calcClassName(servKey));
052            this.model = model;
053            this.finder = new ModelFinder(model);
054            this.directory = directory;
055            this.rootPackage = rootPackage;
056            this.servKey = servKey;
057            this.methods = methods;
058        }
059    
060        public static String calcPackage(String servKey, String rootPackage) {
061    //        String pack = rootPackage + "." + servKey.toLowerCase() + ".";
062    //  StringBuffer buf = new StringBuffer (service.getVersion ().length ());
063    //  for (int i = 0; i < service.getVersion ().length (); i ++)
064    //  {
065    //   char c = service.getVersion ().charAt (i);
066    //   c = Character.toLowerCase (c);
067    //   if (Character.isLetter (c))
068    //   {
069    //    buf.append (c);
070    //    continue;
071    //   }
072    //   if (Character.isDigit (c))
073    //   {
074    //    buf.append (c);
075    //   }
076    //  }
077    //  pack = pack + buf.toString ();
078    //        pack = pack + "service.decorators";
079    //        return pack;
080            return rootPackage;
081        }
082    
083        public static String calcClassName(String servKey) {
084            String name = GetterSetterNameCalculator.calcInitUpper(servKey + "ServiceRemoteImpl");
085            if (name.startsWith("RICE.")) {
086             name = name.substring("RICE.".length());   
087            }
088            return name;
089        }
090    
091        public static String calcDecoratorClassName(String servKey) {
092            String name = GetterSetterNameCalculator.calcInitUpper(servKey + "ServiceDecorator");
093            if (name.startsWith("RICE.")) {
094             name = name.substring("RICE.".length());   
095            }
096            return name;
097        }
098    
099        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            writeHostUrlGetterSetter();
128    
129            indentPrintln("//");
130            indentPrintln("// Have to override and check for null because of a bug in CXF 2.3.8 our current version");
131            indentPrintln("// It was fixed in 2.6.1 but 2.3.8 still renders empty lists as null when transported by soap");
132            indentPrintln("// see http://stackoverflow.com/questions/11384986/apache-cxf-web-services-problems");
133            indentPrintln("//");
134            for (ServiceMethod method : methods) {
135                if (!method.getReturnValue().getType().endsWith("List")) {
136                    continue;
137                }
138    
139                indentPrintln("");
140    //            indentPrintln("/**");
141    //            indentPrintWrappedComment(method.getDescription());
142    //            indentPrintln("* ");
143    //            for (ServiceMethodParameter param : method.getParameters()) {
144    //                indentPrintWrappedComment("@param " + param.getName() + " - "
145    //                        + param.getType() + " - "
146    //                        + param.getDescription());
147    //            }
148    //            indentPrintWrappedComment("@return " + method.getReturnValue().
149    //                    getDescription());
150    //            indentPrintln("*/");
151                indentPrintln("@Override");
152                String type = method.getReturnValue().getType();
153                String realType = stripList(type);
154                indentPrint("public " + calcType(type, realType) + " " + method.getName()
155                        + "(");
156                // now do parameters
157                String comma = "";
158                for (ServiceMethodParameter param : method.getParameters()) {
159                    type = param.getType();
160                    realType = stripList(type);
161                    print(comma);
162                    print(calcType(type, realType));
163                    print(" ");
164                    print(param.getName());
165                    comma = ", ";
166                }
167                println(")");
168                // now do exceptions
169                comma = "throws ";
170                incrementIndent();
171                for (ServiceMethodError error : method.getErrors()) {
172                    indentPrint(comma);
173                    String exceptionClassName = calcExceptionClassName(error);
174                    String exceptionPackageName = this.calcExceptionPackageName(error);
175                    println(exceptionClassName);
176                    this.importsAdd(exceptionPackageName + "." + exceptionClassName);
177                    comma = "      ,";
178                }
179                decrementIndent();
180                openBrace();
181                type = method.getReturnValue().getType();
182                realType = stripList(type);
183                XmlType retValXmlType = finder.findXmlType(realType);
184                importsAdd(retValXmlType.getJavaPackage() + "." + retValXmlType.getName());
185                indentPrint("List<" + retValXmlType.getName() + "> list = this.getNextDecorator ()." + method.getName() + "(");
186                comma = "";
187                for (ServiceMethodParameter param : method.getParameters()) {
188                    type = param.getType();
189                    realType = stripList(type);
190                    print(comma);
191                    print(param.getName());
192                    comma = ", ";
193                }
194                println(");");
195                indentPrintln("if (list == null)");
196                openBrace();
197                importsAdd(ArrayList.class.getName());
198                indentPrintln("return new ArrayList<" + retValXmlType.getName() + "> ();");
199                closeBrace();
200                indentPrintln("return list;");
201                closeBrace();
202            }
203            closeBrace();
204    
205            this.writeJavaClassAndImportsOutToFile();
206            this.getOut().close();
207        }
208    
209        private String calcType(String type, String realType) {
210            XmlType t = finder.findXmlType(this.stripList(type));
211            return MessageStructureTypeCalculator.calculate(this, model, type, realType,
212                    t.getJavaPackage());
213        }
214    
215        private String stripList(String str) {
216            return GetterSetterNameCalculator.stripList(str);
217        }
218    
219        private String calcExceptionClassName(ServiceMethodError error) {
220            if (error.getClassName() == null) {
221                return ServiceExceptionWriter.calcClassName(error.getType());
222            }
223            return error.getClassName();
224        }
225    
226        private String calcExceptionPackageName(ServiceMethodError error) {
227            if (error.getClassName() == null) {
228                return ServiceExceptionWriter.calcPackage(rootPackage);
229            }
230            return error.getPackageName();
231        }
232    
233        private void writeHostUrlGetterSetter() {
234    
235            String initUpper = GetterSetterNameCalculator.calcInitUpper(servKey);
236            if (initUpper.startsWith("RICE.")) {
237                initUpper = initUpper.substring("RICE.".length());
238            }
239    
240            indentPrintln("private String hostUrl;");
241            println("");
242            indentPrintln("public String getHostUrl()");
243            openBrace();
244            indentPrintln("return hostUrl;");
245            closeBrace();
246            indentPrintln("public void setHostUrl(String hostUrl)");
247            openBrace();
248            indentPrintln("this.hostUrl = hostUrl;");
249            indentPrintln("if (hostUrl == null)");
250            openBrace();
251            indentPrintln("this.setNextDecorator(null);");
252            indentPrintln("return;");
253            closeBrace();
254            indentPrintln("URL wsdlURL;");
255            indentPrintln("try");
256            openBrace();
257            String constantsFile = initUpper + "ServiceConstants";
258            // TODO: figure out how to add import for the service constants
259            indentPrintln("String urlStr = hostUrl + \"/services/\" + " + constantsFile + ".SERVICE_NAME_LOCAL_PART + \"?wsdl\";");
260            indentPrintln("wsdlURL = new URL(urlStr);");
261            closeBrace();
262            indentPrintln("catch (MalformedURLException ex)");
263            openBrace();
264            indentPrintln("throw new IllegalArgumentException(ex);");
265            closeBrace();
266    
267            importsAdd("java.net.MalformedURLException");
268            importsAdd("java.net.URL");
269            importsAdd("javax.xml.namespace.QName");
270            importsAdd("javax.xml.ws.Service");
271            Service service = finder.findService(servKey);
272            importsAdd(service.getImplProject() + "." + service.getName());
273    
274            indentPrintln("QName qname = new QName(" + constantsFile + ".NAMESPACE, " + constantsFile + ".SERVICE_NAME_LOCAL_PART);");
275            indentPrintln("Service factory = Service.create(wsdlURL, qname);");
276            indentPrintln(service.getName() + " port = factory.getPort(" + service.getName() + ".class);");
277            indentPrintln("this.setNextDecorator(port);");
278            closeBrace();
279    
280        }
281    }