org.obeonetwork.m2doc.properties.TemplateCustomProperties.java Source code

Java tutorial

Introduction

Here is the source code for org.obeonetwork.m2doc.properties.TemplateCustomProperties.java

Source

/*******************************************************************************
 *  Copyright (c) 2016 Obeo. 
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *   
 *   Contributors:
 *       Obeo - initial API and implementation
 *  
 *******************************************************************************/
package org.obeonetwork.m2doc.properties;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.poi.POIXMLProperties.CustomProperties;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.eclipse.emf.ecore.EPackage;
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty;

/**
 * Template properties grouping the variable and service declaration in templates.
 * 
 * @author Romain Guider
 */
public class TemplateCustomProperties {

    /**
     * id of the integer type to use in variable declaration properties (not supported yet).
     */
    public static final String INT_TYPE = "Integer";

    /**
     * id of the real type to use in variable declaration properties (not supported yet).
     */
    public static final String REAL_TYPE = "Real";

    /**
     * id of the String type to use in variable declaration properties.
     */
    public static final String STRING_TYPE = "String";

    /**
     * id of the boolean type to use in variable declaration properties (not supported yet).
     */
    public static final String BOOLEAN_TYPE = "Boolean";

    /**
     * id of the date type to use in variable declaration properties (not supported yet).
     */
    public static final String DATE_TYPE = "Date";

    /**
     * id of the object type to use in variable declaration properties (not supported yet).
     */
    public static final String OBJECT_TYPE = "Object";

    /**
     * Prefix of the variable declaration custom properties.
     */
    public static final String VAR_PROPERTY_PREFIX = "m:var:";

    /**
     * Prefix of the variable declaration custom properties length.
     */
    public static final int VAR_PROPERTY_PREFIX_LENGTH = VAR_PROPERTY_PREFIX.length();

    /**
     * Prefix of the uri declaration custom properties.
     */
    public static final String URI_PROPERTY_PREFIX = "m:uri:";

    /**
     * Prefix of the uri declaration custom properties length.
     */
    public static final int URI_PROPERTY_PREFIX_LENGTH = URI_PROPERTY_PREFIX.length();

    /**
     * Prefix of the service declaration custom properties.
     */
    public static final String SERVICE_PROPERTY_PREFIX = "m:services:";

    /**
     * Prefix of the service declaration custom properties.
     */
    public static final int SERVICE_PROPERTY_PREFIX_LENGTH = SERVICE_PROPERTY_PREFIX.length();

    /**
     * Prefix of the service import custom properties.
     */
    public static final String SERVICE_IMPORT_PROPERTY_PREFIX = "m:import:";

    /**
     * Prefix of the service import custom properties length.
     */
    public static final int SERVICE_IMPORT_PROPERTY_PREFIX_LENGTH = SERVICE_IMPORT_PROPERTY_PREFIX.length();

    /**
     * The list of service tokens declared in the template.
     */
    private final List<String> serviceTokens = Lists.newArrayList();

    /**
     * A map that associates variables declared in the template with their intended type.
     */
    private final Map<String, String> variables = Maps.newLinkedHashMap();

    /**
     * The list of nsURIs declared in the template.
     */
    private final List<String> nsURIs = Lists.newArrayList();

    /**
     * The {@link List} of service {@link Class#getName() class names}.
     */
    private final List<String> serviceClasses = Lists.newArrayList();

    /**
     * The {@link XWPFDocument}.
     */
    private final XWPFDocument document;

    /**
     * Constructor.
     * 
     * @param document
     *            the {@link XWPFDocument}
     */
    public TemplateCustomProperties(XWPFDocument document) {
        this.document = document;
        parseProperties(document);
    }

    /**
     * Parses {@link CustomProperties}.
     * 
     * @param doc
     *            the {@link XWPFDocument}
     */
    private void parseProperties(XWPFDocument doc) {
        final CustomProperties props = doc.getProperties().getCustomProperties();
        final List<CTProperty> properties = props.getUnderlyingProperties().getPropertyList();
        for (CTProperty property : properties) {
            String propertyName = property.getName();
            if (propertyName == null) {
                continue;
            }
            propertyName = propertyName.trim();
            final String nsURI = getNsURI(propertyName);
            if (nsURI != null) {
                nsURIs.add(nsURI);
                continue;
            }

            final String serviceClasse = getServiceImport(propertyName);
            if (serviceClasse != null) {
                serviceClasses.add(serviceClasse);
                continue;
            }

            final String serviceToken = getServiceToken(propertyName);
            if (serviceToken != null) {
                serviceTokens.add(serviceToken);
                continue;
            }

            final String variableName = getVariableName(propertyName);
            if (variableName != null && isValidVariableName(variableName)) {
                variables.put(variableName, property.getLpwstr());
            }
        }
    }

    /**
     * Saves the properties to the document.
     */
    public void save() {
        final CustomProperties props = document.getProperties().getCustomProperties();
        final List<CTProperty> properties = props.getUnderlyingProperties().getPropertyList();
        final List<Integer> indexToDelete = new ArrayList<Integer>();
        int currentIndex = 0;
        List<String> tmpNsURI = new ArrayList<String>(nsURIs);
        List<String> tmpServiceImports = new ArrayList<String>(serviceClasses);
        List<String> tmpServiceTokens = new ArrayList<String>(serviceTokens);
        Map<String, String> tmpVars = new LinkedHashMap<String, String>(variables);
        for (CTProperty property : properties) {
            final String propertyName = property.getName();
            final String nsURI = getNsURI(propertyName);
            if (nsURI != null) {
                if (!tmpNsURI.remove(nsURI)) {
                    indexToDelete.add(currentIndex);
                }
                currentIndex++;
                continue;
            }

            final String serviceClasse = getServiceImport(propertyName);
            if (serviceClasse != null) {
                if (!tmpServiceImports.remove(serviceClasse)) {
                    indexToDelete.add(currentIndex);
                }
                currentIndex++;
                continue;
            }

            final String serviceToken = getServiceToken(propertyName);
            if (serviceToken != null) {
                if (!tmpServiceTokens.remove(serviceToken)) {
                    indexToDelete.add(currentIndex);
                }
                currentIndex++;
                continue;
            }

            final String variableName = getVariableName(propertyName);
            if (variableName != null) {
                final String type = tmpVars.remove(variableName);
                if (type != null) {
                    property.setLpwstr(type);
                } else {
                    indexToDelete.add(currentIndex);
                }
            }
            currentIndex++;
        }

        for (int i = indexToDelete.size() - 1; i > -1; i--) {
            props.getUnderlyingProperties().removeProperty(indexToDelete.get(i));
        }

        for (String nsURI : tmpNsURI) {
            props.addProperty(URI_PROPERTY_PREFIX + nsURI, "");
        }
        for (String serviceClass : tmpServiceImports) {
            props.addProperty(SERVICE_IMPORT_PROPERTY_PREFIX + serviceClass, "");
        }
        for (String serviceToken : tmpServiceTokens) {
            props.addProperty(SERVICE_PROPERTY_PREFIX + serviceToken, "");
        }
        for (Entry<String, String> entry : tmpVars.entrySet()) {
            props.addProperty(VAR_PROPERTY_PREFIX + entry.getKey(), entry.getValue());
        }
    }

    /**
     * Gets the {@link EPackage#getNsURI() nsURI} from the given {@link CTProperty#getName() property name}.
     * 
     * @param propertyName
     *            the {@link CTProperty#getName() property name}
     * @return the {@link EPackage#getNsURI() nsURI} from the given {@link CTProperty#getName() property name} if any, <code>null</code>
     *         otherwise
     */
    private String getNsURI(String propertyName) {
        final String res;

        if (propertyName.startsWith(URI_PROPERTY_PREFIX) && propertyName.length() > URI_PROPERTY_PREFIX_LENGTH) {
            res = propertyName.substring(URI_PROPERTY_PREFIX_LENGTH);
        } else {
            res = null;
        }

        return res;
    }

    /**
     * Gets the {@link Class#getName() class name} from the given {@link CTProperty#getName() property name}.
     * 
     * @param propertyName
     *            the {@link CTProperty#getName() property name}
     * @return the {@link Class#getName() class name} from the given {@link CTProperty#getName() property name} if any, <code>null</code>
     *         otherwise
     */
    private String getServiceImport(String propertyName) {
        final String res;

        if (propertyName.startsWith(SERVICE_IMPORT_PROPERTY_PREFIX)
                && propertyName.length() > SERVICE_IMPORT_PROPERTY_PREFIX_LENGTH) {
            res = propertyName.substring(SERVICE_IMPORT_PROPERTY_PREFIX_LENGTH);
        } else {
            res = null;
        }

        return res;
    }

    /**
     * Gets the service token from the given {@link CTProperty#getName() property name}.
     * 
     * @param propertyName
     *            the {@link CTProperty#getName() property name}
     * @return the service token from the given {@link CTProperty#getName() property name} if any, <code>null</code>
     *         otherwise
     */
    private String getServiceToken(String propertyName) {
        final String res;

        if (propertyName.startsWith(SERVICE_PROPERTY_PREFIX)
                && propertyName.length() > SERVICE_PROPERTY_PREFIX_LENGTH) {
            res = propertyName.substring(SERVICE_PROPERTY_PREFIX_LENGTH);
        } else {
            res = null;
        }

        return res;
    }

    /**
     * Gets the variable name from the given {@link CTProperty#getName() property name}.
     * 
     * @param propertyName
     *            the {@link CTProperty#getName() property name}
     * @return the variable name from the given {@link CTProperty#getName() property name} if any, <code>null</code>
     *         otherwise
     */
    private String getVariableName(String propertyName) {
        final String res;

        if (propertyName.startsWith(VAR_PROPERTY_PREFIX) && propertyName.length() > VAR_PROPERTY_PREFIX_LENGTH) {
            res = propertyName.substring(VAR_PROPERTY_PREFIX_LENGTH);
        } else {
            res = null;
        }

        return res;
    }

    /**
     * Returns a non modifiable copy of the service tokens.
     * 
     * @return the list of service tokens.
     */
    public List<String> getServiceTokens() {
        return serviceTokens;
    }

    /**
     * Returns a non modifiable copy of the uris.
     * 
     * @return the list of service tokens.
     */
    public List<String> getPackagesURIs() {
        return nsURIs;
    }

    /**
     * Returns an unmodifiable copy of the variable type map.
     * 
     * @return the variable type map.
     */
    public Map<String, String> getVariables() {
        return variables;
    }

    /**
     * Gets the {@link List} of service {@link Class#getName() class names}.
     * 
     * @return the {@link List} of service {@link Class#getName() class names}
     */
    public List<String> getServiceClasses() {
        return serviceClasses;
    }

    /**
     * Check that a given name is a valid M2DOC (I.e. AQL) variable name.
     * 
     * @param name
     *            The variable name to check
     * @return <code>true</code> if the given name matches "[a-zA-Z_][a-zA-Z0-9_]*".
     */
    public static boolean isValidVariableName(String name) {
        return name != null && name.matches("[a-zA-Z_][a-zA-Z0-9_]*");
    }

}