com.liferay.portal.tools.service.builder.ServiceBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.portal.tools.service.builder.ServiceBuilder.java

Source

/* ./liferay-liferay-portal-b66e4b4/modules/util/portal-tools-service-builder/src/com/liferay/portal/tools/service/builder/ServiceBuilder.java */
/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.tools.service.builder;

import com.liferay.portal.freemarker.FreeMarkerUtil;
import com.liferay.portal.kernel.dao.db.IndexMetadata;
import com.liferay.portal.kernel.dao.db.IndexMetadataFactoryUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.ArrayUtil_IW;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.ClearThreadLocalUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.PropertiesUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.StringUtil_IW;
import com.liferay.portal.kernel.util.TextFormatter;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.util.Validator_IW;
import com.liferay.portal.model.CacheField;
import com.liferay.portal.model.ModelHintsUtil;
import com.liferay.portal.security.auth.PrincipalException;
import com.liferay.portal.tools.ArgumentsUtil;
import com.liferay.portal.tools.sourceformatter.JavaImportsFormatter;
import com.liferay.portal.xml.SAXReaderFactory;
import com.liferay.util.xml.XMLFormatter;
import com.liferay.util.xml.XMLSafeReader;

import com.thoughtworks.qdox.JavaDocBuilder;
import com.thoughtworks.qdox.model.AbstractBaseJavaEntity;
import com.thoughtworks.qdox.model.Annotation;
import com.thoughtworks.qdox.model.ClassLibrary;
import com.thoughtworks.qdox.model.DocletTag;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaParameter;
import com.thoughtworks.qdox.model.JavaSource;
import com.thoughtworks.qdox.model.Type;

import de.hunsicker.io.FileFormat;
import de.hunsicker.jalopy.Jalopy;
import de.hunsicker.jalopy.storage.Convention;
import de.hunsicker.jalopy.storage.ConventionKeys;
import de.hunsicker.jalopy.storage.Environment;

import freemarker.ext.beans.BeansWrapper;

import freemarker.log.Logger;

import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateModelException;

import java.beans.Introspector;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;

import java.net.URL;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

/**
 * @author Brian Wing Shun Chan
 * @author Charles May
 * @author Alexander Chow
 * @author Harry Mark
 * @author Tariq Dweik
 * @author Glenn Powell
 * @author Raymond Aug
 * @author Prashant Dighe
 * @author Shuyang Zhou
 * @author James Lefeu
 * @author Miguel Pastor
 * @author Cody Hoag
 * @author James Hinkey
 * @author Hugo Huijser
 */
public class ServiceBuilder {

    public static final String AUTHOR = "Brian Wing Shun Chan";

    public static String getContent(String fileName) throws Exception {
        Document document = _getContentDocument(fileName);

        Element rootElement = document.getRootElement();

        Element authorElement = null;
        Element namespaceElement = null;
        Map<String, Element> entityElements = new TreeMap<>();
        Map<String, Element> exceptionElements = new TreeMap<>();

        List<Element> elements = rootElement.elements();

        for (Element element : elements) {
            String elementName = element.getName();

            if (elementName.equals("author")) {
                element.detach();

                if (authorElement != null) {
                    throw new IllegalArgumentException("There can only be one author element");
                }

                authorElement = element;
            } else if (elementName.equals("namespace")) {
                element.detach();

                if (namespaceElement != null) {
                    throw new IllegalArgumentException("There can only be one namespace element");
                }

                namespaceElement = element;
            } else if (elementName.equals("entity")) {
                element.detach();

                String name = element.attributeValue("name");

                entityElements.put(StringUtil.toLowerCase(name), element);
            } else if (elementName.equals("exceptions")) {
                element.detach();

                List<Element> exceptionElementsList = element.elements("exception");

                for (Element exceptionElement : exceptionElementsList) {
                    exceptionElement.detach();

                    exceptionElements.put(exceptionElement.getText(), exceptionElement);
                }
            }
        }

        if (authorElement != null) {
            rootElement.add(authorElement);
        }

        if (namespaceElement == null) {
            throw new IllegalArgumentException("The namespace element is required");
        } else {
            rootElement.add(namespaceElement);
        }

        _addElements(rootElement, entityElements);

        if (!exceptionElements.isEmpty()) {
            Element exceptionsElement = rootElement.addElement("exceptions");

            _addElements(exceptionsElement, exceptionElements);
        }

        return document.asXML();
    }

    public static boolean hasAnnotation(AbstractBaseJavaEntity abstractBaseJavaEntity, String annotationName) {

        Annotation[] annotations = abstractBaseJavaEntity.getAnnotations();

        if (annotations == null) {
            return false;
        }

        for (int i = 0; i < annotations.length; i++) {
            Type type = annotations[i].getType();

            JavaClass javaClass = type.getJavaClass();

            if (annotationName.equals(javaClass.getName())) {
                return true;
            }
        }

        return false;
    }

    public static void main(String[] args) throws Exception {
        Map<String, String> arguments = ArgumentsUtil.parseArguments(args);

        String apiDirName = arguments.get("service.api.dir");
        boolean autoImportDefaultReferences = GetterUtil
                .getBoolean(arguments.get("service.auto.import.default.references"), true);
        boolean autoNamespaceTables = GetterUtil.getBoolean(arguments.get("service.auto.namespace.tables"));
        String beanLocatorUtil = arguments.get("service.bean.locator.util");
        long buildNumber = GetterUtil.getLong(arguments.get("service.build.number"), 1);
        boolean buildNumberIncrement = GetterUtil.getBoolean(arguments.get("service.build.number.increment"), true);
        String hbmFileName = arguments.get("service.hbm.file");
        String implDirName = arguments.get("service.impl.dir");
        String inputFileName = arguments.get("service.input.file");
        String[] modelHintsConfigs = StringUtil
                .split(GetterUtil.getString(arguments.get("service.model.hints.configs"),
                        StringUtil.merge(ServiceBuilderArgs.MODEL_HINTS_CONFIGS)));
        String modelHintsFileName = arguments.get("service.model.hints.file");
        boolean osgiModule = GetterUtil.getBoolean(arguments.get("service.osgi.module"));
        String pluginName = arguments.get("service.plugin.name");
        String propsUtil = arguments.get("service.props.util");
        String[] readOnlyPrefixes = StringUtil
                .split(GetterUtil.getString(arguments.get("service.read.only.prefixes"),
                        StringUtil.merge(ServiceBuilderArgs.READ_ONLY_PREFIXES)));
        String remotingFileName = arguments.get("service.remoting.file");
        String[] resourceActionsConfigs = StringUtil
                .split(GetterUtil.getString(arguments.get("service.resource.actions.configs"),
                        StringUtil.merge(ServiceBuilderArgs.RESOURCE_ACTION_CONFIGS)));
        String resourcesDirName = arguments.get("service.resources.dir");
        String springFileName = arguments.get("service.spring.file");
        String[] springNamespaces = StringUtil.split(arguments.get("service.spring.namespaces"));
        String sqlDirName = arguments.get("service.sql.dir");
        String sqlFileName = arguments.get("service.sql.file");
        String sqlIndexesFileName = arguments.get("service.sql.indexes.file");
        String sqlSequencesFileName = arguments.get("service.sql.sequences.file");
        String targetEntityName = arguments.get("service.target.entity.name");
        String testDirName = arguments.get("service.test.dir");

        Set<String> resourceActionModels = readResourceActionModels(implDirName, resourceActionsConfigs);

        ModelHintsUtil modelHintsUtil = new ModelHintsUtil();

        ModelHintsImpl modelHintsImpl = new ModelHintsImpl();

        modelHintsImpl.setModelHintsConfigs(modelHintsConfigs);

        modelHintsImpl.afterPropertiesSet();

        modelHintsUtil.setModelHints(modelHintsImpl);

        try {
            ServiceBuilder serviceBuilder = new ServiceBuilder(apiDirName, autoImportDefaultReferences,
                    autoNamespaceTables, beanLocatorUtil, buildNumber, buildNumberIncrement, hbmFileName,
                    implDirName, inputFileName, modelHintsFileName, osgiModule, pluginName, propsUtil,
                    readOnlyPrefixes, remotingFileName, resourceActionModels, resourcesDirName, springFileName,
                    springNamespaces, sqlDirName, sqlFileName, sqlIndexesFileName, sqlSequencesFileName,
                    targetEntityName, testDirName, true);

            String modifiedFileNames = StringUtil.merge(serviceBuilder.getModifiedFileNames());

            System.setProperty(ServiceBuilderArgs.OUTPUT_KEY_MODIFIED_FILES, modifiedFileNames);
        } catch (Throwable t) {
            String message = "Please set these arguments. Sample values are:\n" + "\n"
                    + "\tservice.api.dir=${basedir}/../portal-service/src\n"
                    + "\tservice.auto.import.default.references=true\n" + "\tservice.auto.namespace.tables=false\n"
                    + "\tservice.bean.locator.util=com.liferay.portal.kernel.bean.PortalBeanLocatorUtil\n"
                    + "\tservice.build.number=1\n" + "\tservice.build.number.increment=true\n"
                    + "\tservice.hbm.file=${basedir}/src/META-INF/portal-hbm.xml\n"
                    + "\tservice.impl.dir=${basedir}/src\n" + "\tservice.input.file=${service.file}\n"
                    + "\tservice.model.hints.configs=" + StringUtil.merge(ServiceBuilderArgs.MODEL_HINTS_CONFIGS)
                    + "\n" + "\tservice.model.hints.file=${basedir}/src/META-INF/portal-model-hints.xml\n"
                    + "\tservice.osgi.module=false\n" + "\tservice.plugin.name=\n"
                    + "\tservice.props.util=com.liferay.portal.util.PropsUtil\n" + "\tservice.read.only.prefixes="
                    + StringUtil.merge(ServiceBuilderArgs.READ_ONLY_PREFIXES) + "\n"
                    + "\tservice.remoting.file=${basedir}/../portal-web/docroot/WEB-INF/remoting-servlet.xml\n"
                    + "\tservice.resource.actions.configs="
                    + StringUtil.merge(ServiceBuilderArgs.RESOURCE_ACTION_CONFIGS) + "\n"
                    + "\tservice.resources.dir=${basedir}/src\n"
                    + "\tservice.spring.file=${basedir}/src/META-INF/portal-spring.xml\n"
                    + "\tservice.spring.namespaces=beans\n" + "\tservice.sql.dir=${basedir}/../sql\n"
                    + "\tservice.sql.file=portal-tables.sql\n" + "\tservice.sql.indexes.file=indexes.sql\n"
                    + "\tservice.sql.sequences.file=sequences.sql\n"
                    + "\tservice.target.entity.name=${service.target.entity.name}\n"
                    + "\tservice.test.dir=${basedir}/test/integration\n" + "\n"
                    + "You can also customize the generated code by overriding the default templates with these optional system properties:\n"
                    + "\n" + "\t-Dservice.tpl.bad_alias_names=" + _TPL_ROOT + "bad_alias_names.txt\n"
                    + "\t-Dservice.tpl.bad_column_names=" + _TPL_ROOT + "bad_column_names.txt\n"
                    + "\t-Dservice.tpl.bad_json_types=" + _TPL_ROOT + "bad_json_types.txt\n"
                    + "\t-Dservice.tpl.bad_table_names=" + _TPL_ROOT + "bad_table_names.txt\n"
                    + "\t-Dservice.tpl.base_mode_impl=" + _TPL_ROOT + "base_mode_impl.ftl\n"
                    + "\t-Dservice.tpl.blob_model=" + _TPL_ROOT + "blob_model.ftl\n"
                    + "\t-Dservice.tpl.copyright.txt=copyright.txt\n" + "\t-Dservice.tpl.ejb_pk=" + _TPL_ROOT
                    + "ejb_pk.ftl\n" + "\t-Dservice.tpl.exception=" + _TPL_ROOT + "exception.ftl\n"
                    + "\t-Dservice.tpl.export_actionable_dynamic_query=" + _TPL_ROOT
                    + "export_actionable_dynamic_query.ftl\n" + "\t-Dservice.tpl.extended_model=" + _TPL_ROOT
                    + "extended_model.ftl\n" + "\t-Dservice.tpl.extended_model_base_impl=" + _TPL_ROOT
                    + "extended_model_base_impl.ftl\n" + "\t-Dservice.tpl.extended_model_impl=" + _TPL_ROOT
                    + "extended_model_impl.ftl\n" + "\t-Dservice.tpl.finder=" + _TPL_ROOT + "finder.ftl\n"
                    + "\t-Dservice.tpl.finder_util=" + _TPL_ROOT + "finder_util.ftl\n" + "\t-Dservice.tpl.hbm_xml="
                    + _TPL_ROOT + "hbm_xml.ftl\n" + "\t-Dservice.tpl.json_js=" + _TPL_ROOT + "json_js.ftl\n"
                    + "\t-Dservice.tpl.json_js_method=" + _TPL_ROOT + "json_js_method.ftl\n"
                    + "\t-Dservice.tpl.model=" + _TPL_ROOT + "model.ftl\n" + "\t-Dservice.tpl.model_cache="
                    + _TPL_ROOT + "model_cache.ftl\n" + "\t-Dservice.tpl.model_hints_xml=" + _TPL_ROOT
                    + "model_hints_xml.ftl\n" + "\t-Dservice.tpl.model_impl=" + _TPL_ROOT + "model_impl.ftl\n"
                    + "\t-Dservice.tpl.model_soap=" + _TPL_ROOT + "model_soap.ftl\n"
                    + "\t-Dservice.tpl.model_wrapper=" + _TPL_ROOT + "model_wrapper.ftl\n"
                    + "\t-Dservice.tpl.persistence=" + _TPL_ROOT + "persistence.ftl\n"
                    + "\t-Dservice.tpl.persistence_impl=" + _TPL_ROOT + "persistence_impl.ftl\n"
                    + "\t-Dservice.tpl.persistence_util=" + _TPL_ROOT + "persistence_util.ftl\n"
                    + "\t-Dservice.tpl.props=" + _TPL_ROOT + "props.ftl\n" + "\t-Dservice.tpl.remoting_xml="
                    + _TPL_ROOT + "remoting_xml.ftl\n" + "\t-Dservice.tpl.service=" + _TPL_ROOT + "service.ftl\n"
                    + "\t-Dservice.tpl.service_base_impl=" + _TPL_ROOT + "service_base_impl.ftl\n"
                    + "\t-Dservice.tpl.service_clp=" + _TPL_ROOT + "service_clp.ftl\n"
                    + "\t-Dservice.tpl.service_clp_invoker=" + _TPL_ROOT + "service_clp_invoker.ftl\n"
                    + "\t-Dservice.tpl.service_clp_message_listener=" + _TPL_ROOT
                    + "service_clp_message_listener.ftl\n" + "\t-Dservice.tpl.service_clp_serializer=" + _TPL_ROOT
                    + "service_clp_serializer.ftl\n" + "\t-Dservice.tpl.service_http=" + _TPL_ROOT
                    + "service_http.ftl\n" + "\t-Dservice.tpl.service_impl=" + _TPL_ROOT + "service_impl.ftl\n"
                    + "\t-Dservice.tpl.service_props_util=" + _TPL_ROOT + "service_props_util.ftl\n"
                    + "\t-Dservice.tpl.service_soap=" + _TPL_ROOT + "service_soap.ftl\n"
                    + "\t-Dservice.tpl.service_util=" + _TPL_ROOT + "service_util.ftl\n"
                    + "\t-Dservice.tpl.service_wrapper=" + _TPL_ROOT + "service_wrapper.ftl\n"
                    + "\t-Dservice.tpl.spring_xml=" + _TPL_ROOT + "spring_xml.ftl\n"
                    + "\t-Dservice.tpl.spring_xml_session=" + _TPL_ROOT + "spring_xml_session.ftl";

            if (t instanceof ServiceBuilderException) {
                ServiceBuilderException serviceBuilderException = (ServiceBuilderException) t;

                System.err.println(serviceBuilderException.getMessage());
            } else if (t instanceof Exception) {
                System.out.println(message);

                ArgumentsUtil.processMainException(arguments, (Exception) t);
            } else {
                t.printStackTrace();
            }
        }

        try {
            ClearThreadLocalUtil.clearThreadLocal();
        } catch (Throwable t) {
            t.printStackTrace();
        }

        Introspector.flushCaches();
    }

    public static Set<String> readResourceActionModels(String implDir, String[] resourceActionsConfigs)
            throws Exception {

        Set<String> resourceActionModels = new HashSet<>();

        ClassLoader classLoader = ServiceBuilder.class.getClassLoader();

        for (String config : resourceActionsConfigs) {
            if (config.startsWith("classpath*:")) {
                String name = config.substring("classpath*:".length());

                Enumeration<URL> enu = classLoader.getResources(name);

                while (enu.hasMoreElements()) {
                    URL url = enu.nextElement();

                    InputStream inputStream = url.openStream();

                    _readResourceActionModels(implDir, inputStream, resourceActionModels);
                }
            } else {
                Enumeration<URL> urls = classLoader.getResources(config);

                if (urls.hasMoreElements()) {
                    while (urls.hasMoreElements()) {
                        URL url = urls.nextElement();

                        try (InputStream inputStream = url.openStream()) {
                            _readResourceActionModels(implDir, inputStream, resourceActionModels);
                        }
                    }
                } else {
                    File file = new File(config);

                    if (!file.exists()) {
                        file = new File(implDir, config);
                    }

                    if (!file.exists()) {
                        continue;
                    }

                    try (InputStream inputStream = new FileInputStream(file)) {
                        _readResourceActionModels(implDir, inputStream, resourceActionModels);
                    }
                }
            }
        }

        return resourceActionModels;
    }

    public static String toHumanName(String name) {
        if (name == null) {
            return null;
        }

        String humanName = TextFormatter.format(name, TextFormatter.H);

        if (humanName.equals("id")) {
            humanName = "ID";
        } else if (humanName.equals("ids")) {
            humanName = "IDs";
        }

        if (humanName.endsWith(" id")) {
            humanName = humanName.substring(0, humanName.length() - 3) + " ID";
        } else if (humanName.endsWith(" ids")) {
            humanName = humanName.substring(0, humanName.length() - 4) + " IDs";
        }

        if (humanName.contains(" id ")) {
            humanName = StringUtil.replace(humanName, " id ", " ID ");
        } else if (humanName.contains(" ids ")) {
            humanName = StringUtil.replace(humanName, " ids ", " IDs ");
        }

        return humanName;
    }

    public static void writeFile(File file, String content, Set<String> modifiedFileNames) throws IOException {

        writeFile(file, content, AUTHOR, modifiedFileNames);
    }

    public static void writeFile(File file, String content, String author, Map<String, Object> jalopySettings,
            Set<String> modifiedFileNames) throws IOException {

        String packagePath = _getPackagePath(file);

        String className = file.getName();

        className = className.substring(0, className.length() - 5);

        content = JavaImportsFormatter.stripJavaImports(content, packagePath, className);

        content = _stripFullyQualifiedClassNames(content);

        File tempFile = new File(_TMP_DIR, "ServiceBuilder.temp");

        FileUtils.write(tempFile, content);

        // Beautify

        StringBuffer sb = new StringBuffer();

        Jalopy jalopy = new Jalopy();

        jalopy.setFileFormat(FileFormat.UNIX);
        jalopy.setInput(tempFile);
        jalopy.setOutput(sb);

        File jalopyXmlFile = new File("tools/jalopy.xml");

        if (!jalopyXmlFile.exists()) {
            jalopyXmlFile = new File("../tools/jalopy.xml");
        }

        if (!jalopyXmlFile.exists()) {
            jalopyXmlFile = new File("misc/jalopy.xml");
        }

        if (!jalopyXmlFile.exists()) {
            jalopyXmlFile = new File("../misc/jalopy.xml");
        }

        if (!jalopyXmlFile.exists()) {
            jalopyXmlFile = new File("../../misc/jalopy.xml");
        }

        if (jalopyXmlFile.exists()) {
            Jalopy.setConvention(jalopyXmlFile);
        } else {
            URL url = _readJalopyXmlFromClassLoader();

            Jalopy.setConvention(url);
        }

        if (jalopySettings == null) {
            jalopySettings = new HashMap<>();
        }

        Environment env = Environment.getInstance();

        // Author

        author = GetterUtil.getString((String) jalopySettings.get("author"), author);

        env.set("author", author);

        // File name

        env.set("fileName", file.getName());

        Convention convention = Convention.getInstance();

        String classMask = "/**\n * @author $author$\n*/";

        convention.put(ConventionKeys.COMMENT_JAVADOC_TEMPLATE_CLASS, env.interpolate(classMask));

        convention.put(ConventionKeys.COMMENT_JAVADOC_TEMPLATE_INTERFACE, env.interpolate(classMask));

        jalopy.format();

        String newContent = sb.toString();

        // Remove double blank lines after the package or last import

        newContent = newContent.replaceFirst("(?m)^[ \t]*((?:package|import) .*;)\\s*^[ \t]*/\\*\\*", "$1\n\n/**");

        /*
        // Remove blank lines after try {
            
        newContent = StringUtil.replace(newContent, "try {\n\n", "try {\n");
            
        // Remove blank lines after ) {
            
        newContent = StringUtil.replace(newContent, ") {\n\n", ") {\n");
            
        // Remove blank lines empty braces { }
            
        newContent = StringUtil.replace(newContent, "\n\n\t}", "\n\t}");
            
        // Add space to last }
            
        newContent = newContent.substring(0, newContent.length() - 2) + "\n\n}";
        */

        writeFileRaw(file, newContent, modifiedFileNames);

        tempFile.deleteOnExit();
    }

    public static void writeFile(File file, String content, String author, Set<String> modifiedFileNames)
            throws IOException {

        writeFile(file, content, author, null, modifiedFileNames);
    }

    public static void writeFileRaw(File file, String content, Set<String> modifiedFileNames) throws IOException {

        // Write file if and only if the file has changed

        if (!file.exists() || !content.equals(FileUtils.readFileToString(file))) {

            FileUtils.write(file, content);

            modifiedFileNames.add(file.getAbsolutePath());

            System.out.println("Writing " + file);
        }
    }

    public ServiceBuilder(String apiDirName, boolean autoImportDefaultReferences, boolean autoNamespaceTables,
            String beanLocatorUtil, long buildNumber, boolean buildNumberIncrement, String hbmFileName,
            String implDirName, String inputFileName, String modelHintsFileName, boolean osgiModule,
            String pluginName, String propsUtil, String[] readOnlyPrefixes, String remotingFileName,
            Set<String> resourceActionModels, String resourcesDirName, String springFileName,
            String[] springNamespaces, String sqlDirName, String sqlFileName, String sqlIndexesFileName,
            String sqlSequencesFileName, String targetEntityName, String testDirName, boolean build)
            throws Exception {

        _tplBadAliasNames = _getTplProperty("bad_alias_names", _tplBadAliasNames);
        _tplBadColumnNames = _getTplProperty("bad_column_names", _tplBadColumnNames);
        _tplBadTableNames = _getTplProperty("bad_table_names", _tplBadTableNames);
        _tplBlobModel = _getTplProperty("blob_model", _tplBlobModel);
        _tplEjbPk = _getTplProperty("ejb_pk", _tplEjbPk);
        _tplException = _getTplProperty("exception", _tplException);
        _tplExtendedModel = _getTplProperty("extended_model", _tplExtendedModel);
        _tplExtendedModelBaseImpl = _getTplProperty("extended_model_base_impl", _tplExtendedModelBaseImpl);
        _tplExtendedModelImpl = _getTplProperty("extended_model_impl", _tplExtendedModelImpl);
        _tplFinder = _getTplProperty("finder", _tplFinder);
        _tplFinderUtil = _getTplProperty("finder_util", _tplFinderUtil);
        _tplHbmXml = _getTplProperty("hbm_xml", _tplHbmXml);
        _tplJsonJs = _getTplProperty("json_js", _tplJsonJs);
        _tplJsonJsMethod = _getTplProperty("json_js_method", _tplJsonJsMethod);
        _tplModel = _getTplProperty("model", _tplModel);
        _tplModelCache = _getTplProperty("model_cache", _tplModelCache);
        _tplModelClp = _getTplProperty("model", _tplModelClp);
        _tplModelHintsXml = _getTplProperty("model_hints_xml", _tplModelHintsXml);
        _tplModelImpl = _getTplProperty("model_impl", _tplModelImpl);
        _tplModelSoap = _getTplProperty("model_soap", _tplModelSoap);
        _tplModelWrapper = _getTplProperty("model_wrapper", _tplModelWrapper);
        _tplPersistence = _getTplProperty("persistence", _tplPersistence);
        _tplPersistenceImpl = _getTplProperty("persistence_impl", _tplPersistenceImpl);
        _tplPersistenceUtil = _getTplProperty("persistence_util", _tplPersistenceUtil);
        _tplProps = _getTplProperty("props", _tplProps);
        _tplRemotingXml = _getTplProperty("remoting_xml", _tplRemotingXml);
        _tplService = _getTplProperty("service", _tplService);
        _tplServiceBaseImpl = _getTplProperty("service_base_impl", _tplServiceBaseImpl);
        _tplServiceClp = _getTplProperty("service_clp", _tplServiceClp);
        _tplServiceClpInvoker = _getTplProperty("service_clp_invoker", _tplServiceClpInvoker);
        _tplServiceClpMessageListener = _getTplProperty("service_clp_message_listener",
                _tplServiceClpMessageListener);
        _tplServiceClpSerializer = _getTplProperty("service_clp_serializer", _tplServiceClpSerializer);
        _tplServiceHttp = _getTplProperty("service_http", _tplServiceHttp);
        _tplServiceImpl = _getTplProperty("service_impl", _tplServiceImpl);
        _tplServicePropsUtil = _getTplProperty("service_props_util", _tplServicePropsUtil);
        _tplServiceSoap = _getTplProperty("service_soap", _tplServiceSoap);
        _tplServiceUtil = _getTplProperty("service_util", _tplServiceUtil);
        _tplServiceWrapper = _getTplProperty("service_wrapper", _tplServiceWrapper);
        _tplSpringXml = _getTplProperty("spring_xml", _tplSpringXml);

        try {
            _apiDirName = apiDirName;
            _autoImportDefaultReferences = autoImportDefaultReferences;
            _autoNamespaceTables = autoNamespaceTables;
            _beanLocatorUtil = beanLocatorUtil;
            _buildNumber = buildNumber;
            _buildNumberIncrement = buildNumberIncrement;
            _hbmFileName = hbmFileName;
            _implDirName = implDirName;
            _modelHintsFileName = modelHintsFileName;
            _osgiModule = osgiModule;
            _pluginName = GetterUtil.getString(pluginName);
            _propsUtil = propsUtil;
            _readOnlyPrefixes = readOnlyPrefixes;
            _remotingFileName = remotingFileName;
            _resourceActionModels = resourceActionModels;
            _resourcesDirName = resourcesDirName;
            _springFileName = springFileName;

            _springNamespaces = springNamespaces;

            if (!ArrayUtil.contains(_springNamespaces, _SPRING_NAMESPACE_BEANS)) {

                _springNamespaces = ArrayUtil.append(_springNamespaces, _SPRING_NAMESPACE_BEANS);
            }

            _sqlDirName = sqlDirName;
            _sqlFileName = sqlFileName;
            _sqlIndexesFileName = sqlIndexesFileName;
            _sqlSequencesFileName = sqlSequencesFileName;
            _targetEntityName = targetEntityName;
            _testDirName = testDirName;
            _build = build;

            _badTableNames = _readLines(_tplBadTableNames);
            _badAliasNames = _readLines(_tplBadAliasNames);
            _badColumnNames = _readLines(_tplBadColumnNames);

            _beanLocatorUtilShortName = _beanLocatorUtil.substring(_beanLocatorUtil.lastIndexOf(".") + 1);

            SAXReader saxReader = _getSAXReader();

            Document document = saxReader.read(new XMLSafeReader(getContent(inputFileName)));

            Element rootElement = document.getRootElement();

            String packagePath = rootElement.attributeValue("package-path");

            if (Validator.isNull(packagePath)) {
                throw new IllegalArgumentException("The package-path attribute is required");
            }

            _outputPath = _implDirName + "/" + StringUtil.replace(packagePath, ".", "/");

            _serviceOutputPath = _apiDirName + "/" + StringUtil.replace(packagePath, ".", "/");

            if (Validator.isNotNull(_testDirName)) {
                _testOutputPath = _testDirName + "/" + StringUtil.replace(packagePath, ".", "/");
            }

            _packagePath = packagePath;

            _autoImportDefaultReferences = GetterUtil.getBoolean(
                    rootElement.attributeValue("auto-import-default-references"), _autoImportDefaultReferences);
            _autoNamespaceTables = GetterUtil.getBoolean(rootElement.attributeValue("auto-namespace-tables"),
                    _autoNamespaceTables);
            _mvccEnabled = GetterUtil.getBoolean(rootElement.attributeValue("mvcc-enabled"));

            Element authorElement = rootElement.element("author");

            if (authorElement != null) {
                _author = authorElement.getText();
            } else {
                _author = AUTHOR;
            }

            Element portletElement = rootElement.element("portlet");
            Element namespaceElement = rootElement.element("namespace");

            if (portletElement != null) {
                _portletName = portletElement.attributeValue("name");

                _portletShortName = portletElement.attributeValue("short-name");

                _portletPackageName = TextFormatter.format(_portletName, TextFormatter.B);

                _outputPath += "/" + _portletPackageName;

                _serviceOutputPath += "/" + _portletPackageName;

                _testOutputPath += "/" + _portletPackageName;

                _packagePath += "." + _portletPackageName;
            } else {
                _portletShortName = namespaceElement.getText();
            }

            _portletShortName = _portletShortName.trim();

            for (char c : _portletShortName.toCharArray()) {
                if (!Validator.isChar(c) && (c != CharPool.UNDERLINE)) {
                    throw new RuntimeException("The namespace element must be a valid keyword");
                }
            }

            _ejbList = new ArrayList<>();
            _entityMappings = new HashMap<>();

            List<Element> entityElements = rootElement.elements("entity");

            for (Element entityElement : entityElements) {
                _parseEntity(entityElement);
            }

            List<String> exceptionList = new ArrayList<>();

            Element exceptionsElement = rootElement.element("exceptions");

            if (exceptionsElement != null) {
                List<Element> exceptionElements = exceptionsElement.elements("exception");

                for (Element exceptionElement : exceptionElements) {
                    exceptionList.add(exceptionElement.getText());
                }
            }

            if (build) {
                for (int x = 0; x < _ejbList.size(); x++) {
                    Entity entity = _ejbList.get(x);

                    if (_isTargetEntity(entity)) {
                        System.out.println("Building " + entity.getName());

                        _resolveEntity(entity);

                        if (entity.hasActionableDynamicQuery()) {
                            _createActionableDynamicQuery(entity);

                            if (entity.isStagedModel()) {
                                _createExportActionableDynamicQuery(entity);
                            } else {
                                _removeExportActionableDynamicQuery(entity);
                            }
                        } else {
                            _removeActionableDynamicQuery(entity);
                            _removeExportActionableDynamicQuery(entity);
                        }

                        if (entity.hasColumns()) {
                            _createHbm(entity);
                            _createHbmUtil(entity);

                            _createPersistenceImpl(entity);
                            _createPersistence(entity);
                            _createPersistenceUtil(entity);

                            if (Validator.isNotNull(_testDirName)) {
                                _createPersistenceTest(entity);
                            }

                            _createModelImpl(entity);
                            _createExtendedModelBaseImpl(entity);
                            _createExtendedModelImpl(entity);

                            entity.setTransients(_getTransients(entity, false));
                            entity.setParentTransients(_getTransients(entity, true));

                            _createModel(entity);
                            _createExtendedModel(entity);

                            _createModelCache(entity);
                            _createModelClp(entity);
                            _createModelWrapper(entity);

                            _createModelSoap(entity);

                            _createBlobModels(entity);

                            _createPool(entity);

                            if (entity.getPKList().size() > 1) {
                                _createEJBPK(entity);
                            }
                        }

                        _createFinder(entity);
                        _createFinderUtil(entity);

                        if (entity.hasLocalService()) {
                            _createServiceImpl(entity, _SESSION_TYPE_LOCAL);
                            _createServiceBaseImpl(entity, _SESSION_TYPE_LOCAL);
                            _createService(entity, _SESSION_TYPE_LOCAL);
                            _createServiceFactory(entity, _SESSION_TYPE_LOCAL);
                            _createServiceUtil(entity, _SESSION_TYPE_LOCAL);

                            _createServiceClp(entity, _SESSION_TYPE_LOCAL);
                            _createServiceClpInvoker(entity, _SESSION_TYPE_LOCAL);
                            _createServiceWrapper(entity, _SESSION_TYPE_LOCAL);
                        } else {
                            _removeServiceImpl(entity, _SESSION_TYPE_LOCAL);
                            _removeServiceBaseImpl(entity, _SESSION_TYPE_LOCAL);
                            _removeService(entity, _SESSION_TYPE_LOCAL);
                            _removeServiceUtil(entity, _SESSION_TYPE_LOCAL);

                            _removeServiceClp(entity, _SESSION_TYPE_LOCAL);
                            _removeServiceClpInvoker(entity, _SESSION_TYPE_LOCAL);
                            _removeServiceWrapper(entity, _SESSION_TYPE_LOCAL);
                        }

                        if (entity.hasRemoteService()) {
                            _createServiceImpl(entity, _SESSION_TYPE_REMOTE);
                            _createServiceBaseImpl(entity, _SESSION_TYPE_REMOTE);
                            _createService(entity, _SESSION_TYPE_REMOTE);
                            _createServiceFactory(entity, _SESSION_TYPE_REMOTE);
                            _createServiceUtil(entity, _SESSION_TYPE_REMOTE);

                            _createServiceClp(entity, _SESSION_TYPE_REMOTE);
                            _createServiceClpInvoker(entity, _SESSION_TYPE_REMOTE);
                            _createServiceWrapper(entity, _SESSION_TYPE_REMOTE);

                            if (Validator.isNotNull(_remotingFileName)) {
                                _createServiceHttp(entity);
                            }

                            _createServiceJson(entity);

                            if (entity.hasColumns()) {
                                _createServiceJsonSerializer(entity);
                            }

                            _createServiceSoap(entity);
                        } else {
                            _removeServiceImpl(entity, _SESSION_TYPE_REMOTE);
                            _removeServiceBaseImpl(entity, _SESSION_TYPE_REMOTE);
                            _removeService(entity, _SESSION_TYPE_REMOTE);
                            _removeServiceUtil(entity, _SESSION_TYPE_REMOTE);

                            _removeServiceClp(entity, _SESSION_TYPE_REMOTE);
                            _removeServiceClpInvoker(entity, _SESSION_TYPE_REMOTE);
                            _removeServiceWrapper(entity, _SESSION_TYPE_REMOTE);

                            if (Validator.isNotNull(_remotingFileName)) {
                                _removeServiceHttp(entity);
                            }

                            _removeServiceSoap(entity);
                        }
                    } else {
                        if (entity.hasColumns()) {
                            entity.setTransients(_getTransients(entity, false));
                            entity.setParentTransients(_getTransients(entity, true));
                        }
                    }
                }

                _createHbmXml();
                _createModelHintsXml();
                _createSpringXml();

                _createExceptions(exceptionList);

                _createServiceClpMessageListener();
                _createServiceClpSerializer(exceptionList);
                _createServicePropsUtil();

                if (Validator.isNotNull(_remotingFileName)) {
                    _createRemotingXml();
                }

                _createSQLIndexes();
                _createSQLTables();
                _createSQLSequences();

                _createProps();

                _deleteOrmXml();
                _deleteSpringLegacyXml();
            }
        } catch (FileNotFoundException fnfe) {
            System.out.println(fnfe.getMessage());
        }
    }

    public ServiceBuilder(String apiDir, boolean autoImportDefaultReferences, boolean autoNamespaceTables,
            String beanLocatorUtil, String hbmFileName, String implDir, String inputFileName,
            String modelHintsFileName, boolean osgiModule, String pluginName, String propsUtil,
            String[] readOnlyPrefixes, String remotingFileName, Set<String> resourceActionModels,
            String resourcesDir, String springFileName, String[] springNamespaces, String sqlDir,
            String sqlFileName, String sqlIndexesFileName, String sqlSequencesFileName, String targetEntityName,
            String testDir) throws Exception {

        this(apiDir, autoImportDefaultReferences, autoNamespaceTables, beanLocatorUtil, 1, true, hbmFileName,
                implDir, inputFileName, modelHintsFileName, osgiModule, pluginName, propsUtil, readOnlyPrefixes,
                remotingFileName, resourceActionModels, resourcesDir, springFileName, springNamespaces, sqlDir,
                sqlFileName, sqlIndexesFileName, sqlSequencesFileName, targetEntityName, testDir, true);
    }

    public String annotationToString(Annotation annotation) {
        StringBundler sb = new StringBundler();

        sb.append(StringPool.AT);

        Type type = annotation.getType();

        sb.append(type.getValue());

        Map<String, Object> namedParameters = annotation.getNamedParameterMap();

        if (namedParameters.isEmpty()) {
            return sb.toString();
        }

        sb.append(StringPool.OPEN_PARENTHESIS);

        for (Map.Entry<String, Object> entry : namedParameters.entrySet()) {
            sb.append(entry.getKey());

            sb.append(StringPool.EQUAL);

            Object value = entry.getValue();

            if (value instanceof List) {
                List<String> stringValues = (List<String>) entry.getValue();

                sb.append(StringPool.OPEN_CURLY_BRACE);

                for (String stringValue : stringValues) {
                    sb.append(stringValue);

                    sb.append(StringPool.COMMA_AND_SPACE);
                }

                if (!stringValues.isEmpty()) {
                    sb.setIndex(sb.index() - 1);
                }

                sb.append(StringPool.CLOSE_CURLY_BRACE);
            } else {
                sb.append(value);
            }

            sb.append(StringPool.COMMA_AND_SPACE);
        }

        sb.setIndex(sb.index() - 1);

        sb.append(StringPool.CLOSE_PARENTHESIS);

        return sb.toString();
    }

    public String getCacheFieldMethodName(JavaField javaField) {
        Annotation[] annotations = javaField.getAnnotations();

        for (Annotation annotation : annotations) {
            Type type = annotation.getType();

            String className = type.getFullyQualifiedName();

            if (className.equals(CacheField.class.getName())) {
                String methodName = null;

                Object namedParameter = annotation.getNamedParameter("methodName");

                if (namedParameter != null) {
                    methodName = StringUtil.unquote(StringUtil.trim(namedParameter.toString()));
                }

                if (Validator.isNull(methodName)) {
                    methodName = TextFormatter.format(getVariableName(javaField), TextFormatter.G);
                }

                return methodName;
            }
        }

        throw new IllegalArgumentException(javaField + " is not a cache field");
    }

    public String getClassName(Type type) {
        int dimensions = type.getDimensions();
        String name = type.getValue();

        if (dimensions == 0) {
            return name;
        }

        StringBundler sb = new StringBundler();

        for (int i = 0; i < dimensions; i++) {
            sb.append("[");
        }

        if (name.equals("boolean")) {
            return sb.append("Z").toString();
        } else if (name.equals("byte")) {
            return sb.append("B").toString();
        } else if (name.equals("char")) {
            return sb.append("C").toString();
        } else if (name.equals("double")) {
            return sb.append("D").toString();
        } else if (name.equals("float")) {
            return sb.append("F").toString();
        } else if (name.equals("int")) {
            return sb.append("I").toString();
        } else if (name.equals("long")) {
            return sb.append("J").toString();
        } else if (name.equals("short")) {
            return sb.append("S").toString();
        } else {
            return sb.append("L").append(name).append(";").toString();
        }
    }

    public String getCreateMappingTableSQL(EntityMapping entityMapping) throws Exception {

        String createMappingTableSQL = _getCreateMappingTableSQL(entityMapping);

        createMappingTableSQL = StringUtil.replace(createMappingTableSQL, "\n", "");
        createMappingTableSQL = StringUtil.replace(createMappingTableSQL, "\t", "");
        createMappingTableSQL = createMappingTableSQL.substring(0, createMappingTableSQL.length() - 1);

        return createMappingTableSQL;
    }

    public String getCreateTableSQL(Entity entity) {
        String createTableSQL = _getCreateTableSQL(entity);

        createTableSQL = StringUtil.replace(createTableSQL, "\n", "");
        createTableSQL = StringUtil.replace(createTableSQL, "\t", "");
        createTableSQL = createTableSQL.substring(0, createTableSQL.length() - 1);

        return createTableSQL;
    }

    public String getDimensions(int dims) {
        String dimensions = "";

        for (int i = 0; i < dims; i++) {
            dimensions += "[]";
        }

        return dimensions;
    }

    public String getDimensions(String dims) {
        return getDimensions(GetterUtil.getInteger(dims));
    }

    public Entity getEntity(String name) throws Exception {
        Entity entity = _entityPool.get(name);

        if (entity != null) {
            return entity;
        }

        int pos = name.lastIndexOf(".");

        if (pos == -1) {
            pos = _ejbList.indexOf(new Entity(name));

            if (pos == -1) {
                throw new ServiceBuilderException(
                        "Unable to to find " + name + " in " + ListUtil.toString(_ejbList, Entity.NAME_ACCESSOR));
            }

            entity = _ejbList.get(pos);

            _entityPool.put(name, entity);

            return entity;
        }

        String refPackage = name.substring(0, pos);
        String refEntity = name.substring(pos + 1);

        if (refPackage.equals(_packagePath)) {
            pos = _ejbList.indexOf(new Entity(refEntity));

            if (pos == -1) {
                throw new ServiceBuilderException(
                        "Unable to find " + refEntity + " in " + ListUtil.toString(_ejbList, Entity.NAME_ACCESSOR));
            }

            entity = _ejbList.get(pos);

            _entityPool.put(name, entity);

            return entity;
        }

        String refPackageDirName = StringUtil.replace(refPackage, ".", "/");

        String refFileName = _implDirName + "/" + refPackageDirName + "/service.xml";

        File refFile = new File(refFileName);

        boolean useTempFile = false;

        if (!refFile.exists()) {
            refFileName = String.valueOf(System.currentTimeMillis());
            refFile = new File(_TMP_DIR, refFileName);

            ClassLoader classLoader = getClass().getClassLoader();

            String refContent = null;

            try {
                refContent = StringUtil.read(classLoader, refPackageDirName + "/service.xml");
            } catch (IOException ioe) {
                throw new ServiceBuilderException(
                        "Unable to find " + refEntity + " in " + ListUtil.toString(_ejbList, Entity.NAME_ACCESSOR));
            }

            FileUtils.write(refFile, refContent);

            useTempFile = true;
        }

        ServiceBuilder serviceBuilder = new ServiceBuilder(_apiDirName, _autoImportDefaultReferences,
                _autoNamespaceTables, _beanLocatorUtil, _buildNumber, _buildNumberIncrement, _hbmFileName,
                _implDirName, refFile.getAbsolutePath(), _modelHintsFileName, _osgiModule, _pluginName, _propsUtil,
                _readOnlyPrefixes, _remotingFileName, _resourceActionModels, _resourcesDirName, _springFileName,
                _springNamespaces, _sqlDirName, _sqlFileName, _sqlIndexesFileName, _sqlSequencesFileName,
                _targetEntityName, _testDirName, false);

        entity = serviceBuilder.getEntity(refEntity);

        entity.setPortalReference(useTempFile);

        _entityPool.put(name, entity);

        _modifiedFileNames.addAll(serviceBuilder.getModifiedFileNames());

        if (useTempFile) {
            refFile.deleteOnExit();
        }

        return entity;
    }

    public Entity getEntityByGenericsName(String genericsName) {
        try {
            String name = genericsName;

            if (name.startsWith("<")) {
                name = name.substring(1, name.length() - 1);
            }

            name = StringUtil.replace(name, ".model.", ".");

            return getEntity(name);
        } catch (Exception e) {
            return null;
        }
    }

    public Entity getEntityByParameterTypeValue(String parameterTypeValue) {
        try {
            String name = parameterTypeValue;

            name = StringUtil.replace(name, ".model.", ".");

            return getEntity(name);
        } catch (Exception e) {
            return null;
        }
    }

    public EntityMapping getEntityMapping(String mappingTable) {
        return _entityMappings.get(mappingTable);
    }

    public String getGeneratorClass(String idType) {
        if (Validator.isNull(idType)) {
            idType = "assigned";
        }

        return idType;
    }

    public String getJavadocComment(JavaClass javaClass) {
        return _formatComment(javaClass.getComment(), javaClass.getTags(), StringPool.BLANK);
    }

    public String getJavadocComment(JavaMethod javaMethod) {
        return _formatComment(javaMethod.getComment(), javaMethod.getTags(), StringPool.TAB);
    }

    public String getListActualTypeArguments(Type type) {
        if (type.getValue().equals("java.util.List")) {
            Type[] types = type.getActualTypeArguments();

            if (types != null) {
                return getTypeGenericsName(types[0]);
            }
        }

        return getTypeGenericsName(type);
    }

    public String getLiteralClass(Type type) {
        StringBundler sb = new StringBundler(type.getDimensions() + 2);

        sb.append(type.getValue());

        for (int i = 0; i < type.getDimensions(); i++) {
            sb.append("[]");
        }

        sb.append(".class");

        return sb.toString();
    }

    public List<EntityColumn> getMappingEntities(String mappingTable) throws Exception {

        List<EntityColumn> mappingEntitiesPKList = new ArrayList<>();

        EntityMapping entityMapping = _entityMappings.get(mappingTable);

        for (int i = 0; i < 2; i++) {
            Entity entity = getEntity(entityMapping.getEntity(i));

            if (entity == null) {
                return null;
            }

            mappingEntitiesPKList.addAll(entity.getPKList());
        }

        return mappingEntitiesPKList;
    }

    public Set<String> getModifiedFileNames() {
        return _modifiedFileNames;
    }

    public String getNoSuchEntityException(Entity entity) {
        String noSuchEntityException = entity.getName();

        if (Validator.isNull(entity.getPortletShortName())
                || (noSuchEntityException.startsWith(entity.getPortletShortName())
                        && !noSuchEntityException.equals(entity.getPortletShortName()))) {

            noSuchEntityException = noSuchEntityException.substring(entity.getPortletShortName().length());
        }

        noSuchEntityException = "NoSuch" + noSuchEntityException;

        return noSuchEntityException;
    }

    public String getParameterType(JavaParameter parameter) {
        Type returnType = parameter.getType();

        return getTypeGenericsName(returnType);
    }

    public String getPrimitiveObj(String type) {
        if (type.equals("boolean")) {
            return "Boolean";
        } else if (type.equals("double")) {
            return "Double";
        } else if (type.equals("float")) {
            return "Float";
        } else if (type.equals("int")) {
            return "Integer";
        } else if (type.equals("long")) {
            return "Long";
        } else if (type.equals("short")) {
            return "Short";
        } else {
            return type;
        }
    }

    public String getPrimitiveObjValue(String colType) {
        if (colType.equals("Boolean")) {
            return ".booleanValue()";
        } else if (colType.equals("Double")) {
            return ".doubleValue()";
        } else if (colType.equals("Float")) {
            return ".floatValue()";
        } else if (colType.equals("Integer")) {
            return ".intValue()";
        } else if (colType.equals("Long")) {
            return ".longValue()";
        } else if (colType.equals("Short")) {
            return ".shortValue()";
        }

        return StringPool.BLANK;
    }

    public String getReturnType(JavaMethod method) {
        Type returnType = method.getReturnType();

        return getTypeGenericsName(returnType);
    }

    public List<String> getServiceBaseExceptions(List<JavaMethod> methods, String methodName, List<String> args,
            List<String> exceptions) {

        boolean foundMethod = false;

        for (JavaMethod method : methods) {
            JavaParameter[] parameters = method.getParameters();

            if (method.getName().equals(methodName) && (parameters.length == args.size())) {

                for (int i = 0; i < parameters.length; i++) {
                    JavaParameter parameter = parameters[i];

                    String arg = args.get(i);

                    if (getParameterType(parameter).equals(arg)) {
                        exceptions = ListUtil.copy(exceptions);

                        Type[] methodExceptions = method.getExceptions();

                        for (Type methodException : methodExceptions) {
                            String exception = methodException.getValue();

                            if (exception.equals(PortalException.class.getName())) {

                                exception = "PortalException";
                            }

                            if (exception.equals(SystemException.class.getName())) {

                                exception = "SystemException";
                            }

                            if (!exceptions.contains(exception)) {
                                exceptions.add(exception);
                            }
                        }

                        Collections.sort(exceptions);

                        foundMethod = true;

                        break;
                    }
                }
            }

            if (foundMethod) {
                break;
            }
        }

        if (!exceptions.isEmpty()) {
            return exceptions;
        } else {
            return Collections.emptyList();
        }
    }

    public String getSqlType(String type) {
        if (type.equals("boolean") || type.equals("Boolean")) {
            return "BOOLEAN";
        } else if (type.equals("double") || type.equals("Double")) {
            return "DOUBLE";
        } else if (type.equals("float") || type.equals("Float")) {
            return "FLOAT";
        } else if (type.equals("int") || type.equals("Integer")) {
            return "INTEGER";
        } else if (type.equals("long") || type.equals("Long")) {
            return "BIGINT";
        } else if (type.equals("short") || type.equals("Short")) {
            return "INTEGER";
        } else if (type.equals("Date")) {
            return "TIMESTAMP";
        } else {
            return null;
        }
    }

    public String getSqlType(String model, String field, String type) {
        if (type.equals("boolean") || type.equals("Boolean")) {
            return "BOOLEAN";
        } else if (type.equals("double") || type.equals("Double")) {
            return "DOUBLE";
        } else if (type.equals("float") || type.equals("Float")) {
            return "FLOAT";
        } else if (type.equals("int") || type.equals("Integer")) {
            return "INTEGER";
        } else if (type.equals("long") || type.equals("Long")) {
            return "BIGINT";
        } else if (type.equals("short") || type.equals("Short")) {
            return "INTEGER";
        } else if (type.equals("Blob")) {
            return "BLOB";
        } else if (type.equals("Date")) {
            return "TIMESTAMP";
        } else if (type.equals("Map") || type.equals("String")) {
            Map<String, String> hints = ModelHintsUtil.getHints(model, field);

            if (hints != null) {
                int maxLength = GetterUtil.getInteger(hints.get("max-length"));

                if (maxLength == 2000000) {
                    return "CLOB";
                }
            }

            return "VARCHAR";
        } else {
            return null;
        }
    }

    public String getTypeGenericsName(Type type) {
        StringBundler sb = new StringBundler();

        sb.append(type.getValue());

        Type[] actualTypeArguments = type.getActualTypeArguments();

        if (actualTypeArguments != null) {
            sb.append(StringPool.LESS_THAN);

            for (Type actualTypeArgument : actualTypeArguments) {
                sb.append(getTypeGenericsName(actualTypeArgument));

                sb.append(StringPool.COMMA_AND_SPACE);
            }

            sb.setIndex(sb.index() - 1);

            sb.append(StringPool.GREATER_THAN);
        }

        sb.append(getDimensions(type.getDimensions()));

        return sb.toString();
    }

    public String getVariableName(JavaField field) {
        String fieldName = field.getName();

        if ((fieldName.length() > 0) && (fieldName.charAt(0) == '_')) {
            fieldName = fieldName.substring(1);
        }

        return fieldName;
    }

    public boolean hasEntityByGenericsName(String genericsName) {
        if (Validator.isNull(genericsName)) {
            return false;
        }

        if (!genericsName.contains(".model.")) {
            return false;
        }

        if (getEntityByGenericsName(genericsName) == null) {
            return false;
        } else {
            return true;
        }
    }

    public boolean hasEntityByParameterTypeValue(String parameterTypeValue) {
        if (Validator.isNull(parameterTypeValue)) {
            return false;
        }

        if (!parameterTypeValue.contains(".model.")) {
            return false;
        }

        if (getEntityByParameterTypeValue(parameterTypeValue) == null) {
            return false;
        } else {
            return true;
        }
    }

    public boolean isBasePersistenceMethod(JavaMethod method) {
        String methodName = method.getName();

        if (methodName.equals("clearCache") || methodName.equals("findWithDynamicQuery")) {

            return true;
        } else if (methodName.equals("findByPrimaryKey") || methodName.equals("fetchByPrimaryKey")
                || methodName.equals("remove")) {

            JavaParameter[] parameters = method.getParameters();

            if ((parameters.length == 1) && parameters[0].getName().equals("primaryKey")) {

                return true;
            }

            if (methodName.equals("remove")) {
                Type[] methodExceptions = method.getExceptions();

                for (Type methodException : methodExceptions) {
                    String exception = methodException.getValue();

                    if (exception.contains("NoSuch")) {
                        return false;
                    }
                }

                return true;
            }
        }

        return false;
    }

    public boolean isCustomMethod(JavaMethod method) {
        String methodName = method.getName();

        if (methodName.equals("afterPropertiesSet") || methodName.equals("destroy") || methodName.equals("equals")
                || methodName.equals("getClass") || methodName.equals("hashCode") || methodName.equals("notify")
                || methodName.equals("notifyAll") || methodName.equals("toString") || methodName.equals("wait")) {

            return false;
        } else if (methodName.equals("getPermissionChecker")) {
            return false;
        } else if (methodName.equals("getUser") && (method.getParameters().length == 0)) {

            return false;
        } else if (methodName.equals("getUserId") && (method.getParameters().length == 0)) {

            return false;
        } else if (methodName.endsWith("Finder")
                && (methodName.startsWith("get") || methodName.startsWith("set"))) {

            return false;
        } else if (methodName.endsWith("Persistence")
                && (methodName.startsWith("get") || methodName.startsWith("set"))) {

            return false;
        } else if (methodName.endsWith("Service")
                && (methodName.startsWith("get") || methodName.startsWith("set"))) {

            return false;
        } else {
            return true;
        }
    }

    public boolean isHBMCamelCasePropertyAccessor(String propertyName) {
        if (propertyName.length() < 3) {
            return false;
        }

        char[] chars = propertyName.toCharArray();

        char c0 = chars[0];
        char c1 = chars[1];
        char c2 = chars[2];

        if (Character.isLowerCase(c0) && Character.isUpperCase(c1) && Character.isLowerCase(c2)) {

            return true;
        }

        return false;
    }

    public boolean isReadOnlyMethod(JavaMethod method, List<String> txRequiredList, String[] prefixes) {

        String methodName = method.getName();

        if (isTxRequiredMethod(method, txRequiredList)) {
            return false;
        }

        for (String prefix : prefixes) {
            if (methodName.startsWith(prefix)) {
                return true;
            }
        }

        return false;
    }

    public boolean isServiceReadOnlyMethod(JavaMethod method, List<String> txRequiredList) {

        return isReadOnlyMethod(method, txRequiredList, _readOnlyPrefixes);
    }

    public boolean isSoapMethod(JavaMethod method) {
        Type returnType = method.getReturnType();

        String returnTypeGenericsName = getTypeGenericsName(returnType);
        String returnValueName = returnType.getValue();

        if (returnTypeGenericsName.contains("com.liferay.portal.kernel.search.")
                || returnTypeGenericsName.contains("com.liferay.portal.model.Theme")
                || returnTypeGenericsName.contains("com.liferay.portlet.social.model.SocialActivityDefinition")
                || returnTypeGenericsName.equals("java.util.List<java.lang.Object>")
                || returnValueName.equals("com.liferay.portal.model.Lock")
                || returnValueName.equals("com.liferay.portlet.messageboards.model.MBMessageDisplay")
                || returnValueName.startsWith("java.io") || returnValueName.equals("java.util.Map")
                || returnValueName.equals("java.util.Properties") || returnValueName.startsWith("javax")) {

            return false;
        }

        if (returnTypeGenericsName.contains("com.liferay.portal.kernel.repository.model.FileEntry")
                || returnTypeGenericsName.contains("com.liferay.portal.kernel.repository.model.Folder")) {
        } else if (returnTypeGenericsName.contains("com.liferay.portal.kernel.repository.")) {

            return false;
        }

        JavaParameter[] parameters = method.getParameters();

        for (JavaParameter javaParameter : parameters) {
            Type type = javaParameter.getType();

            String parameterTypeName = type.getValue() + _getDimensions(type);

            if (parameterTypeName.equals("com.liferay.portal.kernel.util.UnicodeProperties")
                    || parameterTypeName.equals("com.liferay.portal.theme.ThemeDisplay")
                    || parameterTypeName.equals("com.liferay.portlet.PortletPreferencesImpl")
                    || parameterTypeName.equals("com.liferay.portlet.dynamicdatamapping.storage.Fields")
                    || parameterTypeName.startsWith("java.io")
                    || parameterTypeName.startsWith("java.util.LinkedHashMap") ||
                    //parameterTypeName.startsWith("java.util.List") ||
                    //parameterTypeName.startsWith("java.util.Locale") ||
                    (parameterTypeName.startsWith("java.util.Map") && !_isStringLocaleMap(javaParameter))
                    || parameterTypeName.startsWith("java.util.Properties")
                    || parameterTypeName.startsWith("javax")) {

                return false;
            }
        }

        return true;
    }

    public boolean isTxRequiredMethod(JavaMethod method, List<String> txRequiredList) {

        if (txRequiredList == null) {
            return false;
        }

        if (txRequiredList.contains(method.getName())) {
            return true;
        }

        return false;
    }

    private static void _addElements(Element element, Map<String, Element> elements) {

        for (Map.Entry<String, Element> entry : elements.entrySet()) {
            Element childElement = entry.getValue();

            element.add(childElement);
        }
    }

    private static Document _getContentDocument(String fileName) throws Exception {

        SAXReader saxReader = _getSAXReader();

        Document document = saxReader.read(new File(fileName));

        Element rootElement = document.getRootElement();

        List<Element> elements = rootElement.elements();

        for (Element element : elements) {
            String elementName = element.getName();

            if (!elementName.equals("service-builder-import")) {
                continue;
            }

            element.detach();

            String dirName = fileName.substring(0, fileName.lastIndexOf(StringPool.SLASH) + 1);
            String serviceBuilderImportFileName = element.attributeValue("file");

            Document serviceBuilderImportDocument = _getContentDocument(dirName + serviceBuilderImportFileName);

            Element serviceBuilderImportRootElement = serviceBuilderImportDocument.getRootElement();

            List<Element> serviceBuilderImportElements = serviceBuilderImportRootElement.elements();

            for (Element serviceBuilderImportElement : serviceBuilderImportElements) {

                serviceBuilderImportElement.detach();

                rootElement.add(serviceBuilderImportElement);
            }
        }

        return document;
    }

    private static String _getPackagePath(File file) {
        String fileName = StringUtil.replace(file.toString(), "\\", "/");

        int x = fileName.indexOf("src/");

        if (x == -1) {
            x = fileName.indexOf("test/");
        }

        int y = fileName.lastIndexOf("/");

        fileName = fileName.substring(x + 4, y);

        return StringUtil.replace(fileName, "/", ".");
    }

    private static SAXReader _getSAXReader() {
        return SAXReaderFactory.getSAXReader(null, false, false);
    }

    private static URL _readJalopyXmlFromClassLoader() {
        ClassLoader classLoader = ServiceBuilder.class.getClassLoader();

        URL url = classLoader.getResource("jalopy.xml");

        if (url == null) {
            throw new RuntimeException("Unable to load jalopy.xml from the class loader");
        }

        return url;
    }

    private static void _readResourceActionModels(String implDir, InputStream inputStream,
            Set<String> resourceActionModels) throws Exception {

        SAXReader saxReader = _getSAXReader();

        Document document = saxReader.read(inputStream);

        Element rootElement = document.getRootElement();

        List<Element> resourceElements = rootElement.elements("resource");

        for (Element resourceElement : resourceElements) {
            resourceActionModels.addAll(
                    readResourceActionModels(implDir, new String[] { resourceElement.attributeValue("file") }));
        }

        XPath xPath = document.createXPath("//model-resource/model-name");

        List<Element> elements = xPath.selectNodes(rootElement);

        for (Element element : elements) {
            resourceActionModels.add(element.getText().trim());
        }
    }

    private static String _stripFullyQualifiedClassNames(String content) throws IOException {

        String imports = JavaImportsFormatter.getImports(content);

        if (Validator.isNull(imports)) {
            return content;
        }

        UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(new UnsyncStringReader(imports));

        String line = null;

        while ((line = unsyncBufferedReader.readLine()) != null) {
            int x = line.indexOf("import ");

            if (x == -1) {
                continue;
            }

            String importPackageAndClassName = line.substring(x + 7, line.lastIndexOf(StringPool.SEMICOLON));

            for (x = -1;;) {
                x = content.indexOf(importPackageAndClassName, x + 1);

                if (x == -1) {
                    break;
                }

                char nextChar = content.charAt(x + importPackageAndClassName.length());
                char previousChar = content.charAt(x - 1);

                if (Character.isAlphabetic(nextChar) || (nextChar == CharPool.QUOTE)
                        || (nextChar == CharPool.SEMICOLON) || (previousChar == CharPool.QUOTE)) {

                    continue;
                }

                String importClassName = importPackageAndClassName
                        .substring(importPackageAndClassName.lastIndexOf(StringPool.PERIOD) + 1);

                content = StringUtil.replaceFirst(content, importPackageAndClassName, importClassName, x);
            }
        }

        return content;
    }

    private void _addIndexMetadata(Map<String, List<IndexMetadata>> indexMetadataMap, String tableName,
            IndexMetadata indexMetadata) {

        List<IndexMetadata> indexMetadataList = indexMetadataMap.get(tableName);

        if (indexMetadataList == null) {
            indexMetadataList = new ArrayList<>();

            indexMetadataMap.put(tableName, indexMetadataList);
        }

        Iterator<IndexMetadata> iterator = indexMetadataList.iterator();

        while (iterator.hasNext()) {
            IndexMetadata currentIndexMetadata = iterator.next();

            Boolean redundant = currentIndexMetadata.redundantTo(indexMetadata);

            if (redundant == null) {
                continue;
            }

            if (redundant) {
                iterator.remove();
            } else {
                indexMetadata = null;

                break;
            }
        }

        if (indexMetadata != null) {
            indexMetadataList.add(indexMetadata);
        }
    }

    private void _createActionableDynamicQuery(Entity entity) throws Exception {
        if (_osgiModule) {
            return;
        }

        Map<String, Object> context = _getContext();

        context.put("entity", entity);

        // Content

        String content = _processTemplate(_tplActionableDynamicQuery, context);

        // Write file

        File ejbFile = new File(
                _serviceOutputPath + "/service/persistence/" + entity.getName() + "ActionableDynamicQuery.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createBlobModels(Entity entity) throws Exception {
        List<EntityColumn> blobList = new ArrayList<>(entity.getBlobList());

        Iterator<EntityColumn> itr = blobList.iterator();

        while (itr.hasNext()) {
            EntityColumn col = itr.next();

            if (!col.isLazy()) {
                itr.remove();
            }
        }

        if (blobList.isEmpty()) {
            return;
        }

        Map<String, Object> context = _getContext();

        context.put("entity", entity);

        for (EntityColumn col : blobList) {
            context.put("column", col);

            // Content

            String content = _processTemplate(_tplBlobModel, context);

            // Write file

            File blobModelFile = new File(
                    _serviceOutputPath + "/model/" + entity.getName() + col.getMethodName() + "BlobModel.java");

            writeFile(blobModelFile, content, _author, _modifiedFileNames);
        }
    }

    private void _createEJBPK(Entity entity) throws Exception {
        Map<String, Object> context = _getContext();

        context.put("entity", entity);

        // Content

        String content = _processTemplate(_tplEjbPk, context);

        // Write file

        File ejbFile = new File(_serviceOutputPath + "/service/persistence/" + entity.getPKClassName() + ".java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createExceptions(List<String> exceptions) throws Exception {
        for (int i = 0; i < _ejbList.size(); i++) {
            Entity entity = _ejbList.get(i);

            if (!_isTargetEntity(entity)) {
                continue;
            }

            if (entity.hasColumns()) {
                exceptions.add(getNoSuchEntityException(entity));
            }
        }

        for (String exception : exceptions) {
            String dirName = StringPool.BLANK;

            if (_osgiModule) {
                dirName = "exception/";
            }

            File exceptionFile = new File(_serviceOutputPath + "/" + dirName + exception + "Exception.java");

            if (!exceptionFile.exists()) {
                Map<String, Object> context = _getContext();

                context.put("exception", exception);

                String content = _processTemplate(_tplException, context);

                if (exception.startsWith("NoSuch")) {
                    content = StringUtil.replace(content, "PortalException", "NoSuchModelException");
                    content = StringUtil.replace(content, "kernel.exception.NoSuchModelException",
                            "NoSuchModelException");
                }

                content = StringUtil.replace(content, "\r\n", "\n");

                writeFileRaw(exceptionFile, content, _modifiedFileNames);
            }

            if (exception.startsWith("NoSuch")) {
                String content = FileUtils.readFileToString(exceptionFile);

                if (!content.contains("NoSuchModelException")) {
                    content = StringUtil.replace(content, "PortalException", "NoSuchModelException");
                    content = StringUtil.replace(content, "kernel.exception.NoSuchModelException",
                            "NoSuchModelException");

                    writeFileRaw(exceptionFile, content, _modifiedFileNames);
                }
            }
        }
    }

    private void _createExportActionableDynamicQuery(Entity entity) throws Exception {

        if (_osgiModule) {
            return;
        }

        Map<String, Object> context = _getContext();

        context.put("entity", entity);

        // Content

        String content = _processTemplate(_tplExportActionableDynamicQuery, context);

        // Write file

        File ejbFile = new File(_serviceOutputPath + "/service/persistence/" + entity.getName()
                + "ExportActionableDynamicQuery.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createExtendedModel(Entity entity) throws Exception {
        JavaClass modelImplJavaClass = _getJavaClass(_outputPath + "/model/impl/" + entity.getName() + "Impl.java");

        List<JavaMethod> methods = ListUtil.fromArray(_getMethods(modelImplJavaClass));

        Iterator<JavaMethod> itr = methods.iterator();

        while (itr.hasNext()) {
            JavaMethod method = itr.next();

            String methodName = method.getName();

            if (methodName.equals("getStagedModelType")) {
                itr.remove();
            }
        }

        JavaClass modelJavaClass = _getJavaClass(_serviceOutputPath + "/model/" + entity.getName() + "Model.java");

        for (JavaMethod method : _getMethods(modelJavaClass)) {
            methods.remove(method);
        }

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", methods.toArray(new Object[methods.size()]));

        // Content

        String content = _processTemplate(_tplExtendedModel, context);

        // Write file

        File modelFile = new File(_serviceOutputPath + "/model/" + entity.getName() + ".java");

        writeFile(modelFile, content, _author, _modifiedFileNames);
    }

    private void _createExtendedModelBaseImpl(Entity entity) throws Exception {
        Map<String, Object> context = _getContext();

        context.put("entity", entity);

        // Content

        String content = _processTemplate(_tplExtendedModelBaseImpl, context);

        // Write file

        File modelFile = new File(_outputPath + "/model/impl/" + entity.getName() + "BaseImpl.java");

        writeFile(modelFile, content, _author, _modifiedFileNames);
    }

    private void _createExtendedModelImpl(Entity entity) throws Exception {
        Map<String, Object> context = _getContext();

        context.put("entity", entity);

        // Content

        String content = _processTemplate(_tplExtendedModelImpl, context);

        // Write file

        File modelFile = new File(_outputPath + "/model/impl/" + entity.getName() + "Impl.java");

        if (modelFile.exists()) {
            content = FileUtils.readFileToString(modelFile);

            content = content.replaceAll(
                    "extends\\s+" + entity.getName() + "ModelImpl\\s+implements\\s+" + entity.getName(),
                    "extends " + entity.getName() + "BaseImpl");

            writeFileRaw(modelFile, content, _modifiedFileNames);
        } else {
            writeFile(modelFile, content, _author, _modifiedFileNames);
        }
    }

    private void _createFinder(Entity entity) throws Exception {
        if (!entity.hasFinderClass()) {
            _removeFinder(entity);

            return;
        }

        JavaClass javaClass = _getJavaClass(
                _outputPath + "/service/persistence/impl/" + entity.getName() + "FinderImpl.java");

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", _getMethods(javaClass));

        // Content

        String content = _processTemplate(_tplFinder, context);

        // Write file

        File ejbFile = new File(_serviceOutputPath + "/service/persistence/" + entity.getName() + "Finder.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createFinderUtil(Entity entity) throws Exception {
        if (!entity.hasFinderClass() || _osgiModule) {
            _removeFinderUtil(entity);

            return;
        }

        JavaClass javaClass = _getJavaClass(
                _outputPath + "/service/persistence/impl/" + entity.getName() + "FinderImpl.java");

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", _getMethods(javaClass));

        // Content

        String content = _processTemplate(_tplFinderUtil, context);

        // Write file

        File ejbFile = new File(
                _serviceOutputPath + "/service/persistence/" + entity.getName() + "FinderUtil.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createHbm(Entity entity) {
        File ejbFile = new File(_outputPath + "/service/persistence/" + entity.getName() + "HBM.java");

        if (ejbFile.exists()) {
            System.out.println("Removing deprecated " + ejbFile);

            ejbFile.delete();
        }
    }

    private void _createHbmUtil(Entity entity) {
        File ejbFile = new File(_outputPath + "/service/persistence/" + entity.getName() + "HBMUtil.java");

        if (ejbFile.exists()) {
            System.out.println("Removing deprecated " + ejbFile);

            ejbFile.delete();
        }
    }

    private void _createHbmXml() throws Exception {
        Map<String, Object> context = _getContext();

        context.put("entities", _ejbList);

        // Content

        String content = _processTemplate(_tplHbmXml, context);

        int lastImportStart = content.lastIndexOf("<import class=");
        int lastImportEnd = content.indexOf("/>", lastImportStart) + 3;

        String imports = content.substring(0, lastImportEnd);

        content = content.substring(lastImportEnd + 1);

        File xmlFile = new File(_hbmFileName);

        if (!xmlFile.exists()) {
            String xml = "<?xml version=\"1.0\"?>\n"
                    + "<!DOCTYPE hibernate-mapping PUBLIC \"-//Hibernate/Hibernate Mapping DTD 3.0//EN\" \"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd\">\n"
                    + "\n" + "<hibernate-mapping default-lazy=\"false\" auto-import=\"false\">\n"
                    + "</hibernate-mapping>";

            FileUtils.write(xmlFile, xml);
        }

        String oldContent = FileUtils.readFileToString(xmlFile);
        String newContent = _fixHbmXml(oldContent);

        int firstImport = newContent.indexOf("<import class=\"" + _packagePath + ".model.");
        int lastImport = newContent.lastIndexOf("<import class=\"" + _packagePath + ".model.");

        if (firstImport == -1) {
            int x = newContent.indexOf("<class");

            if (x != -1) {
                newContent = newContent.substring(0, x) + imports + newContent.substring(x);
            } else {
                content = imports + content;
            }
        } else {
            firstImport = newContent.indexOf("<import", firstImport) - 1;
            lastImport = newContent.indexOf("/>", lastImport) + 3;

            newContent = newContent.substring(0, firstImport) + imports + newContent.substring(lastImport);
        }

        int firstClass = newContent.indexOf("<class name=\"" + _packagePath + ".model.");
        int lastClass = newContent.lastIndexOf("<class name=\"" + _packagePath + ".model.");

        if (firstClass == -1) {
            int x = newContent.indexOf("</hibernate-mapping>");

            if (x != -1) {
                newContent = newContent.substring(0, x) + content + newContent.substring(x);
            }
        } else {
            firstClass = newContent.lastIndexOf("<class", firstClass) - 1;
            lastClass = newContent.indexOf("</class>", lastClass) + 9;

            newContent = newContent.substring(0, firstClass) + content + newContent.substring(lastClass);
        }

        writeFileRaw(xmlFile, _formatXml(newContent), _modifiedFileNames);
    }

    private void _createModel(Entity entity) throws Exception {
        Map<String, Object> context = _getContext();

        context.put("entity", entity);

        // Content

        String content = _processTemplate(_tplModel, context);

        // Write file

        File modelFile = new File(_serviceOutputPath + "/model/" + entity.getName() + "Model.java");

        writeFile(modelFile, content, _author, _modifiedFileNames);
    }

    private void _createModelCache(Entity entity) throws Exception {
        JavaClass javaClass = _getJavaClass(_outputPath + "/model/impl/" + entity.getName() + "Impl.java");

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("cacheFields", _getCacheFields(javaClass));

        // Content

        String content = _processTemplate(_tplModelCache, context);

        // Write file

        File modelFile = new File(_outputPath + "/model/impl/" + entity.getName() + "CacheModel.java");

        writeFile(modelFile, content, _author, _modifiedFileNames);
    }

    private void _createModelClp(Entity entity) throws Exception {
        if (Validator.isNull(_pluginName)) {
            return;
        }

        JavaClass javaClass = _getJavaClass(_outputPath + "/model/impl/" + entity.getName() + "Impl.java");

        Map<String, JavaMethod> methods = new HashMap<>();

        for (JavaMethod method : javaClass.getMethods()) {
            methods.put(method.getDeclarationSignature(false), method);
        }

        Type superClass = javaClass.getSuperClass();

        String superClassValue = superClass.getValue();

        while (!superClassValue.endsWith("BaseModelImpl")) {
            int pos = superClassValue.lastIndexOf(StringPool.PERIOD);

            if (pos > 0) {
                superClassValue = superClassValue.substring(pos + 1);
            }

            javaClass = _getJavaClass(_outputPath + "/model/impl/" + superClassValue + ".java");

            for (JavaMethod method : _getMethods(javaClass)) {
                methods.remove(method.getDeclarationSignature(false));
            }

            superClass = javaClass.getSuperClass();
            superClassValue = superClass.getValue();
        }

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", methods.values());

        // Content

        String content = _processTemplate(_tplModelClp, context);

        // Write file

        File modelFile = new File(_serviceOutputPath + "/model/" + entity.getName() + "Clp.java");

        writeFile(modelFile, content, _author, _modifiedFileNames);
    }

    private void _createModelHintsXml() throws Exception {
        Map<String, Object> context = _getContext();

        context.put("entities", _ejbList);

        // Content

        String content = _processTemplate(_tplModelHintsXml, context);

        File xmlFile = new File(_modelHintsFileName);

        if (!xmlFile.exists()) {
            String xml = "<?xml version=\"1.0\"?>\n" + "\n" + "<model-hints>\n" + "</model-hints>";

            FileUtils.write(xmlFile, xml);
        }

        String oldContent = FileUtils.readFileToString(xmlFile);
        String newContent = oldContent;

        int firstModel = newContent.indexOf("<model name=\"" + _packagePath + ".model.");
        int lastModel = newContent.lastIndexOf("<model name=\"" + _packagePath + ".model.");

        if (firstModel == -1) {
            int x = newContent.indexOf("</model-hints>");

            newContent = newContent.substring(0, x) + content + newContent.substring(x);
        } else {
            firstModel = newContent.lastIndexOf("<model", firstModel) - 1;
            lastModel = newContent.indexOf("</model>", lastModel) + 9;

            newContent = newContent.substring(0, firstModel) + content + newContent.substring(lastModel);
        }

        writeFileRaw(xmlFile, _formatXml(newContent), _modifiedFileNames);
    }

    private void _createModelImpl(Entity entity) throws Exception {
        JavaClass javaClass = _getJavaClass(_outputPath + "/model/impl/" + entity.getName() + "Impl.java");

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("cacheFields", _getCacheFields(javaClass));

        // Content

        String content = _processTemplate(_tplModelImpl, context);

        // Write file

        File modelFile = new File(_outputPath + "/model/impl/" + entity.getName() + "ModelImpl.java");

        writeFile(modelFile, content, _author, _modifiedFileNames);
    }

    private void _createModelSoap(Entity entity) throws Exception {
        File modelFile = new File(_serviceOutputPath + "/model/" + entity.getName() + "Soap.java");

        Map<String, Object> context = _getContext();

        context.put("entity", entity);

        // Content

        String content = _processTemplate(_tplModelSoap, context);

        // Write file

        writeFile(modelFile, content, _author, _modifiedFileNames);
    }

    private void _createModelWrapper(Entity entity) throws Exception {
        JavaClass modelJavaClass = _getJavaClass(_serviceOutputPath + "/model/" + entity.getName() + "Model.java");

        JavaMethod[] methods = _getMethods(modelJavaClass);

        JavaClass extendedModelBaseImplJavaClass = _getJavaClass(
                _outputPath + "/model/impl/" + entity.getName() + "BaseImpl.java");

        methods = _mergeMethods(methods, _getMethods(extendedModelBaseImplJavaClass), false);

        JavaClass extendedModelJavaClass = _getJavaClass(
                _serviceOutputPath + "/model/" + entity.getName() + ".java");

        methods = _mergeMethods(methods, _getMethods(extendedModelJavaClass), false);

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", methods);

        // Content

        String content = _processTemplate(_tplModelWrapper, context);

        // Write file

        File modelFile = new File(_serviceOutputPath + "/model/" + entity.getName() + "Wrapper.java");

        writeFile(modelFile, content, _author, _modifiedFileNames);
    }

    private void _createPersistence(Entity entity) throws Exception {
        JavaClass javaClass = _getJavaClass(
                _outputPath + "/service/persistence/impl/" + entity.getName() + "PersistenceImpl.java");

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", _getMethods(javaClass));

        // Content

        String content = _processTemplate(_tplPersistence, context);

        // Write file

        File ejbFile = new File(
                _serviceOutputPath + "/service/persistence/" + entity.getName() + "Persistence.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createPersistenceImpl(Entity entity) throws Exception {
        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("referenceList", _mergeReferenceList(entity));

        // Content

        Logger.selectLoggerLibrary(Logger.LIBRARY_NONE);

        String content = _processTemplate(_tplPersistenceImpl, context);

        Logger.selectLoggerLibrary(Logger.LIBRARY_AUTO);

        // Write file

        File ejbFile = new File(
                _outputPath + "/service/persistence/impl/" + entity.getName() + "PersistenceImpl.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);

        ejbFile = new File(_outputPath + "/service/persistence/" + entity.getName() + "PersistenceImpl.java");

        if (ejbFile.exists()) {
            System.out.println("Relocating " + ejbFile);

            ejbFile.delete();
        }
    }

    private void _createPersistenceTest(Entity entity) throws Exception {
        Map<String, Object> context = _getContext();

        context.put("entity", entity);

        // Content

        String content = _processTemplate(_tplPersistenceTest, context);

        // Write file

        File ejbFile = new File(
                _testOutputPath + "/service/persistence/test/" + entity.getName() + "PersistenceTest.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);

        ejbFile = new File(_testOutputPath + "/service/persistence/" + entity.getName() + "PersistenceTest.java");

        if (ejbFile.exists()) {
            System.out.println("Relocating " + ejbFile);

            ejbFile.delete();
        }
    }

    private void _createPersistenceUtil(Entity entity) throws Exception {
        JavaClass javaClass = _getJavaClass(
                _outputPath + "/service/persistence/impl/" + entity.getName() + "PersistenceImpl.java");

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", _getMethods(javaClass));

        // Content

        String content = _processTemplate(_tplPersistenceUtil, context);

        // Write file

        File ejbFile = new File(_serviceOutputPath + "/service/persistence/" + entity.getName() + "Util.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createPool(Entity entity) {
        File ejbFile = new File(_outputPath + "/service/persistence/" + entity.getName() + "Pool.java");

        if (ejbFile.exists()) {
            System.out.println("Removing deprecated " + ejbFile);

            ejbFile.delete();
        }
    }

    private void _createProps() throws Exception {
        if (Validator.isNull(_pluginName) && !_osgiModule) {
            return;
        }

        // Content

        File propsFile = null;

        if (Validator.isNotNull(_resourcesDirName)) {
            propsFile = new File(_resourcesDirName + "/service.properties");
        } else {

            // Backwards compatibility

            propsFile = new File(_implDirName + "/service.properties");
        }

        long buildNumber = 1;
        long buildDate = System.currentTimeMillis();

        if (propsFile.exists()) {
            Properties properties = PropertiesUtil.load(FileUtils.readFileToString(propsFile));

            if (!_buildNumberIncrement) {
                buildDate = GetterUtil.getLong(properties.getProperty("build.date"));
                buildNumber = GetterUtil.getLong(properties.getProperty("build.number"));
            } else {
                buildNumber = GetterUtil.getLong(properties.getProperty("build.number")) + 1;
            }
        }

        if (!_buildNumberIncrement && (buildNumber < _buildNumber)) {
            buildNumber = _buildNumber;
            buildDate = System.currentTimeMillis();
        }

        Map<String, Object> context = _getContext();

        context.put("buildNumber", buildNumber);
        context.put("currentTimeMillis", buildDate);

        String content = _processTemplate(_tplProps, context);

        // Write file

        writeFileRaw(propsFile, content, _modifiedFileNames);
    }

    private void _createRemotingXml() throws Exception {
        StringBundler sb = new StringBundler();

        SAXReader saxReader = _getSAXReader();

        Document document = saxReader.read(new File(_springFileName));

        Element rootElement = document.getRootElement();

        List<Element> beanElements = rootElement.elements("bean");

        for (Element beanElement : beanElements) {
            String beanId = beanElement.attributeValue("id");

            if (beanId.endsWith("Service") && !beanId.endsWith("LocalService")) {

                String entityName = beanId;

                entityName = StringUtil.replaceLast(entityName, ".service.", ".");

                int pos = entityName.lastIndexOf("Service");

                entityName = entityName.substring(0, pos);

                Entity entity = getEntity(entityName);

                String serviceName = beanId;

                String serviceMapping = serviceName;

                serviceMapping = StringUtil.replaceLast(serviceMapping, ".service.", ".service.spring.");
                serviceMapping = StringUtil.replace(serviceMapping, StringPool.PERIOD, StringPool.UNDERLINE);

                Map<String, Object> context = _getContext();

                context.put("entity", entity);
                context.put("serviceName", serviceName);
                context.put("serviceMapping", serviceMapping);

                sb.append(_processTemplate(_tplRemotingXml, context));
            }
        }

        File outputFile = new File(_remotingFileName);

        if (!outputFile.exists()) {
            return;
        }

        String content = FileUtils.readFileToString(outputFile);
        String newContent = content;

        int x = content.indexOf("<bean ");
        int y = content.lastIndexOf("</bean>") + 8;

        if (x != -1) {
            newContent = content.substring(0, x - 1) + sb.toString() + content.substring(y);
        } else {
            x = content.indexOf("</beans>");

            if (x != -1) {
                newContent = content.substring(0, x) + sb.toString() + content.substring(x);
            } else {
                x = content.indexOf("<beans/>");
                y = x + 8;

                newContent = content.substring(0, x) + "<beans>" + sb.toString() + "</beans>"
                        + content.substring(y);
            }
        }

        writeFileRaw(outputFile, _formatXml(newContent), _modifiedFileNames);
    }

    private void _createService(Entity entity, int sessionType) throws Exception {

        Set<String> imports = new HashSet<>();

        JavaClass javaClass = _getJavaClass(_outputPath + "/service/impl/" + entity.getName()
                + _getSessionTypeName(sessionType) + "ServiceImpl.java");

        JavaSource javaSource = javaClass.getSource();

        imports.addAll(Arrays.asList(javaSource.getImports()));

        JavaMethod[] methods = _getMethods(javaClass);

        Type superClass = javaClass.getSuperClass();

        String superClassValue = superClass.getValue();

        if (superClassValue.endsWith(entity.getName() + _getSessionTypeName(sessionType) + "ServiceBaseImpl")) {

            JavaClass parentJavaClass = _getJavaClass(_outputPath + "/service/base/" + entity.getName()
                    + _getSessionTypeName(sessionType) + "ServiceBaseImpl.java");

            JavaSource parentJavaSource = parentJavaClass.getSource();

            imports.addAll(Arrays.asList(parentJavaSource.getImports()));

            methods = _mergeMethods(methods, parentJavaClass.getMethods(), true);
        }

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("imports", imports);
        context.put("methods", methods);
        context.put("sessionTypeName", _getSessionTypeName(sessionType));

        context = _putDeprecatedKeys(context, javaClass);

        // Content

        String content = _processTemplate(_tplService, context);

        // Write file

        File ejbFile = new File(_serviceOutputPath + "/service/" + entity.getName()
                + _getSessionTypeName(sessionType) + "Service.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createServiceBaseImpl(Entity entity, int sessionType) throws Exception {

        JavaClass javaClass = _getJavaClass(_outputPath + "/service/impl/" + entity.getName()
                + (sessionType != _SESSION_TYPE_REMOTE ? "Local" : "") + "ServiceImpl.java");

        JavaMethod[] methods = _getMethods(javaClass);

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", methods);
        context.put("sessionTypeName", _getSessionTypeName(sessionType));
        context.put("referenceList", _mergeReferenceList(entity));

        context = _putDeprecatedKeys(context, javaClass);

        // Content

        String content = _processTemplate(_tplServiceBaseImpl, context);

        // Write file

        File ejbFile = new File(_outputPath + "/service/base/" + entity.getName() + _getSessionTypeName(sessionType)
                + "ServiceBaseImpl.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createServiceClp(Entity entity, int sessionType) throws Exception {

        if (Validator.isNull(_pluginName)) {
            return;
        }

        JavaClass javaClass = _getJavaClass(_serviceOutputPath + "/service/" + entity.getName()
                + _getSessionTypeName(sessionType) + "Service.java");

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", _getMethods(javaClass));
        context.put("sessionTypeName", _getSessionTypeName(sessionType));

        context = _putDeprecatedKeys(context, javaClass);

        // Content

        String content = _processTemplate(_tplServiceClp, context);

        // Write file

        File ejbFile = new File(_serviceOutputPath + "/service/" + entity.getName()
                + _getSessionTypeName(sessionType) + "ServiceClp.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createServiceClpInvoker(Entity entity, int sessionType) throws Exception {

        if (Validator.isNull(_pluginName)) {
            return;
        }

        JavaClass javaClass = _getJavaClass(_outputPath + "/service/impl/" + entity.getName()
                + _getSessionTypeName(sessionType) + "ServiceImpl.java");

        JavaMethod[] methods = _getMethods(javaClass);

        Type superClass = javaClass.getSuperClass();

        String superClassValue = superClass.getValue();

        if (superClassValue.endsWith(entity.getName() + _getSessionTypeName(sessionType) + "ServiceBaseImpl")) {

            JavaClass parentJavaClass = _getJavaClass(_outputPath + "/service/base/" + entity.getName()
                    + _getSessionTypeName(sessionType) + "ServiceBaseImpl.java");

            methods = ArrayUtil.append(parentJavaClass.getMethods(), methods);
        }

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", methods);
        context.put("sessionTypeName", _getSessionTypeName(sessionType));

        context = _putDeprecatedKeys(context, javaClass);

        // Content

        String content = _processTemplate(_tplServiceClpInvoker, context);

        // Write file

        File ejbFile = new File(_outputPath + "/service/base/" + entity.getName() + _getSessionTypeName(sessionType)
                + "ServiceClpInvoker.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createServiceClpMessageListener() throws Exception {
        if (Validator.isNull(_pluginName)) {
            return;
        }

        Map<String, Object> context = _getContext();

        context.put("entities", _ejbList);

        // Content

        String content = _processTemplate(_tplServiceClpMessageListener, context);

        // Write file

        File ejbFile = new File(_serviceOutputPath + "/service/messaging/ClpMessageListener.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createServiceClpSerializer(List<String> exceptions) throws Exception {

        if (Validator.isNull(_pluginName)) {
            return;
        }

        Map<String, Object> context = _getContext();

        context.put("entities", _ejbList);
        context.put("exceptions", exceptions);

        // Content

        String content = _processTemplate(_tplServiceClpSerializer, context);

        // Write file

        File ejbFile = new File(_serviceOutputPath + "/service/ClpSerializer.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createServiceFactory(Entity entity, int sessionType) {
        File ejbFile = new File(_serviceOutputPath + "/service/" + entity.getName()
                + _getSessionTypeName(sessionType) + "ServiceFactory.java");

        if (ejbFile.exists()) {
            System.out.println("Removing deprecated " + ejbFile);

            ejbFile.delete();
        }

        ejbFile = new File(_outputPath + "/service/" + entity.getName() + _getSessionTypeName(sessionType)
                + "ServiceFactory.java");

        if (ejbFile.exists()) {
            System.out.println("Removing deprecated " + ejbFile);

            ejbFile.delete();
        }
    }

    private void _createServiceHttp(Entity entity) throws Exception {
        JavaClass javaClass = _getJavaClass(_outputPath + "/service/impl/" + entity.getName() + "ServiceImpl.java");

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", _getMethods(javaClass));
        context.put("hasHttpMethods", _hasHttpMethods(javaClass));

        context = _putDeprecatedKeys(context, javaClass);

        // Content

        String content = _processTemplate(_tplServiceHttp, context);

        // Write file

        File ejbFile = new File(_outputPath + "/service/http/" + entity.getName() + "ServiceHttp.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createServiceImpl(Entity entity, int sessionType) throws Exception {

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("sessionTypeName", _getSessionTypeName(sessionType));

        // Content

        String content = _processTemplate(_tplServiceImpl, context);

        // Write file

        File ejbFile = new File(_outputPath + "/service/impl/" + entity.getName() + _getSessionTypeName(sessionType)
                + "ServiceImpl.java");

        if (!ejbFile.exists()) {
            writeFile(ejbFile, content, _author, _modifiedFileNames);
        }
    }

    private void _createServiceJson(Entity entity) {
        File ejbFile = new File(_outputPath + "/service/http/" + entity.getName() + "ServiceJSON.java");

        if (ejbFile.exists()) {
            System.out.println("Removing deprecated " + ejbFile);

            ejbFile.delete();
        }
    }

    private void _createServiceJsonSerializer(Entity entity) {
        File ejbFile = new File(_serviceOutputPath + "/service/http/" + entity.getName() + "JSONSerializer.java");

        if (ejbFile.exists()) {
            System.out.println("Removing deprecated " + ejbFile);

            ejbFile.delete();
        }
    }

    private void _createServicePropsUtil() throws Exception {
        if (!_osgiModule) {
            return;
        }

        File file = new File(_implDirName + "/" + StringUtil.replace(_propsUtil, ".", "/") + ".java");

        if (file.exists()) {
            return;
        }

        Map<String, Object> context = _getContext();

        int index = _propsUtil.lastIndexOf(".");

        context.put("servicePropsUtilClassName", _propsUtil.substring(index + 1));
        context.put("servicePropsUtilPackagePath", _propsUtil.substring(0, index));

        String content = _processTemplate(_tplServicePropsUtil, context);

        writeFile(file, content, _modifiedFileNames);
    }

    private void _createServiceSoap(Entity entity) throws Exception {
        JavaClass javaClass = _getJavaClass(_outputPath + "/service/impl/" + entity.getName() + "ServiceImpl.java");

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", _getMethods(javaClass));

        context = _putDeprecatedKeys(context, javaClass);

        // Content

        String content = _processTemplate(_tplServiceSoap, context);

        // Write file

        File ejbFile = new File(_outputPath + "/service/http/" + entity.getName() + "ServiceSoap.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createServiceUtil(Entity entity, int sessionType) throws Exception {

        JavaClass javaClass = _getJavaClass(_serviceOutputPath + "/service/" + entity.getName()
                + _getSessionTypeName(sessionType) + "Service.java");

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", _getMethods(javaClass));
        context.put("sessionTypeName", _getSessionTypeName(sessionType));

        context = _putDeprecatedKeys(context, javaClass);

        // Content

        String content = _processTemplate(_tplServiceUtil, context);

        // Write file

        File ejbFile = new File(_serviceOutputPath + "/service/" + entity.getName()
                + _getSessionTypeName(sessionType) + "ServiceUtil.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createServiceWrapper(Entity entity, int sessionType) throws Exception {

        JavaClass javaClass = _getJavaClass(_serviceOutputPath + "/service/" + entity.getName()
                + _getSessionTypeName(sessionType) + "Service.java");

        Map<String, Object> context = _getContext();

        context.put("entity", entity);
        context.put("methods", _getMethods(javaClass));
        context.put("sessionTypeName", _getSessionTypeName(sessionType));

        context = _putDeprecatedKeys(context, javaClass);

        // Content

        String content = _processTemplate(_tplServiceWrapper, context);

        // Write file

        File ejbFile = new File(_serviceOutputPath + "/service/" + entity.getName()
                + _getSessionTypeName(sessionType) + "ServiceWrapper.java");

        writeFile(ejbFile, content, _author, _modifiedFileNames);
    }

    private void _createSpringXml() throws Exception {
        if (_packagePath.equals("com.liferay.counter")) {
            return;
        }

        Map<String, Object> context = _getContext();

        context.put("entities", _ejbList);

        // Content

        String content = _processTemplate(_tplSpringXml, context);

        File xmlFile = new File(_springFileName);

        String xml = "<?xml version=\"1.0\"?>\n" + "\n" + "<beans\n" + "\tdefault-destroy-method=\"destroy\"\n"
                + "\tdefault-init-method=\"afterPropertiesSet\"\n" + _getSpringNamespacesDeclarations()
                + "\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + "\txsi:schemaLocation=\""
                + _getSpringSchemaLocations() + "\">\n" + "</beans>";

        if (!xmlFile.exists()) {
            FileUtils.write(xmlFile, xml);
        }

        String oldContent = FileUtils.readFileToString(xmlFile);

        if (Validator.isNotNull(_pluginName) && oldContent.contains("DOCTYPE beans PUBLIC")) {

            oldContent = xml;
        }

        String newContent = _fixSpringXml(oldContent);

        int x = oldContent.indexOf("<beans");
        int y = oldContent.lastIndexOf("</beans>");

        int firstSession = newContent.indexOf("<bean id=\"" + _packagePath + ".service.", x);

        int lastSession = newContent.lastIndexOf("<bean id=\"" + _packagePath + ".service.", y);

        if ((firstSession == -1) || (firstSession > y)) {
            x = newContent.indexOf("</beans>");

            newContent = newContent.substring(0, x) + content + newContent.substring(x);
        } else {
            firstSession = newContent.lastIndexOf("<bean", firstSession) - 1;

            int tempLastSession = newContent.indexOf("<bean id=\"", lastSession + 1);

            if (tempLastSession == -1) {
                tempLastSession = newContent.indexOf("</beans>", lastSession);
            }

            lastSession = tempLastSession;

            newContent = newContent.substring(0, firstSession) + content + newContent.substring(lastSession);
        }

        writeFileRaw(xmlFile, _formatXml(newContent), _modifiedFileNames);
    }

    private void _createSQLIndexes() throws Exception {
        File sqlDir = new File(_sqlDirName);

        if (!sqlDir.exists()) {
            return;
        }

        // indexes.sql loading

        File sqlFile = new File(_sqlDirName + "/" + _sqlIndexesFileName);

        if (!sqlFile.exists()) {
            FileUtils.touch(sqlFile);
        }

        Map<String, List<IndexMetadata>> indexMetadataMap = new TreeMap<>();

        try (UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(new FileReader(sqlFile))) {

            while (true) {
                String indexSQL = unsyncBufferedReader.readLine();

                if (indexSQL == null) {
                    break;
                }

                indexSQL = indexSQL.trim();

                if (Validator.isNull(indexSQL)) {
                    continue;
                }

                IndexMetadata indexMetadata = IndexMetadataFactoryUtil.createIndexMetadata(indexSQL);

                _addIndexMetadata(indexMetadataMap, indexMetadata.getTableName(), indexMetadata);
            }
        }

        // indexes.sql appending

        for (int i = 0; i < _ejbList.size(); i++) {
            Entity entity = _ejbList.get(i);

            if (!_isTargetEntity(entity)) {
                continue;
            }

            if (!entity.isDefaultDataSource()) {
                continue;
            }

            List<EntityFinder> finderList = entity.getFinderList();

            for (int j = 0; j < finderList.size(); j++) {
                EntityFinder finder = finderList.get(j);

                if (finder.isDBIndex()) {
                    List<String> finderColsNames = new ArrayList<>();

                    List<EntityColumn> finderColsList = finder.getColumns();

                    for (int k = 0; k < finderColsList.size(); k++) {
                        EntityColumn col = finderColsList.get(k);

                        finderColsNames.add(col.getDBName());
                    }

                    if (finderColsNames.isEmpty()) {
                        continue;
                    }

                    IndexMetadata indexMetadata = IndexMetadataFactoryUtil.createIndexMetadata(finder.isUnique(),
                            entity.getTable(), finderColsNames.toArray(new String[finderColsNames.size()]));

                    _addIndexMetadata(indexMetadataMap, indexMetadata.getTableName(), indexMetadata);
                }
            }
        }

        for (Map.Entry<String, EntityMapping> entry : _entityMappings.entrySet()) {

            EntityMapping entityMapping = entry.getValue();

            _getCreateMappingTableIndex(entityMapping, indexMetadataMap);
        }

        StringBundler sb = new StringBundler();

        for (List<IndexMetadata> indexMetadataList : indexMetadataMap.values()) {

            Collections.sort(indexMetadataList);

            for (IndexMetadata indexMetadata : indexMetadataList) {
                sb.append(indexMetadata.getCreateSQL());

                sb.append(StringPool.NEW_LINE);
            }

            sb.append(StringPool.NEW_LINE);
        }

        if (!indexMetadataMap.isEmpty()) {
            sb.setIndex(sb.index() - 2);
        }

        writeFileRaw(sqlFile, sb.toString(), _modifiedFileNames);

        // indexes.properties

        File file = new File(_sqlDirName, "indexes.properties");

        file.delete();
    }

    private void _createSQLMappingTables(File sqlFile, String newCreateTableString, EntityMapping entityMapping,
            boolean addMissingTables) throws IOException {

        if (!sqlFile.exists()) {
            FileUtils.touch(sqlFile);
        }

        String content = FileUtils.readFileToString(sqlFile);

        int x = content.indexOf(_SQL_CREATE_TABLE + entityMapping.getTable() + " (");
        int y = content.indexOf(");", x);

        if (x != -1) {
            String oldCreateTableString = content.substring(x + 1, y);

            if (!oldCreateTableString.equals(newCreateTableString)) {
                content = content.substring(0, x) + newCreateTableString + content.substring(y + 2);

                writeFileRaw(sqlFile, content, _modifiedFileNames);
            }
        } else if (addMissingTables) {
            try (UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
                    new UnsyncStringReader(content))) {

                StringBundler sb = new StringBundler();

                String line = null;
                boolean appendNewTable = true;

                while ((line = unsyncBufferedReader.readLine()) != null) {
                    if (appendNewTable && line.startsWith(_SQL_CREATE_TABLE)) {
                        x = _SQL_CREATE_TABLE.length();
                        y = line.indexOf(" ", x);

                        String tableName = line.substring(x, y);

                        if (tableName.compareTo(entityMapping.getTable()) > 0) {
                            sb.append(newCreateTableString);
                            sb.append("\n\n");

                            appendNewTable = false;
                        }
                    }

                    sb.append(line);
                    sb.append("\n");
                }

                if (appendNewTable) {
                    sb.append("\n");
                    sb.append(newCreateTableString);
                }

                writeFileRaw(sqlFile, sb.toString(), _modifiedFileNames);
            }
        }
    }

    private void _createSQLSequences() throws IOException {
        File sqlDir = new File(_sqlDirName);

        if (!sqlDir.exists()) {
            return;
        }

        File sqlFile = new File(_sqlDirName + "/" + _sqlSequencesFileName);

        if (!sqlFile.exists()) {
            FileUtils.touch(sqlFile);
        }

        Set<String> sequenceSQLs = new TreeSet<>();

        try (UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(new FileReader(sqlFile))) {

            while (true) {
                String sequenceSQL = unsyncBufferedReader.readLine();

                if (sequenceSQL == null) {
                    break;
                }

                if (Validator.isNotNull(sequenceSQL)) {
                    sequenceSQLs.add(sequenceSQL);
                }
            }
        }

        for (int i = 0; i < _ejbList.size(); i++) {
            Entity entity = _ejbList.get(i);

            if (!_isTargetEntity(entity)) {
                continue;
            }

            if (!entity.isDefaultDataSource()) {
                continue;
            }

            List<EntityColumn> columnList = entity.getColumnList();

            for (int j = 0; j < columnList.size(); j++) {
                EntityColumn column = columnList.get(j);

                if ("sequence".equals(column.getIdType())) {
                    StringBundler sb = new StringBundler();

                    String sequenceName = column.getIdParam();

                    if (sequenceName.length() > 30) {
                        sequenceName = sequenceName.substring(0, 30);
                    }

                    sb.append("create sequence ");
                    sb.append(sequenceName);
                    sb.append(";");

                    String sequenceSQL = sb.toString();

                    if (!sequenceSQLs.contains(sequenceSQL)) {
                        sequenceSQLs.add(sequenceSQL);
                    }
                }
            }
        }

        StringBundler sb = new StringBundler(sequenceSQLs.size() * 2);

        for (String sequenceSQL : sequenceSQLs) {
            sb.append(sequenceSQL);
            sb.append("\n");
        }

        if (!sequenceSQLs.isEmpty()) {
            sb.setIndex(sb.index() - 1);
        }

        writeFileRaw(sqlFile, sb.toString(), _modifiedFileNames);
    }

    private void _createSQLTables() throws Exception {
        File sqlDir = new File(_sqlDirName);

        if (!sqlDir.exists()) {
            return;
        }

        File sqlFile = new File(_sqlDirName + "/" + _sqlFileName);

        if (!sqlFile.exists()) {
            FileUtils.touch(sqlFile);
        }

        for (int i = 0; i < _ejbList.size(); i++) {
            Entity entity = _ejbList.get(i);

            if (!_isTargetEntity(entity)) {
                continue;
            }

            if (!entity.isDefaultDataSource()) {
                continue;
            }

            String createTableSQL = _getCreateTableSQL(entity);

            if (Validator.isNotNull(createTableSQL)) {
                _createSQLTables(sqlFile, createTableSQL, entity, true);

                _updateSQLFile("update-6.2.0-7.0.0.sql", createTableSQL, entity);
            }
        }

        for (Map.Entry<String, EntityMapping> entry : _entityMappings.entrySet()) {

            EntityMapping entityMapping = entry.getValue();

            String createMappingTableSQL = _getCreateMappingTableSQL(entityMapping);

            if (Validator.isNotNull(createMappingTableSQL)) {
                _createSQLMappingTables(sqlFile, createMappingTableSQL, entityMapping, true);
            }
        }

        String content = FileUtils.readFileToString(sqlFile);

        writeFileRaw(sqlFile, content.trim(), _modifiedFileNames);
    }

    private void _createSQLTables(File sqlFile, String newCreateTableString, Entity entity,
            boolean addMissingTables) throws IOException {

        if (!sqlFile.exists()) {
            FileUtils.touch(sqlFile);
        }

        String content = FileUtils.readFileToString(sqlFile);

        int x = content.indexOf(_SQL_CREATE_TABLE + entity.getTable() + " (");
        int y = content.indexOf(");", x);

        if (x != -1) {
            String oldCreateTableString = content.substring(x, y + 2);

            if (!oldCreateTableString.equals(newCreateTableString)) {
                content = content.substring(0, x) + newCreateTableString + content.substring(y + 2);

                FileUtils.write(sqlFile, content);
            }
        } else if (addMissingTables) {
            try (UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
                    new UnsyncStringReader(content))) {

                StringBundler sb = new StringBundler();

                String line = null;
                boolean appendNewTable = true;

                while ((line = unsyncBufferedReader.readLine()) != null) {
                    if (appendNewTable && line.startsWith(_SQL_CREATE_TABLE)) {
                        x = _SQL_CREATE_TABLE.length();
                        y = line.indexOf(" ", x);

                        String tableName = line.substring(x, y);

                        if (tableName.compareTo(entity.getTable()) > 0) {
                            sb.append(newCreateTableString);
                            sb.append("\n\n");

                            appendNewTable = false;
                        }
                    }

                    sb.append(line);
                    sb.append("\n");
                }

                if (appendNewTable) {
                    sb.append("\n");
                    sb.append(newCreateTableString);
                }

                writeFileRaw(sqlFile, sb.toString(), _modifiedFileNames);
            }
        }
    }

    private void _deleteFile(String fileName) {
        File file = new File(fileName);

        file.delete();
    }

    private void _deleteOrmXml() throws Exception {
        if (Validator.isNull(_pluginName)) {
            return;
        }

        _deleteFile("docroot/WEB-INF/src/META-INF/portlet-orm.xml");
    }

    private void _deleteSpringLegacyXml() throws Exception {
        if (Validator.isNull(_pluginName)) {
            return;
        }

        _deleteFile("docroot/WEB-INF/src/META-INF/base-spring.xml");
        _deleteFile("docroot/WEB-INF/src/META-INF/cluster-spring.xml");
        _deleteFile("docroot/WEB-INF/src/META-INF/data-source-spring.xml");
        _deleteFile("docroot/WEB-INF/src/META-INF/dynamic-data-source-spring.xml");
        _deleteFile("docroot/WEB-INF/src/META-INF/hibernate-spring.xml");
        _deleteFile("docroot/WEB-INF/src/META-INF/infrastructure-spring.xml");
        _deleteFile("docroot/WEB-INF/src/META-INF/misc-spring.xml");
        _deleteFile("docroot/WEB-INF/src/META-INF/shard-data-source-spring.xml");
    }

    private String _fixHbmXml(String content) throws IOException {
        try (UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
                new UnsyncStringReader(content))) {

            StringBundler sb = new StringBundler();

            String line = null;

            while ((line = unsyncBufferedReader.readLine()) != null) {
                if (line.startsWith("\t<class name=\"")) {
                    line = StringUtil.replace(line, new String[] { ".service.persistence.", "HBM\" table=\"" },
                            new String[] { ".model.", "\" table=\"" });

                    if (!line.contains(".model.impl.") && !line.contains("BlobModel")) {

                        line = StringUtil.replace(line, new String[] { ".model.", "\" table=\"" },
                                new String[] { ".model.impl.", "Impl\" table=\"" });
                    }
                }

                sb.append(line);
                sb.append('\n');
            }

            return sb.toString().trim();
        }
    }

    private String _fixSpringXml(String content) {
        return StringUtil.replace(content, ".service.spring.", ".service.");
    }

    private String _formatComment(String comment, DocletTag[] tags, String indentation) {

        StringBundler sb = new StringBundler();

        if (Validator.isNull(comment) && (tags.length <= 0)) {
            return sb.toString();
        }

        sb.append(indentation);
        sb.append("/**\n");

        if (Validator.isNotNull(comment)) {
            comment = comment.replaceAll("(?m)^", indentation + " * ");

            sb.append(comment);
            sb.append("\n");

            if (tags.length > 0) {
                sb.append(indentation);
                sb.append(" *\n");
            }
        }

        for (DocletTag tag : tags) {
            String tagValue = tag.getValue();

            sb.append(indentation);
            sb.append(" * @");
            sb.append(tag.getName());
            sb.append(" ");

            if (_currentTplName.equals(_tplServiceSoap)) {
                if (tagValue.startsWith(PortalException.class.getName())) {
                    tagValue = tagValue.replaceFirst(PortalException.class.getName(), "RemoteException");
                } else if (tagValue.startsWith(PrincipalException.class.getName())) {

                    tagValue = tagValue.replaceFirst(PrincipalException.class.getName(), "RemoteException");
                }
            }

            sb.append(tagValue);

            sb.append("\n");
        }

        sb.append(indentation);
        sb.append(" */\n");

        return sb.toString();
    }

    private String _formatXml(String xml) throws DocumentException, IOException {

        String doctype = null;

        int x = xml.indexOf("<!DOCTYPE");

        if (x != -1) {
            int y = xml.indexOf(">", x) + 1;

            doctype = xml.substring(x, y);

            xml = xml.substring(0, x) + "\n" + xml.substring(y);
        }

        xml = StringUtil.replace(xml, '\r', "");
        xml = XMLFormatter.toString(xml);
        xml = StringUtil.replace(xml, "\"/>", "\" />");

        if (Validator.isNotNull(doctype)) {
            x = xml.indexOf("?>") + 2;

            xml = xml.substring(0, x) + "\n" + doctype + xml.substring(x);
        }

        return xml;
    }

    private JavaField[] _getCacheFields(JavaClass javaClass) {
        if (javaClass == null) {
            return new JavaField[0];
        }

        List<JavaField> javaFields = new ArrayList<>();

        for (JavaField javaField : javaClass.getFields()) {
            Annotation[] annotations = javaField.getAnnotations();

            for (Annotation annotation : annotations) {
                Type type = annotation.getType();

                String className = type.getFullyQualifiedName();

                if (className.equals(CacheField.class.getName())) {
                    javaFields.add(javaField);

                    break;
                }
            }
        }

        return javaFields.toArray(new JavaField[javaFields.size()]);
    }

    private Map<String, Object> _getContext() throws TemplateModelException {
        BeansWrapper wrapper = BeansWrapper.getDefaultInstance();

        TemplateHashModel staticModels = wrapper.getStaticModels();

        Map<String, Object> context = new HashMap<>();

        context.put("apiDir", _apiDirName);
        context.put("arrayUtil", ArrayUtil_IW.getInstance());
        context.put("author", _author);
        context.put("beanLocatorUtil", _beanLocatorUtil);
        context.put("beanLocatorUtilShortName", _beanLocatorUtilShortName);
        context.put("hbmFileName", _hbmFileName);
        context.put("implDir", _implDirName);
        context.put("modelHintsFileName", _modelHintsFileName);
        context.put("modelHintsUtil", ModelHintsUtil.getModelHints());
        context.put("osgiModule", _osgiModule);
        context.put("outputPath", _outputPath);
        context.put("packagePath", _packagePath);
        context.put("pluginName", _pluginName);
        context.put("portletName", _portletName);
        context.put("portletPackageName", _portletPackageName);
        context.put("portletShortName", _portletShortName);
        context.put("propsUtil", _propsUtil);
        context.put("serviceBuilder", this);
        context.put("serviceOutputPath", _serviceOutputPath);
        context.put("springFileName", _springFileName);
        context.put("sqlDir", _sqlDirName);
        context.put("sqlFileName", _sqlFileName);
        context.put("stringUtil", StringUtil_IW.getInstance());
        context.put("system", staticModels.get("java.lang.System"));
        context.put("tempMap", wrapper.wrap(new HashMap<String, Object>()));
        context.put("textFormatter", staticModels.get(TextFormatter.class.getName()));
        context.put("validator", Validator_IW.getInstance());

        return context;
    }

    private void _getCreateMappingTableIndex(EntityMapping entityMapping,
            Map<String, List<IndexMetadata>> indexMetadataMap) throws Exception {

        Entity[] entities = new Entity[2];

        for (int i = 0; i < entities.length; i++) {
            entities[i] = getEntity(entityMapping.getEntity(i));

            if (entities[i] == null) {
                return;
            }
        }

        String tableName = entityMapping.getTable();

        for (Entity entity : entities) {
            List<EntityColumn> pkList = entity.getPKList();

            for (int j = 0; j < pkList.size(); j++) {
                EntityColumn col = pkList.get(j);

                String colDBName = col.getDBName();

                IndexMetadata indexMetadata = IndexMetadataFactoryUtil.createIndexMetadata(false, tableName,
                        colDBName);

                _addIndexMetadata(indexMetadataMap, tableName, indexMetadata);
            }
        }
    }

    private String _getCreateMappingTableSQL(EntityMapping entityMapping) throws Exception {

        Entity[] entities = new Entity[2];

        for (int i = 0; i < entities.length; i++) {
            entities[i] = getEntity(entityMapping.getEntity(i));

            if (entities[i] == null) {
                return null;
            }
        }

        Arrays.sort(entities, new Comparator<Entity>() {

            @Override
            public int compare(Entity entity1, Entity entity2) {
                String name1 = entity1.getName();
                String name2 = entity2.getName();

                return name1.compareTo(name2);
            }

        });

        StringBundler sb = new StringBundler();

        sb.append(_SQL_CREATE_TABLE);
        sb.append(entityMapping.getTable());
        sb.append(" (\n");

        for (Entity entity : entities) {
            List<EntityColumn> pkList = entity.getPKList();

            for (int i = 0; i < pkList.size(); i++) {
                EntityColumn col = pkList.get(i);

                String colName = col.getName();
                String colType = col.getType();

                sb.append("\t");
                sb.append(col.getDBName());
                sb.append(" ");

                if (StringUtil.equalsIgnoreCase(colType, "boolean")) {
                    sb.append("BOOLEAN");
                } else if (StringUtil.equalsIgnoreCase(colType, "double")
                        || StringUtil.equalsIgnoreCase(colType, "float")) {

                    sb.append("DOUBLE");
                } else if (colType.equals("int") || colType.equals("Integer")
                        || StringUtil.equalsIgnoreCase(colType, "short")) {

                    sb.append("INTEGER");
                } else if (StringUtil.equalsIgnoreCase(colType, "long")) {
                    sb.append("LONG");
                } else if (colType.equals("Map")) {
                    sb.append("TEXT");
                } else if (colType.equals("String")) {
                    Map<String, String> hints = ModelHintsUtil.getHints(_packagePath + ".model." + entity.getName(),
                            colName);

                    int maxLength = 75;

                    if (hints != null) {
                        maxLength = GetterUtil.getInteger(hints.get("max-length"), maxLength);
                    }

                    if (col.isLocalized()) {
                        maxLength = 4000;
                    }

                    if (maxLength < 4000) {
                        sb.append("VARCHAR(");
                        sb.append(maxLength);
                        sb.append(")");
                    } else if (maxLength == 4000) {
                        sb.append("STRING");
                    } else if (maxLength > 4000) {
                        sb.append("TEXT");
                    }
                } else if (colType.equals("Date")) {
                    sb.append("DATE");
                } else {
                    sb.append("invalid");
                }

                if (col.isPrimary()) {
                    sb.append(" not null");
                } else if (colType.equals("Date") || colType.equals("Map") || colType.equals("String")) {

                    sb.append(" null");
                }

                sb.append(",\n");
            }
        }

        sb.append("\tprimary key (");

        for (int i = 0; i < entities.length; i++) {
            Entity entity = entities[i];

            List<EntityColumn> pkList = entity.getPKList();

            for (int j = 0; j < pkList.size(); j++) {
                EntityColumn col = pkList.get(j);

                String colDBName = col.getDBName();

                if ((i != 0) || (j != 0)) {
                    sb.append(", ");
                }

                sb.append(colDBName);
            }
        }

        sb.append(")\n");
        sb.append(");");

        return sb.toString();
    }

    private String _getCreateTableSQL(Entity entity) {
        List<EntityColumn> pkList = entity.getPKList();
        List<EntityColumn> regularColList = entity.getRegularColList();

        if (regularColList.isEmpty()) {
            return null;
        }

        StringBundler sb = new StringBundler();

        sb.append(_SQL_CREATE_TABLE);
        sb.append(entity.getTable());
        sb.append(" (\n");

        for (int i = 0; i < regularColList.size(); i++) {
            EntityColumn col = regularColList.get(i);

            String colName = col.getName();
            String colType = col.getType();
            String colIdType = col.getIdType();

            sb.append("\t");
            sb.append(col.getDBName());
            sb.append(" ");

            if (StringUtil.equalsIgnoreCase(colType, "boolean")) {
                sb.append("BOOLEAN");
            } else if (StringUtil.equalsIgnoreCase(colType, "double")
                    || StringUtil.equalsIgnoreCase(colType, "float")) {

                sb.append("DOUBLE");
            } else if (colType.equals("int") || colType.equals("Integer")
                    || StringUtil.equalsIgnoreCase(colType, "short")) {

                sb.append("INTEGER");
            } else if (StringUtil.equalsIgnoreCase(colType, "long")) {
                sb.append("LONG");
            } else if (colType.equals("Blob")) {
                sb.append("BLOB");
            } else if (colType.equals("Date")) {
                sb.append("DATE");
            } else if (colType.equals("Map")) {
                sb.append("TEXT");
            } else if (colType.equals("String")) {
                Map<String, String> hints = ModelHintsUtil.getHints(_packagePath + ".model." + entity.getName(),
                        colName);

                int maxLength = 75;

                if (hints != null) {
                    maxLength = GetterUtil.getInteger(hints.get("max-length"), maxLength);
                }

                if (col.isLocalized() && (maxLength < 4000)) {
                    maxLength = 4000;
                }

                if (maxLength < 4000) {
                    sb.append("VARCHAR(");
                    sb.append(maxLength);
                    sb.append(")");
                } else if (maxLength == 4000) {
                    sb.append("STRING");
                } else if (maxLength > 4000) {
                    sb.append("TEXT");
                }
            } else {
                sb.append("invalid");
            }

            if (col.isPrimary()) {
                sb.append(" not null");

                if (!entity.hasCompoundPK()) {
                    sb.append(" primary key");
                }
            } else if (colType.equals("Date") || colType.equals("Map") || colType.equals("String")) {

                sb.append(" null");
            }

            if (Validator.isNotNull(colIdType) && colIdType.equals("identity")) {

                sb.append(" IDENTITY");
            }

            if (colName.equals("mvccVersion")) {
                sb.append(" default 0");
            }

            if (((i + 1) != regularColList.size()) || entity.hasCompoundPK()) {
                sb.append(",");
            }

            sb.append("\n");
        }

        if (entity.hasCompoundPK()) {
            sb.append("\tprimary key (");

            for (int j = 0; j < pkList.size(); j++) {
                EntityColumn pk = pkList.get(j);

                sb.append(pk.getDBName());

                if ((j + 1) != pkList.size()) {
                    sb.append(", ");
                }
            }

            sb.append(")\n");
        }

        sb.append(");");

        return sb.toString();
    }

    private String _getDimensions(Type type) {
        String dimensions = "";

        for (int i = 0; i < type.getDimensions(); i++) {
            dimensions += "[]";
        }

        return dimensions;
    }

    private JavaClass _getJavaClass(String fileName) throws IOException {
        int pos = 0;

        if (fileName.startsWith(_implDirName)) {
            pos = _implDirName.length() + 1;
        } else if (fileName.startsWith(_apiDirName)) {
            pos = _apiDirName.length() + 1;
        } else {
            return null;
        }

        String fullyQualifiedClassName = StringUtil.replace(fileName.substring(pos, fileName.length() - 5),
                new String[] { StringPool.BACK_SLASH, StringPool.SLASH },
                new String[] { StringPool.PERIOD, StringPool.PERIOD });

        JavaClass javaClass = _javaClasses.get(fullyQualifiedClassName);

        if (javaClass == null) {
            ClassLibrary classLibrary = new ClassLibrary();

            classLibrary.addClassLoader(getClass().getClassLoader());

            JavaDocBuilder builder = new JavaDocBuilder(classLibrary);

            File file = new File(fileName);

            if (!file.exists()) {
                return null;
            }

            builder.addSource(file);

            javaClass = builder.getClassByName(fullyQualifiedClassName);

            _javaClasses.put(fullyQualifiedClassName, javaClass);
        }

        return javaClass;
    }

    private String _getMethodKey(JavaMethod javaMethod) {
        StringBundler sb = new StringBundler();

        if (!javaMethod.isConstructor()) {
            sb.append(getTypeGenericsName(javaMethod.getReturnType()));
            sb.append(StringPool.SPACE);
        }

        sb.append(javaMethod.getName());
        sb.append(StringPool.OPEN_PARENTHESIS);

        JavaParameter[] javaParameters = javaMethod.getParameters();

        for (JavaParameter javaParameter : javaParameters) {
            sb.append(getTypeGenericsName(javaParameter.getType()));

            sb.append(StringPool.COMMA);
        }

        if (javaParameters.length > 0) {
            sb.setIndex(sb.index() - 1);
        }

        sb.append(StringPool.CLOSE_PARENTHESIS);

        return sb.toString();
    }

    private JavaMethod[] _getMethods(JavaClass javaClass) {
        return _getMethods(javaClass, false);
    }

    private JavaMethod[] _getMethods(JavaClass javaClass, boolean superclasses) {

        JavaMethod[] methods = javaClass.getMethods(superclasses);

        for (JavaMethod method : methods) {
            Arrays.sort(method.getExceptions());
        }

        return methods;
    }

    private String _getSessionTypeName(int sessionType) {
        if (sessionType == _SESSION_TYPE_LOCAL) {
            return "Local";
        } else {
            return "";
        }
    }

    private String _getSpringNamespacesDeclarations() {
        StringBundler sb = new StringBundler(_springNamespaces.length * 4);

        for (String namespace : _springNamespaces) {
            sb.append("\txmlns");

            if (!_SPRING_NAMESPACE_BEANS.equals(namespace)) {
                sb.append(":");
                sb.append(namespace);
            }

            sb.append("=\"http://www.springframework.org/schema/");
            sb.append(namespace);
            sb.append("\"\n");
        }

        return sb.toString();
    }

    private String _getSpringSchemaLocations() {
        StringBundler sb = new StringBundler(_springNamespaces.length * 6);

        for (String namespace : _springNamespaces) {
            sb.append("\thttp://www.springframework.org/schema/");
            sb.append(namespace);
            sb.append(" http://www.springframework.org/schema/");
            sb.append(namespace);
            sb.append("/spring-");
            sb.append(namespace);
            sb.append(".xsd");
        }

        return sb.toString();
    }

    private String _getTplProperty(String key, String defaultValue) {
        return System.getProperty("service.tpl." + key, defaultValue);
    }

    private List<String> _getTransients(Entity entity, boolean parent) throws Exception {

        File modelFile = null;

        if (parent) {
            modelFile = new File(_outputPath + "/model/impl/" + entity.getName() + "ModelImpl.java");
        } else {
            modelFile = new File(_outputPath + "/model/impl/" + entity.getName() + "Impl.java");
        }

        String content = FileUtils.readFileToString(modelFile);

        Matcher matcher = _getterPattern.matcher(content);

        Set<String> getters = new HashSet<>();

        while (!matcher.hitEnd()) {
            boolean found = matcher.find();

            if (found) {
                String property = matcher.group();

                if (property.contains("get")) {
                    property = property.substring(property.indexOf("get") + 3, property.length() - 1);
                } else {
                    property = property.substring(property.indexOf("is") + 2, property.length() - 1);
                }

                if (!entity.hasColumn(property) && !entity.hasColumn(Introspector.decapitalize(property))) {

                    property = Introspector.decapitalize(property);

                    getters.add(property);
                }
            }
        }

        matcher = _setterPattern.matcher(content);

        Set<String> setters = new HashSet<>();

        while (!matcher.hitEnd()) {
            boolean found = matcher.find();

            if (found) {
                String property = matcher.group();

                property = property.substring(property.indexOf("set") + 3, property.length() - 1);

                if (!entity.hasColumn(property) && !entity.hasColumn(Introspector.decapitalize(property))) {

                    property = Introspector.decapitalize(property);

                    setters.add(property);
                }
            }
        }

        getters.retainAll(setters);

        List<String> transients = new ArrayList<>(getters);

        Collections.sort(transients);

        return transients;
    }

    private boolean _hasHttpMethods(JavaClass javaClass) {
        JavaMethod[] methods = _getMethods(javaClass);

        for (JavaMethod javaMethod : methods) {
            if (!javaMethod.isConstructor() && javaMethod.isPublic() && isCustomMethod(javaMethod)) {

                return true;
            }
        }

        return false;
    }

    private boolean _isStringLocaleMap(JavaParameter javaParameter) {
        Type type = javaParameter.getType();

        Type[] actualArgumentTypes = type.getActualTypeArguments();

        if (actualArgumentTypes.length != 2) {
            return false;
        }

        if (!_isTypeValue(actualArgumentTypes[0], Locale.class.getName())
                || !_isTypeValue(actualArgumentTypes[1], String.class.getName())) {

            return false;
        }

        return true;
    }

    private boolean _isTargetEntity(Entity entity) {
        if ((_targetEntityName == null) || _targetEntityName.startsWith("$")) {
            return true;
        }

        return _targetEntityName.equals(entity.getName());
    }

    private boolean _isTypeValue(Type type, String value) {
        return value.equals(type.getValue());
    }

    private Annotation[] _mergeAnnotations(Annotation[] annotations1, Annotation[] annotations2) {

        Map<Type, Annotation> annotationsMap = new HashMap<>();

        for (Annotation annotation : annotations2) {
            annotationsMap.put(annotation.getType(), annotation);
        }

        for (Annotation annotation : annotations1) {
            annotationsMap.put(annotation.getType(), annotation);
        }

        List<Annotation> annotations = new ArrayList<>(annotationsMap.values());

        Comparator<Annotation> comparator = new Comparator<Annotation>() {

            @Override
            public int compare(Annotation annotation1, Annotation annotation2) {
                String annotationString1 = annotation1.toString();
                String annotationString2 = annotation2.toString();

                return annotationString1.compareTo(annotationString2);
            }

        };

        Collections.sort(annotations, comparator);

        return annotations.toArray(new Annotation[annotations.size()]);
    }

    private JavaMethod[] _mergeMethods(JavaMethod[] javaMethods1, JavaMethod[] javaMethods2,
            boolean mergeAnnotations) {

        Map<String, JavaMethod> javaMethodMap = new HashMap<>();

        for (JavaMethod javaMethod : javaMethods2) {
            javaMethodMap.put(_getMethodKey(javaMethod), javaMethod);
        }

        for (JavaMethod javaMethod : javaMethods1) {
            String javaMethodKey = _getMethodKey(javaMethod);

            JavaMethod existingJavaMethod = javaMethodMap.get(javaMethodKey);

            if (existingJavaMethod == null) {
                javaMethodMap.put(javaMethodKey, javaMethod);
            } else if (mergeAnnotations) {
                Annotation[] annotations = _mergeAnnotations(javaMethod.getAnnotations(),
                        existingJavaMethod.getAnnotations());

                existingJavaMethod.setAnnotations(annotations);
            }
        }

        List<JavaMethod> javaMethods = new ArrayList<>(javaMethodMap.values());

        Comparator<JavaMethod> comparator = new Comparator<JavaMethod>() {

            @Override
            public int compare(JavaMethod javaMethod1, JavaMethod javaMethod2) {
                String callSignature1 = javaMethod1.getCallSignature();
                String callSignature2 = javaMethod2.getCallSignature();

                return callSignature1.compareTo(callSignature2);
            }

        };

        Collections.sort(javaMethods, comparator);

        return javaMethods.toArray(new JavaMethod[javaMethods.size()]);
    }

    private List<Entity> _mergeReferenceList(Entity entity) {
        List<Entity> referenceList = entity.getReferenceList();

        Set<Entity> set = new LinkedHashSet<>();

        if (_autoImportDefaultReferences) {
            set.addAll(_ejbList);
        } else {
            set.add(entity);
        }

        set.addAll(referenceList);

        return new ArrayList<>(set);
    }

    private void _parseEntity(Element entityElement) throws Exception {
        String ejbName = entityElement.attributeValue("name");
        String humanName = entityElement.attributeValue("human-name");

        String table = entityElement.attributeValue("table");

        if (Validator.isNull(table)) {
            table = ejbName;

            if (_badTableNames.contains(ejbName)) {
                table += StringPool.UNDERLINE;
            }

            if (_autoNamespaceTables) {
                table = _portletShortName + StringPool.UNDERLINE + ejbName;
            }
        }

        boolean uuid = GetterUtil.getBoolean(entityElement.attributeValue("uuid"));
        boolean uuidAccessor = GetterUtil.getBoolean(entityElement.attributeValue("uuid-accessor"));
        boolean localService = GetterUtil.getBoolean(entityElement.attributeValue("local-service"));
        boolean remoteService = GetterUtil.getBoolean(entityElement.attributeValue("remote-service"), true);
        String persistenceClass = GetterUtil.getString(entityElement.attributeValue("persistence-class"),
                _packagePath + ".service.persistence.impl." + ejbName + "PersistenceImpl");

        String finderClass = "";

        File originalFinderImpl = new File(_outputPath + "/service/persistence/" + ejbName + "FinderImpl.java");
        File newFinderImpl = new File(_outputPath + "/service/persistence/impl/" + ejbName + "FinderImpl.java");

        if (originalFinderImpl.exists()) {
            FileUtils.moveFile(originalFinderImpl, newFinderImpl);

            String content = FileUtils.readFileToString(newFinderImpl);

            StringBundler sb = new StringBundler();

            sb.append("package " + _packagePath + ".service.persistence.impl;\n\n");
            sb.append("import " + _packagePath + ".service.persistence." + ejbName + "Finder;\n");
            sb.append("import " + _packagePath + ".service.persistence." + ejbName + "Util;");

            content = StringUtil.replace(content, "package " + _packagePath + ".service.persistence;",
                    sb.toString());

            writeFileRaw(newFinderImpl, content, _modifiedFileNames);
        }

        if (newFinderImpl.exists()) {
            finderClass = _packagePath + ".service.persistence.impl." + ejbName + "FinderImpl";
        }

        String dataSource = entityElement.attributeValue("data-source");
        String sessionFactory = entityElement.attributeValue("session-factory");
        String txManager = entityElement.attributeValue("tx-manager");
        boolean cacheEnabled = GetterUtil.getBoolean(entityElement.attributeValue("cache-enabled"), true);
        boolean jsonEnabled = GetterUtil.getBoolean(entityElement.attributeValue("json-enabled"), remoteService);
        boolean mvccEnabled = GetterUtil.getBoolean(entityElement.attributeValue("mvcc-enabled"), _mvccEnabled);
        boolean trashEnabled = GetterUtil.getBoolean(entityElement.attributeValue("trash-enabled"));
        boolean deprecated = GetterUtil.getBoolean(entityElement.attributeValue("deprecated"));

        boolean dynamicUpdateEnabled = GetterUtil.getBoolean(entityElement.attributeValue("dynamic-update-enabled"),
                mvccEnabled);

        List<EntityColumn> pkList = new ArrayList<>();
        List<EntityColumn> regularColList = new ArrayList<>();
        List<EntityColumn> blobList = new ArrayList<>();
        List<EntityColumn> collectionList = new ArrayList<>();
        List<EntityColumn> columnList = new ArrayList<>();

        boolean permissionedModel = false;

        List<Element> columnElements = entityElement.elements("column");

        if (uuid) {
            Element columnElement = DocumentHelper.createElement("column");

            columnElement.addAttribute("name", "uuid");
            columnElement.addAttribute("type", "String");

            columnElements.add(0, columnElement);
        }

        if (mvccEnabled && !columnElements.isEmpty()) {
            Element columnElement = DocumentHelper.createElement("column");

            columnElement.addAttribute("name", "mvccVersion");
            columnElement.addAttribute("type", "long");

            columnElements.add(0, columnElement);
        }

        for (Element columnElement : columnElements) {
            String columnName = columnElement.attributeValue("name");

            if (columnName.equals("resourceBlockId") && !ejbName.equals("ResourceBlock")) {

                permissionedModel = true;
            }

            String columnDBName = columnElement.attributeValue("db-name");

            if (Validator.isNull(columnDBName)) {
                columnDBName = columnName;

                if (_badColumnNames.contains(columnName)) {
                    columnDBName += StringPool.UNDERLINE;
                }
            }

            String columnType = columnElement.attributeValue("type");
            boolean primary = GetterUtil.getBoolean(columnElement.attributeValue("primary"));
            boolean accessor = GetterUtil.getBoolean(columnElement.attributeValue("accessor"));
            boolean filterPrimary = GetterUtil.getBoolean(columnElement.attributeValue("filter-primary"));
            String collectionEntity = columnElement.attributeValue("entity");

            String mappingTable = columnElement.attributeValue("mapping-table");

            if (Validator.isNotNull(mappingTable)) {
                if (_badTableNames.contains(mappingTable)) {
                    mappingTable += StringPool.UNDERLINE;
                }

                if (_autoNamespaceTables) {
                    mappingTable = _portletShortName + StringPool.UNDERLINE + mappingTable;
                }
            }

            String idType = columnElement.attributeValue("id-type");
            String idParam = columnElement.attributeValue("id-param");
            boolean convertNull = GetterUtil.getBoolean(columnElement.attributeValue("convert-null"), true);
            boolean lazy = GetterUtil.getBoolean(columnElement.attributeValue("lazy"), true);
            boolean localized = GetterUtil.getBoolean(columnElement.attributeValue("localized"));
            boolean colJsonEnabled = GetterUtil.getBoolean(columnElement.attributeValue("json-enabled"),
                    jsonEnabled);
            boolean containerModel = GetterUtil.getBoolean(columnElement.attributeValue("container-model"));
            boolean parentContainerModel = GetterUtil
                    .getBoolean(columnElement.attributeValue("parent-container-model"));

            EntityColumn col = new EntityColumn(columnName, columnDBName, columnType, primary, accessor,
                    filterPrimary, collectionEntity, mappingTable, idType, idParam, convertNull, lazy, localized,
                    colJsonEnabled, containerModel, parentContainerModel);

            if (primary) {
                pkList.add(col);
            }

            if (columnType.equals("Collection")) {
                collectionList.add(col);
            } else {
                regularColList.add(col);

                if (columnType.equals("Blob")) {
                    blobList.add(col);
                }
            }

            columnList.add(col);

            if (Validator.isNotNull(collectionEntity) && Validator.isNotNull(mappingTable)) {

                EntityMapping entityMapping = new EntityMapping(mappingTable, ejbName, collectionEntity);

                if (!_entityMappings.containsKey(mappingTable)) {
                    _entityMappings.put(mappingTable, entityMapping);
                }
            }
        }

        EntityOrder order = null;

        Element orderElement = entityElement.element("order");

        if (orderElement != null) {
            boolean asc = true;

            if ((orderElement.attribute("by") != null) && orderElement.attributeValue("by").equals("desc")) {

                asc = false;
            }

            List<EntityColumn> orderColsList = new ArrayList<>();

            order = new EntityOrder(asc, orderColsList);

            List<Element> orderColumnElements = orderElement.elements("order-column");

            for (Element orderColElement : orderColumnElements) {
                String orderColName = orderColElement.attributeValue("name");
                boolean orderColCaseSensitive = GetterUtil
                        .getBoolean(orderColElement.attributeValue("case-sensitive"), true);

                boolean orderColByAscending = asc;

                String orderColBy = GetterUtil.getString(orderColElement.attributeValue("order-by"));

                if (orderColBy.equals("asc")) {
                    orderColByAscending = true;
                } else if (orderColBy.equals("desc")) {
                    orderColByAscending = false;
                }

                EntityColumn col = Entity.getColumn(orderColName, columnList);

                col.setOrderColumn(true);

                col = (EntityColumn) col.clone();

                col.setCaseSensitive(orderColCaseSensitive);
                col.setOrderByAscending(orderColByAscending);

                orderColsList.add(col);
            }
        }

        List<EntityFinder> finderList = new ArrayList<>();

        List<Element> finderElements = entityElement.elements("finder");

        if (uuid) {
            if (columnList.contains(new EntityColumn("companyId"))) {
                Element finderElement = DocumentHelper.createElement("finder");

                finderElement.addAttribute("name", "Uuid_C");
                finderElement.addAttribute("return-type", "Collection");

                Element finderColumnElement = finderElement.addElement("finder-column");

                finderColumnElement.addAttribute("name", "uuid");

                finderColumnElement = finderElement.addElement("finder-column");

                finderColumnElement.addAttribute("name", "companyId");

                finderElements.add(0, finderElement);
            }

            if (columnList.contains(new EntityColumn("groupId"))) {
                Element finderElement = DocumentHelper.createElement("finder");

                if (ejbName.equals("Layout")) {
                    finderElement.addAttribute("name", "UUID_G_P");
                } else {
                    finderElement.addAttribute("name", "UUID_G");
                }

                finderElement.addAttribute("return-type", ejbName);
                finderElement.addAttribute("unique", "true");

                Element finderColumnElement = finderElement.addElement("finder-column");

                finderColumnElement.addAttribute("name", "uuid");

                finderColumnElement = finderElement.addElement("finder-column");

                finderColumnElement.addAttribute("name", "groupId");

                if (ejbName.equals("Layout")) {
                    finderColumnElement = finderElement.addElement("finder-column");

                    finderColumnElement.addAttribute("name", "privateLayout");
                }

                finderElements.add(0, finderElement);
            }

            Element finderElement = DocumentHelper.createElement("finder");

            finderElement.addAttribute("name", "Uuid");
            finderElement.addAttribute("return-type", "Collection");

            Element finderColumnElement = finderElement.addElement("finder-column");

            finderColumnElement.addAttribute("name", "uuid");

            finderElements.add(0, finderElement);
        }

        if (permissionedModel) {
            Element finderElement = DocumentHelper.createElement("finder");

            finderElement.addAttribute("name", "ResourceBlockId");
            finderElement.addAttribute("return-type", "Collection");

            Element finderColumnElement = finderElement.addElement("finder-column");

            finderColumnElement.addAttribute("name", "resourceBlockId");

            finderElements.add(0, finderElement);
        }

        String alias = TextFormatter.format(ejbName, TextFormatter.I);

        if (_badAliasNames.contains(StringUtil.toLowerCase(alias))) {
            alias += StringPool.UNDERLINE;
        }

        for (Element finderElement : finderElements) {
            String finderName = finderElement.attributeValue("name");
            String finderReturn = finderElement.attributeValue("return-type");
            boolean finderUnique = GetterUtil.getBoolean(finderElement.attributeValue("unique"));

            String finderWhere = finderElement.attributeValue("where");

            if (Validator.isNotNull(finderWhere)) {
                for (EntityColumn column : columnList) {
                    String name = column.getName();

                    finderWhere = StringUtil.replace(finderWhere, name, alias + "." + name);
                }
            }

            boolean finderDBIndex = GetterUtil.getBoolean(finderElement.attributeValue("db-index"), true);

            List<EntityColumn> finderColsList = new ArrayList<>();

            List<Element> finderColumnElements = finderElement.elements("finder-column");

            for (Element finderColumnElement : finderColumnElements) {
                String finderColName = finderColumnElement.attributeValue("name");
                boolean finderColCaseSensitive = GetterUtil
                        .getBoolean(finderColumnElement.attributeValue("case-sensitive"), true);
                String finderColComparator = GetterUtil.getString(finderColumnElement.attributeValue("comparator"),
                        "=");
                String finderColArrayableOperator = GetterUtil
                        .getString(finderColumnElement.attributeValue("arrayable-operator"));

                EntityColumn col = Entity.getColumn(finderColName, columnList);

                if (!col.isFinderPath()) {
                    col.setFinderPath(true);
                }

                col = (EntityColumn) col.clone();

                col.setCaseSensitive(finderColCaseSensitive);
                col.setComparator(finderColComparator);
                col.setArrayableOperator(finderColArrayableOperator);

                col.validate();

                finderColsList.add(col);
            }

            finderList.add(new EntityFinder(finderName, finderReturn, finderUnique, finderWhere, finderDBIndex,
                    finderColsList));
        }

        List<Entity> referenceList = new ArrayList<>();
        List<String> unresolvedReferenceList = new ArrayList<>();

        if (_build) {
            List<Element> referenceElements = entityElement.elements("reference");

            Set<String> referenceSet = new TreeSet<>();

            for (Element referenceElement : referenceElements) {
                String referencePackage = referenceElement.attributeValue("package-path");
                String referenceEntity = referenceElement.attributeValue("entity");

                referenceSet.add(referencePackage + "." + referenceEntity);
            }

            if (!_packagePath.equals("com.liferay.counter")) {
                referenceSet.add("com.liferay.counter.Counter");
            }

            if (_autoImportDefaultReferences) {
                referenceSet.add("com.liferay.portal.ClassName");
                referenceSet.add("com.liferay.portal.Resource");
                referenceSet.add("com.liferay.portal.User");
            }

            for (String referenceName : referenceSet) {
                try {
                    referenceList.add(getEntity(referenceName));
                } catch (RuntimeException re) {
                    unresolvedReferenceList.add(referenceName);
                }
            }
        }

        List<String> txRequiredList = new ArrayList<>();

        List<Element> txRequiredElements = entityElement.elements("tx-required");

        for (Element txRequiredEl : txRequiredElements) {
            String txRequired = txRequiredEl.getText();

            txRequiredList.add(txRequired);
        }

        boolean resourceActionModel = _resourceActionModels.contains(_packagePath + ".model." + ejbName);

        _ejbList.add(new Entity(_packagePath, _portletName, _portletShortName, ejbName, humanName, table, alias,
                uuid, uuidAccessor, localService, remoteService, persistenceClass, finderClass, dataSource,
                sessionFactory, txManager, cacheEnabled, dynamicUpdateEnabled, jsonEnabled, mvccEnabled,
                trashEnabled, deprecated, pkList, regularColList, blobList, collectionList, columnList, order,
                finderList, referenceList, unresolvedReferenceList, txRequiredList, resourceActionModel));
    }

    private String _processTemplate(String name, Map<String, Object> context) throws Exception {

        _currentTplName = name;

        return StringUtil.strip(FreeMarkerUtil.process(name, context), '\r');
    }

    private Map<String, Object> _putDeprecatedKeys(Map<String, Object> context, JavaClass javaClass) {

        context.put("classDeprecated", false);

        DocletTag tag = javaClass.getTagByName("deprecated");

        if (tag != null) {
            context.put("classDeprecated", true);
            context.put("classDeprecatedComment", tag.getValue());
        }

        return context;
    }

    private Set<String> _readLines(String fileName) throws Exception {
        ClassLoader classLoader = getClass().getClassLoader();

        Set<String> lines = new HashSet<>();

        StringUtil.readLines(classLoader.getResourceAsStream(fileName), lines);

        return lines;
    }

    private void _removeActionableDynamicQuery(Entity entity) {
        _deleteFile(
                _serviceOutputPath + "/service/persistence/" + entity.getName() + "ActionableDynamicQuery.java");
    }

    private void _removeExportActionableDynamicQuery(Entity entity) {
        _deleteFile(_serviceOutputPath + "/service/persistence/" + entity.getName()
                + "ExportActionableDynamicQuery.java");
    }

    private void _removeFinder(Entity entity) {
        _deleteFile(_serviceOutputPath + "/service/persistence/" + entity.getName() + "Finder.java");
    }

    private void _removeFinderUtil(Entity entity) {
        _deleteFile(_serviceOutputPath + "/service/persistence/" + entity.getName() + "FinderUtil.java");
    }

    private void _removeService(Entity entity, int sessionType) {
        _deleteFile(_serviceOutputPath + "/service/" + entity.getName() + _getSessionTypeName(sessionType)
                + "Service.java");
    }

    private void _removeServiceBaseImpl(Entity entity, int sessionType) {
        _deleteFile(_outputPath + "/service/base/" + entity.getName() + _getSessionTypeName(sessionType)
                + "ServiceBaseImpl.java");
    }

    private void _removeServiceClp(Entity entity, int sessionType) {
        _deleteFile(_serviceOutputPath + "/service/" + entity.getName() + _getSessionTypeName(sessionType)
                + "ServiceClp.java");
    }

    private void _removeServiceClpInvoker(Entity entity, int sessionType) {
        _deleteFile(_outputPath + "/service/base/" + entity.getName() + _getSessionTypeName(sessionType)
                + "ServiceClpInvoker.java");
    }

    private void _removeServiceHttp(Entity entity) {
        _deleteFile(_outputPath + "/service/http/" + entity.getName() + "ServiceHttp.java");
    }

    private void _removeServiceImpl(Entity entity, int sessionType) {
        _deleteFile(_outputPath + "/service/impl/" + entity.getName() + _getSessionTypeName(sessionType)
                + "ServiceImpl.java");
    }

    private void _removeServiceSoap(Entity entity) {
        _deleteFile(_outputPath + "/service/http/" + entity.getName() + "ServiceSoap.java");
    }

    private void _removeServiceUtil(Entity entity, int sessionType) {
        _deleteFile(_serviceOutputPath + "/service/" + entity.getName() + _getSessionTypeName(sessionType)
                + "ServiceUtil.java");
    }

    private void _removeServiceWrapper(Entity entity, int sessionType) {
        _deleteFile(_serviceOutputPath + "/service/" + entity.getName() + _getSessionTypeName(sessionType)
                + "ServiceWrapper.java");
    }

    private void _resolveEntity(Entity entity) throws Exception {
        if (entity.isResolved()) {
            return;
        }

        for (String referenceName : entity.getUnresolvedReferenceList()) {
            Entity referenceEntity = getEntity(referenceName);

            if (referenceEntity == null) {
                throw new ServiceBuilderException("Unable to resolve reference " + referenceName + " in "
                        + ListUtil.toString(_ejbList, Entity.NAME_ACCESSOR));
            }

            entity.addReference(referenceEntity);
        }

        entity.setResolved();
    }

    private void _updateSQLFile(String sqlFileName, String createTableSQL, Entity entity) throws IOException {

        File updateSQLFile = new File(_sqlDirName + "/" + sqlFileName);

        if (updateSQLFile.exists()) {
            _createSQLTables(updateSQLFile, createTableSQL, entity, false);
        }
    }

    private static final int _SESSION_TYPE_LOCAL = 1;

    private static final int _SESSION_TYPE_REMOTE = 0;

    private static final String _SPRING_NAMESPACE_BEANS = "beans";

    private static final String _SQL_CREATE_TABLE = "create table ";

    private static final String _TMP_DIR = System.getProperty("java.io.tmpdir");

    private static final String _TPL_ROOT = "com/liferay/portal/tools/service/builder/dependencies/";

    private static Pattern _getterPattern = Pattern
            .compile("public .* get.*" + Pattern.quote("(") + "|public boolean is.*" + Pattern.quote("("));
    private static Pattern _setterPattern = Pattern.compile("public void set.*" + Pattern.quote("("));

    private String _apiDirName;
    private String _author;
    private boolean _autoImportDefaultReferences;
    private boolean _autoNamespaceTables;
    private Set<String> _badAliasNames;
    private Set<String> _badColumnNames;
    private Set<String> _badTableNames;
    private String _beanLocatorUtil;
    private String _beanLocatorUtilShortName;
    private boolean _build;
    private long _buildNumber;
    private boolean _buildNumberIncrement;
    private String _currentTplName;
    private List<Entity> _ejbList;
    private Map<String, EntityMapping> _entityMappings;
    private Map<String, Entity> _entityPool = new HashMap<>();
    private String _hbmFileName;
    private String _implDirName;
    private Map<String, JavaClass> _javaClasses = new HashMap<>();
    private String _modelHintsFileName;
    private Set<String> _modifiedFileNames = new HashSet<>();
    private boolean _mvccEnabled;
    private boolean _osgiModule;
    private String _outputPath;
    private String _packagePath;
    private String _pluginName;
    private String _portletName = StringPool.BLANK;
    private String _portletPackageName = StringPool.BLANK;
    private String _portletShortName = StringPool.BLANK;
    private String _propsUtil;
    private String[] _readOnlyPrefixes;
    private String _remotingFileName;
    private Set<String> _resourceActionModels = new HashSet<>();
    private String _resourcesDirName;
    private String _serviceOutputPath;
    private String _springFileName;
    private String[] _springNamespaces;
    private String _sqlDirName;
    private String _sqlFileName;
    private String _sqlIndexesFileName;
    private String _sqlSequencesFileName;
    private String _targetEntityName;
    private String _testDirName;
    private String _testOutputPath;
    private String _tplActionableDynamicQuery = _TPL_ROOT + "actionable_dynamic_query.ftl";
    private String _tplBadAliasNames = _TPL_ROOT + "bad_alias_names.txt";
    private String _tplBadColumnNames = _TPL_ROOT + "bad_column_names.txt";
    private String _tplBadTableNames = _TPL_ROOT + "bad_table_names.txt";
    private String _tplBlobModel = _TPL_ROOT + "blob_model.ftl";
    private String _tplEjbPk = _TPL_ROOT + "ejb_pk.ftl";
    private String _tplException = _TPL_ROOT + "exception.ftl";
    private String _tplExportActionableDynamicQuery = _TPL_ROOT + "export_actionable_dynamic_query.ftl";
    private String _tplExtendedModel = _TPL_ROOT + "extended_model.ftl";
    private String _tplExtendedModelBaseImpl = _TPL_ROOT + "extended_model_base_impl.ftl";
    private String _tplExtendedModelImpl = _TPL_ROOT + "extended_model_impl.ftl";
    private String _tplFinder = _TPL_ROOT + "finder.ftl";
    private String _tplFinderUtil = _TPL_ROOT + "finder_util.ftl";
    private String _tplHbmXml = _TPL_ROOT + "hbm_xml.ftl";
    private String _tplJsonJs = _TPL_ROOT + "json_js.ftl";
    private String _tplJsonJsMethod = _TPL_ROOT + "json_js_method.ftl";
    private String _tplModel = _TPL_ROOT + "model.ftl";
    private String _tplModelCache = _TPL_ROOT + "model_cache.ftl";
    private String _tplModelClp = _TPL_ROOT + "model_clp.ftl";
    private String _tplModelHintsXml = _TPL_ROOT + "model_hints_xml.ftl";
    private String _tplModelImpl = _TPL_ROOT + "model_impl.ftl";
    private String _tplModelSoap = _TPL_ROOT + "model_soap.ftl";
    private String _tplModelWrapper = _TPL_ROOT + "model_wrapper.ftl";
    private String _tplPersistence = _TPL_ROOT + "persistence.ftl";
    private String _tplPersistenceImpl = _TPL_ROOT + "persistence_impl.ftl";
    private String _tplPersistenceTest = _TPL_ROOT + "persistence_test.ftl";
    private String _tplPersistenceUtil = _TPL_ROOT + "persistence_util.ftl";
    private String _tplProps = _TPL_ROOT + "props.ftl";
    private String _tplRemotingXml = _TPL_ROOT + "remoting_xml.ftl";
    private String _tplService = _TPL_ROOT + "service.ftl";
    private String _tplServiceBaseImpl = _TPL_ROOT + "service_base_impl.ftl";
    private String _tplServiceClp = _TPL_ROOT + "service_clp.ftl";
    private String _tplServiceClpInvoker = _TPL_ROOT + "service_clp_invoker.ftl";
    private String _tplServiceClpMessageListener = _TPL_ROOT + "service_clp_message_listener.ftl";
    private String _tplServiceClpSerializer = _TPL_ROOT + "service_clp_serializer.ftl";
    private String _tplServiceHttp = _TPL_ROOT + "service_http.ftl";
    private String _tplServiceImpl = _TPL_ROOT + "service_impl.ftl";
    private String _tplServicePropsUtil = _TPL_ROOT + "service_props_util.ftl";
    private String _tplServiceSoap = _TPL_ROOT + "service_soap.ftl";
    private String _tplServiceUtil = _TPL_ROOT + "service_util.ftl";
    private String _tplServiceWrapper = _TPL_ROOT + "service_wrapper.ftl";
    private String _tplSpringXml = _TPL_ROOT + "spring_xml.ftl";

}