All Downloads are FREE. Search and download functionalities are using the official Maven repository.

esa.mo.tools.stubgen.GeneratorJava Maven / Gradle / Ivy

The newest version!
/* ----------------------------------------------------------------------------
 * Copyright (C) 2013      European Space Agency
 *                         European Space Operations Centre
 *                         Darmstadt
 *                         Germany
 * ----------------------------------------------------------------------------
 * System                : CCSDS MO Service Stub Generator
 * ----------------------------------------------------------------------------
 * Licensed under the European Space Agency Public License, Version 2.0
 * You may not use this file except in compliance with the License.
 *
 * Except as expressly set forth in this License, the Software is provided to
 * You on an "as is" basis and without warranties of any kind, including without
 * limitation merchantability, fitness for a particular purpose, absence of
 * defects or errors, accuracy or non-infringement of intellectual property rights.
 * 
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 * ----------------------------------------------------------------------------
 */
package esa.mo.tools.stubgen;

import esa.mo.tools.stubgen.java.JavaClassWriter;
import esa.mo.tools.stubgen.java.JavaCompositeFields;
import esa.mo.tools.stubgen.java.JavaLists;
import esa.mo.tools.stubgen.specification.CompositeField;
import esa.mo.tools.stubgen.specification.NativeTypeDetails;
import esa.mo.tools.stubgen.specification.StdStrings;
import esa.mo.tools.stubgen.specification.TypeUtils;
import esa.mo.tools.stubgen.writers.AbstractLanguageWriter;
import esa.mo.tools.stubgen.writers.ClassWriter;
import esa.mo.tools.stubgen.writers.InterfaceWriter;
import esa.mo.tools.stubgen.writers.LanguageWriter;
import esa.mo.tools.stubgen.writers.MethodWriter;
import esa.mo.tools.stubgen.writers.TargetWriter;
import esa.mo.xsd.AnyTypeReference;
import esa.mo.xsd.AreaType;
import esa.mo.xsd.NamedElementReferenceWithCommentType;
import esa.mo.xsd.ServiceType;
import esa.mo.xsd.TypeReference;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBElement;

/**
 * Generates stubs and skeletons for CCSDS MO Service specifications for the
 * Java language.
 */
public class GeneratorJava extends GeneratorLangs {

    /**
     * The file extension for Java files.
     */
    public static final String JAVA_FILE_EXT = "java";
    /**
     * The file name for package level comments.
     */
    public static final String JAVA_PACKAGE_COMMENT_FILE_NAME = "package-info";

    /**
     * Constructor.
     *
     * @param logger The logger to use.
     */
    public GeneratorJava(org.apache.maven.plugin.logging.Log logger) {
        super(logger, true, true, false, true, false,
                new GeneratorConfiguration("org.ccsds.moims.mo.",
                        "structures",
                        "factory",
                        "body",
                        ".",
                        "(Object[]) null",
                        "MALSendOperation",
                        "MALSubmitOperation",
                        "MALRequestOperation",
                        "MALInvokeOperation",
                        "MALProgressOperation",
                        "MALPubSubOperation"));
    }

    @Override
    public String getShortName() {
        return "Java";
    }

    @Override
    public String getDescription() {
        return "Generates a Java language mapping.";
    }

    @Override
    public void init(String destinationFolderName,
            boolean generateStructures,
            boolean generateCOM,
            Map packageBindings,
            Map extraProperties) throws IOException {
        super.init(destinationFolderName, generateStructures, generateCOM, packageBindings, extraProperties);

        setRequiresDefaultConstructors(Boolean.valueOf(extraProperties.get("java.requiresDefaultConstructors")));

        addAttributeType(StdStrings.MAL, StdStrings.BLOB, false, "Blob", "");
        addAttributeType(StdStrings.MAL, StdStrings.BOOLEAN, true, "Boolean", "Boolean.FALSE");
        addAttributeType(StdStrings.MAL, StdStrings.DOUBLE, true, "Double", "Double.MAX_VALUE");
        addAttributeType(StdStrings.MAL, StdStrings.DURATION, false, "Duration", "");
        addAttributeType(StdStrings.MAL, StdStrings.FLOAT, true, "Float", "Float.MAX_VALUE");
        addAttributeType(StdStrings.MAL, StdStrings.INTEGER, true, "Integer", "Integer.MAX_VALUE");
        addAttributeType(StdStrings.MAL, StdStrings.IDENTIFIER, false, "Identifier", "");
        addAttributeType(StdStrings.MAL, StdStrings.LONG, true, "Long", "Long.MAX_VALUE");
        addAttributeType(StdStrings.MAL, StdStrings.OCTET, true, "Byte", "Byte.MAX_VALUE");
        addAttributeType(StdStrings.MAL, StdStrings.SHORT, true, "Short", "Short.MAX_VALUE");
        addAttributeType(StdStrings.MAL, StdStrings.UINTEGER, false, "UInteger", "");
        addAttributeType(StdStrings.MAL, StdStrings.ULONG, false, "ULong", "");
        addAttributeType(StdStrings.MAL, StdStrings.UOCTET, false, "UOctet", "");
        addAttributeType(StdStrings.MAL, StdStrings.USHORT, false, "UShort", "");
        addAttributeType(StdStrings.MAL, StdStrings.STRING, true, "String", "\"\"");
        addAttributeType(StdStrings.MAL, StdStrings.TIME, false, "Time", "");
        addAttributeType(StdStrings.MAL, StdStrings.FINETIME, false, "FineTime", "");
        addAttributeType(StdStrings.MAL, StdStrings.URI, false, "URI", "");
        addAttributeType(StdStrings.MAL, StdStrings.OBJECTREF, false, "ObjectRef", "");

        super.addNativeType("boolean", new NativeTypeDetails("boolean", false, false, null));
        super.addNativeType("_String", new NativeTypeDetails("String", false, false, null));
        super.addNativeType("byte", new NativeTypeDetails("byte", false, false, null));
        super.addNativeType("short", new NativeTypeDetails("short", false, false, null));
        super.addNativeType("int", new NativeTypeDetails("int", false, false, null));
        super.addNativeType("long", new NativeTypeDetails("long", false, false, null));
        super.addNativeType("_Integer", new NativeTypeDetails("Integer", true, false, null));
        super.addNativeType("Class", new NativeTypeDetails("Class", true, false, null));
        super.addNativeType("Map", new NativeTypeDetails("java.util.Map", true, false, null));
        super.addNativeType("Vector", new NativeTypeDetails("java.util.Vector", true, false, null));
    }

    @Override
    public void createRequiredPublisher(String destinationFolderName, String fqPublisherName, RequiredPublisher publisher) throws IOException {
        logger.info(" > Creating Publisher class: " + fqPublisherName);

        String publisherName = fqPublisherName.substring(fqPublisherName.lastIndexOf('.') + 1);
        ClassWriter file = createClassFile(destinationFolderName, fqPublisherName.replace('.', '/'));

        file.addPackageStatement(publisher.getArea(), publisher.getService(), PROVIDER_FOLDER);

        String throwsMALException = createElementType(StdStrings.MAL, null, null, StdStrings.MALEXCEPTION);
        String throwsInteractionException = createElementType(StdStrings.MAL, null, null, StdStrings.MALINTERACTIONEXCEPTION);
        String throwsInteractionAndMALException = throwsInteractionException + ", " + throwsMALException;
        String throwsExceptions = "java.lang.IllegalArgumentException, " + throwsInteractionAndMALException;
        CompositeField publisherSetType = createCompositeElementsDetails(file, false, "publisherSet",
                TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALPublisherSet", false),
                false, true, null);

        file.addClassOpenStatement(publisherName, true, false, null, null,
                "Publisher class for the " + publisher.getOperation().getName() + " operation.");

        file.addClassVariable(false, false, StdStrings.PRIVATE, publisherSetType, false, (String) null);

        MethodWriter method = file.addConstructor(StdStrings.PUBLIC, publisherName,
                createCompositeElementsDetails(file, false, "publisherSet",
                        TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALPublisherSet", false),
                        false, true, "The set of broker connections to use when registering and publishing."),
                false, null, "Creates an instance of this class using the supplied publisher set.", null);
        method.addLine("this.publisherSet = publisherSet");
        method.addMethodCloseStatement();

        CompositeField keyNamesList = createCompositeElementsDetails(file, false, "keyNames",
                TypeUtils.createTypeReference(StdStrings.MAL, null, "Identifier", true),
                true, true, "The key names to use in the method");
        CompositeField keyTypesList = createCompositeElementsDetails(file, false, "keyTypes",
                TypeUtils.createTypeReference(StdStrings.MAL, null, "AttributeType", true),
                true, true, "The key types to use in the method");
        CompositeField psListener = createCompositeElementsDetails(file, false, "listener",
                TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALPublishInteractionListener", false),
                false, true,
                "The listener object to use for callback from the publisher");
        List argPSListenerList = new LinkedList<>();
        argPSListenerList.add(keyNamesList);
        argPSListenerList.add(keyTypesList);
        argPSListenerList.add(psListener);

        // register method
        method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
                false, true, null, "register", argPSListenerList, throwsExceptions,
                "Registers this provider implementation to the set of broker connections", null,
                Arrays.asList("java.lang.IllegalArgumentException If any supplied argument is invalid",
                        throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
                        throwsMALException + " if there is an implementation exception"));
        method.addLine("publisherSet.register(keyNames, keyTypes, listener)");
        method.addMethodCloseStatement();

        // registerWithDefaultKeys method
        List listenerAuto = new LinkedList<>();
        listenerAuto.add(psListener);
        method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
                false, true, null, "registerWithDefaultKeys", listenerAuto, throwsExceptions,
                "Registers this provider implementation to the set of broker connections with the default subscription keys", null,
                Arrays.asList("java.lang.IllegalArgumentException If any supplied argument is invalid",
                        throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
                        throwsMALException + " if there is an implementation exception"));
        method.addLine("org.ccsds.moims.mo.mal.structures.IdentifierList keyNames = new org.ccsds.moims.mo.mal.structures.IdentifierList()");
        method.addLine("org.ccsds.moims.mo.mal.structures.AttributeTypeList keyTypes = new org.ccsds.moims.mo.mal.structures.AttributeTypeList()");

        if (publisher.getOperation() != null) {
            AnyTypeReference keys = publisher.getOperation().getSubscriptionKeys();

            if (keys != null) {
                for (Object key : keys.getAny()) {
                    JAXBElement jaxbElement = (JAXBElement) key;
                    NamedElementReferenceWithCommentType aaa = (NamedElementReferenceWithCommentType) jaxbElement.getValue();
                    method.addLine("keyNames.add(new org.ccsds.moims.mo.mal.structures.Identifier(\"" + aaa.getName() + "\"))");
                    method.addLine("keyTypes.add(org.ccsds.moims.mo.mal.structures.AttributeType." + aaa.getType().getName().toUpperCase() + ")");
                }
            }
        }
        method.addLine("publisherSet.register(keyNames, keyTypes, listener)");
        method.addMethodCloseStatement();

        // asyncRegister method
        method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
                false, true, null, "asyncRegister", argPSListenerList, throwsExceptions,
                "Asynchronously registers this provider implementation to the set of broker connections", null,
                Arrays.asList("java.lang.IllegalArgumentException If any supplied argument is invalid",
                        throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
                        throwsMALException + " if there is an implementation exception"));
        method.addLine("publisherSet.asyncRegister(keyNames, keyTypes, listener)");
        method.addMethodCloseStatement();

        List argList = new LinkedList<>();
        argList.add(createCompositeElementsDetails(file, true, "updateHeader",
                TypeUtils.createTypeReference(StdStrings.MAL, null, "UpdateHeader", false),
                true, true, "The headers of the updates being added"));
        argList.addAll(createOperationArguments(getConfig(), file, publisher.getOperation().getUpdateTypes()));

        String argNameList = "";

        if (argList.size() > 1) {
            List strList = new LinkedList<>();

            for (int i = 1; i < argList.size(); i++) {
                strList.add(argList.get(i).getFieldName());
            }

            argNameList = StubUtils.concatenateStringArguments(true, strList.toArray(new String[0]));
        }

        method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
                false, true, null, "publish", argList, throwsExceptions,
                "Publishes updates to the set of registered broker connections", null,
                Arrays.asList("java.lang.IllegalArgumentException If any supplied argument is invalid",
                        throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
                        throwsMALException + " if there is an implementation exception"));
        method.addLine("publisherSet.publish(updateHeader" + argNameList + ")");
        method.addMethodCloseStatement();

        method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
                false, true, null, "deregister", null, throwsInteractionAndMALException,
                "Deregisters this provider implementation from the set of broker connections", null,
                Arrays.asList(throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
                        throwsMALException + " if there is an implementation exception"));
        method.addLine("publisherSet.deregister()");
        method.addMethodCloseStatement();

        method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
                false, true, null, "asyncDeregister", Arrays.asList(psListener), throwsExceptions,
                "Asynchronously deregisters this provider implementation from the set of broker connections", null,
                Arrays.asList("java.lang.IllegalArgumentException If any supplied argument is invalid",
                        throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
                        throwsMALException + " if there is an implementation exception"));
        method.addLine("publisherSet.asyncDeregister(listener)");
        method.addMethodCloseStatement();

        method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
                false, true, null, "close", null, throwsMALException,
                "Closes this publisher", null, Arrays.asList(throwsMALException + " if there is an implementation exception"));
        method.addLine("publisherSet.close()");
        method.addMethodCloseStatement();

        file.addClassCloseStatement();

        file.flush();
    }

    @Override
    public void createListClass(File folder, AreaType area, ServiceType service,
            String srcTypeName, boolean isAbstract, Long shortFormPart) throws IOException {
        JavaLists javaLists = new JavaLists(this);
        String listName = srcTypeName + "List";

        if (isAbstract) {
            logger.info(" > Creating HeterogeneousList class: " + listName);
            javaLists.createHeterogeneousListClass(folder, area.getName(), service == null ? null : service.getName(), srcTypeName);
        } else {
            logger.info(" > Creating List class: " + listName);
            javaLists.createHomogeneousListClass(folder, area, service, srcTypeName, shortFormPart);
        }
    }

    @Override
    protected void addShortForm(ClassWriter file, long sf) throws IOException {
        file.addStatement("    private static final long serialVersionUID = " + sf + "L;");
        //file.addStatement("    @Deprecated");
        file.addMultilineComment("The TypeId of this Element as a long.");
        file.addStatement("    public static final Long SHORT_FORM = " + sf + "L;");
    }

    @Override
    protected void createAreaFolderComment(File structureFolder, AreaType area) throws IOException {
        String cmt = area.getComment();
        if (cmt == null) {
            cmt = "The " + area.getName() + " area.";
        }

        createFolderComment(structureFolder, area.getName(), null, null, cmt);
    }

    @Override
    protected void createServiceFolderComment(File structureFolder,
            String area, ServiceType service) throws IOException {
        createFolderComment(structureFolder, area, service.getName(), null, service.getComment());
    }

    @Override
    protected void createServiceConsumerFolderComment(File structureFolder,
            String area, String service) throws IOException {
        createFolderComment(structureFolder, area, service, CONSUMER_FOLDER,
                "Package containing the consumer stubs for the " + service + " service.");
    }

    @Override
    protected void createServiceProviderFolderComment(File structureFolder,
            String area, String service) throws IOException {
        createFolderComment(structureFolder, area, service, PROVIDER_FOLDER,
                "Package containing the provider skeletons for the " + service + " service.");
    }

    @Override
    protected void createServiceMessageBodyFolderComment(String baseFolder,
            String area, String service) throws IOException {
        String basePackageName = getConfig().getAreaPackage(area);
        String packageName = basePackageName + "." + area.toLowerCase();
        if (service != null) {
            packageName += "." + service.toLowerCase();
        }

        String className = packageName + "." + getConfig().getBodyFolder() + "." + JAVA_PACKAGE_COMMENT_FILE_NAME;
        className = className.replace('.', '/');
        ClassWriter file = createClassFile(baseFolder, className);

        createFolderComment(file, area, service, getConfig().getBodyFolder(),
                "Package containing the types for holding compound messages.");
    }

    @Override
    protected void createAreaStructureFolderComment(File structureFolder, String area) throws IOException {
        createFolderComment(structureFolder, area, null, getConfig().getStructureFolder(),
                "Package containing types defined in the " + area + " area.");
    }

    @Override
    protected void createServiceStructureFolderComment(File structureFolder,
            String area, String service) throws IOException {
        createFolderComment(structureFolder, area, service, getConfig().getStructureFolder(),
                "Package containing types defined in the " + service + " service.");
    }

    /**
     * Creates a java package file.
     *
     * @param structureFolder The folder containing the generated code.
     * @param area the area.
     * @param service the server.
     * @param extraPackage any extra package level.
     * @param comment the comment.
     * @throws IOException if there is a problem.
     */
    protected void createFolderComment(File structureFolder, String area,
            String service, String extraPackage, String comment) throws IOException {
        ClassWriter file = createClassFile(structureFolder, JAVA_PACKAGE_COMMENT_FILE_NAME);
        createFolderComment(file, area, service, extraPackage, comment);
    }

    /**
     * Creates a java package file.
     *
     * @param file The folder containing the generated code.
     * @param area the area.
     * @param service the server.
     * @param extraPackage any extra package level.
     * @param comment the comment.
     * @throws IOException if there is a problem.
     */
    protected void createFolderComment(ClassWriter file, String area,
            String service, String extraPackage, String comment) throws IOException {
        List list = AbstractLanguageWriter.normaliseComment(new ArrayList(), comment);

        file.addStatement("/**");

        for (String line : list) {
            file.addStatement(" * " + line);
        }

        file.addStatement("*/");
        file.addPackageStatement(area, service, extraPackage);
        file.flush();
    }

    @Override
    public CompositeField createCompositeElementsDetails(TargetWriter file, boolean checkType,
            String fieldName, TypeReference elementType, boolean isStructure, boolean canBeNull, String comment) {
        JavaCompositeFields javaComposites = new JavaCompositeFields(this);
        return javaComposites.createCompositeElementsDetails((LanguageWriter) file,
                checkType, fieldName, elementType, isStructure, canBeNull, comment);
    }

    @Override
    protected String malStringAsElement(LanguageWriter file) {
        return createElementType(StdStrings.MAL, null, StdStrings.UNION);
    }

    @Override
    public ClassWriter createClassFile(File folder, String className) throws IOException {
        return new JavaClassWriter(folder, className, this);
    }

    @Override
    public ClassWriter createClassFile(String destinationFolderName, String className) throws IOException {
        return new JavaClassWriter(destinationFolderName, className, this);
    }

    @Override
    protected InterfaceWriter createInterfaceFile(File folder, String className) throws IOException {
        return new JavaClassWriter(folder, className, this);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy