Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » cfg » [javadoc | source]
    1   /*
    2    * Hibernate, Relational Persistence for Idiomatic Java
    3    *
    4    * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
    5    * indicated by the @author tags or express copyright attribution
    6    * statements applied by the authors.  All third-party contributions are
    7    * distributed under license by Red Hat Middleware LLC.
    8    *
    9    * This copyrighted material is made available to anyone wishing to use, modify,
   10    * copy, or redistribute it subject to the terms and conditions of the GNU
   11    * Lesser General Public License, as published by the Free Software Foundation.
   12    *
   13    * This program is distributed in the hope that it will be useful,
   14    * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   15    * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   16    * for more details.
   17    *
   18    * You should have received a copy of the GNU Lesser General Public License
   19    * along with this distribution; if not, write to:
   20    * Free Software Foundation, Inc.
   21    * 51 Franklin Street, Fifth Floor
   22    * Boston, MA  02110-1301  USA
   23    *
   24    */
   25   package org.hibernate.cfg;
   26   
   27   import java.io.Serializable;
   28   import java.util.Iterator;
   29   import java.util.List;
   30   import java.util.Map;
   31   import java.util.Properties;
   32   import java.util.HashMap;
   33   
   34   import org.slf4j.Logger;
   35   import org.slf4j.LoggerFactory;
   36   import org.hibernate.DuplicateMappingException;
   37   import org.hibernate.MappingException;
   38   import org.hibernate.engine.FilterDefinition;
   39   import org.hibernate.engine.NamedQueryDefinition;
   40   import org.hibernate.engine.NamedSQLQueryDefinition;
   41   import org.hibernate.engine.ResultSetMappingDefinition;
   42   import org.hibernate.mapping.Collection;
   43   import org.hibernate.mapping.DenormalizedTable;
   44   import org.hibernate.mapping.PersistentClass;
   45   import org.hibernate.mapping.Table;
   46   import org.hibernate.mapping.TypeDef;
   47   import org.hibernate.mapping.AuxiliaryDatabaseObject;
   48   import org.hibernate.mapping.Column;
   49   import org.hibernate.util.StringHelper;
   50   
   51   /**
   52    * A collection of mappings from classes and collections to
   53    * relational database tables. (Represents a single
   54    * <tt>&lt;hibernate-mapping&gt;</tt> element.)
   55    * @author Gavin King
   56    */
   57   public class Mappings implements Serializable {
   58   
   59   	private static final Logger log = LoggerFactory.getLogger(Mappings.class);
   60   
   61   	protected final Map classes;
   62   	protected final Map collections;
   63   	protected final Map tables;
   64   	protected final Map queries;
   65   	protected final Map sqlqueries;
   66   	protected final Map resultSetMappings;
   67   	protected final Map typeDefs;
   68   	protected final List secondPasses;
   69   	protected final Map imports;
   70   	protected String schemaName;
   71       protected String catalogName;
   72   	protected String defaultCascade;
   73   	protected String defaultPackage;
   74   	protected String defaultAccess;
   75   	protected boolean autoImport;
   76   	protected boolean defaultLazy;
   77   	protected final List propertyReferences;
   78   	protected final NamingStrategy namingStrategy;
   79   	protected final Map filterDefinitions;
   80   	protected final List auxiliaryDatabaseObjects;
   81   
   82   	protected final Map extendsQueue;
   83   //	private final List extendsQueue;
   84   
   85   	/**
   86   	 * binding table between the logical column name and the name out of the naming strategy
   87   	 * for each table.
   88   	 * According that when the column name is not set, the property name is considered as such
   89   	 * This means that while theorically possible through the naming strategy contract, it is
   90   	 * forbidden to have 2 real columns having the same logical name
   91   	 * <Table, ColumnNames >
   92   	 */
   93   	protected final Map columnNameBindingPerTable;
   94   	/**
   95   	 * binding between logical table name and physical one (ie after the naming strategy has been applied)
   96   	 * <String, TableDescription>
   97   	 */
   98   	protected final Map tableNameBinding;
   99   
  100   
  101   	Mappings(
  102   			final Map classes,
  103   			final Map collections,
  104   			final Map tables,
  105   			final Map queries,
  106   			final Map sqlqueries,
  107   			final Map sqlResultSetMappings,
  108   			final Map imports,
  109   			final List secondPasses,
  110   			final List propertyReferences,
  111   			final NamingStrategy namingStrategy,
  112   			final Map typeDefs,
  113   			final Map filterDefinitions,
  114   //			final List extendsQueue,
  115   			final Map extendsQueue,
  116   			final List auxiliaryDatabaseObjects,
  117   			final Map tableNamebinding,
  118   			final Map columnNameBindingPerTable
  119   			) {
  120   		this.classes = classes;
  121   		this.collections = collections;
  122   		this.queries = queries;
  123   		this.sqlqueries = sqlqueries;
  124   		this.resultSetMappings = sqlResultSetMappings;
  125   		this.tables = tables;
  126   		this.imports = imports;
  127   		this.secondPasses = secondPasses;
  128   		this.propertyReferences = propertyReferences;
  129   		this.namingStrategy = namingStrategy;
  130   		this.typeDefs = typeDefs;
  131   		this.filterDefinitions = filterDefinitions;
  132   		this.extendsQueue = extendsQueue;
  133   		this.auxiliaryDatabaseObjects = auxiliaryDatabaseObjects;
  134   		this.tableNameBinding = tableNamebinding;
  135   		this.columnNameBindingPerTable = columnNameBindingPerTable;
  136   	}
  137   
  138   	public void addClass(PersistentClass persistentClass) throws MappingException {
  139   		Object old = classes.put( persistentClass.getEntityName(), persistentClass );
  140   		if ( old!=null ) {
  141   			throw new DuplicateMappingException( "class/entity", persistentClass.getEntityName() );
  142   		}
  143   	}
  144   	public void addCollection(Collection collection) throws MappingException {
  145   		Object old = collections.put( collection.getRole(), collection );
  146   		if ( old!=null ) {
  147   			throw new DuplicateMappingException( "collection role", collection.getRole() );
  148   		}
  149   	}
  150   	public PersistentClass getClass(String className) {
  151   		return (PersistentClass) classes.get(className);
  152   	}
  153   	public Collection getCollection(String role) {
  154   		return (Collection) collections.get(role);
  155   	}
  156   
  157   	public void addImport(String className, String rename) throws MappingException {
  158   		String existing = (String) imports.put(rename, className);
  159   		if ( existing!=null ) {
  160   			if ( existing.equals(className) ) {
  161   				log.info( "duplicate import: " + className + "->" + rename );
  162   			}
  163   			else {
  164   				throw new DuplicateMappingException(
  165   						"duplicate import: " + rename + 
  166   						" refers to both " + className + 
  167   						" and " + existing + 
  168   						" (try using auto-import=\"false\")",
  169   						"import",
  170   						rename
  171   					);
  172   			}
  173   		}
  174   	}
  175   
  176   	public Table addTable(String schema, 
  177   			String catalog, 
  178   			String name,
  179   			String subselect,
  180   			boolean isAbstract
  181   	) {
  182           String key = subselect==null ?
  183   			Table.qualify(catalog, schema, name) :
  184   			subselect;
  185   		Table table = (Table) tables.get(key);
  186   
  187   		if (table == null) {
  188   			table = new Table();
  189   			table.setAbstract(isAbstract);
  190   			table.setName(name);
  191   			table.setSchema(schema);
  192   			table.setCatalog(catalog);
  193   			table.setSubselect(subselect);
  194   			tables.put(key, table);
  195   		}
  196   		else {
  197   			if (!isAbstract) table.setAbstract(false);
  198   		}
  199   
  200   		return table;
  201   	}
  202   
  203   	public Table addDenormalizedTable(
  204   			String schema, 
  205   			String catalog, 
  206   			String name,
  207   			boolean isAbstract, 
  208   			String subselect,
  209   			Table includedTable)
  210   	throws MappingException {
  211           String key = subselect==null ?
  212           		Table.qualify(catalog, schema, name) :
  213           		subselect;
  214   		if ( tables.containsKey(key) ) {
  215   			throw new DuplicateMappingException("table", name);
  216   		}
  217   		
  218   		Table table = new DenormalizedTable(includedTable);
  219   		table.setAbstract(isAbstract);
  220   		table.setName(name);
  221   		table.setSchema(schema);
  222   		table.setCatalog(catalog);
  223   		table.setSubselect(subselect);
  224   		tables.put(key, table);
  225   		return table;
  226   	}
  227   
  228   	public Table getTable(String schema, String catalog, String name) {
  229           String key = Table.qualify(catalog, schema, name);
  230   		return (Table) tables.get(key);
  231   	}
  232   
  233   	public String getSchemaName() {
  234   		return schemaName;
  235   	}
  236   
  237       public String getCatalogName() {
  238           return catalogName;
  239       }
  240   
  241   	public String getDefaultCascade() {
  242   		return defaultCascade;
  243   	}
  244   
  245   	/**
  246   	 * Sets the schemaName.
  247   	 * @param schemaName The schemaName to set
  248   	 */
  249   	public void setSchemaName(String schemaName) {
  250   		this.schemaName = schemaName;
  251   	}
  252   
  253       /**
  254        * Sets the catalogName.
  255        * @param catalogName The catalogName to set
  256        */
  257       public void setCatalogName(String catalogName) {
  258           this.catalogName = catalogName;
  259       }
  260   
  261   	/**
  262   	 * Sets the defaultCascade.
  263   	 * @param defaultCascade The defaultCascade to set
  264   	 */
  265   	public void setDefaultCascade(String defaultCascade) {
  266   		this.defaultCascade = defaultCascade;
  267   	}
  268   
  269   	/**
  270   	 * sets the default access strategy
  271   	 * @param defaultAccess the default access strategy.
  272   	 */
  273   	public void setDefaultAccess(String defaultAccess) {
  274   		this.defaultAccess = defaultAccess;
  275   	}
  276   
  277   	public String getDefaultAccess() {
  278   		return defaultAccess;
  279   	}
  280   
  281   	public void addQuery(String name, NamedQueryDefinition query) throws MappingException {
  282   		checkQueryExist(name);
  283   		queries.put( name.intern(), query );
  284   	}
  285   
  286   	public void addSQLQuery(String name, NamedSQLQueryDefinition query) throws MappingException {
  287   		checkQueryExist(name);
  288   		sqlqueries.put( name.intern(), query );
  289   	}
  290   
  291   	private void checkQueryExist(String name) throws MappingException {
  292   		if ( sqlqueries.containsKey(name) || queries.containsKey(name) ) {
  293   			throw new DuplicateMappingException("query", name);
  294   		}
  295   	}
  296   
  297   	public void addResultSetMapping(ResultSetMappingDefinition sqlResultSetMapping) {
  298   		final String name = sqlResultSetMapping.getName();
  299   		if ( resultSetMappings.containsKey(name) ) {
  300   			throw new DuplicateMappingException("resultSet",  name);
  301   		}
  302   		resultSetMappings.put(name, sqlResultSetMapping);
  303   	}
  304   
  305   	public ResultSetMappingDefinition getResultSetMapping(String name) {
  306   		return (ResultSetMappingDefinition) resultSetMappings.get(name);
  307   	}
  308   
  309   
  310   	public NamedQueryDefinition getQuery(String name) {
  311   		return (NamedQueryDefinition) queries.get(name);
  312   	}
  313   
  314   	public void addSecondPass(SecondPass sp) {
  315   		addSecondPass(sp, false);
  316   	}
  317       
  318       public void addSecondPass(SecondPass sp, boolean onTopOfTheQueue) {
  319   		if (onTopOfTheQueue) {
  320   			secondPasses.add(0, sp);
  321   		}
  322   		else {
  323   			secondPasses.add(sp);
  324   		}
  325   	}
  326   
  327   	/**
  328   	 * Returns the autoImport.
  329   	 * @return boolean
  330   	 */
  331   	public boolean isAutoImport() {
  332   		return autoImport;
  333   	}
  334   
  335   	/**
  336   	 * Sets the autoImport.
  337   	 * @param autoImport The autoImport to set
  338   	 */
  339   	public void setAutoImport(boolean autoImport) {
  340   		this.autoImport = autoImport;
  341   	}
  342   
  343   	void addUniquePropertyReference(String referencedClass, String propertyName) {
  344   		PropertyReference upr = new PropertyReference();
  345   		upr.referencedClass = referencedClass;
  346   		upr.propertyName = propertyName;
  347   		upr.unique = true;
  348   		propertyReferences.add(upr);
  349   	}
  350   
  351   	void addPropertyReference(String referencedClass, String propertyName) {
  352   		PropertyReference upr = new PropertyReference();
  353   		upr.referencedClass = referencedClass;
  354   		upr.propertyName = propertyName;
  355   		propertyReferences.add(upr);
  356   	}
  357   
  358   	private String buildTableNameKey(String schema, String catalog, String finalName) {
  359   		StringBuffer keyBuilder = new StringBuffer();
  360   		if (schema != null) keyBuilder.append( schema );
  361   		keyBuilder.append( ".");
  362   		if (catalog != null) keyBuilder.append( catalog );
  363   		keyBuilder.append( ".");
  364   		keyBuilder.append( finalName );
  365   		return keyBuilder.toString();
  366   	}
  367   
  368   	static final class PropertyReference implements Serializable {
  369   		String referencedClass;
  370   		String propertyName;
  371   		boolean unique;
  372   	}
  373   
  374   	/**
  375   	 * @return Returns the defaultPackage.
  376   	 */
  377   	public String getDefaultPackage() {
  378   		return defaultPackage;
  379   	}
  380   
  381   	/**
  382   	 * @param defaultPackage The defaultPackage to set.
  383   	 */
  384   	public void setDefaultPackage(String defaultPackage) {
  385   		this.defaultPackage = defaultPackage;
  386   	}
  387   
  388   	public NamingStrategy getNamingStrategy() {
  389   		return namingStrategy;
  390   	}
  391   
  392   	public void addTypeDef(String typeName, String typeClass, Properties paramMap) {
  393   		TypeDef def = new TypeDef(typeClass, paramMap);
  394   		typeDefs.put(typeName, def);
  395   		log.debug("Added " + typeName + " with class " + typeClass);
  396   	}
  397   
  398   	public TypeDef getTypeDef(String typeName) {
  399   		return (TypeDef) typeDefs.get(typeName);
  400   	}
  401   
  402       public Iterator iterateCollections() {
  403           return collections.values().iterator();
  404       }
  405       
  406       public Iterator iterateTables() {
  407       	return tables.values().iterator();
  408       }
  409   
  410   	public Map getFilterDefinitions() {
  411   		return filterDefinitions;
  412   	}
  413   
  414   	public void addFilterDefinition(FilterDefinition definition) {
  415   		filterDefinitions.put( definition.getFilterName(), definition );
  416   	}
  417   	
  418   	public FilterDefinition getFilterDefinition(String name) {
  419   		return (FilterDefinition) filterDefinitions.get(name);
  420   	}
  421   	
  422   	public boolean isDefaultLazy() {
  423   		return defaultLazy;
  424   	}
  425   	public void setDefaultLazy(boolean defaultLazy) {
  426   		this.defaultLazy = defaultLazy;
  427   	}
  428   
  429       public void addToExtendsQueue(ExtendsQueueEntry entry) {
  430   	    extendsQueue.put( entry, null );
  431       }
  432   
  433   	public PersistentClass locatePersistentClassByEntityName(String entityName) {
  434   		PersistentClass persistentClass = ( PersistentClass ) classes.get( entityName );
  435   		if ( persistentClass == null ) {
  436   			String actualEntityName = ( String ) imports.get( entityName );
  437   			if ( StringHelper.isNotEmpty( actualEntityName ) ) {
  438   				persistentClass = ( PersistentClass ) classes.get( actualEntityName );
  439   			}
  440   		}
  441   		return persistentClass;
  442   	}
  443   
  444   	public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject) {
  445   		auxiliaryDatabaseObjects.add( auxiliaryDatabaseObject );
  446   	}
  447   
  448   	public void addTableBinding(
  449   			String schema, String catalog, String logicalName, String physicalName, Table denormalizedSuperTable
  450   	) {
  451   		String key = buildTableNameKey( schema, catalog, physicalName );
  452   		TableDescription tableDescription = new TableDescription(
  453   				logicalName, denormalizedSuperTable
  454   		);
  455   		TableDescription oldDescriptor = (TableDescription) tableNameBinding.put( key, tableDescription );
  456   		if ( oldDescriptor != null && ! oldDescriptor.logicalName.equals( logicalName ) ) {
  457   			//TODO possibly relax that
  458   			throw new MappingException("Same physical table name reference several logical table names: "
  459   					+ physicalName + " => " + "'" + oldDescriptor.logicalName + "' and '" + logicalName + "'");
  460   		}
  461   	}
  462   
  463   	public void addColumnBinding(String logicalName, Column finalColumn, Table table) {
  464   		ColumnNames binding = (ColumnNames) columnNameBindingPerTable.get(table);
  465   		if (binding == null) {
  466   			binding = new ColumnNames();
  467   			columnNameBindingPerTable.put(table, binding);
  468   		}
  469   		String oldFinalName = (String) binding.logicalToPhysical.put(
  470   				logicalName.toLowerCase(),
  471   				finalColumn.getQuotedName()
  472   		);
  473   		if ( oldFinalName != null &&
  474   				! ( finalColumn.isQuoted() ?
  475   						oldFinalName.equals( finalColumn.getQuotedName() ) :
  476   						oldFinalName.equalsIgnoreCase( finalColumn.getQuotedName() ) ) ) {
  477   			//TODO possibly relax that
  478   			throw new MappingException("Same logical column name referenced by different physical ones: "
  479   					+ table.getName() + "." + logicalName + " => '" + oldFinalName + "' and '" + finalColumn.getQuotedName() + "'" );
  480   		}
  481   		String oldLogicalName = (String) binding.physicalToLogical.put(
  482   				finalColumn.getQuotedName(),
  483   				logicalName
  484   		);
  485   		if ( oldLogicalName != null && ! oldLogicalName.equals( logicalName ) ) {
  486   			//TODO possibly relax that
  487   			throw new MappingException("Same physical column represented by different logical column names: "
  488   					+ table.getName() + "." + finalColumn.getQuotedName() + " => '" + oldLogicalName + "' and '" + logicalName + "'");
  489   		}
  490   	}
  491   
  492   	private String getLogicalTableName(String schema, String catalog, String physicalName) {
  493   		String key = buildTableNameKey( schema, catalog, physicalName );
  494   		TableDescription descriptor = (TableDescription) tableNameBinding.get( key );
  495   		if (descriptor == null) {
  496   			throw new MappingException( "Unable to find physical table: " + physicalName);
  497   		}
  498   		return descriptor.logicalName;
  499   	}
  500   
  501   	public String getPhysicalColumnName(String logicalName, Table table) {
  502   		logicalName = logicalName.toLowerCase();
  503   		String finalName = null;
  504   		Table currentTable = table;
  505   		do {
  506   			ColumnNames binding = (ColumnNames) columnNameBindingPerTable.get(currentTable);
  507   			if (binding != null) {
  508   				finalName = (String) binding.logicalToPhysical.get( logicalName );
  509   			}
  510   			String key = buildTableNameKey( currentTable.getSchema(), currentTable.getCatalog(), currentTable.getName() );
  511   			TableDescription description = (TableDescription) tableNameBinding.get(key);
  512   			if (description != null) currentTable = description.denormalizedSupertable;
  513   		}
  514   		while (finalName == null && currentTable != null);
  515   		if (finalName == null) {
  516   			throw new MappingException( "Unable to find column with logical name "
  517   					+ logicalName + " in table " + table.getName() );
  518   		}
  519   		return finalName;
  520   	}
  521   
  522   	public String getLogicalColumnName(String physicalName, Table table) {
  523   		String logical = null;
  524   		Table currentTable = table;
  525   		TableDescription description = null;
  526   		do {
  527   			ColumnNames binding = (ColumnNames) columnNameBindingPerTable.get(currentTable);
  528   			if (binding != null) {
  529   				logical = (String) binding.physicalToLogical.get( physicalName );
  530   			}
  531   			String key = buildTableNameKey( currentTable.getSchema(), currentTable.getCatalog(), currentTable.getName() );
  532   			description = (TableDescription) tableNameBinding.get(key);
  533   			if (description != null) currentTable = description.denormalizedSupertable;
  534   		}
  535   		while (logical == null && currentTable != null && description != null);
  536   		if (logical == null) {
  537   			throw new MappingException( "Unable to find logical column name from physical name "
  538   					+ physicalName + " in table " + table.getName() );
  539   		}
  540   		return logical;
  541   	}
  542   
  543   	public String getLogicalTableName(Table table) {
  544   		return getLogicalTableName( table.getQuotedSchema(), table.getCatalog(), table.getQuotedName() );
  545   	}
  546   
  547   	static public class ColumnNames implements Serializable {
  548   		//<String, String>
  549   		public Map logicalToPhysical = new HashMap();
  550   		//<String, String>
  551   		public Map physicalToLogical = new HashMap();
  552   		public ColumnNames() {
  553   		}
  554   	}
  555   
  556   	static public class TableDescription implements Serializable {
  557   		public TableDescription(String logicalName, Table denormalizedSupertable) {
  558   			this.logicalName = logicalName;
  559   			this.denormalizedSupertable = denormalizedSupertable;
  560   		}
  561   
  562   		public String logicalName;
  563   		public Table denormalizedSupertable;
  564   	}
  565   }

Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » cfg » [javadoc | source]