Java tutorial
/* * Hibernate, Relational Persistence for Idiomatic Java * * Copyright (c) 2010, Red Hat Inc. 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 Inc. * * 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.metamodel.source.hbm; import org.dom4j.Attribute; import org.dom4j.Element; import org.hibernate.InvalidMappingException; import org.hibernate.MappingException; import org.hibernate.mapping.PropertyGeneration; import org.hibernate.mapping.RootClass; import org.hibernate.metamodel.binding.Caching; import org.hibernate.metamodel.binding.EntityBinding; import org.hibernate.metamodel.binding.SimpleAttributeBinding; import org.hibernate.metamodel.relational.Column; import org.hibernate.metamodel.relational.Identifier; import org.hibernate.metamodel.relational.InLineView; import org.hibernate.metamodel.relational.Schema; import org.hibernate.metamodel.relational.Value; /** * TODO : javadoc * * @author Steve Ebersole */ class RootEntityBinder extends AbstractEntityBinder { RootEntityBinder(HibernateMappingBinder hibernateMappingBinder, Element entityElement) { super(hibernateMappingBinder, entityElement); } public void process(Element entityElement) { String entityName = getHibernateMappingBinder().extractEntityName(entityElement); if (entityName == null) { throw new MappingException("Unable to determine entity name"); } EntityBinding entityBinding = new EntityBinding(); basicEntityBinding(entityElement, entityBinding, null); basicTableBinding(entityElement, entityBinding); Attribute mutableAttribute = entityElement.attribute("mutable"); if (mutableAttribute != null) { entityBinding.setMutable(Boolean.valueOf(mutableAttribute.getValue())); } Attribute whereAttribute = entityElement.attribute("where"); if (whereAttribute != null) { entityBinding.setWhereFilter(whereAttribute.getValue()); } Attribute polymorphismAttribute = entityElement.attribute("polymorphism"); if (polymorphismAttribute != null) { entityBinding.setExplicitPolymorphism("explicit".equals(polymorphismAttribute.getValue())); } Attribute rowidAttribute = entityElement.attribute("rowid"); if (rowidAttribute != null) { entityBinding.setRowId(rowidAttribute.getValue()); } bindIdentifier(entityElement, entityBinding); bindDiscriminator(entityElement, entityBinding); bindVersion(entityElement, entityBinding); bindCaching(entityElement, entityBinding); // called createClassProperties in HBMBinder... buildAttributeBindings(entityElement, entityBinding); getHibernateXmlBinder().getMetadata().addEntity(entityBinding); } private void basicTableBinding(Element entityElement, EntityBinding entityBinding) { final Schema schema = getHibernateXmlBinder().getMetadata().getDatabase().getSchema(getSchemaName()); final String subSelect = HbmHelper.getSubselect(entityElement); if (subSelect != null) { final String logicalName = entityBinding.getEntity().getName(); InLineView inLineView = schema.getInLineView(logicalName); if (inLineView == null) { inLineView = schema.createInLineView(logicalName, subSelect); } entityBinding.setBaseTable(inLineView); } else { final Identifier tableName = Identifier .toIdentifier(getClassTableName(entityElement, entityBinding, null)); org.hibernate.metamodel.relational.Table table = schema.getTable(tableName); if (table == null) { table = schema.createTable(tableName); } entityBinding.setBaseTable(table); Element comment = entityElement.element("comment"); if (comment != null) { table.addComment(comment.getTextTrim()); } Attribute checkAttribute = entityElement.attribute("check"); if (checkAttribute != null) { table.addCheckConstraint(checkAttribute.getValue()); } } } private void bindIdentifier(Element entityElement, EntityBinding entityBinding) { final Element idElement = entityElement.element("id"); if (idElement != null) { bindSimpleId(idElement, entityBinding); return; } final Element compositeIdElement = entityElement.element("composite-id"); if (compositeIdElement != null) { bindCompositeId(compositeIdElement, entityBinding); } throw new InvalidMappingException( "Entity [" + entityBinding.getEntity().getName() + "] did not contain identifier mapping", getHibernateMappingBinder().getXmlDocument()); } private void bindSimpleId(Element identifierElement, EntityBinding entityBinding) { // Handle the domain portion of the binding... final String explicitName = identifierElement.attributeValue("name"); final String attributeName = explicitName == null ? RootClass.DEFAULT_IDENTIFIER_COLUMN_NAME : explicitName; entityBinding.getEntity().getOrCreateSingularAttribute(attributeName); SimpleAttributeBinding idBinding = entityBinding.makeSimplePrimaryKeyAttributeBinding(attributeName); bindSimpleAttribute(identifierElement, idBinding, entityBinding, attributeName); if (!Column.class.isInstance(idBinding.getValue())) { // this should never ever happen.. throw new MappingException("Unanticipated situation"); } entityBinding.getBaseTable().getPrimaryKey().addColumn(Column.class.cast(idBinding.getValue())); // if ( propertyName == null || entity.getPojoRepresentation() == null ) { // bindSimpleValue( idNode, id, false, RootClass.DEFAULT_IDENTIFIER_COLUMN_NAME, mappings ); // if ( !id.isTypeSpecified() ) { // throw new MappingException( "must specify an identifier type: " + entity.getEntityName() // ); // } // } // else { // bindSimpleValue( idNode, id, false, propertyName, mappings ); // PojoRepresentation pojo = entity.getPojoRepresentation(); // id.setTypeUsingReflection( pojo.getClassName(), propertyName ); // // Property prop = new Property(); // prop.setValue( id ); // bindProperty( idNode, prop, mappings, inheritedMetas ); // entity.setIdentifierProperty( prop ); // } // if ( propertyName == null ) { // bindSimpleValue( idNode, id, false, RootClass.DEFAULT_IDENTIFIER_COLUMN_NAME, mappings ); // } // else { // bindSimpleValue( idNode, id, false, propertyName, mappings ); // } // // if ( propertyName == null || !entity.hasPojoRepresentation() ) { // if ( !id.isTypeSpecified() ) { // throw new MappingException( "must specify an identifier type: " // + entity.getEntityName() ); // } // } // else { // id.setTypeUsingReflection( entity.getClassName(), propertyName ); // } // // if ( propertyName != null ) { // Property prop = new Property(); // prop.setValue( id ); // bindProperty( idNode, prop, mappings, inheritedMetas ); // entity.setIdentifierProperty( prop ); // } // TODO: /* * if ( id.getHibernateType().getReturnedClass().isArray() ) throw new MappingException( * "illegal use of an array as an identifier (arrays don't reimplement equals)" ); */ // makeIdentifier( idNode, id, mappings ); } private static void bindCompositeId(Element identifierElement, EntityBinding entityBinding) { final String explicitName = identifierElement.attributeValue("name"); // String propertyName = idNode.attributeValue( "name" ); // Component id = new Component( mappings, entity ); // entity.setIdentifier( id ); // bindCompositeId( idNode, id, entity, propertyName, mappings, inheritedMetas ); // if ( propertyName == null ) { // entity.setEmbeddedIdentifier( id.isEmbedded() ); // if ( id.isEmbedded() ) { // // todo : what is the implication of this? // id.setDynamic( !entity.hasPojoRepresentation() ); // /* // * Property prop = new Property(); prop.setName("id"); // * prop.setPropertyAccessorName("embedded"); prop.setValue(id); // * entity.setIdentifierProperty(prop); // */ // } // } // else { // Property prop = new Property(); // prop.setValue( id ); // bindProperty( idNode, prop, mappings, inheritedMetas ); // entity.setIdentifierProperty( prop ); // } // // makeIdentifier( idNode, id, mappings ); } private void bindDiscriminator(Element entityElement, EntityBinding entityBinding) { Element discriminatorElement = entityElement.element("discriminator"); if (discriminatorElement == null) { return; } final String explicitName = discriminatorElement.attributeValue("name"); final String attributeName = explicitName == null ? RootClass.DEFAULT_DISCRIMINATOR_COLUMN_NAME : explicitName; entityBinding.getEntity().getOrCreateSingularAttribute(attributeName); SimpleAttributeBinding discriminatorBinding = entityBinding.makeEntityDiscriminatorBinding(attributeName); // Handle the relational portion of the binding... bindSimpleAttribute(discriminatorElement, discriminatorBinding, entityBinding, attributeName); if (discriminatorBinding.getHibernateTypeDescriptor().getTypeName() == null) { discriminatorBinding.getHibernateTypeDescriptor().setTypeName("string"); } if ("true".equals(discriminatorElement.attributeValue("force"))) { entityBinding.getEntityDiscriminator().setForced(true); } if ("false".equals(discriminatorElement.attributeValue("insert"))) { entityBinding.getEntityDiscriminator().setInserted(false); } } private void bindVersion(Element entityElement, EntityBinding entityBinding) { Element versioningElement = entityElement.element("version"); if (versioningElement == null) { versioningElement = entityElement.element("timestamp"); } if (versioningElement == null) { return; } boolean isVersion = "version".equals(versioningElement.getName()); final String explicitName = versioningElement.attributeValue("name"); if (explicitName == null) { throw new MappingException("Mising property name for version/timestamp mapping [" + entityBinding.getEntity().getName() + "]"); } entityBinding.getEntity().getOrCreateSingularAttribute(explicitName); SimpleAttributeBinding versionBinding = entityBinding.makeVersionBinding(explicitName); bindSimpleAttribute(versioningElement, versionBinding, entityBinding, explicitName); if (versionBinding.getHibernateTypeDescriptor().getTypeName() == null) { if (isVersion) { versionBinding.getHibernateTypeDescriptor().setTypeName("integer"); } else { final String tsSource = versioningElement.attributeValue("source"); if ("db".equals(tsSource)) { versionBinding.getHibernateTypeDescriptor().setTypeName("dbtimestamp"); } else { versionBinding.getHibernateTypeDescriptor().setTypeName("timestamp"); } } } // for version properties marked as being generated, make sure they are "always" // generated; aka, "insert" is invalid; this is dis-allowed by the DTD, // but just to make sure... if (versionBinding.getGeneration() == PropertyGeneration.INSERT) { throw new MappingException("'generated' attribute cannot be 'insert' for versioning property"); } } private void bindCaching(Element entityElement, EntityBinding entityBinding) { final Element cacheElement = entityElement.element("cache"); if (cacheElement == null) { return; } final String explicitRegion = cacheElement.attributeValue("region"); final String region = explicitRegion != null ? explicitRegion : entityBinding.getEntity().getName(); final String strategy = cacheElement.attributeValue("usage"); final boolean cacheLazyProps = !"non-lazy".equals(cacheElement.attributeValue("include")); entityBinding.setCaching(new Caching(region, strategy, cacheLazyProps)); } }