/* * Copyright 2012-2013 iDA MediaFoundry (www.ida-mediafoundry.be) * * 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 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package be.idamediafoundry.sofa.livecycle.dsc.util; import be.idamediafoundry.sofa.livecycle.maven.component.configuration.Component; import be.idamediafoundry.sofa.livecycle.maven.component.configuration.ConfigParameterType; import be.idamediafoundry.sofa.livecycle.maven.component.configuration.FaultType; import be.idamediafoundry.sofa.livecycle.maven.component.configuration.InputParameterType; import be.idamediafoundry.sofa.livecycle.maven.component.configuration.OperationType; import be.idamediafoundry.sofa.livecycle.maven.component.configuration.OutputParameterType; import be.idamediafoundry.sofa.livecycle.maven.component.configuration.Service; import com.thoughtworks.qdox.model.DocletTag; import com.thoughtworks.qdox.model.JavaClass; import com.thoughtworks.qdox.model.JavaMethod; import com.thoughtworks.qdox.model.JavaParameter; import com.thoughtworks.qdox.model.Type; import org.apache.maven.plugin.logging.Log; import java.util.List; import java.util.Map; /** * @author mike */ public class DocletDrivenQDoxComponentInfoExtractor extends AbstractQDoxComponentInfoExtractor { private static final String MAJOR_TAG = "major"; private static final String MINOR_TAG = "minor"; private static final String LARGE_ICON_TAG = "largeIcon"; private static final String SMALL_ICON_TAG = "smallIcon"; private static final String FACTORY_METHOD_TAG = "factoryMethod"; private static final String OUTPUT_PARAM_NAME_TAG = "outputParamName"; private static final String DEFAULT_TAG = "default"; private static final String REQUIRED_TAG = "required"; private static final String OPERATION_NAME_TAG = "operationName"; public DocletDrivenQDoxComponentInfoExtractor(String sourcePath, Log log) { super(sourcePath, log); } @Override public boolean acceptAsService(JavaClass javaClass) { //Naive implementation, kept as is for reverse compatibility (takes all public non-abstract, non-exception classes as service) return (!javaClass.isAbstract() && !javaClass.isInterface() && javaClass.isPublic() && !javaClass.isA("java.lang.Throwable")); } @Override public boolean acceptAsOperation(JavaMethod javaMethod) { Type methodResultType = javaMethod.getReturnType(); DocletTag factoryMethod = javaMethod.getTagByName(FACTORY_METHOD_TAG); return javaMethod.isPublic() && methodResultType != null && !javaMethod.isPropertyAccessor() && !javaMethod.isPropertyMutator() && factoryMethod == null; } @Override public boolean acceptAsConfigParameter(JavaMethod javaMethod) { return javaMethod.isPropertyMutator(); } public void populateComponent(Component component) { //Nothing here for doclets } public boolean populateServices(Service service, JavaClass serviceInfo) { service.setName(serviceInfo.getName()); service.setImplementationClass(serviceInfo.getFullyQualifiedName()); DocletTag smallIconTag = serviceInfo.getTagByName(SMALL_ICON_TAG); DocletTag largeIconTag = serviceInfo.getTagByName(LARGE_ICON_TAG); if (smallIconTag != null) { service.setSmallIcon(smallIconTag.getValue()); } if (largeIconTag != null) { service.setLargeIcon(largeIconTag.getValue()); } String comment = serviceInfo.getComment(); service.setHint(getFirstSentence(comment)); service.setDescription(comment); // Find factory method. JavaMethod factoryMethod = findDocletOnMethods(serviceInfo, FACTORY_METHOD_TAG); if (factoryMethod != null) { if (factoryMethod.isAbstract() || factoryMethod.isConstructor() || !factoryMethod.isPublic() || factoryMethod.isPropertyAccessor() || factoryMethod.isPropertyMutator() || !factoryMethod.isStatic()) { throw new IllegalStateException( "You should not annotate " + factoryMethod.getName() + " as FactoryMethod, it is not a valid factory method!"); } service.setFactoryMethod(factoryMethod.getName()); } return true; } public boolean populateAutoDeploy(Component component, Service.AutoDeploy autoDeploy, JavaClass serviceInfo) { autoDeploy.setServiceId(serviceInfo.getName()); autoDeploy.setCategoryId(component.getComponentId()); DocletTag major = serviceInfo.getTagByName(MAJOR_TAG); if (major != null) { try { autoDeploy.setMajorVersion(Integer.parseInt(major.getValue())); } catch (NumberFormatException e) { getLog().warn("The @major doclet tag should be an integer, but was \"" + major.getValue() + "\". This service will have a major version of 0!", e); } } DocletTag minor = serviceInfo.getTagByName(MINOR_TAG); if (minor != null) { try { autoDeploy.setMinorVersion(Integer.parseInt(minor.getValue())); } catch (NumberFormatException e) { getLog().warn("The @minor doclet tag should be an integer, but was \"" + minor.getValue() + "\". This service will have a minor version of 0!", e); } } return true; } public boolean populateOperation(OperationType operation, JavaMethod operationInfo, List<String> existingOperationNames) { DocletTag operationNameTag = operationInfo.getTagByName(OPERATION_NAME_TAG); String suggestedName = (operationNameTag == null ? null : operationNameTag.getValue()); generateOperationNameMethodTitle(existingOperationNames, operationInfo, operation, suggestedName); String comment = operationInfo.getComment(); operation.setHint(comment); return true; } public boolean populateInputParameter(InputParameterType inputParameter, JavaMethod operationInfo, JavaParameter parameterInfo) { Map<String, String> paramTagMap = getCommentMapForTag(operationInfo, PARAM_TAG); inputParameter.setName(parameterInfo.getName()); inputParameter.setType(getFullyQualifiedJavaType(parameterInfo.getType())); String comment = paramTagMap.get(parameterInfo.getName()); inputParameter.setHint(getFirstSentence(comment)); inputParameter.setDescription(comment); inputParameter.setTitle(generateTitle(parameterInfo.getName())); return true; } public boolean populateOutputParameter(OutputParameterType outputParameter, JavaMethod operationInfo) { Type methodResultType = operationInfo.getReturnType(); if (!methodResultType.equals(Type.VOID)) { DocletTag outputParamNameDocletTag = operationInfo.getTagByName(OUTPUT_PARAM_NAME_TAG); String outputParameterName = outputParamNameDocletTag == null ? DEFAULT_OUT_PARAM_NAME : outputParamNameDocletTag.getValue(); outputParameter.setName(outputParameterName); outputParameter.setTitle(outputParameterName); outputParameter.setType(getFullyQualifiedJavaType(methodResultType)); DocletTag returnDocletTag = operationInfo.getTagByName(RETURN_TAG); if (returnDocletTag != null) { String comment = returnDocletTag.getValue(); outputParameter.setHint(comment); } return true; } else { return false; } } public boolean populateFault(FaultType fault, JavaMethod operationInfo, Type faultInfo) { Map<String, String> exceptionTagMap = getCommentMapForTag(operationInfo, "throws"); String name = faultInfo.getJavaClass().getName(); fault.setName(name); fault.setType(faultInfo.getFullyQualifiedName()); fault.setTitle(generateTitle(name)); String comment = exceptionTagMap.get(name); fault.setHint(getFirstSentence(comment)); fault.setDescription(comment); return true; } public boolean populateConfigParameter(ConfigParameterType configParameter, JavaMethod configParameterInfo) { String comment = configParameterInfo.getComment(); String propertyName = configParameterInfo.getPropertyName(); if (propertyName.length() > 100) { // Following spec: name must be no larger then 100 characters configParameter.setProperty(propertyName); propertyName = propertyName.substring(0, 100); } configParameter.setName(propertyName); configParameter.setType(getFullyQualifiedJavaType(configParameterInfo.getPropertyType())); configParameter.setHint(comment); configParameter.setTitle(generateTitle(propertyName)); if (configParameterInfo.getTagByName(REQUIRED_TAG) != null) { configParameter.setRequired(Boolean.TRUE); } if (configParameterInfo.getTagByName(DEFAULT_TAG) != null) { configParameter.setDefaultValue(configParameterInfo.getTagByName(DEFAULT_TAG).getValue()); } return true; } private JavaMethod findDocletOnMethods(JavaClass javaClass, String doclet) { JavaMethod result = null; JavaMethod[] methods = javaClass.getMethods(); for (JavaMethod javaMethod : methods) { DocletTag tag = javaMethod.getTagByName(doclet); if (tag != null) { result = javaMethod; break; } } return result; } }