001/** 002 * Copyright 2004-2014 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.opensource.org/licenses/ecl2.php 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 */ 016package org.kuali.student.remote.impl.mojo; 017 018import java.util.ArrayList; 019import java.util.List; 020import org.kuali.student.contract.model.Service; 021 022import org.kuali.student.contract.model.ServiceContractModel; 023import org.kuali.student.contract.model.ServiceMethod; 024import org.kuali.student.contract.model.ServiceMethodError; 025import org.kuali.student.contract.model.ServiceMethodParameter; 026import org.kuali.student.contract.model.XmlType; 027import org.kuali.student.contract.model.util.ModelFinder; 028import org.kuali.student.contract.writer.JavaClassWriter; 029import org.kuali.student.contract.writer.service.GetterSetterNameCalculator; 030import org.kuali.student.contract.writer.service.MessageStructureTypeCalculator; 031import org.kuali.student.contract.writer.service.ServiceExceptionWriter; 032 033/** 034 * 035 * @author nwright 036 */ 037public 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 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}