org.hibernate.envers.configuration.internal.metadata.MetadataTools Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-envers-jakarta Show documentation
Show all versions of hibernate-envers-jakarta Show documentation
Hibernate's entity version (audit/history) support Jakarta edition
/*
* 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 .
*/
package org.hibernate.envers.configuration.internal.metadata;
import java.util.Iterator;
import jakarta.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 Element addModifiedFlagPropertyWithColumn(
Element parent,
String propertyName,
String suffix,
String modifiedFlagName,
String columnName) {
final Element property = addProperty(
parent,
(modifiedFlagName != null) ? modifiedFlagName : getModifiedFlagPropertyName( propertyName, suffix ),
"boolean",
true,
false,
false
);
addColumn( property, columnName, null, null, null, null, null, null );
return property;
}
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 column
element. Method assumes that the value of name
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} element with the following attributes (unless empty):
*
* - name
>
* - length
* - scale
* - precision
* - sql-type
* - read
* - write
*
*
*
* @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 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 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() );
// HHH-11463 when cloning a many-to-one to be a key-many-to-one, the FK attribute
// should be explicitly set to 'none' or added to be 'none' to avoid issues with
// making references to the main schema.
if ( property.getName().equals( "key-many-to-one" ) ) {
final Attribute foreignKey = property.attribute( "foreign-key" );
if ( foreignKey == null ) {
property.addAttribute( "foreign-key", "none" );
}
else {
foreignKey.setValue( "none" );
}
}
}
if ( "property".equals( property.getName() ) ) {
final Attribute insert = property.attribute( "insert" );
insert.setText( Boolean.toString( insertable ) );
}
}
}
}
/**
* Adds formula
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 column
or formula
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 abstract static class ColumnNameIterator implements Iterator {
}
public static ColumnNameIterator getColumnNameIterator(final Iterator 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();
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy