com.sap.research.connectivity.gw.GwOperationsImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.sap.research.connectivity.gw.GwOperationsImpl.java

Source

/*
 * Copyright 2012 SAP AG
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sap.research.connectivity.gw;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;

import org.apache.commons.io.IOUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.springframework.roo.classpath.PhysicalTypeCategory;
import org.springframework.roo.classpath.PhysicalTypeIdentifier;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetailsBuilder;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.file.monitor.event.FileDetails;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.project.LogicalPath;
import org.springframework.roo.project.Path;
import org.springframework.roo.support.util.XmlUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import com.sap.research.connectivity.gw.parsers.JavaSourceField;
import com.sap.research.connectivity.gw.parsers.JavaSourceFieldBuilder;
import com.sap.research.connectivity.gw.parsers.JavaSourceFileEditor;
import com.sap.research.connectivity.gw.parsers.JavaSourceMethod;
import com.sap.research.connectivity.gw.parsers.JavaSourceMethodBuilder;
import com.sap.research.connectivity.gw.parsers.MetadataXMLParser;

/**
 * Implementation of {@link GwOperations} interface.
 *
 * @since 1.1.1
 */
@Component
@Service
public class GwOperationsImpl extends GWOperationsUtils implements GwOperations {

    /* ------------------------------------------------------------------------------------------------------------------
     * SAP RESEARCH OWN CODE
     * 
     * 
     */

    //GW Setup command is available only if project and persistence are setup
    public boolean isCommandGWSetupAvailable() {
        return isInstalledInModule(projectOperations.getFocusedModuleName());
    }

    public boolean isInstalledInModule(final String moduleName) {
        final LogicalPath resourcesPath = LogicalPath.getInstance(Path.SRC_MAIN_RESOURCES, moduleName);
        //        System.out.println(moduleName + resourcesPath.toString());
        return isProjectAvailable() && fileManager
                .exists(projectOperations.getPathResolver().getIdentifier(resourcesPath, PERSISTENCE_XML));
    }

    public boolean isProjectAvailable() {
        return projectOperations.isFocusedProjectAvailable();
    }

    //Add ODATA Endpoint command is available only if the class for GW Connectivity is present
    public boolean isCommandODataEndpointAvailable() {
        return fileManager.exists(getSubPackagePath(oDataFolder) + SEPARATOR + "ODataConnectivity.java");
    }

    //Add GW Entity command is available only if an OData Endpoint class has been defined and thus metadata has been extracted
    public boolean isCommandGWEntityAvailable() {
        SortedSet<FileDetails> files = fileManager
                .findMatchingAntPath(getSubPackagePath(oDataFolder) + SEPARATOR + "*_metadata.xml");
        return !files.isEmpty();
    }

    //Add GW Field command is available only if the GW Entity command is available and a java class exists connecting to an ODATA Endpoint
    public boolean isCommandGWFieldAvailable() throws IOException {
        SortedSet<FileDetails> files = fileManager
                .findMatchingAntPath(getSubPackagePath(domain) + SEPARATOR + "*.java");
        for (FileDetails file : files) {
            InputStream inputStream = fileManager.getInputStream(file.getCanonicalPath());
            if (IOUtils.toString(inputStream).contains("ODataConnectivity " + GwUtils.GW_CONNECTION_FIELD_NAME)) {
                IOUtils.closeQuietly(inputStream);
                return true;
            }
            IOUtils.closeQuietly(inputStream);
        }

        return false;
    }

    public boolean isCommandGWMVCAdaptCommandAvailable() throws IOException {
        /*
         * We check first to see if there is a gateway entity available. If so, we check if there are any generated controllers.
         */
        boolean returnResults = false;
        if (isCommandGWFieldAvailable() == true) {
            SortedSet<FileDetails> files = fileManager
                    .findMatchingAntPath(getSubPackagePath(web) + SEPARATOR + "*Controller.java");
            if (!files.isEmpty())
                returnResults = true;
        }

        return returnResults;
    }

    public void addODataConnectivity() {
        addODataDependenciesToPom();
        addOdataConnectivityClass();
    }

    public void addNamespace(String nsName, String url, String user, String pass, String csrfMode, String host,
            String port, int timeout) throws Exception {

        String metadataString = "";
        try {
            metadataString = getMetadataString(url, user, pass, host, port, timeout);
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }

        if (metadataString.isEmpty())
            throw new Exception("The specified URL did not return any valid data!");

        Map<String, String> replacements = new HashMap<String, String>();
        final String subPackagePath = getSubPackagePath(oDataFolder);
        final String topLevelPackageName = getTopLevelPackageName();

        replacements.put("<<PACKAGE>>", "package " + topLevelPackageName + "." + oDataFolder + ";\n");
        replacements.put("<<NSNAME>>", nsName);
        replacements.put("<<URL>>", url);
        replacements.put("<<USER>>", user);
        replacements.put("<<PASSWORD>>", pass);

        if (csrfMode.equals("standard")) {
            replacements.put("<<CSRF_MODE_GET>>", ".header(\"X-CSRF-Token\", \"Fetch\")");
            replacements.put("<<CSRF_MODE_SET>>",
                    ".header(\"X-CSRF-Token\", this.xsrfTokenValue).header(\"Cookie\", xsrfCookieName + \"=\" + xsrfCookieValue)");
        } else {
            replacements.put("<<CSRF_MODE_GET>>", "");
            replacements.put("<<CSRF_MODE_SET>>", ".header(\"X-Requested-With\", \"XMLHttpRequest\")");
        }

        if (host == null && port == null) {

            replacements.put("<<HOST>>", "");
            replacements.put("<<PORT>>", "");

        } else {

            replacements.put("<<HOST>>", host);
            replacements.put("<<PORT>>", port);

        }

        GwUtils.createClassFileFromTemplate(topLevelPackageName, subPackagePath, "ODataNS_template.java",
                nsName + ".java", replacements, fileManager, getClass());

        GwUtils.createFileFromString(subPackagePath, nsName + "_metadata.xml", metadataString, fileManager);
    }

    public void createEntity(final String endpointName, final String remoteEntitySetName) throws Exception {

        final String subPackagePath = getSubPackagePath(oDataFolder);

        // Verify if the endpoint and remote entity set are valid
        if (!fileManager.exists(subPackagePath + SEPARATOR + endpointName + "_metadata.xml")) {
            throw new Exception("Namespace \"" + endpointName
                    + "\" does not exist or is corrupted. Please specify a valid namespace.");
        } else {
            InputStream metaDataIs = fileManager
                    .getInputStream(subPackagePath + SEPARATOR + endpointName + "_metadata.xml");
            Document doc = XmlUtils.getDocumentBuilder().parse(metaDataIs);
            NodeList nodeList = doc.getElementsByTagName("entity");
            boolean remoteEntityExists = false;
            for (int i = 0; i < nodeList.getLength(); i++) {
                Attr attr = (Attr) nodeList.item(i).getAttributes().getNamedItem("name");
                if (attr.getValue().toString().equals(remoteEntitySetName)) {
                    remoteEntityExists = true;
                    break;
                }
            }

            if (!remoteEntityExists) {
                throw new Exception("Remote entity set \"" + remoteEntitySetName
                        + "\" does not exist. Please specify a valid remote entity.");
            }
        }

        //  Create entity class and add JPA Annotations.
        int modifier = Modifier.PUBLIC;

        String localEntityPath = typeLocationService.getTopLevelPackageForModule(
                projectOperations.getFocusedModule()) + "." + domain + "." + remoteEntitySetName;

        JavaType localEntity = new JavaType(localEntityPath);

        final String declaredByMetadataId = PhysicalTypeIdentifier.createIdentifier(localEntity,
                pathResolver.getFocusedPath(Path.SRC_MAIN_JAVA));

        final ClassOrInterfaceTypeDetailsBuilder cidBuilder = new ClassOrInterfaceTypeDetailsBuilder(
                declaredByMetadataId, modifier, localEntity, PhysicalTypeCategory.CLASS);

        final List<AnnotationMetadataBuilder> annotationBuilder = new ArrayList<AnnotationMetadataBuilder>();

        annotationBuilder.add(ROO_JAVA_BEAN_BUILDER);

        annotationBuilder.add(ROO_TO_STRING_BUILDER);

        annotationBuilder.add(ROO_JPA_ACTIVE_RECORD_BUILDER);

        cidBuilder.setAnnotations(annotationBuilder);

        typeManagementService.createOrUpdateTypeOnDisk(cidBuilder.build());
    }

    public void addFieldsMethodsAndRelations(final String namespace, String remoteEntity, boolean importAll,
            boolean importAssociations) throws Exception {

        //   Extract fields and keys from Metadata XML
        Map<String[], String> fields = new HashMap<String[], String>();
        Map<String[], String> keys = new HashMap<String[], String>();
        Map<String[], String> allFields = new HashMap<String[], String>();

        MetadataXMLParser xmlParser = getXMLParser(namespace, remoteEntity);
        xmlParser.parse();

        //   Get handler for File Editor to edit the entity file  
        JavaSourceFileEditor entityClassFile = getJavaFileEditor(domain, remoteEntity);

        //   Add Imports 
        addImports(entityClassFile, namespace);

        if (importAll)
            fields = xmlParser.getFields();

        keys = xmlParser.getKeys();

        //   Add Field declaration for OData Connector
        JavaSourceField odc = new JavaSourceFieldBuilder().fieldPrefix("private final static")
                .fieldType("ODataConnectivity").fieldName(GwUtils.GW_CONNECTION_FIELD_NAME)
                .fieldValue("new " + namespace + "()").build();

        entityClassFile.addGlobalField(odc);

        //   Add Fields and corresponding getter/setters methods to the Entity Class
        Map<String[], String> keysIncludingId = new HashMap<String[], String>();
        // Include id as a key(type String)
        String[] idKeyName = { "Id", "Id" };
        keysIncludingId.put(idKeyName, "String");
        keysIncludingId.putAll(keys);

        addGatewayFields(keysIncludingId, fields, entityClassFile);

        //   Add Persistence Methods
        // Send all the fields (keys plus fields)
        allFields.putAll(keys);
        allFields.putAll(fields);
        addPersistenceMethods(allFields, entityClassFile, remoteEntity, keys);

        //  Add relationships
        if (importAssociations) {
            Map<String, String[]> relationships = new HashMap<String, String[]>();
            relationships = xmlParser.getRelationships();
            addRelationships(relationships, remoteEntity, entityClassFile);
        }

        entityClassFile.makeFile();
        //       throw new Exception(entityClassFile.getFileContent());
    }

    private MetadataXMLParser getXMLParser(final String namespace, String remoteEntity)
            throws IllegalStateException {
        String metaDataPath = getSubPackagePath(oDataFolder);
        String metaDataFile = metaDataPath + SEPARATOR + namespace + "_metadata.xml";

        InputStream metaDataIs = fileManager.getInputStream(metaDataFile);

        Document doc;

        try {
            doc = XmlUtils.getDocumentBuilder().parse(metaDataIs);
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }

        MetadataXMLParser xmlParser = new MetadataXMLParser(doc, remoteEntity);
        return xmlParser;
    }

    public void modifyController(final String remoteEntity) throws Exception {

        //  Get handler for File Editor to edit the entity file  
        String controllerEntityName = remoteEntity + "Controller";
        JavaSourceFileEditor controllerClassFile = getJavaFileEditor(web, controllerEntityName);

        addControllerImports(controllerClassFile);

        /*
         *  We need to overwrite the show method of the .aj file, as we need to pass the itemId to the model as URLEncoded 
         */
        JavaSourceMethod showMethod = new JavaSourceMethodBuilder().methodName("show").methodPrefix("public")
                .returnType("String").annotations("@RequestMapping(value = \"/{Id}\", produces = \"text/html\")")
                .parameters(getControllerShowMethodParameters())
                .methodBody(getControllerShowMethodBody(remoteEntity)).build();
        controllerClassFile.addMethod(showMethod);

        controllerClassFile.makeFile();
    }

    public void addRemoteFieldInGWClass(String localClassName, String fieldName) throws Exception {
        //   Get handler for File Editor to edit (and search) the entity file  
        JavaSourceFileEditor entityClassFile = getJavaFileEditor(domain, localClassName);

        Map.Entry<String[], String> fieldObj = getValidatedField(localClassName, fieldName, entityClassFile);

        if (fieldObj == null)
            throw new Exception("The name \"" + fieldName
                    + "\" is not a valid name. Please choose a name from the provided list.");

        addRemoteFieldInGWJavaFile(entityClassFile, fieldObj);
        addRemoteFieldInPersistenceMethods(entityClassFile, fieldObj);

        entityClassFile.makeFile();
    }

    public void addLocalFieldInGWClass(String localClassName, String fieldName, JavaType fieldType)
            throws Exception {
        //   Get handler for File Editor to edit (and search) the entity file  
        JavaSourceFileEditor entityClassFile = getJavaFileEditor(domain, localClassName);

        Map.Entry<String[], String> fieldObj = getValidatedField(localClassName, fieldName, entityClassFile);

        if (fieldObj != null)
            throw new Exception("The name \"" + fieldName
                    + "\" is a valid name for a remote field. In order to reduce confusions, "
                    + "please choose another name for your local field.");

        String processedTypeName = fieldType.getNameIncludingTypeParameters();
        processedTypeName = processedTypeName.substring(processedTypeName.lastIndexOf(".") + 1);

        addFieldInGWJavaFile(entityClassFile, fieldName, processedTypeName);
        addLocalFieldInPersistenceMethods(entityClassFile, fieldName, processedTypeName);
        entityClassFile.makeFile();
    }
}