esa.mo.tools.stubgen.GeneratorLangs Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of generator-java Show documentation
Show all versions of generator-java Show documentation
Generates Java APIs for CCSDS MO service specifications
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.JavaServiceInfo;
import esa.mo.tools.stubgen.java.JavaExceptions;
import esa.mo.tools.stubgen.java.JavaConsumer;
import esa.mo.tools.stubgen.java.JavaEnumerations;
import esa.mo.tools.stubgen.java.JavaHelpers;
import esa.mo.tools.stubgen.specification.AttributeTypeDetails;
import esa.mo.tools.stubgen.specification.CompositeField;
import esa.mo.tools.stubgen.specification.FieldInfo;
import esa.mo.tools.stubgen.specification.InteractionPatternEnum;
import esa.mo.tools.stubgen.specification.MultiReturnType;
import esa.mo.tools.stubgen.specification.OperationSummary;
import esa.mo.tools.stubgen.specification.ServiceSummary;
import esa.mo.tools.stubgen.specification.StdStrings;
import esa.mo.tools.stubgen.specification.TypeUtils;
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.*;
import esa.mo.xsd.util.XmlSpecification;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import org.apache.maven.plugin.logging.Log;
/**
* Main generator class for programming languages. Iterates over the
* specification model drilling down into the parts of the model and inspecting
* them. Generates stubs and skeletons appropriate to an object orientated
* language.
*/
public abstract class GeneratorLangs extends GeneratorBase {
/**
* The bit shift value for the area part of a Type Id.
*/
public static final int AREA_BIT_SHIFT = 48;
/**
* The bit shift value for the service part of a Type Id.
*/
public static final int SERVICE_BIT_SHIFT = 32;
/**
* The bit shift value for the version part of a Type Id.
*/
public static final int VERSION_BIT_SHIFT = 24;
/**
* The folder that consumer interfaces are created.
*/
public static final String CONSUMER_FOLDER = "consumer";
/**
* The folder that provider interfaces are created.
*/
public static final String PROVIDER_FOLDER = "provider";
/**
* The folder that transport interfaces are held.
*/
public static final String TRANSPORT_FOLDER = "transport";
private final Map comObjectMap = new HashMap<>();
private final Map multiReturnTypeMap = new HashMap<>();
private final Map reservedWordsMap = new HashMap<>();
private final Map requiredPublishers = new HashMap<>();
public boolean supportsToString;
public boolean supportsEquals;
public boolean requiresDefaultConstructors;
public boolean supportsToValue;
private boolean supportsAsync;
private boolean generateStructures;
protected final Log logger;
/**
* Constructor.
*
* @param logger The logger to use.
* @param supportsToString True if should generate to string methods in
* types.
* @param supportsEquals True if should generate equals methods in types.
* @param supportsToValue True if should generate generic get value methods
* in types.
* @param supportsAsync True if should generate async consumer methods.
* @param requiresDefaultConstructors True if type require a default
* constructor.
* @param config The generator configuration.
*/
public GeneratorLangs(Log logger, boolean supportsToString, boolean supportsEquals,
boolean supportsToValue, boolean supportsAsync,
boolean requiresDefaultConstructors, GeneratorConfiguration config) {
super(config);
this.supportsToString = supportsToString;
this.supportsEquals = supportsEquals;
this.supportsToValue = supportsToValue;
this.supportsAsync = supportsAsync;
this.requiresDefaultConstructors = requiresDefaultConstructors;
this.logger = logger;
}
@Override
public void init(String destinationFolderName,
boolean generateStructures,
boolean generateCOM,
Map packageBindings,
Map extraProperties) throws IOException {
super.init(destinationFolderName, generateStructures, generateCOM, packageBindings, extraProperties);
this.generateStructures = generateStructures;
}
@Override
public void postinit(String destinationFolderName,
boolean generateStructures,
boolean generateCOM,
Map packageBindings,
Map extraProperties) throws IOException {
super.postinit(destinationFolderName, generateStructures, generateCOM, packageBindings, extraProperties);
addAttributeType(StdStrings.XML, "hexBinary", getAttributeDetails(StdStrings.MAL, StdStrings.BLOB));
addAttributeType(StdStrings.XML, "boolean", getAttributeDetails(StdStrings.MAL, StdStrings.BOOLEAN));
addAttributeType(StdStrings.XML, "double", getAttributeDetails(StdStrings.MAL, StdStrings.DOUBLE));
addAttributeType(StdStrings.XML, "duration", getAttributeDetails(StdStrings.MAL, StdStrings.DURATION));
addAttributeType(StdStrings.XML, "float", getAttributeDetails(StdStrings.MAL, StdStrings.FLOAT));
addAttributeType(StdStrings.XML, "int", getAttributeDetails(StdStrings.MAL, StdStrings.INTEGER));
addAttributeType(StdStrings.XML, "NCName", getAttributeDetails(StdStrings.MAL, StdStrings.IDENTIFIER));
addAttributeType(StdStrings.XML, "long", getAttributeDetails(StdStrings.MAL, StdStrings.LONG));
addAttributeType(StdStrings.XML, "byte", getAttributeDetails(StdStrings.MAL, StdStrings.OCTET));
addAttributeType(StdStrings.XML, "short", getAttributeDetails(StdStrings.MAL, StdStrings.SHORT));
addAttributeType(StdStrings.XML, "unsignedInt", getAttributeDetails(StdStrings.MAL, StdStrings.UINTEGER));
addAttributeType(StdStrings.XML, "unsignedLong", getAttributeDetails(StdStrings.MAL, StdStrings.ULONG));
addAttributeType(StdStrings.XML, "unsignedByte", getAttributeDetails(StdStrings.MAL, StdStrings.UOCTET));
addAttributeType(StdStrings.XML, "unsignedShort", getAttributeDetails(StdStrings.MAL, StdStrings.USHORT));
addAttributeType(StdStrings.XML, "string", getAttributeDetails(StdStrings.MAL, StdStrings.STRING));
addAttributeType(StdStrings.XML, "dateTime", getAttributeDetails(StdStrings.MAL, StdStrings.TIME));
addAttributeType(StdStrings.XML, "dateTime", getAttributeDetails(StdStrings.MAL, StdStrings.FINETIME));
addAttributeType(StdStrings.XML, "anyURI", getAttributeDetails(StdStrings.MAL, StdStrings.URI));
addAttributeType(StdStrings.XML, "ObjectRef", getAttributeDetails(StdStrings.MAL, StdStrings.OBJECTREF));
AttributeTypeDetails att = new AttributeTypeDetails(this, "Element", true, "Object", "");
addAttributeType(StdStrings.XML, "Element", att);
AttributeTypeDetails att1 = new AttributeTypeDetails(this, "Object", true, "Object", "");
addAttributeType(StdStrings.XML, "Element", att1);
}
@Override
public void loadXML(XmlSpecification xml) throws IOException, JAXBException {
super.loadXML(xml);
SpecificationType spec = xml.getSpecType();
// load in COM object/event definitions
for (AreaType area : spec.getArea()) {
for (ServiceType service : area.getService()) {
if (service instanceof ExtendedServiceType) {
ExtendedServiceType eService = (ExtendedServiceType) service;
SupportedFeatures features = eService.getFeatures();
if (null != features) {
if (null != features.getObjects()) {
for (ModelObjectType obj : features.getObjects().getObject()) {
TypeKey key = new TypeKey(area.getName(), service.getName(), String.valueOf(obj.getNumber()));
comObjectMap.put(key, obj);
}
}
if (null != features.getEvents()) {
for (ModelObjectType obj : features.getEvents().getEvent()) {
TypeKey key = new TypeKey(area.getName(), service.getName(), String.valueOf(obj.getNumber()));
comObjectMap.put(key, obj);
}
}
}
}
}
}
}
@Override
public void generate(String destinationFolderName, XmlSpecification xml,
JAXBElement rootNode) throws IOException, JAXBException {
long totalTime = System.currentTimeMillis();
SpecificationType spec = xml.getSpecType();
for (AreaType area : spec.getArea()) {
long timestamp = System.currentTimeMillis();
processArea(destinationFolderName, area, requiredPublishers);
timestamp = System.currentTimeMillis() - timestamp;
logger.info("-----------");
logger.info("Processed " + area.getName() + " area in " + timestamp + " ms");
logger.info("-----------");
}
for (Map.Entry entry : multiReturnTypeMap.entrySet()) {
String string = entry.getKey();
MultiReturnType rt = entry.getValue();
createMultiReturnType(destinationFolderName, string, rt);
}
logger.info("-----------");
totalTime = System.currentTimeMillis() - totalTime;
logger.info("Processed all Areas in " + totalTime + " ms");
}
@Override
public void close(String destinationFolderName) throws IOException {
// create any extra classes
for (Map.Entry ele : requiredPublishers.entrySet()) {
String string = ele.getKey();
if (!string.contains(".com.com.provider.") || generateCOM()) {
createRequiredPublisher(destinationFolderName, string, ele.getValue());
}
}
}
@Override
public void reset() {
super.reset();
comObjectMap.clear();
multiReturnTypeMap.clear();
reservedWordsMap.clear();
requiredPublishers.clear();
}
/**
* Does the generator support a string generator.
*
* @return True if it supports ToString.
*/
public boolean isSupportsToString() {
return supportsToString;
}
/**
* Does the generator support an equals method on structures.
*
* @return the supportsEquals
*/
public boolean isSupportsEquals() {
return supportsEquals;
}
/**
* Does the generator support a getMALValue method on structures.
*
* @return the supportsToValue
*/
public boolean isSupportsToValue() {
return supportsToValue;
}
/**
* Does the generator need to generate async operation methods.
*
* @return the supportsAsync
*/
public boolean isSupportsAsync() {
return supportsAsync;
}
/**
* Does the generator need to generate default constructors on structures
* and enumerations.
*
* @return the requiresDefaultConstructors
*/
public boolean isRequiresDefaultConstructors() {
return requiresDefaultConstructors;
}
/**
* Sets the generator default constructor value.
*
* @param requiresDefaultConstructors the requiresDefaultConstructors to set
*/
public void setRequiresDefaultConstructors(boolean requiresDefaultConstructors) {
this.requiresDefaultConstructors = requiresDefaultConstructors;
}
/**
* Does the generator need to generate structures.
*
* @return the generateStructures
*/
public boolean isGenerateStructures() {
return generateStructures;
}
/**
* To be used by derived generators to add an entry to the reserved word
* map.
*
* @param word The word to look for.
* @param replacement The replacement to use.
*/
protected void addReservedWord(String word, String replacement) {
reservedWordsMap.put(word, replacement);
}
protected void processArea(String destinationFolderName, AreaType area,
Map requiredPublishers) throws IOException {
if ((!area.getName().equalsIgnoreCase(StdStrings.COM)) || (generateCOM())) {
logger.info("Processing area: " + area.getName());
// create folder
File destinationFolder = StubUtils.createFolder(new File(destinationFolderName),
getConfig().getAreaPackage(area.getName()).replace('.', '/'));
final File areaFolder = StubUtils.createFolder(destinationFolder, area.getName());
ConcurrentLinkedQueue errors_2 = new ConcurrentLinkedQueue<>();
Thread t1 = new Thread() {
@Override
public void run() {
// create services
for (ServiceType service : area.getService()) {
try {
processService(areaFolder, area, service, requiredPublishers);
} catch (IOException ex) {
errors_2.add(ex);
}
}
}
};
t1.start();
// Create a comment for the area folder if supported
createAreaFolderComment(areaFolder, area);
// Create Area Helper
JavaHelpers helper = new JavaHelpers(this);
logger.info(" > Creating Area Helper class: " + area.getName());
helper.createAreaHelperClass(areaFolder, area);
// Create Area Exceptions
JavaExceptions exceptions = new JavaExceptions(this);
logger.info(" > Creating Area Exceptions for area: " + area.getName());
exceptions.createAreaExceptions(areaFolder, area);
// if area level types exist
if (generateStructures && (area.getDataTypes() != null)
&& !area.getDataTypes().getFundamentalOrAttributeOrComposite().isEmpty()) {
// create area structure folder
File structureFolder = StubUtils.createFolder(areaFolder, getConfig().getStructureFolder());
// create a comment for the structure folder if supported
createAreaStructureFolderComment(structureFolder, area.getName());
ConcurrentLinkedQueue errors_1 = new ConcurrentLinkedQueue<>();
// create area level data types
area.getDataTypes().getFundamentalOrAttributeOrComposite().parallelStream().forEach(oType -> {
try {
if (oType instanceof FundamentalType) {
createFundamentalClass(structureFolder, area.getName(), null, (FundamentalType) oType);
} else if (oType instanceof AttributeType) {
String aName = ((AttributeType) oType).getName();
createListClass(structureFolder, area, null, aName,
false, ((AttributeType) oType).getShortFormPart());
CompositeField fld = createCompositeElementsDetails(null, false, "fld",
TypeUtils.createTypeReference(area.getName(), null, aName, false),
true, true, "cmt");
} else if (oType instanceof CompositeType) {
createCompositeClass(structureFolder, area, null, (CompositeType) oType);
} else if (oType instanceof EnumerationType) {
JavaEnumerations enumerations = new JavaEnumerations(this);
EnumerationType enumType = (EnumerationType) oType;
logger.info(" > Creating Enumeration class: " + enumType.getName());
enumerations.createEnumerationClass(structureFolder, area, null, enumType);
} else {
throw new IllegalArgumentException("Unexpected area (" + area.getName() + ") level datatype of " + oType.getClass().getName());
}
} catch (Exception ex) {
errors_1.add(ex);
}
});
if (!errors_1.isEmpty()) {
throw (IOException) new IOException(errors_1.poll());
}
}
try {
t1.join();
} catch (InterruptedException ex) {
Logger.getLogger(GeneratorLangs.class.getName()).log(Level.SEVERE, null, ex);
}
if (!errors_2.isEmpty()) {
throw (IOException) new IOException(errors_2.poll());
}
}
}
protected void processService(File areaFolder, AreaType area, ServiceType service,
Map requiredPublishers) throws IOException {
logger.info("Processing service: " + service.getName());
// create service folders
File serviceFolder = StubUtils.createFolder(areaFolder, service.getName());
// load service operation details
ServiceSummary summary = createOperationElementList(service);
// create a comment for the service folder if supported
createServiceFolderComment(serviceFolder, area.getName(), service);
// create service helper
JavaHelpers helper = new JavaHelpers(this);
logger.info(" > Creating service Helper class: " + service.getName());
helper.createServiceHelperClass(serviceFolder, area.getName(), service, summary);
// create service info
JavaServiceInfo serviceInfo = new JavaServiceInfo(this);
logger.info(" > Creating ServiceInfo class: " + service.getName());
serviceInfo.createServiceInfoClass(serviceFolder, area, service, summary);
// create consumer classes
createServiceConsumerClasses(serviceFolder, area.getName(), service.getName(), summary);
// create provider classes
createServiceProviderClasses(serviceFolder, area.getName(), service.getName(), summary, requiredPublishers);
// if service level types exist
if (generateStructures && (service.getDataTypes() != null) && !service.getDataTypes().getCompositeOrEnumeration().isEmpty()) {
// create structure folder
File structureFolder = StubUtils.createFolder(serviceFolder, getConfig().getStructureFolder());
// create a comment for the structure folder if supported
createServiceStructureFolderComment(structureFolder, area.getName(), service.getName());
String name;
for (Object oType : service.getDataTypes().getCompositeOrEnumeration()) {
if (oType instanceof EnumerationType) {
JavaEnumerations enumerations = new JavaEnumerations(this);
EnumerationType enumType = (EnumerationType) oType;
logger.info(" > Creating Enumeration class: " + enumType.getName());
enumerations.createEnumerationClass(structureFolder, area, service, (EnumerationType) oType);
name = ((EnumerationType) oType).getName();
} else if (oType instanceof CompositeType) {
createCompositeClass(structureFolder, area, service, (CompositeType) oType);
name = ((CompositeType) oType).getName();
} else {
throw new IllegalArgumentException("Unexpected service (" + area.getName()
+ ":" + service.getName() + ") level datatype of " + oType.getClass().getName());
}
logger.warn("Warning! The data structure " + name
+ " is set at Service-level in the " + service.getName()
+ " service! Please move this data structure to Area-level"
+ " in order to be compatible with the latest MO Standard.");
}
}
}
protected void createServiceConsumerClasses(File serviceFolder, String area,
String service, ServiceSummary summary) throws IOException {
logger.info(" > Creating consumer classes: " + service);
File consumerFolder = StubUtils.createFolder(serviceFolder, CONSUMER_FOLDER);
// create a comment for the consumer folder if supported
createServiceConsumerFolderComment(consumerFolder, area, service);
createServiceConsumerInterface(consumerFolder, area, service, summary);
JavaConsumer consumer = new JavaConsumer(this, supportsToValue, supportsAsync);
logger.info(" > Creating consumer adapter: " + service);
consumer.createServiceConsumerAdapter(consumerFolder, area, service, summary);
logger.info(" > Creating consumer stub: " + service);
consumer.createServiceConsumerStub(consumerFolder, area, service, summary);
}
protected void createServiceProviderClasses(File serviceFolder, String area, String service,
ServiceSummary summary, Map requiredPublishers) throws IOException {
logger.info(" > Creating provider classes: " + service);
File providerFolder = StubUtils.createFolder(serviceFolder, PROVIDER_FOLDER);
// create a comment for the provider folder if supported
createServiceProviderFolderComment(providerFolder, area, service);
createServiceProviderHandler(providerFolder, area, service, summary);
createServiceProviderSkeleton(providerFolder, area, service, summary, requiredPublishers);
createServiceProviderInheritance(providerFolder, area, service, summary);
createServiceProviderInteractions(providerFolder, area, service, summary);
}
protected void createServiceProviderInheritance(File providerFolder, String area,
String service, ServiceSummary summary) throws IOException {
logger.info(" > Creating provider inheritance class: " + service);
createServiceProviderSkeletonHandler(providerFolder, area, service, summary, false);
}
protected void createServiceProviderInteractions(File providerFolder, String area,
String service, ServiceSummary summary) throws IOException {
for (OperationSummary op : summary.getOperations()) {
if (op.getPattern() == InteractionPatternEnum.INVOKE_OP) {
createServiceProviderInvokeInteractionClass(providerFolder, area, service, op);
} else if (op.getPattern() == InteractionPatternEnum.PROGRESS_OP) {
createServiceProviderProgressInteractionClass(providerFolder, area, service, op);
}
}
}
protected void createServiceConsumerInterface(File consumerFolder, String area,
String service, ServiceSummary summary) throws IOException {
String serviceName = service;
logger.info(" > Creating consumer interface: " + serviceName);
InterfaceWriter file = createInterfaceFile(consumerFolder, serviceName);
file.addPackageStatement(area, service, CONSUMER_FOLDER);
file.addInterfaceOpenStatement(serviceName, null, "Consumer interface for " + serviceName + " service.");
CompositeField serviceAdapterArg = createCompositeElementsDetails(file, false, "adapter",
TypeUtils.createTypeReference(area, service + "." + CONSUMER_FOLDER, serviceName + "Adapter", false),
false, true, "Listener in charge of receiving the messages from the service provider");
CompositeField lastInteractionStage = createCompositeElementsDetails(file, false, "lastInteractionStage",
TypeUtils.createTypeReference(StdStrings.MAL, null, StdStrings.UOCTET, false),
true, true, "The last stage of the interaction to continue");
CompositeField initiationTimestamp = createCompositeElementsDetails(file, false, "initiationTimestamp",
TypeUtils.createTypeReference(StdStrings.MAL, null, StdStrings.TIME, false),
true, true, "Timestamp of the interaction initiation message");
CompositeField transactionId = createCompositeElementsDetails(file, false, "transactionId",
TypeUtils.createTypeReference(StdStrings.MAL, null, StdStrings.LONG, false),
true, true, "Transaction identifier of the interaction to continue");
List continueOpArgs = StubUtils.concatenateArguments(lastInteractionStage, initiationTimestamp, transactionId, serviceAdapterArg);
String throwsMALException = createElementType(StdStrings.MAL, null, null, StdStrings.MALEXCEPTION);
String throwsInteractionException = createElementType(StdStrings.MAL, null, null, StdStrings.MALINTERACTIONEXCEPTION);
String throwsInteractionAndMALException = throwsInteractionException + ", " + throwsMALException;
CompositeField msgType = createCompositeElementsDetails(file, false, "return",
TypeUtils.createTypeReference(StdStrings.MAL, TRANSPORT_FOLDER, StdStrings.MALMESSAGE, false),
false, true, null);
CompositeField malConsumer = createCompositeElementsDetails(file, false, "return",
TypeUtils.createTypeReference(StdStrings.MAL, CONSUMER_FOLDER, "MALConsumer", false),
false, true, null);
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, malConsumer, "getConsumer", null, null,
"Returns the internal MAL consumer object used for sending of messages from this interface",
"The MAL consumer object.", null);
for (OperationSummary op : summary.getOperations()) {
switch (op.getPattern()) {
case SEND_OP: {
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, msgType, op.getName(),
createOperationArguments(getConfig(), file, op.getArgTypes()),
throwsInteractionAndMALException, op.getComment(),
"the MAL message sent to initiate the interaction",
Arrays.asList(throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
throwsMALException + " if there is an implementation exception"));
break;
}
case SUBMIT_OP:
case REQUEST_OP: {
List opArgs = createOperationArguments(getConfig(), file, op.getArgTypes());
CompositeField opRetType = createOperationReturnType(file, area, service, op);
String opRetComment = (opRetType == null) ? null : "The return value of the interaction";
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, opRetType, op.getName(), opArgs,
throwsInteractionAndMALException, op.getComment(), opRetComment,
Arrays.asList(throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
throwsMALException + " if there is an implementation exception"));
if (supportsAsync) {
List asyncOpArgs = StubUtils.concatenateArguments(opArgs, serviceAdapterArg);
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, msgType,
"async" + StubUtils.preCap(op.getName()), asyncOpArgs, throwsInteractionAndMALException,
"Asynchronous version of method " + op.getName(), "the MAL message sent to initiate the interaction",
Arrays.asList(throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
throwsMALException + " if there is an implementation exception"));
}
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, null, "continue" + StubUtils.preCap(op.getName()),
continueOpArgs, throwsInteractionAndMALException, "Continues a previously started interaction", 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"));
break;
}
case INVOKE_OP:
case PROGRESS_OP: {
List opArgs = StubUtils.concatenateArguments(createOperationArguments(getConfig(), file, op.getArgTypes()), serviceAdapterArg);
CompositeField opRetType = createOperationReturnType(file, area, service, op);
String opRetComment = (opRetType == null) ? null : "The acknowledge value of the interaction";
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, opRetType, op.getName(), opArgs,
throwsInteractionAndMALException, op.getComment(), opRetComment,
Arrays.asList(throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
throwsMALException + " if there is an implementation exception"));
if (supportsAsync) {
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, msgType, "async" + StubUtils.preCap(op.getName()), opArgs,
throwsInteractionAndMALException, "Asynchronous version of method " + op.getName(), "the MAL message sent to initiate the interaction",
Arrays.asList(throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
throwsMALException + " if there is an implementation exception"));
}
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, null, "continue" + StubUtils.preCap(op.getName()), continueOpArgs,
throwsInteractionAndMALException, "Continues a previously started interaction", 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"));
break;
}
case PUBSUB_OP: {
CompositeField subStr = createCompositeElementsDetails(file, false, "subscription",
TypeUtils.createTypeReference(StdStrings.MAL, null, "Subscription", false),
true, true, "The subscription to register for");
CompositeField idStr = createCompositeElementsDetails(file, false, "identifierList",
TypeUtils.createTypeReference(StdStrings.MAL, null, "Identifier", true),
true, true, "The subscription identifiers to deregister");
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, null, op.getName() + "Register", StubUtils.concatenateArguments(subStr, serviceAdapterArg),
throwsInteractionAndMALException, "Register method for the " + op.getName() + " PubSub interaction", 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"));
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, null, op.getName() + "Deregister", Arrays.asList(idStr),
throwsInteractionAndMALException, "Deregister method for the " + op.getName() + " PubSub interaction", 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"));
if (supportsAsync) {
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, msgType, "async" + StubUtils.preCap(op.getName()) + "Register",
StubUtils.concatenateArguments(subStr, serviceAdapterArg),
throwsInteractionAndMALException, "Asynchronous version of method " + op.getName() + "Register", "the MAL message sent to initiate the interaction",
Arrays.asList(throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
throwsMALException + " if there is an implementation exception"));
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, msgType, "async" + StubUtils.preCap(op.getName()) + "Deregister",
StubUtils.concatenateArguments(idStr, serviceAdapterArg),
throwsInteractionAndMALException, "Asynchronous version of method " + op.getName() + "Deregister", "the MAL message sent to initiate the interaction",
Arrays.asList(throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
throwsMALException + " if there is an implementation exception"));
}
break;
}
}
}
file.addInterfaceCloseStatement();
file.flush();
}
protected void createServiceProviderHandler(File providerFolder, String area,
String service, ServiceSummary summary) throws IOException {
logger.info(" > Creating provider handler interface: " + service);
String handlerName = service + "Handler";
InterfaceWriter file = createInterfaceFile(providerFolder, handlerName);
file.addPackageStatement(area, service, PROVIDER_FOLDER);
file.addInterfaceOpenStatement(handlerName, null,
"Interface that providers of the " + service + " service must implement to handle the operations of that service.");
CompositeField intHandler = createCompositeElementsDetails(file, false, "interaction",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, StdStrings.MALINTERACTION, false),
false, true, "The MAL object representing the interaction in the provider.");
String throwsMALException = createElementType(StdStrings.MAL, null, null, StdStrings.MALEXCEPTION);
String throwsInteractionException = createElementType(StdStrings.MAL, null, null, StdStrings.MALINTERACTIONEXCEPTION);
String throwsInteractionAndMALException = throwsInteractionException + ", " + throwsMALException;
for (OperationSummary op : summary.getOperations()) {
if (InteractionPatternEnum.PUBSUB_OP != op.getPattern()) {
List opArgs = createOperationArguments(getConfig(), file, op.getArgTypes());
CompositeField opRetType = null;
String opRetComment = null;
CompositeField serviceHandler = intHandler;
if (InteractionPatternEnum.REQUEST_OP == op.getPattern()) {
opRetType = createOperationReturnType(file, area, service, op);
opRetComment = "The return value of the operation";
} else if ((InteractionPatternEnum.INVOKE_OP == op.getPattern()) || (InteractionPatternEnum.PROGRESS_OP == op.getPattern())) {
serviceHandler = createCompositeElementsDetails(file, false, "interaction",
TypeUtils.createTypeReference(area,
service + "." + PROVIDER_FOLDER, StubUtils.preCap(op.getName()) + "Interaction", false),
false, true, "The MAL object representing the interaction in the provider.");
}
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, opRetType, op.getName(),
StubUtils.concatenateArguments(opArgs, serviceHandler), throwsInteractionAndMALException,
"Implements the operation " + op.getName(), opRetComment,
Arrays.asList(throwsInteractionException + " if there is a problem during the interaction as defined by the MAL specification.",
throwsMALException + " if there is an implementation exception"));
}
}
CompositeField skel = createCompositeElementsDetails(file, false, "skeleton",
TypeUtils.createTypeReference(area, service + "." + PROVIDER_FOLDER, service + "Skeleton", false),
false, true, "The skeleton to be used.");
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, null, "setSkeleton", Arrays.asList(skel), null,
"Sets the skeleton to be used for creation of publishers.", null, null);
file.addInterfaceCloseStatement();
file.flush();
}
protected void createServiceProviderInvokeInteractionClass(File providerFolder,
String area, String service, OperationSummary op) throws IOException {
String className = StubUtils.preCap(op.getName()) + "Interaction";
logger.info(" > Creating provider invoke interaction class: " + className);
ClassWriter file = createClassFile(providerFolder, className);
file.addPackageStatement(area, service, PROVIDER_FOLDER);
String throwsMALException = createElementType(StdStrings.MAL, null, null, StdStrings.MALEXCEPTION);
String throwsInteractionException = createElementType(StdStrings.MAL, null, null, StdStrings.MALINTERACTIONEXCEPTION);
String throwsInteractionAndMALException = throwsInteractionException + ", " + throwsMALException;
CompositeField msgType = createCompositeElementsDetails(file, false, "return",
TypeUtils.createTypeReference(StdStrings.MAL, TRANSPORT_FOLDER, StdStrings.MALMESSAGE, false),
false, true, null);
CompositeField opType = createCompositeElementsDetails(file, false, "return",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALInvoke", false),
false, true, null);
CompositeField opTypeVar = createCompositeElementsDetails(file, false, "interaction",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALInvoke", false),
false, false, null);
CompositeField errType = createCompositeElementsDetails(file, false, "error",
TypeUtils.createTypeReference(StdStrings.MAL, null, "MOErrorException", false),
false, true, "The MAL error to send to the consumer.");
file.addClassOpenStatement(className, false, false, null, null,
"Provider INVOKE interaction class for " + service + "::" + op.getName() + " operation.");
file.addClassVariable(false, false, StdStrings.PRIVATE, opTypeVar, false, (String) null);
MethodWriter method = file.addConstructor(StdStrings.PUBLIC, className,
createCompositeElementsDetails(file, false, "interaction",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALInvoke", false),
false, true, "The MAL interaction action object to use."), false, null,
"Wraps the provided MAL interaction object with methods for sending responses to an INVOKE interaction from a provider.", null);
method.addLine(createMethodCall("this.interaction = interaction"));
method.addMethodCloseStatement();
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
false, true, opType, "getInteraction", null, null,
"Returns the MAL interaction object used for returning messages from the provider.",
"The MAL interaction object provided in the constructor", null);
method.addLine("return interaction");
method.addMethodCloseStatement();
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
false, true, msgType, "sendAcknowledgement",
createOperationArguments(getConfig(), file, op.getAckTypes()), throwsInteractionAndMALException,
"Sends a INVOKE acknowledge to the consumer", "Returns the MAL message created by the acknowledge",
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(createMethodCall("return interaction.sendAcknowledgement(") + createArgNameOrNull(op.getAckTypes()) + ")");
method.addMethodCloseStatement();
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
false, true, msgType, "sendResponse",
createOperationArguments(getConfig(), file, op.getRetTypes()), throwsInteractionAndMALException,
"Sends a INVOKE response to the consumer", "Returns the MAL message created by the response",
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(createMethodCall("return interaction.sendResponse(") + createArgNameOrNull(op.getRetTypes()) + ")");
method.addMethodCloseStatement();
createServiceProviderInteractionErrorHandlers(file, false, msgType, errType, throwsInteractionException, throwsMALException);
file.addClassCloseStatement();
file.flush();
}
protected void createServiceProviderProgressInteractionClass(File providerFolder,
String area, String service, OperationSummary op) throws IOException {
String className = StubUtils.preCap(op.getName()) + "Interaction";
logger.info(" > Creating provider progress interaction class: " + className);
ClassWriter file = createClassFile(providerFolder, className);
file.addPackageStatement(area, service, PROVIDER_FOLDER);
String throwsMALException = createElementType(StdStrings.MAL, null, null, StdStrings.MALEXCEPTION);
String throwsInteractionException = createElementType(StdStrings.MAL, null, null, StdStrings.MALINTERACTIONEXCEPTION);
String throwsInteractionAndMALException = throwsInteractionException + ", " + throwsMALException;
CompositeField msgType = createCompositeElementsDetails(file, false, "return",
TypeUtils.createTypeReference(StdStrings.MAL, TRANSPORT_FOLDER, StdStrings.MALMESSAGE, false),
false, true, null);
CompositeField opType = createCompositeElementsDetails(file, false, "return",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALProgress", false),
false, true, null);
CompositeField opTypeVar = createCompositeElementsDetails(file, false, "interaction",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALProgress", false),
false, false, null);
CompositeField errType = createCompositeElementsDetails(file, false, "error",
TypeUtils.createTypeReference(StdStrings.MAL, null, "MOErrorException", false),
false, true, "error The MAL error to send to the consumer.");
file.addClassOpenStatement(className, false, false, null, null,
"Provider PROGRESS interaction class for " + service + "::" + op.getName() + " operation.");
file.addClassVariable(false, false, StdStrings.PRIVATE, opTypeVar,
false, (String) null);
MethodWriter method = file.addConstructor(StdStrings.PUBLIC, className,
createCompositeElementsDetails(file, false, "interaction",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALProgress", false),
false, true, "The MAL interaction action object to use."), false, null,
"Wraps the provided MAL interaction object with methods for sending responses to an PROGRESS interaction from a provider.", null);
method.addLine(createMethodCall("this.interaction = interaction"));
method.addMethodCloseStatement();
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
false, true, opType, "getInteraction", null, null,
"Returns the MAL interaction object used for returning messages from the provider.",
"The MAL interaction object provided in the constructor", null);
method.addLine("return interaction");
method.addMethodCloseStatement();
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
false, true, msgType, "sendAcknowledgement",
createOperationArguments(getConfig(), file, op.getAckTypes()), throwsInteractionAndMALException,
"Sends a PROGRESS acknowledge to the consumer", "Returns the MAL message created by the acknowledge",
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(createMethodCall("return interaction.sendAcknowledgement(") + createArgNameOrNull(op.getAckTypes()) + ")");
method.addMethodCloseStatement();
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
false, true, msgType, "sendUpdate",
createOperationArguments(getConfig(), file, op.getUpdateTypes()), throwsInteractionAndMALException,
"Sends a PROGRESS update to the consumer", "Returns the MAL message created by the update",
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(createMethodCall("return interaction.sendUpdate(") + createArgNameOrNull(op.getUpdateTypes()) + ")");
method.addMethodCloseStatement();
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
false, true, msgType, "sendResponse",
createOperationArguments(getConfig(), file, op.getRetTypes()), throwsInteractionAndMALException,
"Sends a PROGRESS response to the consumer", "Returns the MAL message created by the response",
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(createMethodCall("return interaction.sendResponse(") + createArgNameOrNull(op.getRetTypes()) + ")");
method.addMethodCloseStatement();
createServiceProviderInteractionErrorHandlers(file, true, msgType, errType, throwsInteractionException, throwsMALException);
file.addClassCloseStatement();
file.flush();
}
protected void createServiceProviderInteractionErrorHandlers(ClassWriter file, boolean withUpdate, CompositeField msgType,
CompositeField errType, String throwsInteractionException, String throwsMALException) throws IOException {
MethodWriter method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC, false, true,
msgType, "sendError", Arrays.asList(errType), throwsInteractionException + ", " + throwsMALException,
"Sends an error to the consumer", "Returns the MAL message created by the error",
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(createMethodCall("return interaction.sendError(error)"));
method.addMethodCloseStatement();
if (withUpdate) {
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC, false, true,
msgType, "sendUpdateError", Arrays.asList(errType), throwsInteractionException + ", " + throwsMALException,
"Sends an update error to the consumer", "Returns the MAL message created by the error",
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(createMethodCall("return interaction.sendUpdateError(error)"));
method.addMethodCloseStatement();
}
}
protected void createServiceProviderSkeleton(File providerFolder, String area, String service,
ServiceSummary summary, Map requiredPublishers) throws IOException {
logger.info(" > Creating provider skeleton interface: " + service);
String skeletonName = service + "Skeleton";
InterfaceWriter file = createInterfaceFile(providerFolder, skeletonName);
String throwsMALException = createElementType(StdStrings.MAL, null, null, StdStrings.MALEXCEPTION);
CompositeField malDomId = createCompositeElementsDetails(file, false, "domain",
TypeUtils.createTypeReference(StdStrings.MAL, null, StdStrings.IDENTIFIER, true),
true, true, "The domain used for publishing");
CompositeField malNetworkZone = createCompositeElementsDetails(file, false, "networkZone",
TypeUtils.createTypeReference(StdStrings.MAL, null, StdStrings.IDENTIFIER, false),
true, true, "~The network zone used for publishing");
CompositeField malSession = createCompositeElementsDetails(file, false, "sessionType",
TypeUtils.createTypeReference(StdStrings.MAL, null, "SessionType", false),
true, true, "The session used for publishing");
CompositeField malSessionName = createCompositeElementsDetails(file, false, "sessionName",
TypeUtils.createTypeReference(StdStrings.MAL, null, StdStrings.IDENTIFIER,
false), true, true, "The session name used for publishing");
CompositeField malqos = createCompositeElementsDetails(file, false, "qos",
TypeUtils.createTypeReference(StdStrings.MAL, null, "QoSLevel", false),
true, true, "The QoS used for publishing");
CompositeField malqosprops = createCompositeElementsDetails(file, false, "qosProps",
TypeUtils.createTypeReference(null, null, "Map<_String;_String>", false),
false, true, "The QoS properties used for publishing");
CompositeField malPriority = createCompositeElementsDetails(file, false, "priority",
TypeUtils.createTypeReference(StdStrings.MAL, null, StdStrings.UINTEGER, false),
true, true, "The priority used for publishing");
file.addPackageStatement(area, service, PROVIDER_FOLDER);
file.addInterfaceOpenStatement(skeletonName, null, "The skeleton interface for the " + service + " service.");
for (OperationSummary op : summary.getOperations()) {
switch (op.getPattern()) {
case PUBSUB_OP: {
String updateType = getConfig().getAreaPackage(area)
+ area.toLowerCase() + "." + service.toLowerCase()
+ "." + PROVIDER_FOLDER + "." + StubUtils.preCap(op.getName()) + "Publisher";
requiredPublishers.put(updateType, new RequiredPublisher(area, service, op));
CompositeField updateTypeField = createCompositeElementsDetails(file, false, "publisher",
TypeUtils.createTypeReference(area,
service + "." + PROVIDER_FOLDER, StubUtils.preCap(op.getName()) + "Publisher", false),
false, true, null);
file.addInterfaceMethodDeclaration(StdStrings.PUBLIC, updateTypeField, "create" + StubUtils.preCap(op.getName()) + "Publisher",
StubUtils.concatenateArguments(malDomId, malNetworkZone, malSession, malSessionName, malqos, malqosprops, malPriority), throwsMALException,
"Creates a publisher object using the current registered provider set for the PubSub operation " + op.getName(),
"The new publisher object.", Arrays.asList(throwsMALException + " if a problem is detected during creation of the publisher"));
break;
}
}
}
file.addInterfaceCloseStatement();
file.flush();
}
protected void createServiceProviderSkeletonHandler(File providerFolder, String area,
String service, ServiceSummary summary, boolean isDelegate) throws IOException {
String className = service;
String comment;
if (isDelegate) {
className += "DelegationSkeleton";
comment = "Provider Delegation skeleton for " + className + " service.";
} else {
className += "InheritanceSkeleton";
comment = "Provider Inheritance skeleton for " + className + " service.";
}
ClassWriter file = createClassFile(providerFolder, className);
file.addPackageStatement(area, service, PROVIDER_FOLDER);
String throwsMALException = createElementType(StdStrings.MAL, null, null, StdStrings.MALEXCEPTION);
String throwsInteractionException = createElementType(StdStrings.MAL, null, null, StdStrings.MALINTERACTIONEXCEPTION);
String throwsMALAndInteractionException = throwsInteractionException + ", " + throwsMALException;
String malHelper = createElementType(StdStrings.MAL, null, null, "MALHelper");
String helperName = createElementType(area, service, null, service + "Helper");
String serviceInfoName = createElementType(area, service, null, service + JavaServiceInfo.SERVICE_INFO);
String malString = malStringAsElement(file);
String malInteger = createElementType(StdStrings.MAL, null, StdStrings.INTEGER);
String stdError = createElementType(StdStrings.MAL, null, null, "MOErrorException");
CompositeField stdBodyArg = createCompositeElementsDetails(file, false, "body",
TypeUtils.createTypeReference(StdStrings.MAL, TRANSPORT_FOLDER, "MALMessageBody", false),
false, true, "The message body");
String stdErrorNs = convertToNamespace("," + stdError + ".," + malString + ".," + malInteger + ".");
CompositeField malDomId = createCompositeElementsDetails(file, false, "domain",
TypeUtils.createTypeReference(StdStrings.MAL, null, StdStrings.IDENTIFIER, true),
true, true, "The domain used for publishing");
CompositeField malNetworkZone = createCompositeElementsDetails(file, false, "networkZone",
TypeUtils.createTypeReference(StdStrings.MAL, null, StdStrings.IDENTIFIER, false),
true, true, "The network zone used for publishing");
CompositeField malSession = createCompositeElementsDetails(file, false, "sessionType",
TypeUtils.createTypeReference(StdStrings.MAL, null, "SessionType", false),
true, true, "The session used for publishing");
CompositeField malSessionName = createCompositeElementsDetails(file, false, "sessionName",
TypeUtils.createTypeReference(StdStrings.MAL, null, StdStrings.IDENTIFIER, false),
true, true, "The session name used for publishing");
CompositeField malqos = createCompositeElementsDetails(file, false, "qos",
TypeUtils.createTypeReference(StdStrings.MAL, null, "QoSLevel", false),
true, true, "The QoS used for publishing");
CompositeField malqosprops = createCompositeElementsDetails(file, false, "qosProps",
TypeUtils.createTypeReference(null, null, "Map<_String;_String>", false),
false, true, "The QoS properties used for publishing");
CompositeField malPriority = createCompositeElementsDetails(file, false, "priority",
TypeUtils.createTypeReference(StdStrings.MAL, null, StdStrings.UINTEGER, false),
true, true, "The priority used for publishing");
CompositeField proviedrSetVar = createCompositeElementsDetails(file, false, "providerSet",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALProviderSet", false),
false, true, null);
List psArgs = StubUtils.concatenateArguments(malDomId, malNetworkZone,
malSession, malSessionName, malqos, malqosprops, malPriority);
String implementsList = createElementType(StdStrings.MAL, null, PROVIDER_FOLDER, "MALInteractionHandler")
+ ", " + createElementType(area, service, PROVIDER_FOLDER, service + "Skeleton");
if (!isDelegate) {
implementsList += ", " + createElementType(area, service, PROVIDER_FOLDER, service + "Handler");
}
file.addClassOpenStatement(className, false, !isDelegate, null, implementsList, comment);
file.addClassVariable(false, false, StdStrings.PRIVATE, proviedrSetVar, false,
"(" + helperName + getConfig().getNamingSeparator() + service.toUpperCase() + "_SERVICE)");
if (isDelegate) {
CompositeField handlerName = createCompositeElementsDetails(file, false, "delegate",
TypeUtils.createTypeReference(area, service + "." + PROVIDER_FOLDER, service + "Handler", false),
false, true, null);
file.addClassVariable(false, false, StdStrings.PRIVATE, handlerName, false, (String) null);
}
if (isDelegate) {
MethodWriter method = file.addConstructor(StdStrings.PUBLIC, className,
createCompositeElementsDetails(file, false, "delegate",
TypeUtils.createTypeReference(area, service.toLowerCase() + "." + PROVIDER_FOLDER, service + "Handler", false),
false, true, "The interaction handler used for delegation"), false, null,
"Creates a delegation skeleton using the supplied delegate.", null);
method.addLine(createMethodCall("this.delegate = delegate"));
method.addLine(createMethodCall("delegate.setSkeleton(this)"));
method.addMethodCloseStatement();
} else {
// Connection object method
CompositeField connectionName = createCompositeElementsDetails(file, false, "connection",
TypeUtils.createTypeReference(StdStrings.MAL, "helpertools.connections", "ConnectionProvider", false),
false, true, "Returns the connection object for this provider.");
ArrayList throwsList = new ArrayList();
throwsList.add("java.io.IOException if the method was not implemented yet.");
MethodWriter method1 = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
false, true, connectionName, "getConnection", null, "java.io.IOException",
"Returns the connection object for this provider.",
"the connection object for this provider", throwsList);
method1.addLine("throw new java.io.IOException(\"This method needs to be overridden!\")");
method1.addMethodCloseStatement();
// SetSkeleton method
CompositeField skeletonName = createCompositeElementsDetails(file, false, "skeleton",
TypeUtils.createTypeReference(area, service + "." + PROVIDER_FOLDER, service + "Skeleton", false),
false, true, "Not used in the inheritance pattern (the skeleton is 'this'");
MethodWriter method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
false, true, null, "setSkeleton", Arrays.asList(skeletonName), null,
"Implements the setSkeleton method of the handler interface but does nothing as this is the skeleton.",
null, null);
method.addLine("// Not used in the inheritance pattern (the skeleton is 'this')");
method.addMethodCloseStatement();
}
CompositeField providerType = createCompositeElementsDetails(file, false, "provider",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALProvider", false),
false, true, "The provider to be added.");
MethodWriter method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
false, true, null, "malInitialize", Arrays.asList(providerType), throwsMALException,
"Adds the supplied MAL provider to the internal list of providers used for PubSub",
null, Arrays.asList(throwsMALException + " If an error is detected."));
method.addLine(createMethodCall("providerSet.addProvider(provider)"));
method.addMethodCloseStatement();
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC,
false, true, null, "malFinalize", Arrays.asList(providerType), throwsMALException,
"Removes the supplied MAL provider from the internal list of providers used for PubSub", null,
Arrays.asList(throwsMALException + " If an error is detected."));
method.addLine(createMethodCall("providerSet.removeProvider(provider)"));
method.addMethodCloseStatement();
// add publisher handler code
for (OperationSummary op : summary.getOperations()) {
switch (op.getPattern()) {
case PUBSUB_OP: {
CompositeField updateType = createCompositeElementsDetails(file, false, "publisher",
TypeUtils.createTypeReference(area, service + "." + PROVIDER_FOLDER, StubUtils.preCap(op.getName()) + "Publisher", false),
false, true, null);
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC, false, false,
updateType, "create" + StubUtils.preCap(op.getName()) + "Publisher", psArgs, throwsMALException,
"Creates a publisher object using the current registered provider set for the PubSub operation " + op.getName(),
"The new publisher object.", Arrays.asList(throwsMALException + " if a problem is detected during creation of the publisher"));
String ns = convertToNamespace(serviceInfoName + "." + op.getName().toUpperCase() + "_OP");
method.addMethodWithDependencyStatement("return new " + updateType.getTypeName()
+ createMethodCall("(providerSet.createPublisherSet(") + ns + ", domain, sessionType, sessionName, qos, qosProps, null))", ns, true);
method.addMethodCloseStatement();
break;
}
}
}
// for each IP type add handler code
String delegateCall = "";
if (isDelegate) {
delegateCall = createMethodCall("delegate.");
}
// SEND handler
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC, false, true, null, "handleSend",
StubUtils.concatenateArguments(createServiceProviderSkeletonSendHandler(file, "interaction", "The interaction object"), stdBodyArg),
throwsMALAndInteractionException,
"Called by the provider MAL layer on reception of a message to handle the interaction", null,
Arrays.asList(throwsMALException + " if there is a internal error", throwsInteractionException + " if there is a operation interaction error"));
String operationNumberGetter = createProviderSkeletonHandlerSwitch();
method.addLine("int opNumber = " + operationNumberGetter);
method.addLine(createMethodCall("switch (opNumber) {"), false);
//String msg = "Unknown operation number: \" + opNumber + \" - className: " + className + " - method: ";
String msg = "org.ccsds.moims.mo.mal.provider.MALInteractionHandler.ERROR_MSG_UNSUPPORTED + opNumber";
String unkErrorMsg;
for (OperationSummary op : summary.getOperations()) {
if (op.getPattern() == InteractionPatternEnum.SEND_OP) {
String opArgs = createAdapterMethodsArgs(op.getArgTypes(), "body", false, true);
String ns = convertToNamespace(serviceInfoName + "._" + op.getName().toUpperCase() + "_OP_NUMBER:");
method.addMethodWithDependencyStatement(" case " + ns, ns, false);
method.addLine(" " + delegateCall + op.getName() + "(" + opArgs + "interaction)");
method.addLine(" break");
}
}
method.addLine(" default:", false);
String ns = convertToNamespace(malHelper + ".UNSUPPORTED_OPERATION_ERROR_NUMBER");
unkErrorMsg = "(\"" + msg + "Send\")";
method.addMethodWithDependencyStatement(" throw new " + throwsInteractionException
+ "(new org.ccsds.moims.mo.mal.UnsupportedOperationException(\n "
+ msg + "))", ns + stdErrorNs, true);
method.addLine("}", false);
method.addMethodCloseStatement();
// SUBMIT handler
CompositeField submitInt = createCompositeElementsDetails(file, false, "interaction",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALSubmit", false),
false, true, "The interaction object");
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC, false, true, null, "handleSubmit",
StubUtils.concatenateArguments(submitInt, stdBodyArg), throwsMALAndInteractionException,
"Called by the provider MAL layer on reception of a message to handle the interaction", null,
Arrays.asList(throwsMALException + " if there is a internal error", throwsInteractionException + " if there is a operation interaction error"));
method.addLine("int opNumber = " + operationNumberGetter);
method.addLine(createMethodCall("switch (opNumber) {"), false);
for (OperationSummary op : summary.getOperations()) {
if (op.getPattern() == InteractionPatternEnum.SUBMIT_OP) {
String opArgs = createAdapterMethodsArgs(op.getArgTypes(), "body", false, true);
ns = convertToNamespace(serviceInfoName + "._" + op.getName().toUpperCase() + "_OP_NUMBER:");
method.addMethodWithDependencyStatement(" case " + ns, ns, false);
method.addLine(" " + delegateCall + op.getName() + "(" + opArgs + "interaction)");
method.addLine(createMethodCall(" interaction.sendAcknowledgement()"));
method.addLine(" break");
}
}
method.addLine(" default:", false);
ns = convertToNamespace(malHelper + ".UNSUPPORTED_OPERATION_ERROR_NUMBER");
unkErrorMsg = "(\"" + msg + "Submit\")";
method.addMethodWithDependencyStatement(createMethodCall(" interaction.sendError"
+ "(new org.ccsds.moims.mo.mal.UnsupportedOperationException(\n "
+ msg + "))"), ns + stdErrorNs, true);
method.addMethodWithDependencyStatement(" throw new " + throwsInteractionException
+ "(new org.ccsds.moims.mo.mal.UnsupportedOperationException(\n "
+ msg + "))", ns + stdErrorNs, true);
method.addLine("}", false);
method.addMethodCloseStatement();
// REQUEST handler
CompositeField requestInt = createCompositeElementsDetails(file, false, "interaction",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALRequest", false),
false, true, "The interaction object");
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC, false, true, null,
"handleRequest", StubUtils.concatenateArguments(requestInt, stdBodyArg), throwsMALAndInteractionException,
"Called by the provider MAL layer on reception of a message to handle the interaction", null,
Arrays.asList(throwsMALException + " if there is a internal error", throwsInteractionException + " if there is a operation interaction error"));
method.addLine("int opNumber = " + operationNumberGetter);
method.addLine(createMethodCall("switch (opNumber) {"), false);
for (OperationSummary op : summary.getOperations()) {
if (op.getPattern() == InteractionPatternEnum.REQUEST_OP) {
String opArgs = createAdapterMethodsArgs(op.getArgTypes(), "body", false, true);
String opResp = delegateCall + op.getName() + "(" + opArgs + "interaction)";
ns = convertToNamespace(serviceInfoName + "._" + op.getName().toUpperCase() + "_OP_NUMBER:");
method.addMethodWithDependencyStatement(" case " + ns, ns, false);
createRequestResponseDecompose(
method, op,
opResp,
createReturnType(file, area, service, op.getName(), "Response", op.getRetTypes())
);
method.addLine(" break");
}
}
method.addLine(" default:", false);
ns = convertToNamespace(malHelper + ".UNSUPPORTED_OPERATION_ERROR_NUMBER");
unkErrorMsg = "(\"" + msg + "Request\")";
method.addMethodWithDependencyStatement(createMethodCall(" interaction.sendError"
+ "(new org.ccsds.moims.mo.mal.UnsupportedOperationException(\n "
+ msg + "))"), ns + stdErrorNs, true);
method.addMethodWithDependencyStatement(" throw new " + throwsInteractionException
+ "(new org.ccsds.moims.mo.mal.UnsupportedOperationException(\n "
+ msg + "))", ns + stdErrorNs, true);
method.addLine("}", false);
method.addMethodCloseStatement();
// INVOKE handler
CompositeField invokeInt = createCompositeElementsDetails(file, false, "interaction",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALInvoke", false),
false, true, "The interaction object");
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC, false, true, null, "handleInvoke",
StubUtils.concatenateArguments(invokeInt, stdBodyArg), throwsMALAndInteractionException,
"Called by the provider MAL layer on reception of a message to handle the interaction", null,
Arrays.asList(throwsMALException + " if there is a internal error", throwsInteractionException + " if there is a operation interaction error"));
method.addLine("int opNumber = " + operationNumberGetter);
method.addLine(createMethodCall("switch (opNumber) {"), false);
for (OperationSummary op : summary.getOperations()) {
if (op.getPattern() == InteractionPatternEnum.INVOKE_OP) {
String opArgs = createAdapterMethodsArgs(op.getArgTypes(), "body", false, true);
ns = convertToNamespace(serviceInfoName + "._" + op.getName().toUpperCase() + "_OP_NUMBER:");
method.addMethodWithDependencyStatement(" case " + ns, ns, false);
method.addLine(" " + delegateCall + op.getName() + "(" + opArgs
+ "new " + StubUtils.preCap(op.getName()) + "Interaction" + "(interaction))");
method.addLine(" break");
}
}
method.addLine(" default:", false);
ns = convertToNamespace(malHelper + ".UNSUPPORTED_OPERATION_ERROR_NUMBER");
unkErrorMsg = "(\"" + msg + "Invoke\")";
method.addMethodWithDependencyStatement(createMethodCall(" interaction.sendError"
+ "(new org.ccsds.moims.mo.mal.UnsupportedOperationException(\n "
+ msg + "))"), ns + stdErrorNs, true);
method.addMethodWithDependencyStatement(" throw new " + throwsInteractionException
+ "(new org.ccsds.moims.mo.mal.UnsupportedOperationException(\n "
+ msg + "))", ns + stdErrorNs, true);
method.addLine("}", false);
method.addMethodCloseStatement();
// PROGRESS handler
CompositeField progressInt = createCompositeElementsDetails(file, false, "interaction",
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, "MALProgress", false),
false, true, "The interaction object");
method = file.addMethodOpenStatement(false, false, StdStrings.PUBLIC, false, true, null, "handleProgress",
StubUtils.concatenateArguments(progressInt, stdBodyArg), throwsMALAndInteractionException,
"Called by the provider MAL layer on reception of a message to handle the interaction", null,
Arrays.asList(throwsMALException + " if there is a internal error", throwsInteractionException + " if there is a operation interaction error"));
method.addLine("int opNumber = " + operationNumberGetter);
method.addLine(createMethodCall("switch (opNumber) {"), false);
for (OperationSummary op : summary.getOperations()) {
if (op.getPattern() == InteractionPatternEnum.PROGRESS_OP) {
String opArgs = createAdapterMethodsArgs(op.getArgTypes(), "body", false, true);
ns = convertToNamespace(serviceInfoName + "._" + op.getName().toUpperCase() + "_OP_NUMBER:");
method.addMethodWithDependencyStatement(" case " + ns, ns, false);
method.addLine(" " + delegateCall + op.getName() + "(" + opArgs + "new " + StubUtils.preCap(op.getName()) + "Interaction" + "(interaction))");
method.addLine(" break");
}
}
method.addLine(" default:", false);
ns = convertToNamespace(malHelper + ".UNSUPPORTED_OPERATION_ERROR_NUMBER");
unkErrorMsg = "(\"" + msg + "Progress\")";
method.addMethodWithDependencyStatement(createMethodCall(" interaction.sendError"
+ "(new org.ccsds.moims.mo.mal.UnsupportedOperationException(\n "
+ msg + "))"), ns + stdErrorNs, true);
method.addMethodWithDependencyStatement(" throw new " + throwsInteractionException
+ "(new org.ccsds.moims.mo.mal.UnsupportedOperationException(\n "
+ msg + "))", ns + stdErrorNs, true);
method.addLine("}", false);
method.addMethodCloseStatement();
file.addClassCloseStatement();
file.flush();
}
private void createRequestResponseDecompose(MethodWriter method, OperationSummary op,
String opCall, CompositeField opRetType) throws IOException {
List targetTypes = op.getRetTypes();
if ((targetTypes != null) && (!targetTypes.isEmpty())) {
if (targetTypes.size() == 1) {
if ((op.getRetTypes().get(0).isNativeType())) {
String arg = op.getName() + "Rt";
method.addLine(" " + opRetType.getTypeName() + " " + arg + " = " + opCall);
StringBuilder buf = new StringBuilder();
buf.append("(").append(arg).append(" == null) ? null : new ").append(getConfig().getAreaPackage(StdStrings.MAL));
buf.append("mal.").append(getConfig().getStructureFolder()).append(".").append(StdStrings.UNION);
buf.append("(").append(arg).append(")");
method.addLine(createMethodCall(" interaction.sendResponse(" + buf.toString() + ")"));
} else {
method.addLine(createMethodCall(" interaction.sendResponse(" + opCall + ")"));
}
} else {
String arg = op.getName() + "Rt";
StringBuilder buf = new StringBuilder();
for (int i = 0; i < targetTypes.size(); i++) {
FieldInfo ti = targetTypes.get(i);
if (i > 0) {
buf.append(", ");
}
if (ti.isNativeType()) {
buf.append("(").append(arg).append(".getBodyElement").append(i).append("()").append(" == null) ? null : new ");
buf.append(getConfig().getAreaPackage(StdStrings.MAL)).append("mal.").append(getConfig().getStructureFolder());
buf.append(".").append(StdStrings.UNION).append("(").append(arg).append(".getBodyElement").append(i).append("()").append(")");
} else {
buf.append(arg).append(".getBodyElement").append(i).append("()");
}
}
method.addLine(" " + opRetType.getTypeName() + " " + arg + " = " + opCall);
method.addLine(createMethodCall(" interaction.sendResponse(" + buf.toString() + ")"));
}
} else {
// operation has an empty response
method.addLine(createMethodCall(" " + opCall));
method.addLine(createMethodCall(" interaction.sendResponse()"));
}
}
public String getReferenceShortForm(AnyTypeReference ref) {
String rv = null;
if ((null != ref) && (null != ref.getAny()) && (!ref.getAny().isEmpty())) {
List refs = TypeUtils.convertTypeReferences(this, TypeUtils.getTypeListViaXSDAny(ref.getAny()));
rv = refs.get(0).getMalShortFormField();
}
return rv;
}
public String getReferenceShortForm(TargetWriter file, OptionalObjectReference oor) {
if (oor == null || oor.getObjectType() == null) {
return null;
}
ObjectReference any = oor.getObjectType();
String service = any.getService();
TypeKey key = new TypeKey(any.getArea(), service, String.valueOf(any.getNumber()));
if (!comObjectMap.containsKey(key)) {
logger.warn("Unknown COM object referenced: " + key);
return null;
}
ModelObjectType refObj = comObjectMap.get(key);
return convertToNamespace(createElementType(any.getArea(), service, null, service + JavaServiceInfo.SERVICE_INFO)
+ "." + refObj.getName().toUpperCase() + "_OBJECT_TYPE");
}
protected void createFundamentalClass(File folder, String area, String service, FundamentalType enumeration) throws IOException {
// fundamental types are usually hand created as part of a language mapping, but we have this here in case this
// is not the case for a particular language
}
protected void createCompositeClass(File folder, AreaType area, ServiceType service, CompositeType composite) throws IOException {
String className = composite.getName();
logger.info(" > Creating Composite class: " + className);
ClassWriter file = createClassFile(folder, className);
String parentClass = null;
TypeReference parentType = null;
String parentInterface = createElementType(StdStrings.MAL, null, StdStrings.COMPOSITE);
// Check if it is an extended Composite Type:
if (composite.getExtends() != null) {
parentType = composite.getExtends().getType();
if (!StdStrings.MAL.equals(composite.getExtends().getType().getArea())
&& !StdStrings.COMPOSITE.equals(composite.getExtends().getType().getName())) {
parentClass = createElementType(parentType, true);
parentInterface = null;
}
// Check if it is an MO Object:
if (StdStrings.MAL.equals(composite.getExtends().getType().getArea())
&& StdStrings.MOOBJECT.equals(composite.getExtends().getType().getName())) {
parentClass = createElementType(parentType, true);
parentInterface = null;
}
}
file.addPackageStatement(area.getName(), service == null ? null : service.getName(), getConfig().getStructureFolder());
CompositeField elementType = createCompositeElementsDetails(file, false, "return",
TypeUtils.createTypeReference(StdStrings.MAL, null, StdStrings.ELEMENT, false),
true, true, null);
List compElements = createCompositeElementsList(file, composite);
List superCompElements = createCompositeSuperElementsList(file, parentType);
boolean abstractComposite = (composite.getShortFormPart() == null);
file.addClassOpenStatement(className, !abstractComposite, abstractComposite,
parentClass, parentInterface, composite.getComment());
String fqName = createElementType(area.getName(), service == null ? null : service.getName(), className);
if (!abstractComposite) {
addTypeShortFormDetails(file, area, service, composite.getShortFormPart());
}
// Create the composite fields
if (!compElements.isEmpty()) {
for (CompositeField element : compElements) {
file.addClassVariable(false, false, StdStrings.PRIVATE, element, false, (String) null);
}
}
// create blank constructor
file.addConstructorDefault(className);
// if we or our parents have attributes then we need a typed constructor
if (!compElements.isEmpty() || !superCompElements.isEmpty()) {
List superArgs = new LinkedList<>();
List args = new LinkedList<>();
List superArgsNonNullable = new LinkedList<>();
List argsNonNullable = new LinkedList<>();
for (CompositeField element : superCompElements) {
superArgs.add(element);
args.add(element);
if (!element.isCanBeNull()) {
superArgsNonNullable.add(element);
argsNonNullable.add(element);
}
}
args.addAll(compElements);
for (CompositeField element : compElements) {
if (!element.isCanBeNull()) {
argsNonNullable.add(element);
}
}
// Creates constructor with all arguments
MethodWriter method = file.addConstructor(StdStrings.PUBLIC, className, args,
superArgs, null, "Constructor that initialises the values of the structure.", null);
for (CompositeField element : compElements) {
String call = createMethodCall("this." + element.getFieldName() + " = " + element.getFieldName());
method.addLine(call);
}
method.addMethodCloseStatement();
// Add a contructor that has only the non-nullable fields. Sets the nullable fields to null.
boolean hasNonNullable = !argsNonNullable.isEmpty() || !superArgsNonNullable.isEmpty();
boolean allArgsNonNullable = argsNonNullable.size() == args.size(); // All args are non-nullable?
// Note: If all method arguments are non-nullable, then the
// contructor will look the same as the one with all arguments. So,
// same type signature and therefore that needs to be avoided.
if (hasNonNullable && !allArgsNonNullable) {
MethodWriter method2 = file.addConstructor(StdStrings.PUBLIC, className,
argsNonNullable, superArgsNonNullable, null,
"Constructor that initialises the non-nullable values of the structure.", null);
for (CompositeField element : compElements) {
String ending = (!element.isCanBeNull()) ? element.getFieldName() : "null";
String call = createMethodCall("this." + element.getFieldName() + " = " + ending);
method.addLine(call);
}
method2.addMethodCloseStatement();
}
// create copy constructor
if (supportsToValue && !abstractComposite) {
file.addConstructorCopy(fqName, compElements);
}
}
if (!abstractComposite) {
MethodWriter method = file.addMethodOpenStatementOverride(elementType, "createElement", null, null);
method.addLine("return new " + fqName + "()");
method.addMethodCloseStatement();
}
// add getters and setters
for (CompositeField element : compElements) {
addGetter(file, element, null);
addSetter(file, element, null);
}
// create equals method
if (supportsEquals) {
CompositeField boolType = createCompositeElementsDetails(file, false, "return",
TypeUtils.createTypeReference(null, null, "boolean", false),
false, true, "return value");
CompositeField intType = createCompositeElementsDetails(file, false, "return",
TypeUtils.createTypeReference(null, null, "int", false),
false, true, "return value");
CompositeField objType = createCompositeElementsDetails(file, false, "obj",
TypeUtils.createTypeReference(null, null, "Object", false),
false, true, "The object to compare with.");
MethodWriter method = file.addMethodOpenStatementOverride(boolType, "equals", Arrays.asList(objType), null);
method.addLine("if (obj instanceof " + className + ") {", false);
if (null != parentClass) {
method.addLine(" if (! super.equals(obj)) {", false);
method.addLine(" return false");
method.addLine(" }", false);
}
if (!compElements.isEmpty()) {
method.addLine(" " + className + " other = (" + className + ") obj");
for (CompositeField element : compElements) {
method.addLine(" if (" + element.getFieldName() + " == null) {", false);
method.addLine(" if (other." + element.getFieldName() + " != null) {", false);
method.addLine(" return false");
method.addLine(" }", false);
method.addLine(" } else {", false);
method.addLine(" if (! " + element.getFieldName() + ".equals(other." + element.getFieldName() + ")) {", false);
method.addLine(" return false");
method.addLine(" }", false);
method.addLine(" }", false);
}
}
method.addLine(" return true");
method.addLine("}", false);
method.addLine("return false");
method.addMethodCloseStatement();
method = file.addMethodOpenStatementOverride(intType, "hashCode", null, null);
if (null != parentClass) {
method.addLine("int hash = super.hashCode()");
} else {
method.addLine("int hash = 7");
}
for (CompositeField element : compElements) {
method.addLine("hash = 83 * hash + (" + element.getFieldName() + " != null ? " + element.getFieldName() + ".hashCode() : 0)");
}
method.addLine("return hash");
method.addMethodCloseStatement();
}
// create toString method
if (supportsToString) {
CompositeField strType = createCompositeElementsDetails(file, false, "return",
TypeUtils.createTypeReference(null, null, "_String", false),
false, true, "return value");
MethodWriter method = file.addMethodOpenStatementOverride(strType, "toString", null, null);
method.addLine("StringBuilder buf = new StringBuilder()");
method.addLine("buf.append(\"(" + className + ": \")");
String prefixSeparator = "";
if (parentClass != null) {
method.addLine("buf.append(super.toString())");
prefixSeparator = ", ";
}
for (CompositeField element : compElements) {
StringBuilder str = new StringBuilder();
str.append("buf.append(\"").append(prefixSeparator).append(element.getFieldName());
str.append("=\")").append(".append(").append(element.getFieldName()).append(")");
method.addLine(str.toString());
prefixSeparator = ", ";
}
method.addLine("buf.append(')')");
method.addLine("return buf.toString()");
method.addMethodCloseStatement();
}
// create getMALValue method
if (supportsToValue && !abstractComposite) {
addCompositeCloneMethod(file, fqName);
}
// create encode method
MethodWriter method = encodeMethodOpen(file);
if (parentClass != null) {
method.addSuperMethodStatement("encode", "encoder");
}
// Add the if condition to check if there are null fields for non-nullable fields!
for (int i = 0; i < compElements.size(); i++) {
CompositeField element = compElements.get(i);
String fieldName = element.getFieldName();
if (!element.isCanBeNull()) {
method.addLine("if (" + fieldName + " == null) {", false);
method.addLine(" throw new org.ccsds.moims.mo.mal.MALException(\"The field '" + fieldName + "' cannot be null!\")");
method.addLine("}", false);
}
}
for (CompositeField element : compElements) {
boolean isAbstract = isAbstract(element.getTypeReference()) && !element.getTypeReference().getName().contentEquals(StdStrings.ATTRIBUTE);
String canBeNullStr = element.isCanBeNull() ? "Nullable" : "";
String fieldName = element.getFieldName();
if (isAbstract) {
if (element.isList()) { // Abstract List?
// The Abstract Lists do not not need an SPF because we know what we will get!
method.addLine(createMethodCall("encoder.encode" + canBeNullStr + "Element(" + fieldName + ")"));
} else {
method.addLine(createMethodCall("encoder.encode" + canBeNullStr + "AbstractElement(" + fieldName + ")"));
}
} else {
if (element.getEncodeCall() != null) {
method.addLine(createMethodCall("encoder.encode" + canBeNullStr + element.getEncodeCall() + "(" + fieldName + ")"));
} else {
// This is when the Element is set as the abstract Attribute type
method.addLine(createMethodCall("encoder.encode" + canBeNullStr + "Element(" + fieldName + ")"));
}
}
}
method.addMethodCloseStatement();
// create decode method
method = decodeMethodOpen(file, elementType);
if (parentClass != null) {
method.addSuperMethodStatement("decode", "decoder");
}
for (CompositeField element : compElements) {
boolean isAbstract = isAbstract(element.getTypeReference())
&& !element.getTypeReference().getName().contentEquals(StdStrings.ATTRIBUTE);
String canBeNullStr = element.isCanBeNull() ? "Nullable" : "";
String castString = element.getDecodeCast();
if (isAbstract) {
if (element.isList()) { // Abstract List?
// Strip the parenthesis around the cast: "(abc) " -> "abc"
// Note: Yes, the string has a space at the end... that's why we have: length() - 2
String classPath = castString.substring(1, castString.length() - 2);
method.addLine(element.getFieldName() + " = " + castString
+ createMethodCall("decoder.decode" + canBeNullStr
+ "Element(new " + classPath + "())"));
} else {
method.addLine(element.getFieldName() + " = " + castString
+ createMethodCall("decoder.decode" + canBeNullStr + "AbstractElement()"));
}
} else {
// Needs the "." before the AttributeList because of the NullableAttributeList
if (castString.contains(".AttributeList")) {
// This is when the Element is set as the abstract AttributeList type
String attNew = "new org.ccsds.moims.mo.mal.structures.AttributeList()";
method.addLine(element.getFieldName() + " = " + castString
+ createMethodCall("decoder.decode" + canBeNullStr + element.getDecodeCall() + "(" + attNew + ")"));
} else {
method.addLine(element.getFieldName() + " = " + castString
+ createMethodCall("decoder.decode" + canBeNullStr + element.getDecodeCall()
+ "(" + (element.isDecodeNeedsNewCall() ? element.getNewCall() : "") + ")"));
}
}
}
method.addLine("return this");
method.addMethodCloseStatement();
if (!abstractComposite) {
addTypeIdGetterMethod(file, area, service);
}
file.addClassCloseStatement();
file.flush();
createListClass(folder, area, service, className, abstractComposite, composite.getShortFormPart());
}
public abstract void createListClass(File folder, AreaType area, ServiceType service, String srcTypeName, boolean isAbstract, Long shortFormPart) throws IOException;
protected final void createMultiReturnType(String destinationFolderName, String returnTypeFqName, MultiReturnType returnTypeInfo) throws IOException {
logger.info(" > Creating multiple return class class " + returnTypeFqName);
// create a comment for the body folder if supported
createServiceMessageBodyFolderComment(destinationFolderName, returnTypeInfo.getArea(), returnTypeInfo.getService());
ClassWriter file = createClassFile(destinationFolderName, returnTypeFqName.replace('.', '/'));
file.addPackageStatement(returnTypeInfo.getArea(), returnTypeInfo.getService(), getConfig().getBodyFolder());
file.addClassOpenStatement(returnTypeInfo.getShortName(), true, false, null, null,
"Multi body return class for " + returnTypeInfo.getShortName() + ".");
List argsList = createOperationArguments(getConfig(), file, returnTypeInfo.getReturnTypes());
// create attributes
for (int i = 0; i < argsList.size(); i++) {
CompositeField argType = argsList.get(i);
CompositeField memType = createCompositeElementsDetails(file, true, argType.getFieldName(),
argType.getTypeReference(), true, true, argType.getFieldName() + ": " + argType.getComment());
file.addClassVariable(false, false, StdStrings.PRIVATE, memType, false, (String) null);
}
// create blank constructor
file.addConstructorDefault(returnTypeInfo.getShortName());
// if we or our parents have attributes then we need a typed constructor
MethodWriter method = file.addConstructor(StdStrings.PUBLIC, returnTypeInfo.getShortName(), argsList, null, null,
"Constructs an instance of this type using provided values.", null);
for (int i = 0; i < argsList.size(); i++) {
CompositeField argType = argsList.get(i);
method.addLine(createMethodCall("this." + argType.getFieldName() + " = " + argType.getFieldName()));
}
method.addMethodCloseStatement();
// add getters and setters
for (int i = 0; i < argsList.size(); i++) {
CompositeField argType = createCompositeElementsDetails(file, true, argsList.get(i).getFieldName(),
returnTypeInfo.getReturnTypes().get(i).getSourceType(), true, true, "The new value.");
addGetter(file, argType, null);
addSetter(file, argType, null);
}
// add deprecated getters and setters
for (int i = 0; i < argsList.size(); i++) {
CompositeField argType = createCompositeElementsDetails(file, true, argsList.get(i).getFieldName(),
returnTypeInfo.getReturnTypes().get(i).getSourceType(), true, true, "The new value.");
addGetter(file, argType, "BodyElement" + i);
addSetter(file, argType, "BodyElement" + i);
}
file.addClassCloseStatement();
file.flush();
}
public void addTypeShortFormDetails(ClassWriter file, AreaType area, ServiceType service, long sf) throws IOException {
//addTypeShortForm(file, sf);
long asf = ((long) area.getNumber()) << AREA_BIT_SHIFT;
asf += ((long) area.getVersion()) << VERSION_BIT_SHIFT;
if (service != null) {
asf += ((long) service.getNumber()) << SERVICE_BIT_SHIFT;
}
if (sf >= 0) {
asf += sf;
} else {
asf += Long.parseLong(Integer.toHexString((int) sf).toUpperCase().substring(2), 16);
}
addShortForm(file, asf);
addTypeId(file, asf);
}
protected abstract void addShortForm(ClassWriter file, long sf) throws IOException;
protected void addTypeId(ClassWriter file, long sf) throws IOException {
CompositeField var = createCompositeElementsDetails(file, false, "TYPE_ID",
TypeUtils.createTypeReference(StdStrings.MAL, null, "TypeId", false),
true, false, "The TypeId of this Element.");
file.addClassVariable(true, true, StdStrings.PUBLIC, var, false, "(SHORT_FORM)");
}
public void addTypeIdGetterMethod(ClassWriter file, AreaType area, ServiceType service) throws IOException {
CompositeField typeIdType = createCompositeElementsDetails(file, false, "return",
TypeUtils.createTypeReference(StdStrings.MAL, null, "TypeId", false),
true, true, null);
MethodWriter method = file.addMethodOpenStatementOverride(typeIdType, "getTypeId", null, null);
method.addLine("return TYPE_ID");
method.addMethodCloseStatement();
}
protected static void addGetter(ClassWriter file, CompositeField element, String backwardCompatibility) throws IOException {
String getOpPrefix = "get";
String attributeName = element.getFieldName();
boolean isDeprecated = (backwardCompatibility != null);
String getOpName = (backwardCompatibility == null) ? StubUtils.preCap(attributeName) : backwardCompatibility;
MethodWriter method = file.addMethodOpenStatement(false, false, true, false, StdStrings.PUBLIC,
!element.isCanBeNull(), !element.isCanBeNull() && element.isActual(), element,
getOpPrefix + getOpName, null, null, "Returns the field " + attributeName,
"The field " + attributeName, null, isDeprecated);
method.addLine("return " + attributeName);
method.addMethodCloseStatement();
}
@Deprecated
protected static void addSetter(ClassWriter file, CompositeField element, String backwardCompatibility) throws IOException {
String setOpPrefix = "set";
String attributeName = element.getFieldName();
//boolean isDeprecated = (backwardCompatibility != null);
boolean isDeprecated = true;
String getOpName = (backwardCompatibility == null) ? StubUtils.preCap(attributeName) : backwardCompatibility;
if (StdStrings.BOOLEAN.equals(element.getTypeName()) && getOpName.startsWith("Is")) {
getOpName = getOpName.substring(2);
}
CompositeField fld = new CompositeField(element, "__newValue", "The new value.");
MethodWriter method = file.addMethodOpenStatement(false, false, false, false,
StdStrings.PUBLIC, false, true, null,
setOpPrefix + getOpName, Arrays.asList(fld), null, "Sets the field " + attributeName,
null, null, isDeprecated);
method.addLine(attributeName + " = __newValue");
method.addMethodCloseStatement();
}
protected void addCompositeCloneMethod(ClassWriter file, String fqName) throws IOException {
}
protected CompositeField createServiceProviderSkeletonSendHandler(ClassWriter file, String argumentName, String argumentComment) {
return createCompositeElementsDetails(file, false, argumentName,
TypeUtils.createTypeReference(StdStrings.MAL, PROVIDER_FOLDER, StdStrings.MALINTERACTION, false),
false, true, argumentComment);
}
public String createAdapterMethodsArgs(List typeInfos, String argNamePrefix, boolean precedingArgs, boolean moreArgs) {
if (typeInfos == null) {
return "";
}
StringBuilder buf = new StringBuilder();
for (int i = 0; i < typeInfos.size(); i++) {
FieldInfo ti = typeInfos.get(i);
boolean morePrecedingArgs = precedingArgs || (i > 0);
boolean evenMoreArgs = moreArgs && i == (typeInfos.size() - 1);
buf.append(createAdapterMethodsArgs(ti, argNamePrefix, i, morePrecedingArgs, evenMoreArgs));
}
return buf.toString();
}
public String createAdapterMethodsArgs(FieldInfo typeInfo, String argName, int argIndex, boolean precedingArgs, boolean moreArgs) {
String retStr = "";
if ((typeInfo.getTargetType() != null) && !(StdStrings.VOID.equals(typeInfo.getTargetType()))) {
if (precedingArgs) {
retStr = ",\n ";
}
if (typeInfo.isNativeType()) {
// If is is Java native (Short, Long, etc), then needs to be wrapped into a Union type!
String unionType = getConfig().getAreaPackage(StdStrings.MAL)
+ "mal." + getConfig().getStructureFolder() + "." + StdStrings.UNION;
AttributeTypeDetails details = getAttributeDetails(typeInfo.getSourceType());
String av = argName + createMethodCall(".getBodyElement(") + argIndex + ", "
+ "new " + unionType + "(" + details.getDefaultValue() + "))";
retStr += "(" + av + " == null) ? null : ((" + unionType + ") " + av + ").get" + details.getMalType() + "Value()";
} else {
// Not Java native...
String expectedType = generateExpectedType(typeInfo);
String cast = typeInfo.getTargetType();
cast = cast.replace(".ElementList", ".HeterogeneousList");
String av = argName + createMethodCall(".getBodyElement(") + argIndex + ", " + expectedType + ")";
retStr += "(" + cast + ") " + av;
}
if (moreArgs) {
retStr += ",\n ";
}
}
return retStr;
}
private String generateExpectedType(FieldInfo ti) {
// Not Java native...
String cast = ti.getTargetType();
String at = null;
if (!isAbstract(ti.getSourceType())) {
CompositeField ce = createCompositeElementsDetails(null, false,
"", ti.getSourceType(), true, true, null);
at = ce.getNewCall();
}
if (at == null && cast.contains("List") && !cast.contains(".Element")) {
at = "new " + cast + "()";
}
if (cast.contains(".MOObject")) {
at = "null";
}
return at;
}
public String checkForReservedWords(String arg) {
if (arg == null) {
return arg;
}
String replacementWord = reservedWordsMap.get(arg);
return (replacementWord != null) ? replacementWord : arg;
}
public String createConsumerPatternCall(OperationSummary op) {
switch (op.getPattern()) {
case SEND_OP:
return "send";
case SUBMIT_OP:
return "submit";
case REQUEST_OP:
return "request";
case INVOKE_OP:
return "invoke";
case PROGRESS_OP:
return "progress";
}
return null;
}
public String getOperationInstanceType(OperationSummary op) {
switch (op.getPattern()) {
case SEND_OP:
return getConfig().getSendOperationType();
case SUBMIT_OP:
return getConfig().getSubmitOperationType();
case REQUEST_OP:
return getConfig().getRequestOperationType();
case INVOKE_OP:
return getConfig().getInvokeOperationType();
case PROGRESS_OP:
return getConfig().getProgressOperationType();
case PUBSUB_OP:
return getConfig().getPubsubOperationType();
}
return null;
}
public CompositeField createOperationReturnType(LanguageWriter file, String area, String service, OperationSummary op) {
switch (op.getPattern()) {
case REQUEST_OP: {
if (op.getRetTypes() != null) {
CompositeField ret = createReturnType(file, area, service, op.getName(), "Response", op.getRetTypes());
return createReturnReference(ret);
}
break;
}
case INVOKE_OP:
case PROGRESS_OP: {
if ((op.getAckTypes() != null) && (!op.getAckTypes().isEmpty())) {
CompositeField ret = createReturnType(file, area, service, op.getName(), "Ack", op.getAckTypes());
return createReturnReference(ret);
}
break;
}
}
return null;
}
public List createOperationArguments(GeneratorConfiguration config,
LanguageWriter file, List opArgs) {
if (opArgs == null) {
return new LinkedList<>();
}
List outputArgs = new LinkedList<>();
for (int i = 0; i < opArgs.size(); i++) {
FieldInfo ti = opArgs.get(i);
TypeReference tir = ti.getSourceType();
String argName = ti.getFieldName();
if (argName == null) {
String shortName = TypeUtils.shortTypeName(config.getNamingSeparator(), ti.getTargetType());
// Remove any ">" from the ObjectRef types
shortName = shortName.replace(">", "_");
argName = "_" + shortName + i;
// Give a Warning here!!
logger.warn("Warning! The field name is not set in the xml file! "
+ "The autogenerated value is: " + argName);
}
String cmt = argName + " Argument number " + i + " as defined by the service operation";
if ((null != ti.getFieldName()) && (null != ti.getFieldComment())) {
cmt = ti.getFieldComment();
}
CompositeField argType = createCompositeElementsDetails(file, true,
argName, tir, true, true, cmt);
outputArgs.add(argType);
}
return outputArgs;
}
public String createOperationArgReturn(LanguageWriter file, MethodWriter method,
FieldInfo typeInfo, String argName, int argIndex) throws IOException {
if ((typeInfo.getTargetType() != null) && !(StdStrings.VOID.equals(typeInfo.getTargetType()))) {
String eleType = "Object";
String tv = argName + argIndex;
String av;
String returnParameter;
if (typeInfo.isNativeType()) {
AttributeTypeDetails details = getAttributeDetails(typeInfo.getSourceType());
String elementType = createElementType(StdStrings.MAL, null, StdStrings.UNION);
av = argName + ".getBodyElement(" + argIndex + ", new " + elementType + "(" + details.getDefaultValue() + "))";
returnParameter = "(" + tv + " == null) ? null : ((" + elementType + ") " + tv + ").get" + details.getMalType() + "Value()";
} else {
String cast = typeInfo.getTargetType();
cast = cast.replace(".ElementList", ".HeterogeneousList");
String expectedType = generateExpectedType(typeInfo);
av = argName + ".getBodyElement(" + argIndex + ", " + expectedType + ")";
returnParameter = "(" + cast + ") " + tv;
}
method.addLine(eleType + " " + tv + " = (" + eleType + ") " + av);
return returnParameter;
}
return "";
}
protected CompositeField createReturnType(LanguageWriter file, String area,
String service, String opName, String messageType, List returnTypes) {
if (returnTypes == null || returnTypes.isEmpty()) {
return null;
}
if (returnTypes.size() == 1) {
return createCompositeElementsDetails(file, false, "return",
returnTypes.get(0).getSourceType(), true, true, null);
}
String shortName = StubUtils.preCap(opName) + messageType;
String rt = getConfig().getAreaPackage(area)
+ area.toLowerCase() + "."
+ service.toLowerCase() + "."
+ getConfig().getBodyFolder() + "."
+ shortName;
if (!multiReturnTypeMap.containsKey(rt)) {
multiReturnTypeMap.put(rt, new MultiReturnType(rt, area, service, shortName, returnTypes));
}
return createCompositeElementsDetails(file, false, "return",
TypeUtils.createTypeReference(area.toLowerCase(),
service.toLowerCase() + "." + getConfig().getBodyFolder(), shortName, false),
false, true, null);
}
/**
* Creates a set of argument names based on the type, wrapping the type in a
* Union if a native type.
*
* @param typeNames The list of arguments.
* @return The argument string.
*/
public String createArgNameOrNull(List typeNames) {
if (typeNames == null || typeNames.isEmpty()) {
return getConfig().getNullValue();
}
StringBuilder buf = new StringBuilder();
for (int i = 0; i < typeNames.size(); i++) {
FieldInfo ti = typeNames.get(i);
if (i > 0) {
buf.append(", ");
}
String argName = ti.getFieldName();
if (argName == null) {
argName = "_" + TypeUtils.shortTypeName(getConfig().getNamingSeparator(), ti.getTargetType()) + i;
}
if (ti.isNativeType()) {
buf.append("(").append(argName).append(" == null)");
buf.append(" ? null : new ");
buf.append(getConfig().getAreaPackage(StdStrings.MAL));
buf.append("mal.").append(getConfig().getStructureFolder()).append(".").append(StdStrings.UNION);
buf.append("(").append(argName).append(")");
} else {
buf.append(argName);
}
}
String ret = buf.toString();
ret = ret.replaceAll("<", "_");
ret = ret.replaceAll(">", "_");
return ret;
}
public MethodWriter encodeMethodOpen(ClassWriter file) throws IOException {
String throwsMALException = createElementType(StdStrings.MAL, null, null, StdStrings.MALEXCEPTION);
CompositeField fld = createCompositeElementsDetails(file, false, "encoder",
TypeUtils.createTypeReference(StdStrings.MAL, null, "MALEncoder", false),
false, true, "The encoder to use for encoding.");
return file.addMethodOpenStatementOverride(null, "encode", Arrays.asList(fld), throwsMALException);
}
public MethodWriter decodeMethodOpen(ClassWriter file, CompositeField returnType) throws IOException {
String throwsMALException = createElementType(StdStrings.MAL, null, null, StdStrings.MALEXCEPTION);
CompositeField fld = createCompositeElementsDetails(file, false, "decoder",
TypeUtils.createTypeReference(StdStrings.MAL, null, "MALDecoder", false),
false, true, "The decoder to use for decoding.");
return file.addMethodOpenStatementOverride(returnType, "decode", Arrays.asList(fld), throwsMALException);
}
protected String createProviderSkeletonHandlerSwitch() {
return "interaction.getOperation().getNumber().getValue()";
}
public CompositeField createReturnReference(CompositeField targetType) {
return targetType;
}
public String createMethodCall(String call) {
return call;
}
protected void createAreaFolderComment(File structureFolder, AreaType area) throws IOException {
}
protected void createServiceFolderComment(File structureFolder, String area, ServiceType service) throws IOException {
}
protected void createAreaStructureFolderComment(File structureFolder, String area) throws IOException {
}
protected void createServiceConsumerFolderComment(File structureFolder, String area, String service) throws IOException {
}
protected void createServiceProviderFolderComment(File structureFolder, String area, String service) throws IOException {
}
protected void createServiceMessageBodyFolderComment(String baseFolder, String area, String service) throws IOException {
}
protected void createServiceStructureFolderComment(File structureFolder, String area, String service) throws IOException {
}
protected abstract void createRequiredPublisher(String destinationFolderName, String fqPublisherName, RequiredPublisher op) throws IOException;
protected abstract String malStringAsElement(LanguageWriter file);
public abstract ClassWriter createClassFile(File folder, String className) throws IOException;
public abstract ClassWriter createClassFile(String destinationFolderName, String className) throws IOException;
protected abstract InterfaceWriter createInterfaceFile(File folder, String className) throws IOException;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy