/* * Hibernate, Relational Persistence for Idiomatic Java * * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Middleware LLC. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program 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. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package org.hibernate.envers.configuration.metadata; import java.util.Iterator; import javax.persistence.JoinColumn; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.Element; import org.hibernate.envers.tools.StringTools; import org.hibernate.mapping.Column; import org.hibernate.mapping.Formula; /** * @author Adam Warski (adam at warski dot org) * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ public class MetadataTools { public static Element addNativelyGeneratedId(Element parent, String name, String type) { Element id_mapping = parent.addElement("id"); id_mapping.addAttribute("name", name).addAttribute("type", type); Element generator_mapping = id_mapping.addElement("generator"); generator_mapping.addAttribute("class", "native"); /*generator_mapping.addAttribute("class", "sequence"); generator_mapping.addElement("param").addAttribute("name", "sequence").setText("custom");*/ return id_mapping; } public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean updateable, boolean key) { Element prop_mapping; if (key) { prop_mapping = parent.addElement("key-property"); } else { prop_mapping = parent.addElement("property"); } prop_mapping.addAttribute("name", name); prop_mapping.addAttribute("insert", Boolean.toString(insertable)); prop_mapping.addAttribute("update", Boolean.toString(updateable)); if (type != null) { prop_mapping.addAttribute("type", type); } return prop_mapping; } public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean key) { return addProperty(parent, name, type, insertable, false, key); } private static void addOrModifyAttribute(Element parent, String name, String value) { 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) { Element column_mapping = parent.element("column"); if (column_mapping == null) { return addColumn(parent, name, null, 0, 0, null, null, null); } if (!StringTools.isEmpty(name)) { addOrModifyAttribute(column_mapping, "name", name); } return column_mapping; } /** * 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) { Element column_mapping = parent.addElement("column"); column_mapping.addAttribute("name", quoted ? "`" + name + "`" : name); if (length != null) { column_mapping.addAttribute("length", length.toString()); } if (scale != 0) { column_mapping.addAttribute("scale", Integer.toString(scale)); } if (precision != 0) { column_mapping.addAttribute("precision", Integer.toString(precision)); } if (!StringTools.isEmpty(sqlType)) { column_mapping.addAttribute("sql-type", sqlType); } if (!StringTools.isEmpty(customRead)) { column_mapping.addAttribute("read", customRead); } if (!StringTools.isEmpty(customWrite)) { column_mapping.addAttribute("write", customWrite); } return column_mapping; } private static Element createEntityCommon(Document document, String type, AuditTableData auditTableData, String discriminatorValue) { Element hibernate_mapping = document.addElement("hibernate-mapping"); hibernate_mapping.addAttribute("auto-import", "false"); Element class_mapping = hibernate_mapping.addElement(type); if (auditTableData.getAuditEntityName() != null) { class_mapping.addAttribute("entity-name", auditTableData.getAuditEntityName()); } if (discriminatorValue != null) { class_mapping.addAttribute("discriminator-value", discriminatorValue); } if (!StringTools.isEmpty(auditTableData.getAuditTableName())) { class_mapping.addAttribute("table", auditTableData.getAuditTableName()); } if (!StringTools.isEmpty(auditTableData.getSchema())) { class_mapping.addAttribute("schema", auditTableData.getSchema()); } if (!StringTools.isEmpty(auditTableData.getCatalog())) { class_mapping.addAttribute("catalog", auditTableData.getCatalog()); } return class_mapping; } public static Element createEntity(Document document, AuditTableData auditTableData, String discriminatorValue) { return createEntityCommon(document, "class", auditTableData, discriminatorValue); } public static Element createSubclassEntity(Document document, String subclassType, AuditTableData auditTableData, String extendsEntityName, String discriminatorValue) { Element class_mapping = createEntityCommon(document, subclassType, auditTableData, discriminatorValue); class_mapping.addAttribute("extends", extendsEntityName); return class_mapping; } public static Element createJoin(Element parent, String tableName, String schema, String catalog) { Element join_mapping = parent.addElement("join"); join_mapping.addAttribute("table", tableName); if (!StringTools.isEmpty(schema)) { join_mapping.addAttribute("schema", schema); } if (!StringTools.isEmpty(catalog)) { join_mapping.addAttribute("catalog", catalog); } return join_mapping; } public static void addColumns(Element any_mapping, Iterator<Column> columns) { while (columns.hasNext()) { addColumn(any_mapping, columns.next()); } } /** * 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 any_mapping Parent element. * @param column Column descriptor. */ public static void addColumn(Element any_mapping, Column column) { addColumn(any_mapping, 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) { Iterator<Element> properties = element.elementIterator(); while (properties.hasNext()) { Element property = properties.next(); if ("column".equals(property.getName())) { 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) { Iterator<Element> properties = element.elementIterator(); while (properties.hasNext()) { Element property = properties.next(); if ("property".equals(property.getName())) { Attribute nameAttr = property.attribute("name"); if (nameAttr != null) { nameAttr.setText(prefix + nameAttr.getText()); } changeNamesInColumnElement(property, columnNameIterator); if (changeToKey) { property.setName("key-property"); } 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()) { 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<Column> columnIterator) { return new ColumnNameIterator() { public boolean hasNext() { return columnIterator.hasNext(); } public String next() { return columnIterator.next().getName(); } public void remove() { columnIterator.remove(); } }; } public static ColumnNameIterator getColumnNameIterator(final JoinColumn[] joinColumns) { return new ColumnNameIterator() { int counter = 0; public boolean hasNext() { return counter < joinColumns.length; } public String next() { return joinColumns[counter++].name(); } public void remove() { throw new UnsupportedOperationException(); } }; } }