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 return GetterSetterNameCalculator.calcInitUpper(servKey + "ServiceRemoteImpl"); 085 } 086 087 public static String calcDecoratorClassName(String servKey) { 088 return GetterSetterNameCalculator.calcInitUpper(servKey + "ServiceDecorator"); 089 } 090 091 private static enum MethodType { 092 093 VALIDATE, CREATE, UPDATE 094 }; 095 096 private MethodType calcMethodType(ServiceMethod method) { 097 if (method.getName().startsWith("validate")) { 098 return MethodType.VALIDATE; 099 } 100 if (method.getName().startsWith("create")) { 101 return MethodType.CREATE; 102 } 103 if (method.getName().startsWith("update")) { 104 return MethodType.UPDATE; 105 } 106 return null; 107 } 108 109 /** 110 * Write out the entire file 111 * 112 * @param out 113 */ 114 public void write() { 115 indentPrint("public class " + calcClassName(servKey)); 116 println(" extends " + calcDecoratorClassName(servKey)); 117 // TODO: figure out how to add import for the decorator 118 openBrace(); 119 writeHostUrlGetterSetter(); 120 121 indentPrintln("//"); 122 indentPrintln("// Have to override and check for null because of a bug in CXF 2.3.8 our current version"); 123 indentPrintln("// It was fixed in 2.6.1 but 2.3.8 still renders empty lists as null when transported by soap"); 124 indentPrintln("// see http://stackoverflow.com/questions/11384986/apache-cxf-web-services-problems"); 125 indentPrintln("//"); 126 for (ServiceMethod method : methods) { 127 if (!method.getReturnValue().getType().endsWith("List")) { 128 continue; 129 } 130 131 indentPrintln(""); 132 // indentPrintln("/**"); 133 // indentPrintWrappedComment(method.getDescription()); 134 // indentPrintln("* "); 135 // for (ServiceMethodParameter param : method.getParameters()) { 136 // indentPrintWrappedComment("@param " + param.getName() + " - " 137 // + param.getType() + " - " 138 // + param.getDescription()); 139 // } 140 // indentPrintWrappedComment("@return " + method.getReturnValue(). 141 // getDescription()); 142 // indentPrintln("*/"); 143 indentPrintln("@Override"); 144 String type = method.getReturnValue().getType(); 145 String realType = stripList(type); 146 indentPrint("public " + calcType(type, realType) + " " + method.getName() 147 + "("); 148 // now do parameters 149 String comma = ""; 150 for (ServiceMethodParameter param : method.getParameters()) { 151 type = param.getType(); 152 realType = stripList(type); 153 print(comma); 154 print(calcType(type, realType)); 155 print(" "); 156 print(param.getName()); 157 comma = ", "; 158 } 159 println(")"); 160 // now do exceptions 161 comma = "throws "; 162 incrementIndent(); 163 for (ServiceMethodError error : method.getErrors()) { 164 indentPrint(comma); 165 String exceptionClassName = calcExceptionClassName(error); 166 String exceptionPackageName = this.calcExceptionPackageName(error); 167 println(exceptionClassName); 168 this.importsAdd(exceptionPackageName + "." + exceptionClassName); 169 comma = " ,"; 170 } 171 decrementIndent(); 172 openBrace(); 173 type = method.getReturnValue().getType(); 174 realType = stripList(type); 175 XmlType retValXmlType = finder.findXmlType(realType); 176 importsAdd(retValXmlType.getJavaPackage() + "." + retValXmlType.getName()); 177 indentPrint("List<" + retValXmlType.getName() + "> list = this.getNextDecorator ()." + method.getName() + "("); 178 comma = ""; 179 for (ServiceMethodParameter param : method.getParameters()) { 180 type = param.getType(); 181 realType = stripList(type); 182 print(comma); 183 print(param.getName()); 184 comma = ", "; 185 } 186 println(");"); 187 indentPrintln("if (list == null)"); 188 openBrace(); 189 importsAdd(ArrayList.class.getName()); 190 indentPrintln("return new ArrayList<" + retValXmlType.getName() + "> ();"); 191 closeBrace(); 192 indentPrintln("return list;"); 193 closeBrace(); 194 } 195 closeBrace(); 196 197 this.writeJavaClassAndImportsOutToFile(); 198 this.getOut().close(); 199 } 200 201 private String calcType(String type, String realType) { 202 XmlType t = finder.findXmlType(this.stripList(type)); 203 return MessageStructureTypeCalculator.calculate(this, model, type, realType, 204 t.getJavaPackage()); 205 } 206 207 private String stripList(String str) { 208 return GetterSetterNameCalculator.stripList(str); 209 } 210 211 private String calcExceptionClassName(ServiceMethodError error) { 212 if (error.getClassName() == null) { 213 return ServiceExceptionWriter.calcClassName(error.getType()); 214 } 215 return error.getClassName(); 216 } 217 218 private String calcExceptionPackageName(ServiceMethodError error) { 219 if (error.getClassName() == null) { 220 return ServiceExceptionWriter.calcPackage(rootPackage); 221 } 222 return error.getPackageName(); 223 } 224 225 private void writeHostUrlGetterSetter() { 226 227 String initUpper = GetterSetterNameCalculator.calcInitUpper(servKey); 228 229 indentPrintln("private String hostUrl;"); 230 println(""); 231 indentPrintln("public String getHostUrl()"); 232 openBrace(); 233 indentPrintln("return hostUrl;"); 234 closeBrace(); 235 indentPrintln("public void setHostUrl(String hostUrl)"); 236 openBrace(); 237 indentPrintln("this.hostUrl = hostUrl;"); 238 indentPrintln("if (hostUrl == null)"); 239 openBrace(); 240 indentPrintln("this.setNextDecorator(null);"); 241 indentPrintln("return;"); 242 closeBrace(); 243 indentPrintln("URL wsdlURL;"); 244 indentPrintln("try"); 245 openBrace(); 246 String constantsFile = initUpper + "ServiceConstants"; 247 // TODO: figure out how to add import for the service constants 248 indentPrintln("String urlStr = hostUrl + \"/services/\" + " + constantsFile + ".SERVICE_NAME_LOCAL_PART + \"?wsdl\";"); 249 indentPrintln("wsdlURL = new URL(urlStr);"); 250 closeBrace(); 251 indentPrintln("catch (MalformedURLException ex)"); 252 openBrace(); 253 indentPrintln("throw new IllegalArgumentException(ex);"); 254 closeBrace(); 255 256 importsAdd("java.net.MalformedURLException"); 257 importsAdd("java.net.URL"); 258 importsAdd("javax.xml.namespace.QName"); 259 importsAdd("javax.xml.ws.Service"); 260 Service service = finder.findService(servKey); 261 importsAdd(service.getImplProject() + "." + service.getName()); 262 263 indentPrintln("QName qname = new QName(" + constantsFile + ".NAMESPACE, " + constantsFile + ".SERVICE_NAME_LOCAL_PART);"); 264 indentPrintln("Service factory = Service.create(wsdlURL, qname);"); 265 indentPrintln(service.getName() + " port = factory.getPort(" + service.getName() + ".class);"); 266 indentPrintln("this.setNextDecorator(port);"); 267 closeBrace(); 268 269 } 270 }