/*******************************************************************************
* Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*******************************************************************************/
package org.ebayopensource.turmeric.tools.codegen.builders;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import org.ebayopensource.turmeric.runtime.common.impl.internal.utils.ServiceNameUtils;
import org.ebayopensource.turmeric.runtime.common.impl.utils.LogManager;
import org.ebayopensource.turmeric.tools.codegen.CodeGenContext;
import org.ebayopensource.turmeric.tools.codegen.InputOptions;
import org.ebayopensource.turmeric.tools.codegen.JTypeTable;
import org.ebayopensource.turmeric.tools.codegen.SourceGenerator;
import org.ebayopensource.turmeric.tools.codegen.exception.CodeGenFailedException;
import org.ebayopensource.turmeric.tools.codegen.util.CodeGenConstants;
import org.ebayopensource.turmeric.tools.codegen.util.CodeGenUtil;
import org.ebayopensource.turmeric.tools.codegen.util.ContextClassLoaderUtil;
import com.sun.codemodel.JBlock;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JType;
/**
* Generates Service Implementation skeleton class based on interface.
*
*
* @author rmandapati
*/
public class ServiceSkeletonGenerator extends BaseCodeGenerator implements SourceGenerator {
private static ServiceSkeletonGenerator s_serviceSkeletonGenerator =
new ServiceSkeletonGenerator();
private static Logger s_logger = LogManager.getInstance(ServiceSkeletonGenerator.class);
private ServiceSkeletonGenerator() {}
public static ServiceSkeletonGenerator getInstance() {
return s_serviceSkeletonGenerator;
}
public boolean continueOnError() {
return false;
}
private Logger getLogger() {
return s_logger;
}
public void generate(CodeGenContext codeGenCtx) throws CodeGenFailedException {
// checking whether service impl skeleton need to be generated or not?
if (!shouldGenSkeletonClass(codeGenCtx)) {
return;
}
JTypeTable jTypeTable = codeGenCtx.getJTypeTable();
JCodeModel jCodeModel = new JCodeModel();
Class<?> svcInterfaceClass = jTypeTable.getClazz();
String svcSkeletonClassName =
generateQualifiedSkeletonClassName(
codeGenCtx.getServiceQName(),
codeGenCtx.getServiceImplClassName(),
svcInterfaceClass.getName(),
codeGenCtx);
JDefinedClass serviceSkeletonClass = createNewClass(jCodeModel, svcSkeletonClassName);
implement(serviceSkeletonClass, svcInterfaceClass);
List<Method> interfaceMethods = jTypeTable.getMethods();
JMethod[] jServiceMethods = addMethods(serviceSkeletonClass, interfaceMethods);
JMethod[] allSvcImplMethods = null;
if (!codeGenCtx.getInputOptions().isImplCommonSvcInterface()) {
allSvcImplMethods = new JMethod[jServiceMethods.length];
System.arraycopy(jServiceMethods, 0, allSvcImplMethods, 0, jServiceMethods.length);
}
else {
implement(serviceSkeletonClass, getCommonServiceInterface());
Method[] commonMethods = getCommonServiceInterface().getDeclaredMethods();
JMethod[] jCommonMethods = addMethods(serviceSkeletonClass, commonMethods);
allSvcImplMethods = new JMethod[jServiceMethods.length + jCommonMethods.length];
System.arraycopy(jServiceMethods, 0, allSvcImplMethods, 0, jServiceMethods.length);
System.arraycopy(jCommonMethods, 0, allSvcImplMethods, jServiceMethods.length, jCommonMethods.length);
}
addDummyImplementation(allSvcImplMethods, jCodeModel);
String destLocation = null;
if ( (codeGenCtx.getInputOptions().getCodeGenType() == InputOptions.CodeGenType.SISkeleton )
||
(codeGenCtx.getInputOptions().getCodeGenType() == InputOptions.CodeGenType.ServiceFromWSDLImpl)
){
destLocation = CodeGenUtil.toOSFilePath(codeGenCtx.getSrcLocation());
} else {
// [LEGACY] Adding extra "service" folder name.
destLocation =
generateDestLocation(
codeGenCtx.getJavaSrcDestLocation(),
CodeGenConstants.SERVICE_GEN_FOLDER);
}
generateJavaFile(jCodeModel, destLocation);
codeGenCtx.setServiceImplSkeletonName(svcSkeletonClassName);
String serviceImplJavaFilePath =
CodeGenUtil.toJavaSrcFilePath(destLocation, svcSkeletonClassName);
codeGenCtx.addGeneratedJavaSrcFile(serviceImplJavaFilePath);
if (codeGenCtx.getInputOptions().isNoCompile() == false) {
compileJavaFilesNoException(
codeGenCtx.getGeneratedJavaFiles(),
codeGenCtx.getBinLocation());
}
getLogger().log(Level.INFO, "Successfully generated " + svcSkeletonClassName);
}
private void addDummyImplementation(
JMethod[] jServiceMethods,
JCodeModel jCodeModel) throws CodeGenFailedException {
for (JMethod serviceMethod : jServiceMethods) {
JBlock methodBody = serviceMethod.body();
JType returnType = serviceMethod.type();
if ( returnType == null || returnType == jCodeModel.VOID) {
methodBody._return();
}
else {
methodBody._return(getValueForType(returnType));
}
}
}
private boolean shouldGenSkeletonClass(CodeGenContext codeGenCtx) {
boolean shouldGenSkeleton = false;
String serviceImplClassName = codeGenCtx.getServiceImplClassName();
//If externaleServiceFactoryMode then dont generate impl class SOAPLATFORM-497
if ( codeGenCtx.getInputOptions().isUseExternalServiceFactory() ) {
s_logger.log(Level.INFO, "It is factory mode. So dont generate the impl skeleton class");
shouldGenSkeleton = false;
} else if (CodeGenUtil.isEmptyString(serviceImplClassName)) {
shouldGenSkeleton = true;
s_logger.log(Level.INFO, "serviceImplClassName is empty");
} else {
String impleClassNameAsPath = CodeGenUtil.convertToFilePath(serviceImplClassName, ".class");
URL svcImplClass = this.getClass().getClassLoader().getResource(impleClassNameAsPath);
if (svcImplClass == null) {
s_logger.log(Level.INFO, "svcImplClass is empty");
// Check whether Service Impl source file exists?
shouldGenSkeleton = !isServiceImplSourceExists(codeGenCtx.getInputOptions());
} else {
s_logger.log(Level.INFO, "svcImplClass is not empty");
shouldGenSkeleton = codeGenCtx.getInputOptions().isGenSkeleton();
}
}
s_logger.log(Level.INFO, "value of shouldGenSkeleton "+ shouldGenSkeleton);
return shouldGenSkeleton;
}
private boolean isServiceImplSourceExists(InputOptions inputOptions) {
String[] allSrcLocations = inputOptions.getAllSrcLocations();
if (allSrcLocations == null || allSrcLocations.length == 0) {
allSrcLocations = new String[] { inputOptions.getSrcLocation() };
}
boolean isSvcImplExists = false;
for (String srcLoc : allSrcLocations) {
String serviceImplSrcFile =
CodeGenUtil.toJavaSrcFilePath(srcLoc, inputOptions.getServiceImplClassName());
isSvcImplExists = CodeGenUtil.isFileExists(serviceImplSrcFile);
if (isSvcImplExists) {
break;
}
}
return isSvcImplExists;
}
private String generateQualifiedSkeletonClassName(
QName svcQName,
String svcImplClassName,
String interfaceClassName, CodeGenContext codeGenCtx) {
String skeletonClassName = null;
InputOptions inputOptions = codeGenCtx.getInputOptions();
if (CodeGenUtil.isEmptyString(svcImplClassName)) {
skeletonClassName = defaultSkeletonClassName(svcQName, interfaceClassName);
}
else {
Class<?> svcImplClass = ContextClassLoaderUtil.loadOptionalClass(svcImplClassName);
if (svcImplClass == null || inputOptions.isOverWriteSkeleton()) {
skeletonClassName = svcImplClassName;
} else {
skeletonClassName =
generateQualifiedClassName(
svcImplClassName,
GEN_PKG_NAME,
svcImplClass.getSimpleName());
}
}
return skeletonClassName;
}
private String defaultSkeletonClassName(QName svcQName, String interfaceClassName) {
String skeletonClassName =
ServiceNameUtils.getServiceImplSkeletonClassName(
svcQName.getLocalPart(),
interfaceClassName);
return skeletonClassName;
}
public String getFilePath(String serviceAdminName, String interfaceName){
return null;
}
}