From 24f7fa9b5b26ae46b6dde3bc2f7062a75983aa5b Mon Sep 17 00:00:00 2001 From: Felix Niemann Date: Sun, 9 Jul 2017 18:32:34 +0200 Subject: [PATCH 1/5] fixed backend bugs backend generated as maven project changed persistence provider to hibernate compatibility with wildfly --- .../generator/backend/BackendGenerator.xtend | 283 ++-- .../generator/backend/CommonClasses.xtend | 391 +++--- .../backend/ExternalWebServiceClass.xtend | 2 +- .../generator/backend/PersistenceXml.xtend | 136 +- .../generator/backend/WebServiceClass.xtend | 1171 +++++++++-------- 5 files changed, 1077 insertions(+), 906 deletions(-) diff --git a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/BackendGenerator.xtend b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/BackendGenerator.xtend index baba887f..325ce150 100644 --- a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/BackendGenerator.xtend +++ b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/BackendGenerator.xtend @@ -1,141 +1,142 @@ -package de.wwu.md2.framework.generator.backend - -import de.wwu.md2.framework.generator.AbstractPlatformGenerator -import de.wwu.md2.framework.generator.IExtendedFileSystemAccess -import de.wwu.md2.framework.mD2.Entity -import de.wwu.md2.framework.mD2.ModelElement -import de.wwu.md2.framework.mD2.ReferencedModelType - -import static de.wwu.md2.framework.generator.backend.BeanClass.* -import static de.wwu.md2.framework.generator.backend.CommonClasses.* -import static de.wwu.md2.framework.generator.backend.DatatypeClasses.* -import static de.wwu.md2.framework.generator.backend.DotProjectFile.* -import static de.wwu.md2.framework.generator.backend.EnumAndEntityClass.* -import static de.wwu.md2.framework.generator.backend.FileUpload.* -import static de.wwu.md2.framework.generator.backend.ExternalWebServiceClass.* -import static de.wwu.md2.framework.generator.backend.PersistenceXml.* -import static de.wwu.md2.framework.generator.backend.ProjectSettings.* -import static de.wwu.md2.framework.generator.backend.ValidationResult.* -import static de.wwu.md2.framework.generator.backend.WebContentFiles.* -import static de.wwu.md2.framework.generator.backend.WebServiceClass.* -import static de.wwu.md2.framework.util.MD2Util.* - -/** - * backend generator - */ -class BackendGenerator extends AbstractPlatformGenerator { - - override doGenerate(IExtendedFileSystemAccess fsa) { - - ///////////////////////////////////////// - // Generation work flow - ///////////////////////////////////////// - - // Generate models, web services and beans - dataContainer.model.modelElements.filter(typeof(ModelElement)). // remove auto-generated local entities starting with "__" - filter[!it.name.startsWith("__")].forEach[modelElement | - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/entities/models/" - + modelElement.name.toFirstUpper + ".java", createModel(rootFolder, modelElement)) - - val isUsedInRemoteContentProvider = dataContainer.contentProviders.exists[ c | - c.type instanceof ReferencedModelType - && !c.local - && (c.type as ReferencedModelType).entity.identityEquals(modelElement) - ] - - // web services and beans for an entity are only generated if they are used in any remote content provider - if(modelElement instanceof Entity && isUsedInRemoteContentProvider) { - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/" - + modelElement.name.toFirstUpper + "WS.java", createEntityWS(rootFolder, modelElement as Entity)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/beans/" - + modelElement.name.toFirstUpper + "Bean.java", createEntityBean(rootFolder, modelElement as Entity)) - } - ] - - // Generate datatype wrapper - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/BooleanWrapper.java", createBooleanWrapper(basePackageName)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/DateWrapper.java", createDateWrapper(basePackageName)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/DecimalWrapper.java", createDecimalWrapper(basePackageName)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/IntegerWrapper.java", createIntegerWrapper(basePackageName)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/InternalIdWrapper.java", createInternalIdWrapper(basePackageName)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/IsValidWrapper.java", createIsValidWrapper(basePackageName)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/StringWrapper.java", createStringWrapper(basePackageName)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/TimestampWrapper.java", createTimestampWrapper(basePackageName)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/TimeWrapper.java", createTimeWrapper(basePackageName)) - - // Generate validation and model version web services - val affectedEntities = newHashSet - affectedEntities.addAll(dataContainer.remoteValidators.filter(v | v.contentProvider != null && v.contentProvider.contentProvider.type instanceof ReferencedModelType) - .map(v | (v.contentProvider.contentProvider.type as ReferencedModelType).entity).filter(typeof(Entity))) - - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/VersionNegotiationWS.java", createVersionNegotiationWS(basePackageName)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/ValidationResult.java", createValidationResult(basePackageName)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/ValidationError.java", createValidationError(basePackageName)) - - if(!dataContainer.remoteValidators.empty) { - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/RemoteValidationWS.java", - createRemoteValidationWS(rootFolder, affectedEntities, dataContainer.remoteValidators)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/beans/RemoteValidationBean.java", - createRemoteValidationBean(rootFolder, affectedEntities, dataContainer.remoteValidators)) - } - - // Generate workflow managing files - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/beans/WorkflowStateBean.java", createWorkflowStateBean(rootFolder)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/entities/WorkflowState.java", createWorkflowState(rootFolder)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/WorkflowStateWS.java", createWorkflowStateWS(rootFolder)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/EventHandlerWS.java", createEventHandlerWS(rootFolder)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/FileUploadWS.java", createFileUploadWS(rootFolder)) - - // Generate additional servlet - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/filedownload/DownloadServlet.java", createDownloadServlet(rootFolder)) - - // External Werbservices - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/entities/RequestDTO.java", createRequestDTO(rootFolder)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/CallExternalWebServiceWS.java", createCallExternalWSProxy(basePackageName)) - - - // Gemerate external webService files - dataContainer.workflow.workflowElementEntries.filter[it.workflowElement.invoke.size>0].forEach[wfeEntry| - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/external/" + wfeEntry.workflowElement.name.toFirstUpper + "ExternalWS.java", createExternalWorkflowElementWS(basePackageName, wfeEntry, dataContainer.main.workflowManager)) - ] - // Generate common backend files - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/Utils.java", createUtils(basePackageName)) - fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/Config.java", createConfig(basePackageName, dataContainer)) - - // Generate persistence.xml - fsa.generateFile(rootFolder + "/src/META-INF/persistence.xml", createPersistenceXml(basePackageName)) - - // Generate .settings folder - // TODO: check necessity - fsa.generateFile(rootFolder + "/.settings/.jsdtscope", jsdtscope) - fsa.generateFile(rootFolder + "/.settings/org.eclipse.jdt.core.prefs", orgEclipseJdtCorePrefs) - fsa.generateFile(rootFolder + "/.settings/org.eclipse.jpt.core.prefs", orgEclipseJptCorePrefs) - fsa.generateFile(rootFolder + "/.settings/org.eclipse.wst.common.component", orgEclipseWstCommonComponent(basePackageName)) - fsa.generateFile(rootFolder + "/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml", orgEclipseWstCommonProjectFacetCorePrefs) - fsa.generateFile(rootFolder + "/.settings/org.eclipse.wst.common.project.facet.core.xml", orgEclipseWstCommonProjectFacetCore) - fsa.generateFile(rootFolder + "/.settings/org.eclipse.wst.jsdt.ui.superType.container", orgEclipseWstJsdtUiSuperTypeContainer) - fsa.generateFile(rootFolder + "/.settings/org.eclipse.wst.jsdt.ui.superType.name", orgEclipseWstJsdtUiSuperTypeName) - - // Generate .classpath and .project files - fsa.generateFileFromInputStream(getSystemResource("/backend/classpath.txt"), rootFolder + "/.classpath") - fsa.generateFile(rootFolder + "/.project", createProjectFile(basePackageName)) - - // Generate WebContent folder - fsa.generateFile(rootFolder + "/WebContent/index.jsp", indexJsp) - fsa.generateFile(rootFolder + "/WebContent/META-INF/MANIFEST.MF", manifest) - fsa.generateFile(rootFolder + "/WebContent/WEB-INF/sun-web.xml", sunWebXml(basePackageName)) // TODO: necessary? - fsa.generateFile(rootFolder + "/WebContent/WEB-INF/web.xml", webXml(basePackageName)) - - // Copy static jar libs - fsa.generateFileFromInputStream(getSystemResource("/backend/json-simple-1.1.1.jar"), rootFolder + "/WebContent/WEB-INF/lib/json-simple-1.1.1.jar") - fsa.generateFileFromInputStream(getSystemResource("/backend/guava-13.0.jar"), rootFolder + "/WebContent/WEB-INF/lib/guava-13.0.jar") - fsa.generateFileFromInputStream(getSystemResource("/backend/jackson-core-asl-1.9.2.jar"), rootFolder + "/WebContent/WEB-INF/lib/jackson-core-asl-1.9.2.jar") - fsa.generateFileFromInputStream(getSystemResource("/backend/jackson-jaxrs-1.9.2.jar"), rootFolder + "/WebContent/WEB-INF/lib/jackson-jaxrs-1.9.2.jar") - fsa.generateFileFromInputStream(getSystemResource("/backend/jackson-mapper-asl-1.9.2.jar"), rootFolder + "/WebContent/WEB-INF/lib/jackson-mapper-asl-1.9.2.jar") - fsa.generateFileFromInputStream(getSystemResource("/backend/jackson-xc-1.9.2.jar"), rootFolder + "/WebContent/WEB-INF/lib/jackson-xc-1.9.2.jar") - } - - override getPlatformPrefix() { - "backend" - } -} +package de.wwu.md2.framework.generator.backend + +import de.wwu.md2.framework.generator.AbstractPlatformGenerator +import de.wwu.md2.framework.generator.IExtendedFileSystemAccess +import de.wwu.md2.framework.mD2.Entity +import de.wwu.md2.framework.mD2.ModelElement +import de.wwu.md2.framework.mD2.ReferencedModelType + +import static de.wwu.md2.framework.generator.backend.BeanClass.* +import static de.wwu.md2.framework.generator.backend.CommonClasses.* +import static de.wwu.md2.framework.generator.backend.DatatypeClasses.* +import static de.wwu.md2.framework.generator.backend.DotProjectFile.* +import static de.wwu.md2.framework.generator.backend.EnumAndEntityClass.* +import static de.wwu.md2.framework.generator.backend.FileUpload.* +import static de.wwu.md2.framework.generator.backend.ExternalWebServiceClass.* +import static de.wwu.md2.framework.generator.backend.PersistenceXml.* +import static de.wwu.md2.framework.generator.backend.ProjectSettings.* +import static de.wwu.md2.framework.generator.backend.ValidationResult.* +import static de.wwu.md2.framework.generator.backend.WebContentFiles.* +import static de.wwu.md2.framework.generator.backend.WebServiceClass.* +import static de.wwu.md2.framework.util.MD2Util.* + +/** + * backend generator + */ +class BackendGenerator extends AbstractPlatformGenerator { + + override doGenerate(IExtendedFileSystemAccess fsa) { + + ///////////////////////////////////////// + // Generation work flow + ///////////////////////////////////////// + + // Generate models, web services and beans + dataContainer.model.modelElements.filter(typeof(ModelElement)). // remove auto-generated local entities starting with "__" + filter[!it.name.startsWith("__")].forEach[modelElement | + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/entities/models/" + + modelElement.name.toFirstUpper + ".java", createModel(rootFolder, modelElement)) + + val isUsedInRemoteContentProvider = dataContainer.contentProviders.exists[ c | + c.type instanceof ReferencedModelType + && !c.local + && (c.type as ReferencedModelType).entity.identityEquals(modelElement) + ] + + // web services and beans for an entity are only generated if they are used in any remote content provider + if(modelElement instanceof Entity && isUsedInRemoteContentProvider) { + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/" + + modelElement.name.toFirstUpper + "WS.java", createEntityWS(rootFolder, modelElement as Entity)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/beans/" + + modelElement.name.toFirstUpper + "Bean.java", createEntityBean(rootFolder, modelElement as Entity)) + } + ] + + // Generate datatype wrapper + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/BooleanWrapper.java", createBooleanWrapper(basePackageName)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/DateWrapper.java", createDateWrapper(basePackageName)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/DecimalWrapper.java", createDecimalWrapper(basePackageName)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/IntegerWrapper.java", createIntegerWrapper(basePackageName)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/InternalIdWrapper.java", createInternalIdWrapper(basePackageName)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/IsValidWrapper.java", createIsValidWrapper(basePackageName)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/StringWrapper.java", createStringWrapper(basePackageName)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/TimestampWrapper.java", createTimestampWrapper(basePackageName)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/TimeWrapper.java", createTimeWrapper(basePackageName)) + + // Generate validation and model version web services + val affectedEntities = newHashSet + affectedEntities.addAll(dataContainer.remoteValidators.filter(v | v.contentProvider != null && v.contentProvider.contentProvider.type instanceof ReferencedModelType) + .map(v | (v.contentProvider.contentProvider.type as ReferencedModelType).entity).filter(typeof(Entity))) + + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/VersionNegotiationWS.java", createVersionNegotiationWS(basePackageName)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/ValidationResult.java", createValidationResult(basePackageName)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/datatypes/ValidationError.java", createValidationError(basePackageName)) + + if(!dataContainer.remoteValidators.empty) { + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/RemoteValidationWS.java", + createRemoteValidationWS(rootFolder, affectedEntities, dataContainer.remoteValidators)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/beans/RemoteValidationBean.java", + createRemoteValidationBean(rootFolder, affectedEntities, dataContainer.remoteValidators)) + } + + // Generate workflow managing files + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/beans/WorkflowStateBean.java", createWorkflowStateBean(rootFolder)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/entities/WorkflowState.java", createWorkflowState(rootFolder)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/WorkflowStateWS.java", createWorkflowStateWS(rootFolder)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/EventHandlerWS.java", createEventHandlerWS(rootFolder)) + //fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/FileUploadWS.java", createFileUploadWS(rootFolder)) + + // Generate additional servlet + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/filedownload/DownloadServlet.java", createDownloadServlet(rootFolder)) + + // External Werbservices + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/entities/RequestDTO.java", createRequestDTO(rootFolder)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/CallExternalWebServiceWS.java", createCallExternalWSProxy(basePackageName)) + + + // Gemerate external webService files + dataContainer.workflow.workflowElementEntries.filter[it.workflowElement.invoke.size>0].forEach[wfeEntry| + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/ws/external/" + wfeEntry.workflowElement.name.toFirstUpper + "ExternalWS.java", createExternalWorkflowElementWS(basePackageName, wfeEntry, dataContainer.main.workflowManager)) + ] + // Generate common backend files + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/Utils.java", createUtils(basePackageName)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/Config.java", createConfig(basePackageName, dataContainer)) + fsa.generateFile(rootFolder + "/src/" + rootFolder.replace('.', '/') + "/BackendApplication.java", createBackendApplication(basePackageName)) + // Generate persistence.xml + fsa.generateFile(rootFolder + "/src/META-INF/persistence.xml", createPersistenceXml(basePackageName)) + fsa.generateFile(rootFolder+"/pom.xml", createPom(basePackageName)) + + // Generate .settings folder + // TODO: check necessity + fsa.generateFile(rootFolder + "/.settings/.jsdtscope", jsdtscope) + fsa.generateFile(rootFolder + "/.settings/org.eclipse.jdt.core.prefs", orgEclipseJdtCorePrefs) + fsa.generateFile(rootFolder + "/.settings/org.eclipse.jpt.core.prefs", orgEclipseJptCorePrefs) + fsa.generateFile(rootFolder + "/.settings/org.eclipse.wst.common.component", orgEclipseWstCommonComponent(basePackageName)) + fsa.generateFile(rootFolder + "/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml", orgEclipseWstCommonProjectFacetCorePrefs) + fsa.generateFile(rootFolder + "/.settings/org.eclipse.wst.common.project.facet.core.xml", orgEclipseWstCommonProjectFacetCore) + fsa.generateFile(rootFolder + "/.settings/org.eclipse.wst.jsdt.ui.superType.container", orgEclipseWstJsdtUiSuperTypeContainer) + fsa.generateFile(rootFolder + "/.settings/org.eclipse.wst.jsdt.ui.superType.name", orgEclipseWstJsdtUiSuperTypeName) + + // Generate .classpath and .project files + fsa.generateFileFromInputStream(getSystemResource("/backend/classpath.txt"), rootFolder + "/.classpath") + fsa.generateFile(rootFolder + "/.project", createProjectFile(basePackageName)) + + // Generate WebContent folder + fsa.generateFile(rootFolder + "/WebContent/index.jsp", indexJsp) + fsa.generateFile(rootFolder + "/WebContent/META-INF/MANIFEST.MF", manifest) + fsa.generateFile(rootFolder + "/WebContent/WEB-INF/sun-web.xml", sunWebXml(basePackageName)) // TODO: necessary? + //fsa.generateFile(rootFolder + "/WebContent/WEB-INF/web.xml", webXml(basePackageName)) + + // Copy static jar libs + fsa.generateFileFromInputStream(getSystemResource("/backend/json-simple-1.1.1.jar"), rootFolder + "/WebContent/WEB-INF/lib/json-simple-1.1.1.jar") + fsa.generateFileFromInputStream(getSystemResource("/backend/guava-13.0.jar"), rootFolder + "/WebContent/WEB-INF/lib/guava-13.0.jar") + fsa.generateFileFromInputStream(getSystemResource("/backend/jackson-core-asl-1.9.2.jar"), rootFolder + "/WebContent/WEB-INF/lib/jackson-core-asl-1.9.2.jar") + fsa.generateFileFromInputStream(getSystemResource("/backend/jackson-jaxrs-1.9.2.jar"), rootFolder + "/WebContent/WEB-INF/lib/jackson-jaxrs-1.9.2.jar") + fsa.generateFileFromInputStream(getSystemResource("/backend/jackson-mapper-asl-1.9.2.jar"), rootFolder + "/WebContent/WEB-INF/lib/jackson-mapper-asl-1.9.2.jar") + fsa.generateFileFromInputStream(getSystemResource("/backend/jackson-xc-1.9.2.jar"), rootFolder + "/WebContent/WEB-INF/lib/jackson-xc-1.9.2.jar") + } + + override getPlatformPrefix() { + "backend" + } +} diff --git a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/CommonClasses.xtend b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/CommonClasses.xtend index d160a4e5..2b5a5c51 100644 --- a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/CommonClasses.xtend +++ b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/CommonClasses.xtend @@ -1,187 +1,204 @@ -package de.wwu.md2.framework.generator.backend - -import de.wwu.md2.framework.generator.util.DataContainer -import de.wwu.md2.framework.mD2.WorkflowEvent -import de.wwu.md2.framework.mD2.WorkflowElement -import static extension de.wwu.md2.framework.generator.util.MD2GeneratorUtil.getEscapedStoragePath -import static extension de.wwu.md2.framework.generator.backend.util.MD2BackendUtil.* - -class CommonClasses { - - def static createConfig(String basePackageName, DataContainer dataContainer) ''' - package «basePackageName»; - - import java.io.File; - import java.util.HashMap; - import java.util.List; - - import com.google.common.collect.Lists; - - /** - * This class allows to define the current model version as well as all model versions that can be handled by this - * backend module. - */ - public class Config { - - /** - * Define a string that represents the current version of the backend model. - */ - public final static String MODEL_VERSION = "«dataContainer.main.modelVersion»"; - - /** - * Define a list of all model versions that are supported by this backend implementation - * to allow backward compatibility. - */ - public final static List SUPPORTED_MODEL_VERSIONS = Lists.newArrayList("«dataContainer.main.modelVersion»"); - - public final static HashMap APP_WORKFLOWELEMENT_RELATIONSHIP = setAppWorkflowElementRelationship(); - - public final static HashMap> WORKFLOWELEMENT_EVENT_SUCCESSION = setAppWorkflowElementSuccession(); - - «IF dataContainer.main.fileUploadConnection != null» - public final static File UPLOAD_FILE_STORAGE_PATH = new File("«dataContainer.main.fileUploadConnection.escapedStoragePath»"); - «ELSE» - public final static File UPLOAD_FILE_STORAGE_PATH = null; - «ENDIF» - - - public static final String UPLOAD_FILE_PREFIX = "upload-"; - - /** - * provides a hashmap for filtering workflowelements by apps - * setAppWorkflowElementRelationship : (App) --> (Wfe)* - * @return - */ - private static HashMap setAppWorkflowElementRelationship(){ - - HashMap map = new HashMap(); - «FOR app: dataContainer.apps» - map.put("«app.name»", new String[]{«FOR wfe: dataContainer.workflowElementsForApp(app) SEPARATOR ","»"«wfe.name»"«ENDFOR»}); - «ENDFOR» - return map; - } - - - /** - * Given an event-throwing app and a thrown event, this map knows what workflow element has to follow - * setAppWorkflowElementSuccession : (Wfe x Event) --> Wfe - * @return - */ - private static HashMap> setAppWorkflowElementSuccession() { - HashMap> map = new HashMap>(); - HashMap innerMap; - - «FOR wfe : dataContainer.workflowElements» - // Coming from «wfe.name» - innerMap = new HashMap(); - «FOR event : dataContainer.getEventsFromWorkflowElement(wfe)» - «IF (eventIsEndEvent(event, wfe, dataContainer))» - innerMap.put("«event.name»", "_terminate"); - «ELSE» - innerMap.put("«event.name»", "«dataContainer.getNextWorkflowElement(wfe, event).name»"); - «ENDIF» - «ENDFOR» - map.put("«wfe.name»", innerMap); - - «ENDFOR» - - - // Coming from invokables - innerMap = new HashMap(); - «FOR eventDesc : dataContainer.workflow.workflowElementEntries.map[wfe | wfe.eventDescription].toSet» - HashMap map«eventDesc.toFirstUpper» = new HashMap(); - «ENDFOR» - «FOR wfeEntry : dataContainer.workflow.workflowElementEntries.filter(wfe | wfe.isInvokable())» - map«wfeEntry.eventDescription.toFirstUpper».put("«wfeEntry.eventDescription»", "«wfeEntry.workflowElement.name»"); - «ENDFOR» - «FOR eventDesc : dataContainer.workflow.workflowElementEntries.map[wfe | wfe.eventDescription].toSet» - map.put("«eventDesc»", map«eventDesc.toFirstUpper»); - «ENDFOR» - - return map; - } - } - ''' - - def static boolean eventIsEndEvent(WorkflowEvent event, WorkflowElement wfe, DataContainer dataContainer) { - val fee = dataContainer.getFireEventEntryForWorkflowEvent(event, wfe) - return (fee.endWorkflow) - } - - def static createUtils(String basePackageName) ''' - package «basePackageName»; - - import java.util.regex.Matcher; - import java.util.regex.Pattern; - - /** - * Common functionality that is used throughout the project. - */ - public class Utils { - - /** - * Converts the standardized filter string received from the frontend to a valid - * WHERE clause that can be interpreted by the SQL parser - * - * Assumes an incoming string with conditions connected by 'and', 'or' and 'not'. Each - * condition may be an atomic boolean value 'true' or 'false' or a condition of the form - * fully.qualified.attribute.name (equals|greater|smaller|>=|<=) anyValue - * - * @param filter Filter string from the frontend. - * @return String in the common format for WHERE clauses that can be interpreted by the SQL parser. - */ - public static String buildWhereParameterFromFilterString(String filter) { - - if(filter == null) - return ""; - - // add one whitespace at the end of the filter string to facilitate the patterns in the - // following steps - filter = "(" + filter + ")"; - - // replace all double quotes by single quotes - filter = filter.replace("\"", "'"); - - // replace true by (1 = 1) - filter = filter.replaceAll("(\\s+|\\()true(\\s+|\\))", "$1(1 = 1)$2"); - - // replace false by (1 <> 1) - filter = filter.replaceAll("(\\s+|\\()false(\\s+|\\))", "$1(1 <> 1)$2"); - - // add a t. to all attributes and replace operators by internal ones - Pattern p = Pattern.compile("(\\s+|\\()(\\w+)\\s*(equals|greater|smaller|>=|<=)\\s*(\\S+)(\\s+|\\))"); - Matcher m = p.matcher(filter); - StringBuffer s = new StringBuffer(); - while(m.find()) { - m.appendReplacement(s, "$1 t.$2 " + transformOperator(m.group(3)) + " $4$5"); - } - m.appendTail(s); - - //System.out.println("WHERE clause: " + s.toString()); - - return "WHERE " + s.toString(); - } - - private static String transformOperator(String op) { - if(op.equals("greater")) { - return ">"; - } - - if(op.equals("smaller")) { - return "<"; - } - - if(op.equals(">=")) { - return ">="; - } - - if(op.equals("<=")) { - return "<="; - } - - // default: equals - return "="; - } - } - ''' -} +package de.wwu.md2.framework.generator.backend + +import de.wwu.md2.framework.generator.util.DataContainer +import de.wwu.md2.framework.mD2.WorkflowEvent +import de.wwu.md2.framework.mD2.WorkflowElement +import static extension de.wwu.md2.framework.generator.util.MD2GeneratorUtil.getEscapedStoragePath +import static extension de.wwu.md2.framework.generator.backend.util.MD2BackendUtil.* + +class CommonClasses { + + def static createConfig(String basePackageName, DataContainer dataContainer) ''' + package «basePackageName»; + + import java.io.File; + import java.util.HashMap; + import java.util.List; + + import com.google.common.collect.Lists; + + /** + * This class allows to define the current model version as well as all model versions that can be handled by this + * backend module. + */ + public class Config { + + /** + * Define a string that represents the current version of the backend model. + */ + public final static String MODEL_VERSION = "«dataContainer.main.modelVersion»"; + + /** + * Define a list of all model versions that are supported by this backend implementation + * to allow backward compatibility. + */ + public final static List SUPPORTED_MODEL_VERSIONS = Lists.newArrayList("«dataContainer.main.modelVersion»"); + + public final static HashMap APP_WORKFLOWELEMENT_RELATIONSHIP = setAppWorkflowElementRelationship(); + + public final static HashMap> WORKFLOWELEMENT_EVENT_SUCCESSION = setAppWorkflowElementSuccession(); + + «IF dataContainer.main.fileUploadConnection != null» + public final static File UPLOAD_FILE_STORAGE_PATH = new File("«dataContainer.main.fileUploadConnection.escapedStoragePath»"); + «ELSE» + public final static File UPLOAD_FILE_STORAGE_PATH = null; + «ENDIF» + + + public static final String UPLOAD_FILE_PREFIX = "upload-"; + + /** + * provides a hashmap for filtering workflowelements by apps + * setAppWorkflowElementRelationship : (App) --> (Wfe)* + * @return + */ + private static HashMap setAppWorkflowElementRelationship(){ + + HashMap map = new HashMap(); + «FOR app: dataContainer.apps» + map.put("«app.name»", new String[]{«FOR wfe: dataContainer.workflowElementsForApp(app) SEPARATOR ","»"«wfe.name»"«ENDFOR»}); + «ENDFOR» + return map; + } + + + /** + * Given an event-throwing app and a thrown event, this map knows what workflow element has to follow + * setAppWorkflowElementSuccession : (Wfe x Event) --> Wfe + * @return + */ + private static HashMap> setAppWorkflowElementSuccession() { + HashMap> map = new HashMap>(); + HashMap innerMap; + + «FOR wfe : dataContainer.workflowElements» + // Coming from «wfe.name» + innerMap = new HashMap(); + «FOR event : dataContainer.getEventsFromWorkflowElement(wfe)» + «IF (eventIsEndEvent(event, wfe, dataContainer))» + innerMap.put("«event.name»", "_terminate"); + «ELSE» + innerMap.put("«event.name»", "«dataContainer.getNextWorkflowElement(wfe, event).name»"); + «ENDIF» + «ENDFOR» + map.put("«wfe.name»", innerMap); + + «ENDFOR» + + + // Coming from invokables + innerMap = new HashMap(); + «FOR eventDesc : dataContainer.workflow.workflowElementEntries.map[wfe | wfe.eventDescription].toSet» + HashMap map«eventDesc.toFirstUpper» = new HashMap(); + «ENDFOR» + «FOR wfeEntry : dataContainer.workflow.workflowElementEntries.filter(wfe | wfe.isInvokable())» + map«wfeEntry.eventDescription.toFirstUpper».put("«wfeEntry.eventDescription»", "«wfeEntry.workflowElement.name»"); + «ENDFOR» + «FOR eventDesc : dataContainer.workflow.workflowElementEntries.map[wfe | wfe.eventDescription].toSet» + map.put("«eventDesc»", map«eventDesc.toFirstUpper»); + «ENDFOR» + + return map; + } + } + ''' + + def static boolean eventIsEndEvent(WorkflowEvent event, WorkflowElement wfe, DataContainer dataContainer) { + val fee = dataContainer.getFireEventEntryForWorkflowEvent(event, wfe) + return (fee.endWorkflow) + } + + def static createUtils(String basePackageName) ''' + package «basePackageName»; + + import java.util.regex.Matcher; + import java.util.regex.Pattern; + + /** + * Common functionality that is used throughout the project. + */ + public class Utils { + + /** + * Converts the standardized filter string received from the frontend to a valid + * WHERE clause that can be interpreted by the SQL parser + * + * Assumes an incoming string with conditions connected by 'and', 'or' and 'not'. Each + * condition may be an atomic boolean value 'true' or 'false' or a condition of the form + * fully.qualified.attribute.name (equals|greater|smaller|>=|<=) anyValue + * + * @param filter Filter string from the frontend. + * @return String in the common format for WHERE clauses that can be interpreted by the SQL parser. + */ + public static String buildWhereParameterFromFilterString(String filter) { + + if(filter == null) + return ""; + + // add one whitespace at the end of the filter string to facilitate the patterns in the + // following steps + filter = "(" + filter + ")"; + + // replace all double quotes by single quotes + filter = filter.replace("\"", "'"); + + // replace true by (1 = 1) + filter = filter.replaceAll("(\\s+|\\()true(\\s+|\\))", "$1(1 = 1)$2"); + + // replace false by (1 <> 1) + filter = filter.replaceAll("(\\s+|\\()false(\\s+|\\))", "$1(1 <> 1)$2"); + + // add a t. to all attributes and replace operators by internal ones + Pattern p = Pattern.compile("(\\s+|\\()(\\w+)\\s*(equals|greater|smaller|>=|<=)\\s*(\\S+)(\\s+|\\))"); + Matcher m = p.matcher(filter); + StringBuffer s = new StringBuffer(); + while(m.find()) { + m.appendReplacement(s, "$1 t.$2 " + transformOperator(m.group(3)) + " $4$5"); + } + m.appendTail(s); + + //System.out.println("WHERE clause: " + s.toString()); + + return "WHERE " + s.toString(); + } + + private static String transformOperator(String op) { + if(op.equals("greater")) { + return ">"; + } + + if(op.equals("smaller")) { + return "<"; + } + + if(op.equals(">=")) { + return ">="; + } + + if(op.equals("<=")) { + return "<="; + } + + // default: equals + return "="; + } + } + ''' + + + + def static createBackendApplication(String basePackageName) ''' + package «basePackageName»; + + import javax.ws.rs.ApplicationPath; + import javax.ws.rs.core.Application; + + @ApplicationPath("service") + public class BackendApplication extends Application { + + } + ''' + + + +} diff --git a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/ExternalWebServiceClass.xtend b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/ExternalWebServiceClass.xtend index d1143cde..9956dd1e 100644 --- a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/ExternalWebServiceClass.xtend +++ b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/ExternalWebServiceClass.xtend @@ -32,7 +32,7 @@ class ExternalWebServiceClass { «FOR cp: wfe.getInternalContentProviders(workflowManager)» import «basePackageName».beans.«cp.contentProviderEntity.name.toFirstUpper»Bean; «ENDFOR» - import CurrentStateProject.backend.beans.WorkflowStateBean; + import «basePackageName».beans.WorkflowStateBean; «FOR entity : wfe.allEntitiesWithinInvoke» import «basePackageName».entities.models.«entity.name.toFirstUpper»; diff --git a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/PersistenceXml.xtend b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/PersistenceXml.xtend index d79b28f7..b6445b0c 100644 --- a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/PersistenceXml.xtend +++ b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/PersistenceXml.xtend @@ -1,20 +1,116 @@ -package de.wwu.md2.framework.generator.backend - -class PersistenceXml { - - def static createPersistenceXml(String basePackageName) ''' - - - - org.eclipse.persistence.jpa.PersistenceProvider - java:app/env/«basePackageName» - - - - - - - - ''' -} +package de.wwu.md2.framework.generator.backend + +class PersistenceXml { + + def static createPersistenceXml(String basePackageName) ''' + + + + java:jboss/datasources/ExampleDS + + + + + + + + + + + + + + + + + ''' + + +def static createPom(String basePackageName){ ''' + + 4.0.0 + «basePackageName» + «basePackageName» + 0.0.1-SNAPSHOT + war + + «basePackageName» + src + + + src + + **/*.java + + + + + + maven-compiler-plugin + 3.5.1 + + false + 1.6 + 1.6 + + + + maven-war-plugin + 3.0.0 + + false + WebContent + + + + + + + javax + javaee-api + 7.0 + provided + + + + com.google.guava + guava + 13.0.1 + + + + org.codehaus.jackson + jackson-xc + 1.9.13 + + + + com.googlecode.json-simple + json-simple + 1.1.1 + + + + + org.codehaus.jackson + jackson-mapper-asl + 1.9.13 + + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + 2.8.8 + + + + org.codehaus.jackson + jackson-core-asl + 1.9.13 + + + + + + '''} +} diff --git a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/WebServiceClass.xtend b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/WebServiceClass.xtend index 9dc3223c..777f71b0 100644 --- a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/WebServiceClass.xtend +++ b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/WebServiceClass.xtend @@ -1,557 +1,614 @@ -package de.wwu.md2.framework.generator.backend - -import de.wwu.md2.framework.mD2.Entity -import de.wwu.md2.framework.mD2.ModelElement -import de.wwu.md2.framework.mD2.ReferencedModelType -import de.wwu.md2.framework.mD2.RemoteValidator -import java.util.Collection - -import static de.wwu.md2.framework.generator.util.MD2GeneratorUtil.* - -import static extension de.wwu.md2.framework.util.IterableExtensions.* - -class WebServiceClass { - - def static createEntityWS(String basePackageName, Entity entity) ''' - package «basePackageName».ws; - - import java.util.List; - - import javax.ejb.EJB; - import javax.ejb.Stateless; - import javax.ws.rs.Consumes; - import javax.ws.rs.DELETE; - import javax.ws.rs.GET; - import javax.ws.rs.POST; - import javax.ws.rs.Path; - import javax.ws.rs.PathParam; - import javax.ws.rs.FormParam; - import javax.ws.rs.Produces; - import javax.ws.rs.QueryParam; - import javax.ws.rs.core.GenericEntity; - import javax.ws.rs.core.MediaType; - import javax.ws.rs.core.Response; - - import «basePackageName».Config; - import «basePackageName».beans.«entity.name.toFirstUpper»Bean; - import «basePackageName».datatypes.InternalIdWrapper; - import «basePackageName».entities.models.«entity.name.toFirstUpper»; - - @Path("/«entity.name.toFirstLower»") - @Stateless - public class «entity.name.toFirstUpper»WS { - - @EJB - «entity.name.toFirstUpper»Bean «entity.name.toFirstLower»Bean; - - @GET - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response getAll(@QueryParam("filter") final String filter, @QueryParam("limit") final int limit) { - final GenericEntity> «entity.name.toFirstLower»s = - new GenericEntity>(«entity.name.toFirstLower»Bean.getAll«entity.name.toFirstUpper»s(filter, limit)) {}; - return Response - .ok() - .entity(«entity.name.toFirstLower»s) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - } - - @GET - @Path("{id}") - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response get(@PathParam("id") Integer id) { - final «entity.name.toFirstUpper» «entity.name.toFirstLower» = «entity.name.toFirstLower»Bean.get«entity.name.toFirstUpper»(id); - - if («entity.name.toFirstLower» != null) { - return Response - .ok() - .entity(new GenericEntity<«entity.name.toFirstUpper»>(«entity.name.toFirstLower») {}) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - } else { - return Response - .status(404) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - } - - } - - /** - * Possibly needs to be extended by a filter parameter - */ - @POST - @Path("ids") - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response get(@FormParam("ids") List ids) { - final List<«entity.name.toFirstUpper»> «entity.name.toFirstLower»s = «entity.name.toFirstLower»Bean.get«entity.name.toFirstUpper»s(ids); - - return Response - .ok() - .entity(«entity.name.toFirstLower»s) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - } - - /** - * Exemplary input format: - * [ - * { - * "firstName": "John", - * "lastName": "Doe", - * "customerId": "2443232", - * "dateOfBirth": "1954-07-18" - * } - * ] - */ - @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response createOrUpdate(List<«entity.name.toFirstUpper»> «entity.name.toFirstLower»s) { - final GenericEntity> ids = - new GenericEntity>(«entity.name.toFirstLower»Bean.createOrUpdate«entity.name.toFirstUpper»s(«entity.name.toFirstLower»s)) {}; - return Response - .ok() - .entity(ids) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - } - - @DELETE - public Response delete(@QueryParam("id") List ids) { - if («entity.name.toFirstLower»Bean.delete«entity.name.toFirstUpper»s(ids)) { - return Response - .noContent() - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - } else { - return Response - .status(409) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - } - } - - /** - * Workaround for ESRI proxy that forwards DELETE requests as GET requests! - */ - @GET - @Path("delete") - public Response deleteWithGet(@QueryParam("id") List ids) { - return delete(ids); - } - - } - ''' - - def static createVersionNegotiationWS(String basePackageName) ''' - package «basePackageName».ws; - - import javax.ejb.Stateless; - import javax.ws.rs.GET; - import javax.ws.rs.Path; - import javax.ws.rs.Produces; - import javax.ws.rs.QueryParam; - import javax.ws.rs.core.GenericEntity; - import javax.ws.rs.core.MediaType; - import javax.ws.rs.core.Response; - - import «basePackageName».Config; - import «basePackageName».datatypes.IsValidWrapper; - - @Path("/md2_model_version") - @Stateless - public class VersionNegotiationWS { - - /** - * WS that provides the current backend model version. - */ - @GET - @Path(value = "current") - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response jsonGetModelVersion() { - final GenericEntity entity = new GenericEntity(Config.MODEL_VERSION) {}; - Response response = Response - .ok() - .entity(entity) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - return response; - } - - /** - * WS checks whether the requested model version is supported by the backend (returns true or false). - * @param version String representation of the requested version. - */ - @GET - @Path(value = "is_valid") - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response jsonGetSupportsModelVersion(@QueryParam("version") final String version) { - final IsValidWrapper entity = new IsValidWrapper(Config.SUPPORTED_MODEL_VERSIONS.contains(version)); - Response response = Response - .ok() - .entity(entity) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - return response; - } - - } - ''' - - def static createRemoteValidationWS(String basePackageName, Collection affectedEntities, Collection remoteValidators) ''' - package «basePackageName».ws; - - import javax.ejb.EJB; - import javax.ejb.Stateless; - import javax.ws.rs.Consumes; - import javax.ws.rs.GET; - import javax.ws.rs.Path; - import javax.ws.rs.Produces; - import javax.ws.rs.QueryParam; - import javax.ws.rs.core.MediaType; - import javax.ws.rs.core.Response; - - import «basePackageName».Config; - import «basePackageName».beans.RemoteValidationBean; - import «basePackageName».datatypes.ValidationResult; - «FOR entity : affectedEntities» - import «basePackageName».entities.models.«entity.name.toFirstUpper»; - «ENDFOR» - - @Path("/md2_validator") - @Stateless - public class RemoteValidationWS { - - @EJB - RemoteValidationBean validatorBean; - - «FOR validator : remoteValidators» - «IF validator.contentProvider != null && validator.contentProvider.contentProvider.type instanceof ReferencedModelType» - @GET - @Path(value = "«validator.name.toFirstLower»") - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - @Consumes(MediaType.APPLICATION_JSON) - public Response json«validator.name.toFirstUpper»(«(validator.contentProvider.contentProvider.type as ReferencedModelType).entity.name.toFirstUpper» «(validator.contentProvider.contentProvider.type as ReferencedModelType).entity.name.toFirstLower») { - - ValidationResult result = validatorBean.validate«validator.name.toFirstUpper»(«(validator.contentProvider.contentProvider.type as ReferencedModelType).entity.name.toFirstLower»); - - Response response = Response - .ok() - .entity(result) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - return response; - } - - «ELSE /* based on attributes */» - @GET - @Path(value = "«validator.name.toFirstLower»") - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response json«validator.name.toFirstUpper»( - «validator.provideAttributes.joinWithIdx("", "," + System::getProperty("line.separator"), "", [p, i | '''@QueryParam("«p.contentProviderRef.name + "." + getPathTailAsString(p.tail)»") final String param«i + 1»'''])») { - - ValidationResult result = validatorBean.validate«validator.name.toFirstUpper»(«validator.provideAttributes.joinWithIdx("", ", ", "", [s, i | '''param«i + 1»'''])»); - - Response response = Response - .ok() - .entity(result) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - return response; - } - - «ENDIF» - «ENDFOR» - } - ''' - - def public static createEventHandlerWS(String basePackage) ''' - package «basePackage».ws; - - import javax.ejb.EJB; - import javax.ejb.Stateless; - import javax.ws.rs.FormParam; - import javax.ws.rs.POST; - import javax.ws.rs.Path; - import javax.ws.rs.Produces; - import javax.ws.rs.core.MediaType; - import javax.ws.rs.core.Response; - - import «basePackage».Config; - import «basePackage».beans.WorkflowStateBean; - - @Path("/eventHandler") - @Stateless - public class EventHandlerWS { - - @EJB - WorkflowStateBean workflowStateBean; - - - - /** - * Receives workflowInstanceId, lastEventFired and the current workflowElement and starts their persistence. - */ - - @POST - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response createOrUpdate(@FormParam("instanceId") String id, @FormParam("lastEventFired") String event, - @FormParam("currentWfe") String wfe, @FormParam("contentProviderIds") String contentProviderIds) { - - workflowStateBean.createOrUpdateWorkflowState(event, id, wfe, contentProviderIds); - - return Response - .ok() - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - } - } - ''' - - def public static createWorkflowStateWS(String basePackage) ''' - package «basePackage».ws; - - import java.util.ArrayList; - import java.util.List; - - import javax.ejb.EJB; - import javax.ejb.Stateless; - import javax.ws.rs.GET; - import javax.ws.rs.Path; - import javax.ws.rs.PathParam; - import javax.ws.rs.Produces; - import javax.ws.rs.QueryParam; - import javax.ws.rs.core.GenericEntity; - import javax.ws.rs.core.MediaType; - import javax.ws.rs.core.Response; - - import «basePackage».Config; - import «basePackage».beans.WorkflowStateBean; - import «basePackage».entities.WorkflowState; - - @Path("/workflowState") - @Stateless - public class WorkflowStateWS { - - @EJB - WorkflowStateBean workflowStateBean; - - /** - * - * @return all open issues - */ - @GET - @Path("all") - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response getAllOpenIssues() { - - final List workflowStates = - new ArrayList(workflowStateBean.getAllWorkflowStates("")); - - - return Response - .ok() - .entity(workflowStates) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - } - - @GET - @Path("filteredOpenIssues") - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response getFilteredOpenIssues(@QueryParam("app") String app) { - - final List workflowStates = - new ArrayList(workflowStateBean.getAllWorkflowStates(app)); - - - return Response - .ok() - .entity(workflowStates) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - } - - @GET - @Path("{id}") - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response get(@PathParam("id") String id) { - final WorkflowState workflowState = workflowStateBean.getWorkflowState(id); - - if (workflowState != null) { - return Response - .ok() - .entity(new GenericEntity(workflowState) {}) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - } else { - return Response - .status(404) - .header("MD2-Model-Version", Config.MODEL_VERSION) - .build(); - } - } - - } - ''' - - def public static createCallExternalWSProxy(String basePackage) ''' - package «basePackage».ws; - import org.json.simple.JSONValue; - - import java.io.BufferedReader; - import java.io.IOException; - import java.io.InputStreamReader; - import java.io.OutputStream; - import java.io.UnsupportedEncodingException; - import java.net.ConnectException; - import java.net.HttpURLConnection; - import java.net.MalformedURLException; - import java.net.URL; - import java.net.URLEncoder; - import java.util.List; - import java.util.logging.Logger; - - import javax.ejb.Stateless; - import javax.ws.rs.Consumes; - import javax.ws.rs.POST; - import javax.ws.rs.Path; - import javax.ws.rs.Produces; - import javax.ws.rs.core.MediaType; - import javax.ws.rs.core.Response; - - import «basePackage».Config; - import «basePackage».entities.RequestDTO; - import «basePackage».entities.RequestDTO.RequestMethod; - - @Path("/externalWS") - @Stateless - public class CallExternalWebServiceWS { - - private final static Logger LOGGER = Logger.getLogger(CallExternalWebServiceWS.class.getName()); - - /** - * Receives a json-encoded object containing a url, a REST method type and a set of parameters. - * Based on this data, a new request is created. - * @param dto contains the request data. - * @return A response signaling success or failure of the request. - */ - @POST - @Path("/callExternalWS") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response getMethod(RequestDTO dto) { - - logRequest(dto); - Boolean responseOk = false; - int code = 0; - try { - URL url; - RequestMethod type = dto.getRequestMethod(); - - // Add query parameters to URL - if(dto.getQueryParams() != null){ - String urlParams = buildUrlParameters(dto.getQueryParams()); - url = new URL(dto.getUrl() + urlParams); - } else { - url = new URL(dto.getUrl()); - } - - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setRequestMethod(type.toString()); - - if(type != RequestMethod.GET){ - // Only support JSON-encoded body data - conn.setRequestProperty("Content-Type", "application/json"); - conn.setDoOutput(true); - - // JSON-encode body content - if(dto.getBody() != null){ - String postParams = JSONValue.toJSONString(dto.getBody()); - OutputStream os = conn.getOutputStream(); - os.write(postParams.getBytes()); - os.flush(); - } - } else { - conn.setDoOutput(false); - } - - // Check if request was successful - code = conn.getResponseCode(); - responseOk = (code == 200); - - // TODO: Implement real logging of requests - logRequestResult(conn); - - conn.disconnect(); - - } catch (MalformedURLException e) { - e.printStackTrace(); - } catch (ConnectException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - if (responseOk) { - return Response.ok() - .header("MD2-Model-Version", Config.MODEL_VERSION).build(); - } else { - return Response.status(502) - .header("MD2-Model-Version", Config.MODEL_VERSION).build(); - } - } - - /** - * Creates a string containing URL parameters, that can be added to a normal URL. - * Example: {"hello": "world", "example": 42} will return '?hello=world&example=42' - * @param map a HashMap containing all query parameters - * @return a String containing query parameters - */ - private String buildUrlParameters(List map){ - String urlParams = "?"; - - try { - for (RequestDTO.CustomHashMapEntry entry : map) { - urlParams += URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue().toString(), "UTF-8") + "&"; - } - // remove trailing "&" - urlParams = urlParams.substring(0, urlParams.length() - 1); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return urlParams; - } - - /** - * Logs the result of a HttpURLConnection - * @param conn the HttpURLConnection - * @throws IOException when the inputStream cannot be read - */ - private void logRequestResult(HttpURLConnection conn) throws IOException { - String output; - try { - BufferedReader br = new BufferedReader(new InputStreamReader( - (conn.getInputStream()))); - LOGGER.info("Server response content:"); - while ((output = br.readLine()) != null) { - LOGGER.info(output); - } - } catch (IOException e) { - throw e; - } - } - - private void logRequest(RequestDTO dto){ - LOGGER.info("New " + dto.getRequestMethod() + " request to " + dto.getUrl()); - if(dto.getQueryParams() != null){ - LOGGER.info("Query Params: " + dto.getQueryParams().toString()); - } - if(dto.getBody() != null){ - LOGGER.info("Body Params: " + dto.getBody().toString()); - } - } - } - ''' -} +package de.wwu.md2.framework.generator.backend + +import de.wwu.md2.framework.mD2.Entity +import de.wwu.md2.framework.mD2.ModelElement +import de.wwu.md2.framework.mD2.ReferencedModelType +import de.wwu.md2.framework.mD2.RemoteValidator +import java.util.Collection + +import static de.wwu.md2.framework.generator.util.MD2GeneratorUtil.* + +import static extension de.wwu.md2.framework.util.IterableExtensions.* + +class WebServiceClass { + + def static createEntityWS(String basePackageName, Entity entity) ''' + package «basePackageName».ws; + + import java.util.List; + + import javax.ejb.EJB; + import javax.ejb.Stateless; + import javax.ws.rs.Consumes; + import javax.ws.rs.DELETE; + import javax.ws.rs.GET; + import javax.ws.rs.POST; + import javax.ws.rs.Path; + import javax.ws.rs.PathParam; + import javax.ws.rs.FormParam; + import javax.ws.rs.Produces; + import javax.ws.rs.QueryParam; + import javax.ws.rs.core.GenericEntity; + import javax.ws.rs.core.MediaType; + import javax.ws.rs.core.Response; + + import «basePackageName».Config; + import «basePackageName».beans.«entity.name.toFirstUpper»Bean; + import «basePackageName».datatypes.InternalIdWrapper; + import «basePackageName».entities.models.«entity.name.toFirstUpper»; + + @Path("/«entity.name.toFirstLower»") + @Stateless + public class «entity.name.toFirstUpper»WS { + + @EJB + «entity.name.toFirstUpper»Bean «entity.name.toFirstLower»Bean; + + @GET + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response getAll(@QueryParam("filter") final String filter, @QueryParam("limit") final int limit) { + final GenericEntity> «entity.name.toFirstLower»s = + new GenericEntity>(«entity.name.toFirstLower»Bean.getAll«entity.name.toFirstUpper»s(filter, limit)) {}; + return Response + .ok() + .entity(«entity.name.toFirstLower»s) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + } + + @GET + @Path("{id}") + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response get(@PathParam("id") Integer id) { + final «entity.name.toFirstUpper» «entity.name.toFirstLower» = «entity.name.toFirstLower»Bean.get«entity.name.toFirstUpper»(id); + + if («entity.name.toFirstLower» != null) { + return Response + .ok() + .entity(new GenericEntity<«entity.name.toFirstUpper»>(«entity.name.toFirstLower») {}) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + } else { + return Response + .status(404) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + } + + } + + /** + * Possibly needs to be extended by a filter parameter + */ + @POST + @Path("ids") + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response get(@FormParam("ids") List ids) { + final List<«entity.name.toFirstUpper»> «entity.name.toFirstLower»s = «entity.name.toFirstLower»Bean.get«entity.name.toFirstUpper»s(ids); + + return Response + .ok() + .entity(«entity.name.toFirstLower»s) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + } + + /** + * Exemplary input format: + * [ + * { + * "firstName": "John", + * "lastName": "Doe", + * "customerId": "2443232", + * "dateOfBirth": "1954-07-18" + * } + * ] + */ + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response createOrUpdate(List<«entity.name.toFirstUpper»> «entity.name.toFirstLower»s) { + final GenericEntity> ids = + new GenericEntity>(«entity.name.toFirstLower»Bean.createOrUpdate«entity.name.toFirstUpper»s(«entity.name.toFirstLower»s)) {}; + return Response + .ok() + .entity(ids) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + } + + @DELETE + public Response delete(@QueryParam("id") List ids) { + if («entity.name.toFirstLower»Bean.delete«entity.name.toFirstUpper»s(ids)) { + return Response + .noContent() + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + } else { + return Response + .status(409) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + } + } + + /** + * Workaround for ESRI proxy that forwards DELETE requests as GET requests! + */ + @GET + @Path("delete") + public Response deleteWithGet(@QueryParam("id") List ids) { + return delete(ids); + } + + } + ''' + + def static createVersionNegotiationWS(String basePackageName) ''' + package «basePackageName».ws; + + import javax.ejb.Stateless; + import javax.ws.rs.GET; + import javax.ws.rs.Path; + import javax.ws.rs.Produces; + import javax.ws.rs.QueryParam; + import javax.ws.rs.core.GenericEntity; + import javax.ws.rs.core.MediaType; + import javax.ws.rs.core.Response; + + import «basePackageName».Config; + import «basePackageName».datatypes.IsValidWrapper; + + @Path("/md2_model_version") + @Stateless + public class VersionNegotiationWS { + + /** + * WS that provides the current backend model version. + */ + @GET + @Path(value = "current") + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response jsonGetModelVersion() { + final GenericEntity entity = new GenericEntity(Config.MODEL_VERSION) {}; + Response response = Response + .ok() + .entity(entity) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + return response; + } + + /** + * WS checks whether the requested model version is supported by the backend (returns true or false). + * @param version String representation of the requested version. + */ + @GET + @Path(value = "is_valid") + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response jsonGetSupportsModelVersion(@QueryParam("version") final String version) { + final IsValidWrapper entity = new IsValidWrapper(Config.SUPPORTED_MODEL_VERSIONS.contains(version)); + Response response = Response + .ok() + .entity(entity) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + return response; + } + + } + ''' + + def static createRemoteValidationWS(String basePackageName, Collection affectedEntities, Collection remoteValidators) ''' + package «basePackageName».ws; + + import javax.ejb.EJB; + import javax.ejb.Stateless; + import javax.ws.rs.Consumes; + import javax.ws.rs.GET; + import javax.ws.rs.Path; + import javax.ws.rs.Produces; + import javax.ws.rs.QueryParam; + import javax.ws.rs.core.MediaType; + import javax.ws.rs.core.Response; + + import «basePackageName».Config; + import «basePackageName».beans.RemoteValidationBean; + import «basePackageName».datatypes.ValidationResult; + «FOR entity : affectedEntities» + import «basePackageName».entities.models.«entity.name.toFirstUpper»; + «ENDFOR» + + @Path("/md2_validator") + @Stateless + public class RemoteValidationWS { + + @EJB + RemoteValidationBean validatorBean; + + «FOR validator : remoteValidators» + «IF validator.contentProvider != null && validator.contentProvider.contentProvider.type instanceof ReferencedModelType» + @GET + @Path(value = "«validator.name.toFirstLower»") + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + @Consumes(MediaType.APPLICATION_JSON) + public Response json«validator.name.toFirstUpper»(«(validator.contentProvider.contentProvider.type as ReferencedModelType).entity.name.toFirstUpper» «(validator.contentProvider.contentProvider.type as ReferencedModelType).entity.name.toFirstLower») { + + ValidationResult result = validatorBean.validate«validator.name.toFirstUpper»(«(validator.contentProvider.contentProvider.type as ReferencedModelType).entity.name.toFirstLower»); + + Response response = Response + .ok() + .entity(result) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + return response; + } + + «ELSE /* based on attributes */» + @GET + @Path(value = "«validator.name.toFirstLower»") + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response json«validator.name.toFirstUpper»( + «validator.provideAttributes.joinWithIdx("", "," + System::getProperty("line.separator"), "", [p, i | '''@QueryParam("«p.contentProviderRef.name + "." + getPathTailAsString(p.tail)»") final String param«i + 1»'''])») { + + ValidationResult result = validatorBean.validate«validator.name.toFirstUpper»(«validator.provideAttributes.joinWithIdx("", ", ", "", [s, i | '''param«i + 1»'''])»); + + Response response = Response + .ok() + .entity(result) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + return response; + } + + «ENDIF» + «ENDFOR» + } + ''' + + def public static createEventHandlerWS(String basePackage) ''' + package «basePackage».ws; + + import javax.ejb.EJB; + import javax.ejb.Stateless; + import javax.ws.rs.FormParam; + import javax.ws.rs.POST; + import javax.ws.rs.Path; + import javax.ws.rs.Produces; + import javax.ws.rs.core.MediaType; + import javax.ws.rs.core.Response; + + import «basePackage».Config; + import «basePackage».beans.WorkflowStateBean; + + @Path("/eventHandler") + @Stateless + public class EventHandlerWS { + + @EJB + WorkflowStateBean workflowStateBean; + + + + /** + * Receives workflowInstanceId, lastEventFired and the current workflowElement and starts their persistence. + */ + + @POST + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response createOrUpdate(@FormParam("instanceId") String id, @FormParam("lastEventFired") String event, + @FormParam("currentWfe") String wfe, @FormParam("contentProviderIds") String contentProviderIds) { + + workflowStateBean.createOrUpdateWorkflowState(event, id, wfe, contentProviderIds); + + return Response + .ok() + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + } + } + ''' + + def public static createWorkflowStateWS(String basePackage) ''' + package «basePackage».ws; + + import java.util.ArrayList; + import java.util.List; + + import javax.ejb.EJB; + import javax.ejb.Stateless; + import javax.ws.rs.GET; + import javax.ws.rs.Path; + import javax.ws.rs.PathParam; + import javax.ws.rs.Produces; + import javax.ws.rs.QueryParam; + import javax.ws.rs.core.GenericEntity; + import javax.ws.rs.core.MediaType; + import javax.ws.rs.core.Response; + + import «basePackage».Config; + import «basePackage».beans.WorkflowStateBean; + import «basePackage».entities.WorkflowState; + + @Path("/workflowState") + @Stateless + public class WorkflowStateWS { + + @EJB + WorkflowStateBean workflowStateBean; + + /** + * + * @return all open issues + */ + @GET + @Path("all") + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response getAllOpenIssues() { + + final List workflowStates = + new ArrayList(workflowStateBean.getAllWorkflowStates("")); + + + return Response + .ok() + .entity(workflowStates) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + } + + @GET + @Path("filteredOpenIssues") + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response getFilteredOpenIssues(@QueryParam("app") String app) { + + final List workflowStates = + new ArrayList(workflowStateBean.getAllWorkflowStates(app)); + + + return Response + .ok() + .entity(workflowStates) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + } + + @GET + @Path("{id}") + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response get(@PathParam("id") String id) { + final WorkflowState workflowState = workflowStateBean.getWorkflowState(id); + + if (workflowState != null) { + return Response + .ok() + .entity(new GenericEntity(workflowState) {}) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + } else { + return Response + .status(404) + .header("MD2-Model-Version", Config.MODEL_VERSION) + .build(); + } + } + + } + ''' + + def public static createCallExternalWSProxy(String basePackage) ''' + package «basePackage».ws; + import org.json.simple.JSONValue; + + import java.io.BufferedReader; + import java.io.IOException; + import java.io.InputStreamReader; + import java.io.OutputStream; + import java.io.UnsupportedEncodingException; + import java.net.ConnectException; + import java.net.HttpURLConnection; + import java.net.MalformedURLException; + import java.net.URL; + import java.net.URLEncoder; + import java.util.List; + import java.util.logging.Logger; + + import javax.ejb.Stateless; + import javax.ws.rs.Consumes; + import javax.ws.rs.POST; + import javax.ws.rs.Path; + import javax.ws.rs.Produces; + import javax.ws.rs.core.MediaType; + import javax.ws.rs.core.Response; + + import «basePackage».Config; + import «basePackage».entities.RequestDTO; + import «basePackage».entities.RequestDTO.RequestMethod; + + @Path("/externalWS") + @Stateless + public class CallExternalWebServiceWS { + + private final static Logger LOGGER = Logger.getLogger(CallExternalWebServiceWS.class.getName()); + + /** + * Receives a json-encoded object containing a url, a REST method type and a set of parameters. + * Based on this data, a new request is created. + * @param dto contains the request data. + * @return A response signaling success or failure of the request. + */ + @POST + @Path("/callExternalWS") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response getMethod(RequestDTO dto) { + + logRequest(dto); + Boolean responseOk = false; + int code = 0; + try { + URL url; + RequestMethod type = dto.getRequestMethod(); + + // Add query parameters to URL + if(dto.getQueryParams() != null){ + String urlParams = buildUrlParameters(dto.getQueryParams()); + url = new URL(dto.getUrl() + urlParams); + } else { + url = new URL(dto.getUrl()); + } + + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod(type.toString()); + + if(type != RequestMethod.GET){ + // Only support JSON-encoded body data + conn.setRequestProperty("Content-Type", "application/json"); + conn.setDoOutput(true); + + // JSON-encode body content + if(dto.getBody() != null){ + String postParams = JSONValue.toJSONString(dto.getBody()); + OutputStream os = conn.getOutputStream(); + os.write(postParams.getBytes()); + os.flush(); + } + } else { + conn.setDoOutput(false); + } + + // Check if request was successful + code = conn.getResponseCode(); + responseOk = (code == 200); + + // TODO: Implement real logging of requests + logRequestResult(conn); + + conn.disconnect(); + + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (ConnectException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + if (responseOk) { + return Response.ok() + .header("MD2-Model-Version", Config.MODEL_VERSION).build(); + } else { + return Response.status(502) + .header("MD2-Model-Version", Config.MODEL_VERSION).build(); + } + } + + /** + * Creates a string containing URL parameters, that can be added to a normal URL. + * Example: {"hello": "world", "example": 42} will return '?hello=world&example=42' + * @param map a HashMap containing all query parameters + * @return a String containing query parameters + */ + private String buildUrlParameters(List map){ + String urlParams = "?"; + + try { + for (RequestDTO.CustomHashMapEntry entry : map) { + urlParams += URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue().toString(), "UTF-8") + "&"; + } + // remove trailing "&" + urlParams = urlParams.substring(0, urlParams.length() - 1); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return urlParams; + } + + /** + * Logs the result of a HttpURLConnection + * @param conn the HttpURLConnection + * @throws IOException when the inputStream cannot be read + */ + private void logRequestResult(HttpURLConnection conn) throws IOException { + String output; + try { + BufferedReader br = new BufferedReader(new InputStreamReader( + (conn.getInputStream()))); + LOGGER.info("Server response content:"); + while ((output = br.readLine()) != null) { + LOGGER.info(output); + } + } catch (IOException e) { + throw e; + } + } + + private void logRequest(RequestDTO dto){ + LOGGER.info("New " + dto.getRequestMethod() + " request to " + dto.getUrl()); + if(dto.getQueryParams() != null){ + LOGGER.info("Query Params: " + dto.getQueryParams().toString()); + } + if(dto.getBody() != null){ + LOGGER.info("Body Params: " + dto.getBody().toString()); + } + } + } + ''' + + + + + +def static createEntityJWSInterface(String basePackageName, Entity entity){ +''' + package «basePackageName».ws; +import javax.jws.*; +import «basePackageName».Config; + import «basePackageName».beans.«entity.name.toFirstUpper»Bean; + import «basePackageName».datatypes.InternalIdWrapper; + import «basePackageName».entities.models.«entity.name.toFirstUpper»; +import java.util.List; + +@Webservice +public interface «entity.name.toFirstUpper»WS{ + +public List<«entity.name»> getAll(String filter, int limit); + +public «entity.name» get(int id); + +public List<«entity.name»> get(List ids); + +public List createOrUpdate(List<«entity.name»> addresss) + + +public void delete(int id); + +public List deleteWithGet(List ids); +} +''' +} +def static createEntityJWS(String basePackageName, Entity entity){ +''' +import javax.jws.WebService; + +@WebService( endpointInterface="webservices.«entity.name»WS" ) +public class «entity.name.toFirstUpper»WSImpl implements «entity.name.toFirstUpper»WS +{ + public List<«entity.name»> getAll(String filter, int limit); + + public «entity.name» get(int id); + + public List<«entity.name»> get(List ids); + + public List createOrUpdate(List<«entity.name»> addresss) + + + public void delete(int id); + + public List deleteWithGet(List ids); + } +} +''' +} + +} From 7b6bc6163b6087f2c7bd2b39491f187895f6c4ce Mon Sep 17 00:00:00 2001 From: Felix Niemann Date: Sun, 9 Jul 2017 18:41:04 +0200 Subject: [PATCH 2/5] added serialization mapping for entity ids added dependency to gradle build --- .../framework/generator/android/wearable/misc/GradleGen.xtend | 1 + .../generator/android/wearable/model/ContentProviderGen.xtend | 4 ++++ .../generator/android/wearable/model/EntityGen.xtend | 1 + 3 files changed, 6 insertions(+) diff --git a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/misc/GradleGen.xtend b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/misc/GradleGen.xtend index b55fac61..9bd221fc 100644 --- a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/misc/GradleGen.xtend +++ b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/misc/GradleGen.xtend @@ -74,6 +74,7 @@ class GradleGen { compile 'com.google.android.support:wearable:2.0.1' compile 'com.google.android.gms:play-services-wearable:10.2.1' compile group: 'com.j256.ormlite', name: 'ormlite-android', version: '4.45' + compile 'com.google.code.gson:gson:2.8.0' } ''' diff --git a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/ContentProviderGen.xtend b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/ContentProviderGen.xtend index 955f92c9..4c1a3f3e 100644 --- a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/ContentProviderGen.xtend +++ b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/ContentProviderGen.xtend @@ -225,6 +225,10 @@ import «Settings.MD2LIBRARY_PACKAGE»controller.eventhandler.implementation.Md2 } } + @Override + public void newEntity(){ + content = new «(content.entity as Entity).name»(); + } } '''} diff --git a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/EntityGen.xtend b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/EntityGen.xtend index aa448fce..668bce30 100644 --- a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/EntityGen.xtend +++ b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/EntityGen.xtend @@ -108,6 +108,7 @@ public class «entity.name.toFirstUpper» extends AbstractMd2Entity { @DatabaseTable(tableName = "«entity.name.toFirstLower»") public class «entity.name.toFirstUpper» implements Serializable,Md2Entity{ + @SerializedName("__internalId") @DatabaseField(generatedId = true, columnName = "id") private long id; From cd4230b2378e52eefc3d1b72edb3ccb710bc9c0a Mon Sep 17 00:00:00 2001 From: Felix Niemann Date: Sun, 9 Jul 2017 18:45:34 +0200 Subject: [PATCH 3/5] merged contentProvider --- .../wearable/model/ContentProviderGen.xtend | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/ContentProviderGen.xtend b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/ContentProviderGen.xtend index 4c1a3f3e..e70cf04e 100644 --- a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/ContentProviderGen.xtend +++ b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/ContentProviderGen.xtend @@ -64,8 +64,8 @@ class ContentProviderGen { «var content = contentProvider.type as ReferencedModelType» «FOR element : (content.entity as Entity).attributes» -«IF element.type instanceof ReferencedType» - import «mainPackage + ".md2.model"».«(element.type as ReferencedType).element.name.toFirstUpper»; +«IF element.type instanceof ReferencedType» + import «mainPackage + ".md2.model"».«(element.type as ReferencedType).element.name.toFirstUpper»; «ENDIF» «ENDFOR» @@ -135,11 +135,11 @@ import «Settings.MD2LIBRARY_PACKAGE»controller.eventhandler.implementation.Md2 switch (attribute){ «FOR attribute: (content.entity as Entity).attributes» case "«attribute.name»": return - «IF attribute.type instanceof ReferencedType && !attribute.type.many» - ((«(content.entity as Entity).name»)content).get«attribute.name.toFirstUpper»(); + «IF attribute.type instanceof ReferencedType && !attribute.type.many» + ((«(content.entity as Entity).name»)content).get«attribute.name.toFirstUpper»(); «ELSE» - new «IF attribute.type.many» - Md2List<«EntityGen.getMd2TypeStringForAttributeType(attribute.type)»> «ELSE» + new «IF attribute.type.many» + Md2List<«EntityGen.getMd2TypeStringForAttributeType(attribute.type)»> «ELSE» «EntityGen.getMd2TypeStringForAttributeType(attribute.type)»«ENDIF»(((«(content.entity as Entity).name»)content).get«attribute.name.toFirstUpper»()); «ENDIF» «ENDFOR» @@ -157,8 +157,8 @@ import «Settings.MD2LIBRARY_PACKAGE»controller.eventhandler.implementation.Md2 if ((this.getValue(name) == null && value != null) || !this.getValue(name).equals(value)) { switch (name){ «FOR attribute: (content.entity as Entity).attributes» - case "«attribute.name»": ((«(content.entity as Entity).name»)content).set«attribute.name.toFirstUpper»(((«IF attribute.type.many» - Md2List«ELSE»«getMd2TypeStringForAttributeType(attribute.type)»«ENDIF») value)«IF attribute.type instanceof ReferencedType && !attribute.type.many» + case "«attribute.name»": ((«(content.entity as Entity).name»)content).set«attribute.name.toFirstUpper»(((«IF attribute.type.many» + Md2List«ELSE»«getMd2TypeStringForAttributeType(attribute.type)»«ENDIF») value)«IF attribute.type instanceof ReferencedType && !attribute.type.many» ); «ELSEIF attribute.type.many» .getContents()); From de29c9e79feeb97914fa8df057f1e0542f9ad12f Mon Sep 17 00:00:00 2001 From: Felix Niemann Date: Sun, 9 Jul 2017 18:46:09 +0200 Subject: [PATCH 4/5] merged contentProvider --- .../android/wearable/model/ContentProviderGen.xtend | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/ContentProviderGen.xtend b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/ContentProviderGen.xtend index e70cf04e..99a03e28 100644 --- a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/ContentProviderGen.xtend +++ b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/android/wearable/model/ContentProviderGen.xtend @@ -64,8 +64,8 @@ class ContentProviderGen { «var content = contentProvider.type as ReferencedModelType» «FOR element : (content.entity as Entity).attributes» -«IF element.type instanceof ReferencedType» - import «mainPackage + ".md2.model"».«(element.type as ReferencedType).element.name.toFirstUpper»; +«IF element.type instanceof ReferencedType» + import «mainPackage + ".md2.model"».«(element.type as ReferencedType).element.name.toFirstUpper»; «ENDIF» «ENDFOR» @@ -135,11 +135,11 @@ import «Settings.MD2LIBRARY_PACKAGE»controller.eventhandler.implementation.Md2 switch (attribute){ «FOR attribute: (content.entity as Entity).attributes» case "«attribute.name»": return - «IF attribute.type instanceof ReferencedType && !attribute.type.many» - ((«(content.entity as Entity).name»)content).get«attribute.name.toFirstUpper»(); + «IF attribute.type instanceof ReferencedType && !attribute.type.many» + ((«(content.entity as Entity).name»)content).get«attribute.name.toFirstUpper»(); «ELSE» - new «IF attribute.type.many» - Md2List<«EntityGen.getMd2TypeStringForAttributeType(attribute.type)»> «ELSE» + new «IF attribute.type.many» + Md2List<«EntityGen.getMd2TypeStringForAttributeType(attribute.type)»> «ELSE» «EntityGen.getMd2TypeStringForAttributeType(attribute.type)»«ENDIF»(((«(content.entity as Entity).name»)content).get«attribute.name.toFirstUpper»()); «ENDIF» «ENDFOR» From 1f72572609f5e8c4eb47500f7b4dd459958a00c5 Mon Sep 17 00:00:00 2001 From: Felix Witt Date: Mon, 24 Jul 2017 14:45:25 +0200 Subject: [PATCH 5/5] Activated backend generator, Updated utils to parse sql style filters --- .../wwu/md2/framework/MD2RuntimeModule.java | 2 +- .../generator/backend/CommonClasses.xtend | 203 +++++++++--------- 2 files changed, 102 insertions(+), 103 deletions(-) diff --git a/de.wwu.md2.framework/src/de/wwu/md2/framework/MD2RuntimeModule.java b/de.wwu.md2.framework/src/de/wwu/md2/framework/MD2RuntimeModule.java index 923c50a4..3f3567b0 100644 --- a/de.wwu.md2.framework/src/de/wwu/md2/framework/MD2RuntimeModule.java +++ b/de.wwu.md2.framework/src/de/wwu/md2/framework/MD2RuntimeModule.java @@ -30,7 +30,7 @@ public void configure(Binder binder) { // Bind all generators here //multiGenBinder.addBinding().to(IOSGenerator.class); //multiGenBinder.addBinding().to(AndroidLollipopGenerator.class); - //multiGenBinder.addBinding().to(BackendGenerator.class); + multiGenBinder.addBinding().to(BackendGenerator.class); multiGenBinder.addBinding().to(AndroidWearableGenerator.class); //multiGenBinder.addBinding().to(TestGenerator.class); //multiGenBinder.addBinding().to(MapAppsGenerator.class); diff --git a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/CommonClasses.xtend b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/CommonClasses.xtend index 2b5a5c51..ed50c9e0 100644 --- a/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/CommonClasses.xtend +++ b/de.wwu.md2.framework/src/de/wwu/md2/framework/generator/backend/CommonClasses.xtend @@ -7,7 +7,7 @@ import static extension de.wwu.md2.framework.generator.util.MD2GeneratorUtil.get import static extension de.wwu.md2.framework.generator.backend.util.MD2BackendUtil.* class CommonClasses { - + def static createConfig(String basePackageName, DataContainer dataContainer) ''' package «basePackageName»; @@ -35,7 +35,7 @@ class CommonClasses { public final static List SUPPORTED_MODEL_VERSIONS = Lists.newArrayList("«dataContainer.main.modelVersion»"); public final static HashMap APP_WORKFLOWELEMENT_RELATIONSHIP = setAppWorkflowElementRelationship(); - + public final static HashMap> WORKFLOWELEMENT_EVENT_SUCCESSION = setAppWorkflowElementSuccession(); «IF dataContainer.main.fileUploadConnection != null» @@ -44,19 +44,19 @@ class CommonClasses { public final static File UPLOAD_FILE_STORAGE_PATH = null; «ENDIF» - + public static final String UPLOAD_FILE_PREFIX = "upload-"; /** - * provides a hashmap for filtering workflowelements by apps - * setAppWorkflowElementRelationship : (App) --> (Wfe)* - * @return - */ + * provides a hashmap for filtering workflowelements by apps + * setAppWorkflowElementRelationship : (App) --> (Wfe)* + * @return + */ private static HashMap setAppWorkflowElementRelationship(){ HashMap map = new HashMap(); - «FOR app: dataContainer.apps» - map.put("«app.name»", new String[]{«FOR wfe: dataContainer.workflowElementsForApp(app) SEPARATOR ","»"«wfe.name»"«ENDFOR»}); + «FOR app : dataContainer.apps» + map.put("«app.name»", new String[]{«FOR wfe: dataContainer.workflowElementsForApp(app) SEPARATOR ","»"«wfe.name»"«ENDFOR»}); «ENDFOR» return map; } @@ -72,42 +72,42 @@ class CommonClasses { HashMap innerMap; «FOR wfe : dataContainer.workflowElements» - // Coming from «wfe.name» - innerMap = new HashMap(); - «FOR event : dataContainer.getEventsFromWorkflowElement(wfe)» - «IF (eventIsEndEvent(event, wfe, dataContainer))» - innerMap.put("«event.name»", "_terminate"); - «ELSE» - innerMap.put("«event.name»", "«dataContainer.getNextWorkflowElement(wfe, event).name»"); - «ENDIF» - «ENDFOR» - map.put("«wfe.name»", innerMap); - + // Coming from «wfe.name» + innerMap = new HashMap(); + «FOR event : dataContainer.getEventsFromWorkflowElement(wfe)» + «IF (eventIsEndEvent(event, wfe, dataContainer))» + innerMap.put("«event.name»", "_terminate"); + «ELSE» + innerMap.put("«event.name»", "«dataContainer.getNextWorkflowElement(wfe, event).name»"); + «ENDIF» + «ENDFOR» + map.put("«wfe.name»", innerMap); + «ENDFOR» // Coming from invokables innerMap = new HashMap(); «FOR eventDesc : dataContainer.workflow.workflowElementEntries.map[wfe | wfe.eventDescription].toSet» - HashMap map«eventDesc.toFirstUpper» = new HashMap(); + HashMap map«eventDesc.toFirstUpper» = new HashMap(); «ENDFOR» «FOR wfeEntry : dataContainer.workflow.workflowElementEntries.filter(wfe | wfe.isInvokable())» - map«wfeEntry.eventDescription.toFirstUpper».put("«wfeEntry.eventDescription»", "«wfeEntry.workflowElement.name»"); + map«wfeEntry.eventDescription.toFirstUpper».put("«wfeEntry.eventDescription»", "«wfeEntry.workflowElement.name»"); «ENDFOR» «FOR eventDesc : dataContainer.workflow.workflowElementEntries.map[wfe | wfe.eventDescription].toSet» - map.put("«eventDesc»", map«eventDesc.toFirstUpper»); + map.put("«eventDesc»", map«eventDesc.toFirstUpper»); «ENDFOR» return map; } } ''' - + def static boolean eventIsEndEvent(WorkflowEvent event, WorkflowElement wfe, DataContainer dataContainer) { val fee = dataContainer.getFireEventEntryForWorkflowEvent(event, wfe) return (fee.endWorkflow) } - + def static createUtils(String basePackageName) ''' package «basePackageName»; @@ -115,90 +115,89 @@ class CommonClasses { import java.util.regex.Pattern; /** - * Common functionality that is used throughout the project. - */ + * Common functionality that is used throughout the project. + */ public class Utils { + + /** + * Converts the standardized filter string received from the frontend to a valid + * WHERE clause that can be interpreted by the SQL parser + * + * Assumes an incoming string with conditions connected by 'and', 'or' and 'not'. Each + * condition may be an atomic boolean value 'true' or 'false' or a condition of the form + * fully.qualified.attribute.name (equals|greater|smaller|>=|<=) anyValue + * + * @param filter Filter string from the frontend. + * @return String in the common format for WHERE clauses that can be interpreted by the SQL parser. + */ + public static String buildWhereParameterFromFilterString(String filter) { - /** - * Converts the standardized filter string received from the frontend to a valid - * WHERE clause that can be interpreted by the SQL parser - * - * Assumes an incoming string with conditions connected by 'and', 'or' and 'not'. Each - * condition may be an atomic boolean value 'true' or 'false' or a condition of the form - * fully.qualified.attribute.name (equals|greater|smaller|>=|<=) anyValue - * - * @param filter Filter string from the frontend. - * @return String in the common format for WHERE clauses that can be interpreted by the SQL parser. - */ - public static String buildWhereParameterFromFilterString(String filter) { - - if(filter == null) - return ""; - - // add one whitespace at the end of the filter string to facilitate the patterns in the - // following steps - filter = "(" + filter + ")"; - - // replace all double quotes by single quotes - filter = filter.replace("\"", "'"); - - // replace true by (1 = 1) - filter = filter.replaceAll("(\\s+|\\()true(\\s+|\\))", "$1(1 = 1)$2"); - - // replace false by (1 <> 1) - filter = filter.replaceAll("(\\s+|\\()false(\\s+|\\))", "$1(1 <> 1)$2"); - - // add a t. to all attributes and replace operators by internal ones - Pattern p = Pattern.compile("(\\s+|\\()(\\w+)\\s*(equals|greater|smaller|>=|<=)\\s*(\\S+)(\\s+|\\))"); - Matcher m = p.matcher(filter); - StringBuffer s = new StringBuffer(); - while(m.find()) { - m.appendReplacement(s, "$1 t.$2 " + transformOperator(m.group(3)) + " $4$5"); - } - m.appendTail(s); - - //System.out.println("WHERE clause: " + s.toString()); - - return "WHERE " + s.toString(); + if(filter == null) + return ""; + /* + // add one whitespace at the end of the filter string to facilitate the patterns in the + // following steps + filter = "(" + filter + ")"; + + // replace all double quotes by single quotes + filter = filter.replace("\"", "'"); + + // replace true by (1 = 1) + filter = filter.replaceAll("(\\s+|\\()true(\\s+|\\))", "$1(1 = 1)$2"); + + // replace false by (1 <> 1) + filter = filter.replaceAll("(\\s+|\\()false(\\s+|\\))", "$1(1 <> 1)$2"); + + // add a t. to all attributes and replace operators by internal ones + Pattern p = Pattern.compile("(\\s+|\\()(\\w+)\\s*(equals|greater|smaller|>=|<=)\\s*(\\S+)(\\s+|\\))"); + Matcher m = p.matcher(filter); + StringBuffer s = new StringBuffer(); + while(m.find()) { + m.appendReplacement(s, "$1 t.$2 " + transformOperator(m.group(3)) + " $4$5"); } + m.appendTail(s); + */ - private static String transformOperator(String op) { - if(op.equals("greater")) { - return ">"; - } - - if(op.equals("smaller")) { - return "<"; - } - - if(op.equals(">=")) { - return ">="; - } - - if(op.equals("<=")) { - return "<="; - } - - // default: equals - return "="; + //System.out.println("WHERE clause: " + s.toString()); + + //return "WHERE " + s.toString(); + return "WHERE " + filter; + } + + private static String transformOperator(String op) { + if(op.equals("greater")) { + return ">"; + } + + if(op.equals("smaller")) { + return "<"; } + + if(op.equals(">=")) { + return ">="; + } + + if(op.equals("<=")) { + return "<="; + } + + // default: equals + return "="; + } } + ''' - - - + def static createBackendApplication(String basePackageName) ''' - package «basePackageName»; - - import javax.ws.rs.ApplicationPath; - import javax.ws.rs.core.Application; - - @ApplicationPath("service") - public class BackendApplication extends Application { - - } + package «basePackageName»; + + import javax.ws.rs.ApplicationPath; + import javax.ws.rs.core.Application; + + @ApplicationPath("service") + public class BackendApplication extends Application { + + } ''' - - - + }