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

io.joynr.generator.interfaces.InterfaceAsyncTemplate.xtend Maven / Gradle / Ivy

The newest version!
package io.joynr.generator.interfaces
/*
 * !!!
 *
 * Copyright (C) 2011 - 2017 BMW Car IT GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import com.google.inject.Inject
import io.joynr.generator.templates.InterfaceTemplate
import io.joynr.generator.templates.util.AttributeUtil
import io.joynr.generator.templates.util.InterfaceUtil
import io.joynr.generator.templates.util.MethodUtil
import io.joynr.generator.templates.util.NamingUtil
import io.joynr.generator.util.JavaTypeUtil
import io.joynr.generator.util.JoynrJavaGeneratorExtensions
import io.joynr.generator.util.TemplateBase
import java.util.ArrayList
import java.util.HashMap
import org.franca.core.franca.FInterface
import org.franca.core.franca.FMethod

class InterfaceAsyncTemplate extends InterfaceTemplate {
	@Inject extension JoynrJavaGeneratorExtensions
	@Inject extension JavaTypeUtil
	@Inject extension InterfaceUtil
	@Inject extension MethodUtil
	@Inject extension NamingUtil
	@Inject extension AttributeUtil
	@Inject extension TemplateBase

	def init(FInterface serviceInterface, HashMap methodToCallbackName, HashMap methodToFutureName,  HashMap methodToErrorEnumName, HashMap methodToSyncReturnedName, ArrayList uniqueMultioutMethods, boolean generateVersion) {
		val packagePath = getPackagePathWithJoynrPrefix(serviceInterface, ".", generateVersion)
		var uniqueMultioutMethodSignatureToOutputContainerName = new HashMap();
		var methodCounts = overloadedMethodCounts(getMethods(serviceInterface));
		var indexForMethod = new HashMap();

		for (FMethod method : getMethods(serviceInterface)) {
			if (method.outputParameters.size < 2) {
				val outputParamterType = method.typeNamesForOutputParameter.iterator.next;
				var outputType = if (outputParamterType == "void") "Void" else getObjectDataTypeForPlainType(outputParamterType)

				if (method.hasErrorEnum) {
					var errorEnumType = ""
					if (method.errors !== null) {
						errorEnumType = packagePath + "." + serviceInterface.joynrName + "." +
							methodToErrorEnumName.get(method)
					} else {
						errorEnumType = method.errorEnum.buildPackagePath(".", true, generateVersion) + "." + method.errorEnum.joynrName
					}
					methodToCallbackName.put(method, "CallbackWithModeledError<" + outputType + "," + errorEnumType + ">");
				} else {
					methodToCallbackName.put(method, "Callback<" + outputType + ">");
				}
				methodToFutureName.put(method, "Future<" + outputType + ">");
				methodToSyncReturnedName.put(method, outputType);
			} else {
				// Multiple Out Parameters
				var callbackName = method.name.toFirstUpper;
				var futureName = method.name.toFirstUpper;
				var syncReturnedName = method.name.toFirstUpper;
				if (methodCounts.get(method.name) == 1) {
				// method not overloaded, so no index needed
					uniqueMultioutMethods.add(method);
					callbackName += "Callback";
					futureName += "Future";
					syncReturnedName += "Returned";
				} else {
					// initialize index if not existent
					if (!indexForMethod.containsKey(method.name)) {
						indexForMethod.put(method.name, 0);
					}
					val methodSignature = method.createMethodSignatureFromOutParameters;
					if (!uniqueMultioutMethodSignatureToOutputContainerName.containsKey(methodSignature)) {
						var Integer index = indexForMethod.get(method.name);
						index++;
						indexForMethod.put(method.name, index);
						uniqueMultioutMethodSignatureToOutputContainerName.put(methodSignature, method.name.toFirstUpper + index);
						uniqueMultioutMethods.add(method);
					}
					val outputContainerName = uniqueMultioutMethodSignatureToOutputContainerName.get(methodSignature);
					callbackName +=  outputContainerName+ "Callback";
					futureName += outputContainerName + "Future";
					syncReturnedName += outputContainerName + "Returned";
				}
				methodToCallbackName.put(method, callbackName);
				methodToFutureName.put(method, futureName);
				methodToSyncReturnedName.put(method, syncReturnedName);
			}
		}
	}

	override generate(boolean generateVersion) {
		var methodToCallbackName = new HashMap();
		var methodToFutureName = new HashMap();
		var methodToErrorEnumName = francaIntf.methodToErrorEnumName
		var methodToSyncReturnedName = new HashMap();
		var uniqueMultioutMethods = new ArrayList();
		init(francaIntf, methodToCallbackName, methodToFutureName, methodToErrorEnumName, methodToSyncReturnedName, uniqueMultioutMethods, generateVersion);
		val interfaceName =  francaIntf.joynrName
		val asyncClassName = interfaceName + "Async"

		val packagePath = getPackagePathWithJoynrPrefix(francaIntf, ".", generateVersion)
		val hasReadAttribute = hasReadAttribute(francaIntf);
		val hasWriteAttribute = hasWriteAttribute(francaIntf);
		'''
«warning()»
package «packagePath»;

import io.joynr.messaging.MessagingQos;
«IF getMethods(francaIntf).size > 0 || hasReadAttribute»
import io.joynr.proxy.Callback;
«IF francaIntf.hasMethodWithErrorEnum»
import io.joynr.proxy.ICallbackWithModeledError;
import io.joynr.proxy.CallbackWithModeledError;
«ENDIF»
import io.joynr.proxy.Future;
import io.joynr.dispatcher.rpc.annotation.JoynrRpcCallback;
«ENDIF»
«IF uniqueMultioutMethods.size > 0»
import io.joynr.proxy.ICallback;
«ENDIF»
import io.joynr.Async;
import io.joynr.ProvidedBy;
import io.joynr.UsedBy;
«IF hasWriteAttribute»
import io.joynr.exceptions.DiscoveryException;
«ENDIF»

«FOR datatype: getRequiredIncludesFor(francaIntf, true, true, true, false, false, false, generateVersion)»
	import «datatype»;
«ENDFOR»

«FOR method: uniqueMultioutMethods»
«val syncReturnedName = methodToSyncReturnedName.get(method)»
	import «packagePath».«interfaceName»Sync.«syncReturnedName»;
«ENDFOR»

@Async
@ProvidedBy(«francaIntf.providerClassName».class)
@UsedBy(«francaIntf.proxyClassName».class)
public interface «asyncClassName» extends «interfaceName»«IF hasFireAndForgetMethods(francaIntf)», «interfaceName»FireAndForget«ENDIF» {

	«FOR attribute: getAttributes(francaIntf)»
		«var attributeName = attribute.joynrName»
		«var attributeType = attribute.typeName.objectDataTypeForPlainType»
		«var getAttribute = "get" + attributeName.toFirstUpper»
		«var setAttribute = "set" + attributeName.toFirstUpper»
		«IF isReadable(attribute)»
			public Future<«attributeType»> «getAttribute»(@JoynrRpcCallback(deserializationType = «attributeType»«IF isArray(attribute)»[]«ENDIF».class) Callback<«attributeType»> callback);
			default public Future<«attributeType»> «getAttribute»(@JoynrRpcCallback(deserializationType = «attributeType»«IF isArray(attribute)»[]«ENDIF».class) Callback<«attributeType»> callback, MessagingQos messagingQos) {
				return «getAttribute»(callback);
			}
		«ENDIF»
		«IF isWritable(attribute)»
			Future «setAttribute»(@JoynrRpcCallback(deserializationType = Void.class) Callback callback, «attributeType» «attributeName») throws DiscoveryException;
			default Future «setAttribute»(@JoynrRpcCallback(deserializationType = Void.class) Callback callback, «attributeType» «attributeName», MessagingQos messagingQos) throws DiscoveryException {
				return «setAttribute»(callback, «attributeName»);
			}
		«ENDIF»
	«ENDFOR»

	«FOR method: uniqueMultioutMethods»
	«val futureName = methodToFutureName.get(method)»
	«val syncReturnedName = methodToSyncReturnedName.get(method)»
	public static class «futureName» extends Future<«syncReturnedName»> {
		public void resolve(Object... outParameters) {
			if (outParameters.length == 0) {
				onSuccess(null);
			} else {
				onSuccess(new «syncReturnedName»(outParameters));
			}
		}

		public static Class[] getDatatypes() {
			return «syncReturnedName».getDatatypes();
		}
	}
	«ENDFOR»

	«FOR method: uniqueMultioutMethods»
		«val callbackName = methodToCallbackName.get(method)»
		«val outputParametersLength = method.outputParameters.length»
		«IF method.hasErrorEnum»
			«IF method.errors !== null»
				«val errorEnumType = packagePath + "." + interfaceName + "." + methodToErrorEnumName.get(method)»
				public abstract class «callbackName» implements ICallback, ICallbackWithModeledError<«errorEnumType»> {
			«ELSE»
				«val errorEnumType = method.errorEnum.buildPackagePath(".", true, generateVersion) + "." + method.errorEnum.joynrName»
				public abstract class «callbackName» implements ICallback, ICallbackWithModeledError<«errorEnumType»> {
			«ENDIF»
		«ELSE»
		public abstract class «callbackName» implements ICallback {
		«ENDIF»
			public abstract void onSuccess(«method.commaSeperatedTypedOutputParameterList»);

			public void resolve(Object... outParameters) {
				if (outParameters.length < «outputParametersLength») {
					onSuccess(«FOR i : 0 ..< outputParametersLength SEPARATOR ", "»null«ENDFOR»);
				} else {
						«var index = 0»
						onSuccess(
							«FOR outParameter : method.outputParameters»
								(«outParameter.typeName») outParameters[«index++»]«IF index < method.outputParameters.length»,«ENDIF»
							«ENDFOR»
					);
				}
			}
		}
	«ENDFOR»

	«FOR method: getMethods(francaIntf).filter[!fireAndForget]»
		«var methodName = method.joynrName»
		«var params = method.inputParameters.typedParameterList»
		«var callbackParameter = getCallbackParameter(method, methodToCallbackName)»

		/*
		* «methodName»
		*/
		public «methodToFutureName.get(method)» «methodName»(
				«callbackParameter»«IF !method.inputParameters.empty»,«ENDIF»
				«params»
		);
		default public «methodToFutureName.get(method)» «methodName»(
				«callbackParameter»«IF !method.inputParameters.empty»,«ENDIF»
				«params»,
				MessagingQos messagingQos
		) {
			return «methodName»(
				callback«IF !method.inputParameters.empty»,«ENDIF»
				«FOR inParameter : method.inputParameters SEPARATOR ","»
				«inParameter.name»
				«ENDFOR»
			);
		}

	«ENDFOR»
}
		'''
	}

	def getCallbackParameter(FMethod method, HashMap methodToCallbackName) {
		var outputParameterType = method.typeNamesForOutputParameter.iterator.next;
		var outputObjectType = getObjectDataTypeForPlainType(outputParameterType);
		var callbackType = methodToCallbackName.get(method);
		if (method.outputParameters.size < 2) {
			if (outputParameterType!="void") {
				if (outputObjectType == "") {
					throw new IllegalArgumentException("error in method: " + method
						+ ". outputObjectType is empty even though outputParameterType is not void")
				} else {
					return "@JoynrRpcCallback(deserializationType = " + outputObjectType + ".class) " + callbackType + " callback"
				}
			} else {
				return "@JoynrRpcCallback(deserializationType = Void.class) " + callbackType + " callback"
			}
		} else {
			return "@JoynrRpcCallback " + callbackType + " callback"
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy