org.hibernate.envers.configuration.internal.metadata.MetadataTools.java Source code

Java tutorial

Introduction

Here is the source code for org.hibernate.envers.configuration.internal.metadata.MetadataTools.java

Source

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
 */
package org.hibernate.envers.configuration.internal.metadata;

import java.util.Iterator;
import javax.persistence.JoinColumn;

import org.hibernate.envers.internal.tools.StringTools;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Formula;
import org.hibernate.mapping.Selectable;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;

/**
 * @author Adam Warski (adam at warski dot org)
 * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
 * @author Michal Skowronek (mskowr at o2 dot pl)
 */
public final class MetadataTools {
    private MetadataTools() {
    }

    public static Element addNativelyGeneratedId(Element parent, String name, String type,
            boolean useRevisionEntityWithNativeId) {
        final Element idMapping = parent.addElement("id");
        idMapping.addAttribute("name", name).addAttribute("type", type);

        final Element generatorMapping = idMapping.addElement("generator");
        if (useRevisionEntityWithNativeId) {
            generatorMapping.addAttribute("class", "native");
        } else {
            generatorMapping.addAttribute("class", "org.hibernate.envers.enhanced.OrderedSequenceGenerator");
            generatorMapping.addElement("param").addAttribute("name", "sequence_name")
                    .setText("REVISION_GENERATOR");
            generatorMapping.addElement("param").addAttribute("name", "table_name").setText("REVISION_GENERATOR");
            generatorMapping.addElement("param").addAttribute("name", "initial_value").setText("1");
            generatorMapping.addElement("param").addAttribute("name", "increment_size").setText("1");
        }
        //        generatorMapping.addAttribute("class", "sequence");
        //        generatorMapping.addElement("param").addAttribute("name", "sequence").setText("custom");

        return idMapping;
    }

    public static Element addProperty(Element parent, String name, String type, boolean insertable,
            boolean updateable, boolean key) {
        final Element propMapping;
        if (key) {
            propMapping = parent.addElement("key-property");
        } else {
            propMapping = parent.addElement("property");
            propMapping.addAttribute("insert", Boolean.toString(insertable));
            propMapping.addAttribute("update", Boolean.toString(updateable));
        }

        propMapping.addAttribute("name", name);

        if (type != null) {
            propMapping.addAttribute("type", type);
        }

        return propMapping;
    }

    public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean key) {
        return addProperty(parent, name, type, insertable, false, key);
    }

    public static Element addModifiedFlagProperty(Element parent, String propertyName, String suffix,
            String modifiedFlagName) {
        return addProperty(parent,
                (modifiedFlagName != null) ? modifiedFlagName : getModifiedFlagPropertyName(propertyName, suffix),
                "boolean", true, false, false);
    }

    public static String getModifiedFlagPropertyName(String propertyName, String suffix) {
        return propertyName + suffix;
    }

    private static void addOrModifyAttribute(Element parent, String name, String value) {
        final Attribute attribute = parent.attribute(name);
        if (attribute == null) {
            parent.addAttribute(name, value);
        } else {
            attribute.setValue(value);
        }
    }

    /**
     * Column name shall be wrapped with '`' signs if quotation required.
     */
    public static Element addOrModifyColumn(Element parent, String name) {
        final Element columnMapping = parent.element("column");

        if (columnMapping == null) {
            return addColumn(parent, name, null, null, null, null, null, null);
        }

        if (!StringTools.isEmpty(name)) {
            addOrModifyAttribute(columnMapping, "name", name);
        }

        return columnMapping;
    }

    /**
     * Adds new <code>column</code> element. Method assumes that the value of <code>name</code> attribute is already
     * wrapped with '`' signs if quotation required. It shall be invoked when column name is taken directly from configuration
     * file and not from {@link org.hibernate.mapping.PersistentClass} descriptor.
     */
    public static Element addColumn(Element parent, String name, Integer length, Integer scale, Integer precision,
            String sqlType, String customRead, String customWrite) {
        return addColumn(parent, name, length, scale, precision, sqlType, customRead, customWrite, false);
    }

    public static Element addColumn(Element parent, String name, Integer length, Integer scale, Integer precision,
            String sqlType, String customRead, String customWrite, boolean quoted) {
        final Element columnMapping = parent.addElement("column");

        columnMapping.addAttribute("name", quoted ? "`" + name + "`" : name);
        if (length != null) {
            columnMapping.addAttribute("length", length.toString());
        }
        if (scale != null) {
            columnMapping.addAttribute("scale", Integer.toString(scale));
        }
        if (precision != null) {
            columnMapping.addAttribute("precision", Integer.toString(precision));
        }
        if (!StringTools.isEmpty(sqlType)) {
            columnMapping.addAttribute("sql-type", sqlType);
        }

        if (!StringTools.isEmpty(customRead)) {
            columnMapping.addAttribute("read", customRead);
        }
        if (!StringTools.isEmpty(customWrite)) {
            columnMapping.addAttribute("write", customWrite);
        }

        return columnMapping;
    }

    private static Element createEntityCommon(Document document, String type, AuditTableData auditTableData,
            String discriminatorValue, Boolean isAbstract) {
        final Element hibernateMapping = document.addElement("hibernate-mapping");
        hibernateMapping.addAttribute("auto-import", "false");

        final Element classMapping = hibernateMapping.addElement(type);

        if (auditTableData.getAuditEntityName() != null) {
            classMapping.addAttribute("entity-name", auditTableData.getAuditEntityName());
        }

        if (discriminatorValue != null) {
            classMapping.addAttribute("discriminator-value", discriminatorValue);
        }

        if (!StringTools.isEmpty(auditTableData.getAuditTableName())) {
            classMapping.addAttribute("table", auditTableData.getAuditTableName());
        }

        if (!StringTools.isEmpty(auditTableData.getSchema())) {
            classMapping.addAttribute("schema", auditTableData.getSchema());
        }

        if (!StringTools.isEmpty(auditTableData.getCatalog())) {
            classMapping.addAttribute("catalog", auditTableData.getCatalog());
        }

        if (isAbstract != null) {
            classMapping.addAttribute("abstract", isAbstract.toString());
        }

        return classMapping;
    }

    public static Element createEntity(Document document, AuditTableData auditTableData, String discriminatorValue,
            Boolean isAbstract) {
        return createEntityCommon(document, "class", auditTableData, discriminatorValue, isAbstract);
    }

    public static Element createSubclassEntity(Document document, String subclassType,
            AuditTableData auditTableData, String extendsEntityName, String discriminatorValue,
            Boolean isAbstract) {
        final Element classMapping = createEntityCommon(document, subclassType, auditTableData, discriminatorValue,
                isAbstract);

        classMapping.addAttribute("extends", extendsEntityName);

        return classMapping;
    }

    public static Element createJoin(Element parent, String tableName, String schema, String catalog) {
        final Element joinMapping = parent.addElement("join");

        joinMapping.addAttribute("table", tableName);

        if (!StringTools.isEmpty(schema)) {
            joinMapping.addAttribute("schema", schema);
        }

        if (!StringTools.isEmpty(catalog)) {
            joinMapping.addAttribute("catalog", catalog);
        }

        return joinMapping;
    }

    public static void addColumns(Element anyMapping, Iterator selectables) {
        while (selectables.hasNext()) {
            final Selectable selectable = (Selectable) selectables.next();
            if (selectable.isFormula()) {
                throw new FormulaNotSupportedException();
            }
            addColumn(anyMapping, (Column) selectable);
        }
    }

    /**
     * Adds <code>column</code> element with the following attributes (unless empty): <code>name</code>,
     * <code>length</code>, <code>scale</code>, <code>precision</code>, <code>sql-type</code>, <code>read</code>
     * and <code>write</code>.
     *
     * @param anyMapping Parent element.
     * @param column Column descriptor.
     */
    public static void addColumn(Element anyMapping, Column column) {
        addColumn(anyMapping, column.getName(), column.getLength(), column.getScale(), column.getPrecision(),
                column.getSqlType(), column.getCustomRead(), column.getCustomWrite(), column.isQuoted());
    }

    @SuppressWarnings({ "unchecked" })
    private static void changeNamesInColumnElement(Element element, ColumnNameIterator columnNameIterator) {
        final Iterator<Element> properties = element.elementIterator();
        while (properties.hasNext()) {
            final Element property = properties.next();

            if ("column".equals(property.getName())) {
                final Attribute nameAttr = property.attribute("name");
                if (nameAttr != null) {
                    nameAttr.setText(columnNameIterator.next());
                }
            }
        }
    }

    @SuppressWarnings({ "unchecked" })
    public static void prefixNamesInPropertyElement(Element element, String prefix,
            ColumnNameIterator columnNameIterator, boolean changeToKey, boolean insertable) {
        final Iterator<Element> properties = element.elementIterator();
        while (properties.hasNext()) {
            final Element property = properties.next();

            if ("property".equals(property.getName()) || "many-to-one".equals(property.getName())) {
                final Attribute nameAttr = property.attribute("name");
                if (nameAttr != null) {
                    nameAttr.setText(prefix + nameAttr.getText());
                }

                changeNamesInColumnElement(property, columnNameIterator);

                if (changeToKey) {
                    property.setName("key-" + property.getName());
                }

                if ("property".equals(property.getName())) {
                    final Attribute insert = property.attribute("insert");
                    insert.setText(Boolean.toString(insertable));
                }
            }
        }
    }

    /**
     * Adds <code>formula</code> element.
     *
     * @param element Parent element.
     * @param formula Formula descriptor.
     */
    public static void addFormula(Element element, Formula formula) {
        element.addElement("formula").setText(formula.getText());
    }

    /**
     * Adds all <code>column</code> or <code>formula</code> elements.
     *
     * @param element Parent element.
     * @param columnIterator Iterator pointing at {@link org.hibernate.mapping.Column} and/or
     * {@link org.hibernate.mapping.Formula} objects.
     */
    public static void addColumnsOrFormulas(Element element, Iterator columnIterator) {
        while (columnIterator.hasNext()) {
            final Object o = columnIterator.next();
            if (o instanceof Column) {
                addColumn(element, (Column) o);
            } else if (o instanceof Formula) {
                addFormula(element, (Formula) o);
            }
        }
    }

    /**
     * An iterator over column names.
     */
    public static abstract class ColumnNameIterator implements Iterator<String> {
    }

    public static ColumnNameIterator getColumnNameIterator(final Iterator<Selectable> selectableIterator) {
        return new ColumnNameIterator() {
            public boolean hasNext() {
                return selectableIterator.hasNext();
            }

            public String next() {
                final Selectable next = selectableIterator.next();
                if (next.isFormula()) {
                    throw new FormulaNotSupportedException();
                }
                return ((Column) next).getName();
            }

            public void remove() {
                selectableIterator.remove();
            }
        };
    }

    public static ColumnNameIterator getColumnNameIterator(final JoinColumn[] joinColumns) {
        return new ColumnNameIterator() {
            int counter;

            public boolean hasNext() {
                return counter < joinColumns.length;
            }

            public String next() {
                return joinColumns[counter++].name();
            }

            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }
}