/** * Create inner builder class, that is used within the child worker thread classes to create new * thread objects at runtime. The code that is generated by this method, makes use of the * Singleton and the Builder design pattern. * * @param workerThreadClassName Name of outer worker thread class * @return JClass object with inner builder class * @throws Exception Error during code generation */ private JClass createInnerBuilderClass(final String workerThreadClassName) throws Exception { String builderClassName = workerThreadClassName + "Builder"; // Create inner builder class JClass builderClass = JClass.factory.create( JModifier.PUBLIC | JModifier.STATIC | JModifier.FINAL, builderClassName); builderClass.setComment( new JClassCommentImpl(String.format("Inner '%s' class.", builderClassName))); LOGGER.debug( String.format( "Created '%s' class as inner class of '%s'.", builderClassName, workerThreadClassName)); /** * *************************************************************** Create fields * *************************************************************** */ JField instance = JField.factory.create(JModifier.PRIVATE | JModifier.STATIC, builderClassName, "instance"); instance.setComment(new JFieldCommentImpl("Builder instance for Singleton pattern")); builderClass.add(instance); JField request = JField.factory.create(JModifier.PRIVATE, this.messageClassFullName, "request"); builderClass.add(request); JField serviceProvider = JField.factory.create(JModifier.PRIVATE, this.serviceProviderClassName, "serviceProvider"); builderClass.add(serviceProvider); JField webSocket = JField.factory.create(JModifier.PRIVATE, "WebSocket", "webSocket"); builderClass.add(webSocket); /** * *************************************************************** Create constructor * *************************************************************** */ JConstructor constructor = JConstructor.factory.create(JModifier.PRIVATE, builderClassName); constructor.setComment( new JConstructorCommentImpl("Private constructor for Singleton pattern.")); // Set method body String methodBody = String.format("this.request = new %s();", this.messageClassFullName); constructor.getBody().setSource(methodBody); // Add constructor to class builderClass.add(constructor); /** * *************************************************************** Create method to get instance * *************************************************************** */ JMethod getInstance = JMethod.factory.create( JModifier.PUBLIC | JModifier.STATIC | JModifier.SYNCHRONIZED, builderClassName, "getInstance"); getInstance.setComment( new JMethodCommentImpl( "Create a new builder instance, if it does not yet exist, and return the object.")); // Set method body methodBody = String.format( "if (null == %s.instance) {\n" + "\t %s.instance = new %s();\n" + "}\n\n" + "return %s.instance;", builderClassName, builderClassName, builderClassName, builderClassName); getInstance.getBody().setSource(methodBody); // Add method to class builderClass.add(getInstance); /** * *************************************************************** Create method to set RPC * method *************************************************************** */ JParameter methodParameter = JParameter.factory.create(JModifier.FINAL, "String", "method"); JMethodSignature jms = JMethodSignature.factory.create(methodParameter); JMethod executeMethod = JMethod.factory.create(JModifier.PUBLIC, builderClassName, "executeMethod", jms); executeMethod.setComment(new JMethodCommentImpl("Set RPC method to execute.")); // Set method body methodBody = "this.request.setMethod(method);\n\n" + "return this;"; executeMethod.getBody().setSource(methodBody); // Add method to class builderClass.add(executeMethod); /** * *************************************************************** Create method to set data of * request *************************************************************** */ JParameter uuidParameter = JParameter.factory.create(JModifier.FINAL, "String", "uuid"); JParameter payloadParameter = JParameter.factory.create(JModifier.FINAL, "String", "payload"); jms = JMethodSignature.factory.create(uuidParameter, payloadParameter); JMethod dataMethod = JMethod.factory.create(JModifier.PUBLIC, builderClassName, "withData", jms); dataMethod.setComment(new JMethodCommentImpl("Set data of request.")); // Set method body methodBody = "this.request.setUUID(uuid);\n" + "this.request.setPayload(payload);\n\n" + "return this;"; dataMethod.getBody().setSource(methodBody); // Add method to class builderClass.add(dataMethod); /** * *************************************************************** Create method to set service * provider *************************************************************** */ JParameter serviceProviderParameter = JParameter.factory.create( JModifier.FINAL, this.serviceProviderClassName, "serviceProvider"); jms = JMethodSignature.factory.create(serviceProviderParameter); JMethod providerMethod = JMethod.factory.create(JModifier.PUBLIC, builderClassName, "onProvider", jms); providerMethod.setComment(new JMethodCommentImpl("Set service provider to use.")); // Set method body methodBody = "this.serviceProvider = serviceProvider;\n\n" + "return this;"; providerMethod.getBody().setSource(methodBody); // Add method to class builderClass.add(providerMethod); /** * *************************************************************** Create method to set * connection *************************************************************** */ JParameter webSocketParameter = JParameter.factory.create(JModifier.FINAL, "WebSocket", "webSocket"); jms = JMethodSignature.factory.create(webSocketParameter); JMethod connectionMethod = JMethod.factory.create(JModifier.PUBLIC, builderClassName, "viaConnection", jms); connectionMethod.setComment(new JMethodCommentImpl("Set connection for communication.")); // Set method body methodBody = "this.webSocket = webSocket;\n\n" + "return this;"; connectionMethod.getBody().setSource(methodBody); // Add method to class builderClass.add(connectionMethod); /** * *************************************************************** Create method to build worker * thread object *************************************************************** */ JMethod buildMethod = JMethod.factory.create(JModifier.PUBLIC, workerThreadClassName, "build"); buildMethod.addException("Exception"); buildMethod.setComment(new JMethodCommentImpl("Build the worker thread object.")); // Set method body methodBody = String.format( "if (null == this.request || null == this.serviceProvider || null == this.webSocket || " + "null == this.request.method() || null == this.request.uuid() || null == this.request.payload()) {\n" + "\tthrow new Exception(\"Initialize '%s' object properly before building.\");\n" + "}\n\n" + "// Message is a per-request object, so we need to create a DEEP COPY here!\n" + "%s requestCopy = new %s(this.request.asString());\n\n" + "return new %s(this.serviceProvider, this.webSocket, requestCopy);", workerThreadClassName, this.messageClassFullName, this.messageClassFullName, workerThreadClassName); buildMethod.getBody().setSource(methodBody); // Add method to class builderClass.add(buildMethod); return builderClass; }
/** * Create Java class for a single child worker thread. The generated class will be derived from * the base worker thread class and only contains a run() method to start the thread. * * <p>Furthermore, the code includes an inner class that utilizes the Singleton and Builder design * pattern, to create new worker thread objects at runtime. * * @param operation FOperation object from WSDL parser * @return JClass object with child worker thread class * @throws Exception Error during code generation */ private JClass createWorkerThreadClass(final FOperation operation) throws Exception { String rpcMethodName = WorkerThreadGenerator.firstLetterCapital(operation.getOperationName()); String workerClassName = rpcMethodName + "Worker"; // Create worker thread class JClass workerClass = JClass.factory.create(JModifier.PUBLIC, workerClassName); workerClass.setExtends(WORKER_THREAD_CLASS_NAME); workerClass.setComment( new JClassCommentImpl(String.format("The '%s' class.", workerClassName))); LOGGER.debug(String.format("Created '%s' class for child worker thread.", workerClassName)); /** * *************************************************************** Create fields * *************************************************************** */ JField logger = JField.factory.create( JModifier.PRIVATE | JModifier.STATIC | JModifier.FINAL, "Logger", "LOGGER", String.format("LoggerFactory.getLogger(%s.class)", workerClassName)); logger.setComment(new JFieldCommentImpl("Logger object.")); workerClass.add(logger); String builderClassName = workerClassName + "Builder"; JField builder = JField.factory.create( JModifier.PUBLIC | JModifier.STATIC | JModifier.FINAL, builderClassName, "BUILDER", String.format("%s.getInstance()", builderClassName)); builder.setComment( new JFieldCommentImpl( String.format("Builder instance to create new '%s' objects.", workerClassName))); workerClass.add(builder); /** * *************************************************************** Create constructor * *************************************************************** */ JParameter serviceProvider = JParameter.factory.create( JModifier.FINAL, this.serviceProviderClassName, "serviceProvider"); JParameter webSocket = JParameter.factory.create(JModifier.FINAL, "WebSocket", "webSocket"); JParameter requestMessage = JParameter.factory.create(JModifier.FINAL, this.messageClassFullName, "requestMessage"); JMethodSignature jms = JMethodSignature.factory.create(serviceProvider, webSocket, requestMessage); JConstructor constructor = JConstructor.factory.create(JModifier.PRIVATE, workerClassName, jms); constructor.setComment( new JConstructorCommentImpl( String.format("Constructor to create a new '%s' object.", workerClassName))); // Set method body String methodBody = "super(serviceProvider, webSocket, requestMessage);"; constructor.getBody().setSource(methodBody); // Add constructor to class workerClass.add(constructor); /** * *************************************************************** Create run method * *************************************************************** */ JMethod run = JMethod.factory.create(JModifier.PUBLIC, "void", "run"); run.addAnnotation(JMethodAnnotationImpl.OVERRIDE); run.setComment(new JMethodCommentImpl("Run worker thread to handle request.")); // Set method body run.getBody().setSource(this.createRunMethodBody(operation, rpcMethodName)); // Add method to class workerClass.add(run); /** * *************************************************************** Add inner builder class * *************************************************************** */ workerClass.add(this.createInnerBuilderClass(workerClassName)); return workerClass; }