[Schmitzm-commits] r2278 - in trunk/schmitzm-hibernate/src/main: . java/de/schmitzm/db/hibernate java/de/schmitzm/db/hibernate/types resources resources/de resources/de/schmitzm resources/de/schmitzm/db resources/de/schmitzm/db/hibernate resources/de/schmitzm/db/hibernate/resource resources/de/schmitzm/db/hibernate/resource/locales

scm-commit at wald.intevation.org scm-commit at wald.intevation.org
Sun Mar 24 12:15:47 CET 2013


Author: mojays
Date: 2013-03-24 12:15:47 +0100 (Sun, 24 Mar 2013)
New Revision: 2278

Added:
   trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/DBUtil.java
   trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/HibernateApplication.java
   trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/HibernateSessionFactory.java
   trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/types/BasicType.java
   trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/types/BasicTypeInterface.java
   trunk/schmitzm-hibernate/src/main/resources/
   trunk/schmitzm-hibernate/src/main/resources/de/
   trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/
   trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/db/
   trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/db/hibernate/
   trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/db/hibernate/resource/
   trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/db/hibernate/resource/locales/
   trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/db/hibernate/resource/locales/HibernateResourceBundle.properties
   trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/db/hibernate/resource/locales/HibernateResourceBundle_de.properties
Log:
schmitzm-hibernate: Generic HibernateSessionFactory and HibernateApplication, generic BasicType for enums

Added: trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/DBUtil.java
===================================================================
--- trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/DBUtil.java	                        (rev 0)
+++ trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/DBUtil.java	2013-03-24 11:15:47 UTC (rev 2278)
@@ -0,0 +1,358 @@
+package de.schmitzm.db.hibernate;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.log4j.Logger;
+import org.hibernate.Criteria;
+import org.hibernate.Session;
+import org.hibernate.criterion.Criterion;
+import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Restrictions;
+
+import de.schmitzm.db.hibernate.types.BasicType;
+import de.schmitzm.db.hibernate.types.BasicTypeInterface;
+import de.schmitzm.db.hibernate.types.UniqueIDType;
+import de.schmitzm.lang.LangUtil;
+import de.schmitzm.lang.ResourceProvider;
+import de.schmitzm.swing.SwingUtil;
+
+/**
+ * Utility methods for hibernate.
+ * 
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public class DBUtil {
+	private static Logger LOGGER = LangUtil.createLogger(DBUtil.class);
+
+    /**
+     * {@link ResourceProvider} for the localization in the package
+     * {@code de.schmitzm.db.hibernate}.
+     */
+    public static ResourceProvider RESOURCE = ResourceProvider.newInstance(
+            LangUtil.extendPackagePath(DBUtil.class,
+                    "resource.locales.HibernateResourceBundle"), Locale.ENGLISH);
+
+	/**
+	 * Can hold a global {@link Session} used for updates. Should never
+	 * be closed!
+	 */
+	protected static Session GLOBAL_SESSION = null;
+	
+    /**
+     * Returns the global {@link Session} which is used for internal/automatic
+     * database update, e.g. in {@link #getOrCreateBasicType(Class, String)}
+     * @param checkNull if {@code true} an exception is thrown if {@link #GLOBAL_SESSION}
+     *                  is not set or closed.
+     */
+	public static Session getGlobalSession(boolean checkNull) {
+	  if ( checkNull ) {
+	    if ( GLOBAL_SESSION == null )
+	      throw new UnsupportedOperationException("DBUtil.GLOBAL_SESSION is not set.");
+        if ( !GLOBAL_SESSION.isOpen() )
+          throw new UnsupportedOperationException("DBUtil.GLOBAL_SESSION is not open.");
+	    if ( !GLOBAL_SESSION.isConnected() )
+	      throw new UnsupportedOperationException("DBUtil.GLOBAL_SESSION is not connected.");
+	  }
+	  return GLOBAL_SESSION;
+	}
+	
+	/**
+	 * Sets the global {@link Session} which is used for internal/automatic
+	 * database update, e.g. in {@link #getOrCreateBasicType(Class, String)}
+	 */
+    public static void setGlobalSession(Session session) {
+      GLOBAL_SESSION = session;
+    }
+
+    /**
+	 * Checks whether two objects represent the same record. The ID is 
+	 * used for compare.
+	 * 
+	 * @return {@code false}, if {@code o1 == null} and {@code o2 == null}
+	 */
+	public static boolean equalsIdBased(UniqueIDType o1, UniqueIDType o2) {
+		if (o1 == null && o2 == null)
+			return false;
+		if (o1 == o2)
+			return true;
+		if (!(o1.getClass().equals(o2.getClass())))
+			return false;
+
+		// if bothe items are stored in DB, check the ID
+		if (o1.getId() != null && o2.getId() != null)
+			return o1.getId().equals(o2.getId());
+
+		// otherwise we expect the objects are unequal
+		return false;
+	}
+
+	/**
+	 * Returns {@code o.getID().hashCode()} if the object is already persistent.
+	 * @return {@link System#identityHashCode(Object)} for not-persistent objects
+	 */
+	public static int hashCodeIdBased(UniqueIDType o) {
+		if (o == null)
+			throw new UnsupportedOperationException("DBUtil.hashCodeIdBased(.) can not be applied to NULL.");
+		if (o.getId() != null)
+			return o.getId().hashCode();
+		return System.identityHashCode(o);
+	}
+
+	/**
+	 * Returns the description of a {@link BasicType}.
+	 * @return {@code null} if the given instance is {@code null}
+	 */
+	public static String getBasicTypeDescription(BasicType instance) {
+	  if ( instance == null )
+	    return null;
+	  return instance.getDescription(); 
+	}
+
+	/**
+	 * Creates a {@link BasicTypeInterface} instance (only object, NO persistence
+     * in database!). Expects that the given {@link BasicTypeInterface}
+	 * sub-class has a parameter less constructor!
+     * @param basicType basic type to create the instance for
+	 */
+	public static <E extends BasicTypeInterface> E createBasicTypeInstance(Class<E> basicType) {
+		try {
+			E basicTypeInstance = basicType.newInstance();
+			return basicTypeInstance;
+		} catch (Exception err) {
+			LOGGER.error(err.getMessage(), err);
+			return null;
+		}
+	}
+
+	/**
+     * Creates a {@link BasicTypeInterface} instance (only object, NO persistence
+     * in database!). Expects that the given {@link BasicType} sub-class has
+     * a parameter less constructor!
+     * @param basicType basic type to create the instance for
+	 * @param desc description for the {@link BasicTypeInterface} instance
+	 */
+	public static <E extends BasicTypeInterface> E createBasicType(Class<E> basicType, String desc) {
+		E instance = createBasicTypeInstance(basicType);
+		instance.setDescription(desc);
+		return instance;
+	}
+
+    /**
+     * Returns a {@link BasicTypeInterface} instance for the given description
+     * or creates it if it does not exist. The {@linkplain #getGlobalSession(boolean) global session}
+     * is used for possible database updates.
+     * @param basicType basic type to determine the instance for
+     * @param desc description for the {@link BasicTypeInterface} instance
+     * @see #getGlobalSession(boolean)
+     */
+    public static <E extends BasicTypeInterface> E getOrCreateBasicType(Class<E> basicType, String desc) {
+      return getOrCreateBasicType(basicType, desc, true);
+    }
+    
+    /**
+     * Returns a {@link BasicTypeInterface} instance for the given description
+     * or creates it if it does not exist. The {@linkplain #getGlobalSession(boolean) global session}
+     * is used for possible database updates.
+     * @param basicType basic type to determine the instance for
+     * @param desc description for the {@link BasicTypeInterface} instance
+     * @param saveOrUpdate
+     *            if {@code false}, no {@code Session.saveOrUpdate(.)} is performed (on possible
+     *            creation). This has to be done explicitly later, e.g. in case when
+     *            additional {@link BasicTypeInterface} attributes has to be
+     *            filled before insert.
+     * @see #getGlobalSession(boolean)
+     */
+    public static <E extends BasicTypeInterface> E getOrCreateBasicType(Class<E> basicType, String desc, boolean saveOrUpdate) {
+        return getOrCreateBasicType(null, basicType, desc, saveOrUpdate);
+    }
+
+    /**
+     * Returns a {@link BasicTypeInterface} instance for the given description
+     * or creates it if it does not exist.
+     * @param basicType basic type to determine the instance for
+     * @param session session to use for update (if {@code null} the
+     *                {@linkplain #getGlobalSession(boolean) global session} is used)
+     * @param desc description for the {@link BasicTypeInterface} instance
+     * @param saveOrUpdate
+     *            if {@code false}, no {@code Session.saveOrUpdate(.)} is performed (on possible
+     *            creation). This has to be done explicitly later, e.g. in case when
+     *            additional {@link BasicTypeInterface} attributes has to be
+     *            filled before insert.
+     * @see #getGlobalSession(boolean)
+	 */
+	public static <E extends BasicTypeInterface> E getOrCreateBasicType(Session session, Class<E> basicType, String desc, boolean saveOrUpdate) {
+		if (org.apache.commons.lang.StringUtils.trimToNull(desc) == null)
+			return null;
+		if ( session == null )
+		  session = getGlobalSession(true);
+		E instance = determineBasicType(basicType, desc);
+		if (instance == null) {
+			instance = createBasicTypeInstance(basicType);
+			instance.setDescription(desc);
+			if ( saveOrUpdate )
+			  session.saveOrUpdate(instance);
+		}
+		return instance;
+	}
+
+    /**
+     * Checks whether a {@link BasicTypeInterface} instance is already persistent.
+     * If not it will be stored in database.
+     * @param session session to use for update (if {@code null} the
+     *                {@linkplain #getGlobalSession(boolean) global session} is used)
+     * @param basicType basic type to check
+     * @return always {@code basicType}
+     */
+    public static <E extends BasicTypeInterface> E getOrCreateBasicType(Session session, E basicType) {
+      if ( basicType == null )
+        return null;
+      // if instance already has an id, it is already persistent
+      if ( basicType.getId() != null )
+        return basicType;
+      
+      if ( session == null )
+        session = getGlobalSession(true);
+      session.persist(basicType);
+      
+      return basicType;
+    }
+
+
+	/**
+	 * Retrieves the first instances of a {@link BasicType} from database.
+	 * The {@linkplain #getGlobalSession(boolean) global session} is used 
+	 * for database access.
+     * @param basicType basic type to determine an instance for
+	 * @return {@code null} if the table is empty
+	 */
+	public static <E extends BasicTypeInterface> E determineDefaultBasicType(Class<E> basicType) {
+		List<E> types = determineAllBasicTypes(basicType);
+		if (types.isEmpty())
+			return null;
+		return types.get(0);
+	}
+
+	/**
+	 * Retrieves all instances of a type from database.
+     * @param session session to use for database access (if {@code null} the
+     *                {@linkplain #getGlobalSession(boolean) global session} is used)
+     * @param type type to determine the instances for
+	 */
+	public static <E extends Object> List<E> determineAllRecords(Session session, Class<E> type) {
+		return determineAllRecords(session,type, null, null);
+	}
+
+	/**
+	 * Retrieves all instances of a type from database, which satisfies a filter.
+     * @param session session to use for database access (if {@code null} the
+     *                {@linkplain #getGlobalSession(boolean) global session} is used)
+     * @param type type to determine the instances for
+     * @param filter filter to apply
+	 */
+	public static <E extends Object> List<E> determineAllRecords(Session session, Class<E> type, Criterion filter, Order order) {
+	    // if no session is specified, use the global session 
+	    if ( session == null )
+	      session = getGlobalSession(true);
+
+	    // Query muss in einer Transaktion erfolgen, damit die
+		// korrekten Daten ermittelt werden.
+		// -> Wenn keine Transaktion offen ist, eine neue beginnen
+		Criteria query = session.createCriteria(type);
+		if (filter != null)
+			query.add(filter);
+		if (order != null)
+			query.addOrder(order);
+
+		return (List<E>) query.list();
+	}
+
+    /**
+     * Retrieves all instances of a {@link BasicType} from database. The
+     * {@linkplain #getGlobalSession(boolean) global session} is used for database access.
+     * @param basicType type to determine the instances for
+     */
+    public static <E extends BasicTypeInterface> List<E> determineAllBasicTypes(Class<E> basicType) {
+        List<E> list = determineAllRecords(null, basicType, null, Order.asc(BasicType.DESCRIPTION_COL));
+        return list;
+    }
+
+    /**
+	 * Retrieves all instances of a {@link BasicType} from database.
+     * @param session session to use for database access (if {@code null} the
+     *                {@linkplain #getGlobalSession(boolean) global session} is used)
+     * @param basicType type to determine the instances for
+	 */
+	public static <E extends BasicTypeInterface> List<E> determineAllBasicTypes(Session session, Class<E> basicType) {
+		return determineAllRecords(session, basicType, null, Order.asc(BasicType.DESCRIPTION_COL));
+	}
+
+    /**
+     * Retrieves all instances of a {@link BasicType} from database.
+     * @param session session to use for database access (if {@code null} the
+     *                {@linkplain #getGlobalSession(boolean) global session} is used)
+     * @param basicType type to determine the instances for
+     * @param filter filter to apply
+     */
+    public static <E extends BasicTypeInterface> List<E> determineAllBasicTypes(Session session, Class<E> basicType, Criterion filter) {
+        return determineAllRecords(session, basicType, filter, Order.asc(BasicType.DESCRIPTION_COL));
+    }
+    
+	/**
+	 * Retrieves an instances of a {@link BasicType} from database with the specified description.
+	 * The {@linkplain #getGlobalSession(boolean) global session} is used for database access.
+	 */
+	public static <E extends BasicTypeInterface> E determineBasicType(Class<E> basicType, String description) {
+		Criteria query = getGlobalSession(true).createCriteria(basicType);
+		query.add(Restrictions.eq("bezeichnung", description));
+		List<E> resultList = (List<E>) query.list();
+
+		if (resultList.isEmpty())
+			return null;
+		if (resultList.size() > 1)
+			LOGGER.warn(LangUtil.getSimpleClassName(basicType) + " not unique for description: " + description);
+
+		return resultList.get(0);
+	}
+
+	/**
+	 * Retrieves the description of all {@link BasicType} instances from database.
+     * The {@linkplain #getGlobalSession(boolean) global session} is used for database access.
+	 */
+	public static <E extends BasicTypeInterface> List<String> determineAllBasicTypeDescriptions(Class<E> basicType) {
+		List<E> basicTypes = determineAllBasicTypes(basicType);
+		List<String> basicTypeDesc = new ArrayList<String>();
+		for (E basicTypeInst : basicTypes)
+			basicTypeDesc.add(basicTypeInst.getDescription());
+		return basicTypeDesc;
+	}
+
+	/**
+	 * Returns the name of the discriminator column for a given type. This method expects that the types which are
+	 * define the shared table ("InheritanceType.SINGLE_TABLE") hold a static String field "DESCR_COLUMN".
+	 */
+	public static String getDisciminatorColumn(Class<?> type) {
+		try {
+			return (String) type.getDeclaredField("DESCR_COLUMN").get(null);
+		} catch (Exception err) {
+			// no discriminator column available
+			return null;
+		}
+	}
+
+	/**
+	 * Returns the value of the discriminator column for a given type. This method expects that the types which are
+	 * organized in a shared table ("InheritanceType.SINGLE_TABLE") hold a static String field "DESCR_VALUE".
+	 */
+	public static String getDisciminatorValue(Class<?> type) {
+		try {
+			return (String) type.getDeclaredField("DESCR_VALUE").get(null);
+		} catch (Exception err) {
+			// no discriminator column available
+			return null;
+		}
+	}
+
+
+}

Added: trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/HibernateApplication.java
===================================================================
--- trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/HibernateApplication.java	                        (rev 0)
+++ trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/HibernateApplication.java	2013-03-24 11:15:47 UTC (rev 2278)
@@ -0,0 +1,296 @@
+/**
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ * 
+ * This file is part of the SCHMITZM library - a collection of utility 
+ * classes based on Java 1.6, focusing (not only) on Java Swing 
+ * and the Geotools library.
+ * 
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ * 
+ * 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ * 
+ * Contributors:
+ *     Martin O. J. Schmitz - initial API and implementation
+ *     Stefan A. Tzeggai - additional utility classes
+ */
+package de.schmitzm.db.hibernate;
+
+import java.awt.Frame;
+
+import javax.swing.JOptionPane;
+
+import org.apache.log4j.Logger;
+
+import de.schmitzm.swing.Disposable;
+import de.schmitzm.swing.ExceptionDialog;
+import de.schmitzm.swing.SwingUtil;
+import de.schmitzm.swing.SwingWorker;
+import de.schmitzm.swing.input.InputOption;
+import de.schmitzm.swing.input.MultipleOptionPane;
+import de.schmitzm.temp.BaseTypeUtil;
+
+/**
+ * Super class for an application which connects to a database via
+ * hibernate.
+ * This class provides some useful, generic methods to deal with
+ * the database. 
+ * @author Martin O.J. Schmitz
+ */
+public abstract class HibernateApplication implements Disposable {
+  
+  /** Holds the {@link HibernateSessionFactory} which handles the
+   *  database connection via hibernate.  */
+  protected HibernateSessionFactory sessionFactory = null;
+  
+  /** Holds the input options for database login. */
+  protected InputOption<?>[] dbConnectOptions = null;
+  
+  /**
+   * Creates new application.
+   */
+  public HibernateApplication(HibernateSessionFactory sessionFactory) {
+    this.sessionFactory = sessionFactory;
+  }
+
+  /**
+   * Disposes the application.
+   */
+  @Override
+  public void dispose() {
+    // close open session
+    // HibernateSessionFactory.closeSession();
+    disconnectFromDatabase();
+  }
+
+  /**
+   * Returns the main frame of the application.
+   */
+  protected abstract Frame getMainFrame();
+  
+  /**
+   * Returns the {@link HibernateSessionFactory} which controls the
+   * database connection for this application.
+   */
+  public HibernateSessionFactory getHibernateSessionFactory() {
+    return sessionFactory;
+  }
+  
+  
+  /**
+   * Checks whether a connection to the database exists.
+   */
+  public boolean isConnected() {
+    return sessionFactory.isConnected();
+  }
+  
+  /**
+   * Returns the information of the last connection (application depended e.g.
+   * stored in properties). This implementation always returns {@code null}.
+   * Sub-classes can overwrite this method and return host (0), port (1), database
+   * name (2), user (3) and password (4).
+   */
+  protected String getLastConnectionSetting(int idx) {
+    switch (idx) {
+//      case 0: return Props.INST.getString(Props.Keys.db_host);
+//      case 1: return Props.INST.getString(Props.Keys.db_port, "5432");
+//      case 2: return Props.INST.getString(Props.Keys.db_dbname);
+//      case 3: return Props.INST.getString(Props.Keys.db_user);
+//      case 4: return Props.STORE_DB_PASSWD ? Props.INST.getStringDecrypted(Props.Keys.db_passwd) : null;
+    }
+    return null;
+  }
+  
+  /**
+   * This implementation does nothing.
+   * Sub-classes can overwrite this method and store the last connection
+   * information application depended e.g. in properties.
+   */
+  protected void setLastConnectionSettings(String host, Integer port, String dbname, String user, char[] passwd) {
+//    Props.INST.set(Props.Keys.db_host, host);
+//    Props.INST.set(Props.Keys.db_port, port);
+//    Props.INST.set(Props.Keys.db_dbname, dbname);
+//    Props.INST.set(Props.Keys.db_user, user);
+//    if ( Props.STORE_DB_PASSWD )
+//      Props.INST.setEncrypted(Props.Keys.db_passwd, new String(passwd));
+//    Props.INST.store();
+  }
+  
+  /**
+   * Returns whether password should be cleared (for security reasons)
+   * immediately after login (and not be stored in internal variables or
+   * properties).
+   * This default implementation always returns {@code true}. Sub-classes
+   * can overwrite this method to implement another behavior. 
+   */
+  protected boolean clearPassword() {
+//    return !Props.STORE_DB_PASSWD;
+    return true;
+  }
+  
+  /**
+   * Called in case of error during connection procedure.
+   * This method does nothing. Sub-classes can overwrite this method do
+   * handle special exceptions, e.g. offer application update.  
+   */
+  protected void handleConnectionException(Throwable err) {
+//    if ( err instanceof ReleaseException ) {
+//      checkApplicationUpdate(true,false);
+//    }
+  }
+
+  /**
+   * Recreates the database completely. ALL DATA IS LOST!
+   * @return {@code false} if no new connection is established
+   */
+  public boolean initializeDatabase() {
+      if (isConnected())
+          disconnectFromDatabase();
+      boolean ret = connectToDatabase(true);
+      if (ret)
+          JOptionPane.showMessageDialog(getMainFrame(),
+                                        DBUtil.RESOURCE.getString("HibernateApplication.db.init.confirm.mess"),
+                                        DBUtil.RESOURCE.getString("HibernateApplication.db.init.title"),
+                                        JOptionPane.INFORMATION_MESSAGE);
+      return ret;
+  }
+
+  /**
+   * Creates a connection to the database, so that {@link #getSession()} returns an open session.
+   * Does nothing if a connection already exists.
+   * @return {@code false} if no new connection is established
+   */
+  public boolean connectToDatabase() {
+      return connectToDatabase(false);
+  }
+
+  /**
+   * Creates a connection to the database, so that {@link #getSession()} returns an open session. Does nothing if a
+   * connection already exists.
+   * 
+   * @param forceCreate
+   *            if {@code true} the database is completely rebuild; ALL DATA WILL BE LOST!
+   * @return {@code false} if no new connection is established
+   */
+  protected boolean connectToDatabase(final boolean forceCreate) {
+      if (isConnected())
+          return false;
+
+      // show dialog
+      if (dbConnectOptions == null) {
+        String server = getLastConnectionSetting(0);
+        Integer port = BaseTypeUtil.convertFromString(getLastConnectionSetting(1), Integer.class);
+        String databaseName = getLastConnectionSetting(2);
+        String userName = getLastConnectionSetting(3);
+        String pw = getLastConnectionSetting(4);
+        dbConnectOptions = SwingUtil.createDatabaseLoginDialogOptions(server,port,databaseName,
+                                                                      userName,pw).toArray(new InputOption<?>[0]);
+      }
+
+      // Show dialog until connection is established or
+      // dialog is canceled
+      while (true)
+          try {
+              Object[] optionValues = MultipleOptionPane.showMultipleInputDialog(
+                                              getMainFrame(),
+                                              DBUtil.RESOURCE.getString("HibernateApplication.db.conn.dialog.title"),
+                                              dbConnectOptions);
+              if (optionValues == null) {
+                  // clear Password for security reasons
+                  dbConnectOptions[4].setValue(null);
+                  return false;
+              }
+              if (forceCreate) {
+                  int ret = JOptionPane.showConfirmDialog(getMainFrame(),
+                                DBUtil.RESOURCE.getString("HibernateApplication.db.init.warn.mess"),
+                                DBUtil.RESOURCE.getString("HibernateApplication.db.init.title"),
+                                JOptionPane.YES_NO_OPTION);
+                  if (ret != JOptionPane.YES_OPTION) {
+                      dbConnectOptions[4].setValue(null);
+                      return false;
+                  }
+              }
+
+              final String host = (String) optionValues[0];
+              final Integer port = (Integer) optionValues[1];
+              final String dbname = (String) optionValues[2];
+              final String user = (String) optionValues[3];
+              final char[] passwd = (char[]) optionValues[4];
+
+              // Aufbau der DB-Verbindung in einem Thread mit Dialog, der die
+              // GUI blockiert
+              SwingWorker.Work connectionWork = new SwingWorker.Work() {
+                  @Override
+                  public Object execute() throws Exception {
+                      sessionFactory.rebuildSessionFactory(host, // Server
+                              port, // Port
+                              dbname, // DB-Name
+                              user, // User
+                              passwd,
+                              forceCreate);
+                      return sessionFactory.getSessionFactory();
+                  }
+
+                  @Override
+                  public void performError(Throwable err) {
+                      // nichts machen... wir behandeln die Exeception selbst
+                  }
+              };
+              SwingWorker worker = new SwingWorker(connectionWork,
+                                                   getMainFrame(),
+                                                   DBUtil.RESOURCE.getString("HibernateApplication.db.conn.progress.mess"),
+                                                   0.5, 0.5);
+              // worker.getDialog().setDialogOption(StatusDialog.NONE_OPTION);
+              worker.start();
+              if (worker.getError() != null)
+                  throw worker.getError();
+              if (worker.isCanceled())
+                  continue;
+
+              // clear Password for security reasons
+              if ( clearPassword() )
+                dbConnectOptions[4].setValue(null);
+
+              // Nach erfolgreicher Verbindung die Benutezrdaten in die
+              // .properties schreiben
+              setLastConnectionSettings(host, port, dbname, user, passwd);
+              break;
+          } catch (Throwable err) {
+              // clear Password for security reasons
+              if ( clearPassword() )
+                dbConnectOptions[4].setValue(null);
+              ExceptionDialog.show(getMainFrame(), err);// , null,
+                                                      // "Fehler bei der Datenbank-Anmeldung");
+              handleConnectionException(err);
+          }
+
+      return true;
+  }
+
+  /**
+   * Terminates the connection to the database.
+   * 
+   * @return {@code false} if there was no open connection
+   */
+  public boolean disconnectFromDatabase() {
+      if (!isConnected())
+          return false;
+      sessionFactory.disconnectAllSessions();
+      sessionFactory.killSessionFactory();
+      return true;
+  }
+
+}

Added: trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/HibernateSessionFactory.java
===================================================================
--- trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/HibernateSessionFactory.java	                        (rev 0)
+++ trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/HibernateSessionFactory.java	2013-03-24 11:15:47 UTC (rev 2278)
@@ -0,0 +1,597 @@
+package de.schmitzm.db.hibernate;
+
+import java.io.File;
+import java.io.Serializable;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.hibernate.HibernateException;
+import org.hibernate.Query;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+import org.hibernate.cfg.AnnotationConfiguration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.jdbc.Work;
+
+import de.schmitzm.io.IOUtil;
+import de.schmitzm.lang.LangUtil;
+import de.schmitzm.versionnumber.ReleaseControl;
+import de.schmitzm.versionnumber.ReleaseUpdater;
+
+/**
+ * Configures and provides access to Hibernate sessions, tied to the current thread of execution. Follows the Thread
+ * Local Session pattern, see {@link http://hibernate.org/42.html }.
+ */
+public abstract class HibernateSessionFactory {
+	private Logger LOGGER = LangUtil.createLogger(this);
+
+    private Session globalSession = null;
+	private Map<Object,Session> sessions = new HashMap<Object,Session>();
+
+	/** Indicates whether the applications deals with multiple sessions ({@code true})
+	 *  or only with the one global {@link Session} ({@code false}). */
+    protected boolean MULTIPLE_SESSIONS = true;
+	
+	/**
+	 * Internal variable to temporary hold the JDBC connection for {@link #getConnection()}.
+	 */
+	private Connection tempConnection = null;
+
+	/**
+	 * Location of hibernate.cfg.xml file. Location should be on the classpath as Hibernate uses #resourceAsStream style
+	 * lookup for its configuration file. The default classpath location of the hibernate config file is in the default
+	 * package. Use #setConfigFile() to update the location of the configuration file for the current session.
+	 */
+	public  static final String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
+	private String configFile = null;
+	private AnnotationConfiguration configuration = null;
+	private org.hibernate.SessionFactory sessionFactory;
+
+    /**
+     * Creates a new session factory instance.
+     */
+    public HibernateSessionFactory(boolean multipleSessions) {
+      this(multipleSessions, CONFIG_FILE_LOCATION);
+    }
+
+    /**
+	 * Creates a new session factory instance.
+	 */
+	public HibernateSessionFactory(boolean multipleSessions, String configFile) {
+	  this.MULTIPLE_SESSIONS = multipleSessions;
+	  this.configFile = configFile;
+	}
+	
+//	/**
+//     * return session factory
+//     * 
+//     * session factory will be rebuilded in the next call
+//     */
+//    public static void setConfigFile(String configFile) {
+//      sessionFactory = null;
+//    }
+
+    /**
+     * return hibernate configuration
+     * 
+     */
+    public AnnotationConfiguration getConfiguration() {
+      return configuration;
+    }
+
+//    public static void setConfiguration(AnnotationConfiguration configuration) {
+//      HibernateSessionFactory.configuration = configuration;
+//    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    //////////////////  FUNCTIONS TO MAINTAIN DB CONNECTION  ///////////////////
+    ////////////////////////////////////////////////////////////////////////////
+
+	/**
+	 * Returns the session factory.
+	 * @return {@code null} if {@link #rebuildSessionFactory()} was not yet called
+	 */
+	public org.hibernate.SessionFactory getSessionFactory() {
+	  return sessionFactory;
+	}
+
+	/**
+	 * Kills the session factory.
+	 */
+	public void killSessionFactory() {
+	  if (sessionFactory == null)
+	    return;
+	  sessionFactory.close();
+	  sessionFactory = null;
+	}
+	
+	/**
+	 * Checks whether database connection is established.
+	 * @return
+	 */
+	public boolean isConnected() {
+	  return sessionFactory != null && !sessionFactory.isClosed();
+	}
+
+	/**
+	 * Rebuild hibernate session factory
+	 */
+	public void rebuildSessionFactory() throws SQLException {
+		rebuildSessionFactory(null, null, null, null, (String) null, false);
+	}
+
+	/**
+	 * Rebuild hibernate session factory
+	 */
+	public void rebuildSessionFactory(String host, Integer port, String dbName, String user, char[] password)
+			throws SQLException {
+		rebuildSessionFactory(host, port, dbName, user, new String(password), false);
+	}
+
+	/**
+	 * Rebuild hibernate session factory
+	 */
+	public void rebuildSessionFactory(String host, Integer port, String dbName, String user, char[] password,
+			boolean forceCreate) throws SQLException {
+		rebuildSessionFactory(host, port, dbName, user, password != null ? new String(password) : null, forceCreate);
+	}
+
+	/**
+	 * Rebuild hibernate session factory
+	 */
+	public void rebuildSessionFactory(String host, Integer port, String dbName, String user, String password,
+			boolean forceCreate) throws SQLException {
+		// if host, port and dbName given, combine to URL
+		String connectionUrl = null;
+		if (host != null && port != null && dbName != null)
+			connectionUrl = createConnectionURL(host, port, dbName);
+
+		// first: get default configuration from file
+		configuration = new AnnotationConfiguration();
+		addAnnotations(configuration);
+
+		// use defaults from file
+		getConfiguration().configure(configFile);
+
+		if (connectionUrl != null)
+			getConfiguration().setProperty(Environment.URL, connectionUrl);
+		if (user != null)
+			getConfiguration().setProperty(Environment.USER, user);
+		if (password != null)
+			getConfiguration().setProperty(Environment.PASS, password);
+		// force create database
+		if (forceCreate) {
+			getConfiguration().setProperty(Environment.HBM2DDL_AUTO, "create");
+		}
+		
+		// Leider "verschluckt" Hibernate etwaige Exceptions und es
+		// scheint keine moeglichkeit zu geben, dass diese abfangbar
+		// durchgereicht werden...
+		// http://www.java-forum.org/datenbankprogrammierung/85763-sqlexception-fangen-beim-verbinden-hibernate.html
+		// -> hier erstmal "antesten", ob die Anmelde-Informationen korrekt sind
+		checkDatabaseConnection(getConfiguration().getProperty(Environment.URL),
+				getConfiguration().getProperty(Environment.USER), getConfiguration().getProperty(Environment.PASS));
+
+		
+		// check whether program version fits the program version
+		// required by the database schema
+		checkApplicationRelease();
+		
+		// KLAPPT NICHT SO WIE GEDACHT
+		// // Wenn DB neu erstellt wird, alte DB zunaecht loeschen,
+		// // um Konflikte mit manuell angelegten Constraints
+		// // zu vermeiden
+		// if ( "create".equals(getConfiguration().getProperty(Environment.HBM2DDL_AUTO)) )
+		// dropAndRecreateDatabase(host, port, dbName, user, password);
+
+		sessionFactory = getConfiguration().buildSessionFactory();
+		if ("create".equals(getConfiguration().getProperty(Environment.HBM2DDL_AUTO))) {
+			initAdditionalConstraints();
+		}
+	}
+
+	/**
+	 * Checks whether the running application version is compatible to existing
+	 * database scheme. This method is called by {@link #rebuildSessionFactory(String, Integer, String, String, String, boolean)}
+	 * after database connection check and before {@link #rebuildSessionFactory()} call.
+	 * This default implementation does nothing. Sub-classes can overwrite this method
+	 * to implement application depended check.
+	 */
+	protected void checkApplicationRelease() {
+//	  RELEASE_CONTROL.checkApplicationRelease(getConfiguration().getProperty(Environment.URL),
+//	                                          getConfiguration().getProperty(Environment.USER),
+//	                                          getConfiguration().getProperty(Environment.PASS));
+	}
+
+    ////////////////////////////////////////////////////////////////////////////
+    /////////////////////  FUNCTIONS TO MAINTAIN SESSIONS  /////////////////////
+    ////////////////////////////////////////////////////////////////////////////
+	/**
+	 * Closes all open sessions.
+	 */
+	public void disconnectAllSessions() {
+	  for (Session s : sessions.values())
+	    if ( s != null && s.isConnected() ) {
+	      s.disconnect();
+	      s.close();
+	    }
+	  if ( globalSession != null && globalSession.isConnected() ) {
+	    globalSession.disconnect();
+	    globalSession.close();
+	  }
+	  // remove session references
+	  globalSession = null;
+	  sessions.clear();
+	}
+
+	/**
+	 * Closes a session if it is still open.
+	 */
+	public void closeSession(Session session) {
+	  if ( session == null )
+	    return;
+	  if ( session.isOpen() )
+	    session.close();
+	}
+	
+    /**
+     * Returns an open global session which can be used to
+     * read-only queries. For database updated the
+     * "caller" should create and maintain its own session.
+     */
+    public Session getSession() {
+      return getSession(true);
+    }
+    
+	/**
+	 * Returns a global session which can be used to
+	 * read-only queries. For database updated the
+	 * "caller" should create and maintain its own session.
+     * @param renew indicates whether a new session is created
+     *              if the current global session is
+     *              closed (or does not yet exist). If {@code false},
+     *              {@code null} or a closed session may be returned!
+	 */
+	public Session getSession(boolean renew) {
+	  if ( !isConnected() )
+	    return null;
+	  if ( globalSession == null || !globalSession.isOpen() ) {
+	    if ( renew )
+	      globalSession = getSessionFactory().openSession();
+	  }
+	  return globalSession;
+	}
+
+    /**
+     * Returns an open session for an individual object.
+     */
+    public Session getSession(Object key) {
+      return getSession(key,true);
+    }
+    
+    /**
+     * Returns a session for an individual object.
+     * @param renew indicates whether a new session is created
+     *              if the current session for the object is
+     *              closed (or does not yet exist). If {@code false},
+     *              {@code null} or a closed session may be returned!
+     */
+    public Session getSession(Object key, boolean renew) {
+      if ( !isConnected() )
+        return null;
+      // if no key is given, return the global session
+      if ( key == null )
+        return getSession(renew);
+      
+      Session session = null;
+      if ( MULTIPLE_SESSIONS )
+        // use individual sessions for every key
+        session = sessions.get(key);
+      else
+        // use always the one global session
+        session = getSession();
+      
+      
+      if ( session == null || !session.isOpen() ) {
+        if ( renew ) {
+          session = getSessionFactory().openSession();
+          sessions.put(key, session);
+        }
+      }
+      if ( session != null && session.isOpen() )
+        beginTransactionIfNeeded(session);
+      
+      return session;
+    }
+    
+    /**
+     * Closes a session for an individual object and removes it
+     * from session cache.
+     */
+    public void disposeSession(Object key) {
+      Session session = getSession(key,false);
+      if ( session != null ) {
+        session.flush(); // ??
+        session.clear();
+        session.disconnect();
+        closeSession(session);
+        sessions.remove(key);
+        session = null;
+      }
+    }
+
+    /**
+     * Starts a new transaction if no transaction is active.
+     * 
+     * @param deferredChecks
+     *            if {@code true}, all constraints are set to <i>deferred</i>, so that they are not checked before
+     *            transaction end (<b>Note:</b> it depends on the database and version, which constraints are effected
+     *            by the <i>deferred</i> setting!!)
+     */
+    private void beginTransactionIfNeeded(Session session, boolean deferredChecks) {
+      if (session == null)
+        throw new UnsupportedOperationException(
+        "Transaktion kann nicht begonnen werden, da keine Session zur Verfuegung steht!");
+      if (session.getTransaction() == null || !session.getTransaction().isActive())
+        session.beginTransaction();
+      if (deferredChecks) {
+        SQLQuery query = session.createSQLQuery("SET CONSTRAINTS ALL DEFERRED");
+        query.executeUpdate();
+      }
+    }
+    
+    /**
+     * Starts a new transaction for the global session
+     * if no transaction is active.
+     * 
+     * @param deferredChecks
+     *            if {@code true}, all constraints are set to <i>deferred</i>, so that they are not checked before
+     *            transaction end (<b>Note:</b> it depends on the database and version, which constraints are effected
+     *            by the <i>deferred</i> setting!!)
+     */
+    private void beginTransactionIfNeeded(boolean deferredChecks) {
+      beginTransactionIfNeeded(getSession(), deferredChecks);
+    }
+    
+
+    /**
+     * Starts a new transaction with immediate constraint checking.
+     */
+    public void beginTransactionIfNeeded(Session session) {
+        beginTransactionIfNeeded(session,false);
+    }
+
+    /**
+     * Starts a new transaction with immediate constraint checking.
+     */
+    public void beginTransactionIfNeeded(Object key) {
+      Session session = getSession(key);
+      beginTransactionIfNeeded(session,false);
+    }
+
+    /**
+     * Starts a new transaction for the global session with
+     * immediate constraint checking.
+     */
+    public void beginTransactionIfNeeded() {
+        beginTransactionIfNeeded(getSession());
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    ///////////////////////////  UTILITY FUNCTIONS  ////////////////////////////
+    ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Calls {@code getSession().get(..)} and casts the returning object automatically to the called type.
+     */
+    public <E> E get(Class<E> type, Serializable objectID) {
+        return (E) getSession().get(type, objectID);
+    }
+
+    /**
+     * Combines hostname, port and database name to a connection URL. "jdbc:postgres" is currently used as protocoll
+     * everytime.
+     * 
+     * @param host
+     *            hostname
+     * @param port
+     *            port
+     * @param dbName
+     *            database name
+     */
+    public static String createConnectionURL(String host, int port, String dbName) {
+        String connectionUrl = "jdbc:postgresql://" + host + ":" + port + "/" + dbName + "?characterEncoding=utf8";
+        return connectionUrl;
+    }
+
+    /**
+     * Testet an, ob die Anmelde-Informationen korrekt sind und wirft gegebenfalls eine Exception. Ist alles ok,
+     * passiert nichts.
+     * 
+     * @param host
+     *            Server
+     * @param port
+     *            Port
+     * @param dbName
+     *            Datenbank-Name
+     * @param user
+     *            Benutzer
+     * @param password
+     *            Passwort
+     * @throws SQLException
+     */
+    public static void checkDatabaseConnection(String host, Integer port, String dbName, String user, String password)
+            throws SQLException {
+        String connectionUrl = createConnectionURL(host, port, dbName);
+        checkDatabaseConnection(connectionUrl, user, password);
+    }
+
+    /**
+     * Testet an, ob die Anmelde-Informationen korrekt sind und wirft gegebenfalls eine Exception. Ist alles ok,
+     * passiert nichts.
+     * 
+     * @param dbURL
+     *            Protokoll + Server + Port + Datenbank-Name
+     * @param user
+     *            Benutzer
+     * @param password
+     *            Passwort
+     * @throws SQLException
+     */
+    public static void checkDatabaseConnection(String dbURL, String user, String password) throws SQLException {
+        Connection conn = DriverManager.getConnection(dbURL, user, password);
+        conn.close();
+    }
+    
+    /**
+     * Returns the JDBC {@link Connection} of the current session.
+     * 
+     * @return {@code null} if there is no session established
+     */
+    public Connection getConnection() {
+        if (!isConnected())
+            return null;
+
+        Work work = new Work() {
+            @Override
+            public void execute(Connection connection) throws SQLException {
+                tempConnection = connection;
+            }
+        };
+        beginTransactionIfNeeded();
+        getSession().doWork(work);
+        return tempConnection;
+    }
+
+    /**
+     * Returns the JDBC {@link Connection} of the current session.
+     * 
+     * @return {@code null} if there is no session established
+     */
+    public DatabaseMetaData getConnectionMetadata() {
+        Connection conn = getConnection();
+        if (conn == null)
+            return null;
+        try {
+            return conn.getMetaData();
+        } catch (SQLException err) {
+            return null;
+        }
+
+    }
+    
+//    /**
+//     * Liefert die Anzahl der offenen Sessions fuer die aktuelle
+//     * Verbindung des Users.
+//     * @deprecated funktioniert irgendwie nicht, liefert nur bei der
+//     *             ersten Anfrage das richtige Ergebnis; danach immer
+//     *             wieder das gleiche...
+//     */
+//    public int getOpenSessionCount() throws SQLException {
+//      int count = 0;
+//      
+//      
+//      // klappt leider so nicht...
+//      count = PGUtil.getOpenSessionCount(
+//                getConnection(),
+//                Props.INST.getString(Props.Keys.db_dbname),
+//                DBUtil.getCurrentUser());
+//      
+////      // TEST MIT Abfrage direkt im doWork(.)
+////      final AtomicInteger countA = new AtomicInteger();
+////      Work work = new Work() {
+////        @Override
+////        public void execute(Connection connection) throws SQLException {
+////          int c = PGUtil.getOpenSessionCount(
+////                       connection,
+////                       Props.get(Props.Keys.db_dbname),
+////                       DBUtil.getCurrentUser());
+////          countA.set(c);
+////        }
+////      };
+////      HibernateSessionFactory.getSession().doWork(work);
+////      count = countA.get();
+//      
+////      // TEST MIT HIBERNATE-SQL STATT Statement ueber Connection...
+////      // ... leider ohne Erfolg
+////      SQLQuery q = HibernateSessionFactory.getSession().createSQLQuery("SELECT COUNT(*) FROM pg_stat_activity WHERE datname = ? and usename = ?");
+////      q.setString(0, Props.get(Props.Keys.db_dbname) );
+////      q.setString(1, DBUtil.getCurrentUser());
+////      BigInteger result = (BigInteger)q.uniqueResult();
+////      count = result.intValue();
+//      
+//      System.err.println(count);
+//      return count; 
+//    }
+
+	////////////////////////////////////////////////////////////////////////////
+    //////////////////////  INTERNAL UTILITY FUNCTIONS  ////////////////////////
+    ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Adds all annotated classes (types) to the configuaration. Has to implemented
+     * application dependend.
+     */
+    protected abstract void addAnnotations(AnnotationConfiguration configuration);
+    
+    /**
+	 * Adds additional constraints (via SQL), which can not be created automatically by hibernate. If their creation
+	 * fails (probably because they already exist), it is ignored.
+	 * This default implementation does nothing. Sub-classes can overwrite this method to implement
+	 * create database constraints on database initialisation.
+	 */
+	protected void initAdditionalConstraints() {
+//		executeInTransactionIgnoreEx(new Runnable() {
+//			@Override
+//			public void run() {
+//				new PermissionManagement().setupPermissions();
+//			}
+//		});
+		
+	}
+
+	/**
+	 * Executes some work within an transaction.
+	 */
+	protected void executeInTransactionIgnoreEx(Runnable runnable) {
+		beginTransactionIfNeeded();
+		try {
+			runnable.run();
+			getSession().getTransaction().commit();
+		} catch (HibernateException e) {
+			getSession().getTransaction().rollback();
+		} finally {
+			beginTransactionIfNeeded();
+		}
+	}
+
+
+    /**
+     * Creates a {@link Query} to add a primary key constraint a table ("ALTER TABLE ADD CONSTRAINT...").
+     * @param type
+     *            data type
+     * @param attr
+     *            attribute names the primary key is created for
+     */
+    protected Query createPrimaryKeyConstraintQuery(String tableName, String... attr) {
+        String constrName = "PK_"+tableName;
+        String queryStr = "ALTER TABLE " + tableName + " ADD CONSTRAINT \"" + constrName + "\" PRIMARY KEY (";
+        for (int i=0; i<attr.length; i++) {
+          if ( i>0 )
+            queryStr += ", ";
+          queryStr += attr[i];
+        }
+        queryStr += ")";
+        LOGGER.debug("Primary Key Query: " + queryStr);
+//        getSession().createSQLQuery("alter table "+Mitarbeiter.TABLENAME+"_mailverteiler add constraint pk_"+Mitarbeiter.TABLENAME+"_mailverteiler PRIMARY KEY (mitarbeiter_id, mailverteiler_id)").executeUpdate();
+        return getSession().createSQLQuery(queryStr);
+
+    }
+    
+}
\ No newline at end of file

Added: trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/types/BasicType.java
===================================================================
--- trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/types/BasicType.java	                        (rev 0)
+++ trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/types/BasicType.java	2013-03-24 11:15:47 UTC (rev 2278)
@@ -0,0 +1,89 @@
+package de.schmitzm.db.hibernate.types;
+
+import javax.persistence.Column;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.MappedSuperclass;
+
+import de.schmitzm.db.hibernate.DBUtil;
+import de.schmitzm.lang.LangUtil;
+
+
+/**
+ * Super type for all Basic types. Basic types represent enums on the database.
+ * They are identified by a (unique) ID and a description.
+ * 
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+ at MappedSuperclass
+ at Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+public abstract class BasicType extends AbstractUniqueIDType implements BasicTypeInterface {
+    /** Name of the description column */
+    public static final String DESCRIPTION_COL = "description";
+    /** Size of the description column. Can be redefined by sub class using:<br>
+     * <code> @AttributeOverrides({
+     *            @AttributeOverride(name = BasicType.DESCRIPTION_COL, column = @Column(length=...))
+     *        })
+     * </code>
+     * */
+    public static final int DESCRIPTION_SIZE = 100;
+    
+    /** The "readable" value of the enum value. */
+    @Column(name = DESCRIPTION_COL, length = DESCRIPTION_SIZE, nullable = false)
+    protected String description;
+
+    /**
+     * Creates a new enum value with empty description.
+     */
+    public BasicType() {
+      this("");
+    }
+    
+    /**
+     * Creates a new enum value.
+     */
+    public BasicType(String desc) {
+      setDescription(desc);
+    }
+
+	/**
+	 * Returns the "readable" description of the enum value.
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Sets the "readable" description of the enum value.
+	 */
+	public void setDescription(String bezeichnung) {
+		this.description = LangUtil.trimToSize(bezeichnung,DESCRIPTION_SIZE);
+	}
+	
+	/**
+	 * Returns {@link #getDescription()}.
+	 */
+	public String toString() {
+	  return getDescription();
+	}
+	
+	/**
+	 * Checks whether a {@link BasicType} instances equals
+	 * another by ID.
+	 */
+    public boolean equals(Object object) {
+      if ( !(object instanceof BasicType) )
+        return false;
+      return DBUtil.equalsIdBased(this, (BasicType)object);
+    }
+
+    /**
+     * Returns {@code getID().hashCode()} if the instance is already
+     * persistent (has an ID). For inpersistent instances the method
+     * returns {@link System#identityHashCode(Object)}. 
+     */
+    @Override
+    public int hashCode() {
+      return DBUtil.hashCodeIdBased(this);
+    }
+}

Added: trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/types/BasicTypeInterface.java
===================================================================
--- trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/types/BasicTypeInterface.java	                        (rev 0)
+++ trunk/schmitzm-hibernate/src/main/java/de/schmitzm/db/hibernate/types/BasicTypeInterface.java	2013-03-24 11:15:47 UTC (rev 2278)
@@ -0,0 +1,20 @@
+package de.schmitzm.db.hibernate.types;
+
+
+/**
+ * Super type for all Basic types. Basic types represent enums on the database.
+ * They are identified by a (unique) ID and a description.
+ * 
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public interface BasicTypeInterface extends UniqueIDType {
+  /**   
+   * Returns the "readable" description of the enum value.
+   */
+  public String getDescription();
+
+  /**
+   * Sets the "readable" description of the enum value.
+   */
+  public void setDescription(String desc);
+}

Added: trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/db/hibernate/resource/locales/HibernateResourceBundle.properties
===================================================================
--- trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/db/hibernate/resource/locales/HibernateResourceBundle.properties	                        (rev 0)
+++ trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/db/hibernate/resource/locales/HibernateResourceBundle.properties	2013-03-24 11:15:47 UTC (rev 2278)
@@ -0,0 +1,38 @@
+##########
+#This file is part of the SCHMITZM library - a collection of utility 
+#classes based on Java 1.6, focussing (not only) on Java Swing 
+#and the Geotools library.
+#
+#The SCHMITZM project is hosted at:
+#http://wald.intevation.org/projects/schmitzm/
+#
+#This program is free software; you can redistribute it and/or
+#modify it under the terms of the GNU Lesser General Public License
+#as published by the Free Software Foundation; either version 3
+#of the License, or (at your option) any later version.
+#
+#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 General Public License for more details.
+#
+#You should have received a copy of the GNU Lesser General Public License (license.txt)
+#along with this program; if not, write to the Free Software
+#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#or try this link: http://www.gnu.org/licenses/lgpl.html
+#
+#Contributors:
+#    Martin O. J. Schmitz - initial API and implementation
+#    Stefan A. Tzeggai - additional utility classes
+##########
+# ---------------------------------------------------------------
+# ------ Default Translations (english) for GUI components ------
+# ------ in Package de.schmitzm.db.hibernate               ------
+# ---------------------------------------------------------------
+HibernateApplication.db.init.title=Database initialization
+HibernateApplication.db.init.warn.mess=WARNING! During initialize all data will be deleted! Continue anyway?
+HibernateApplication.db.init.confirm.mess=Database was rebuild
+HibernateApplication.db.conn.dialog.title=Database connection
+HibernateApplication.db.conn.progress.mess=Establishing database connection ...
+
+

Added: trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/db/hibernate/resource/locales/HibernateResourceBundle_de.properties
===================================================================
--- trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/db/hibernate/resource/locales/HibernateResourceBundle_de.properties	                        (rev 0)
+++ trunk/schmitzm-hibernate/src/main/resources/de/schmitzm/db/hibernate/resource/locales/HibernateResourceBundle_de.properties	2013-03-24 11:15:47 UTC (rev 2278)
@@ -0,0 +1,37 @@
+##########
+#This file is part of the SCHMITZM library - a collection of utility 
+#classes based on Java 1.6, focussing (not only) on Java Swing 
+#and the Geotools library.
+#
+#The SCHMITZM project is hosted at:
+#http://wald.intevation.org/projects/schmitzm/
+#
+#This program is free software; you can redistribute it and/or
+#modify it under the terms of the GNU Lesser General Public License
+#as published by the Free Software Foundation; either version 3
+#of the License, or (at your option) any later version.
+#
+#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 General Public License for more details.
+#
+#You should have received a copy of the GNU Lesser General Public License (license.txt)
+#along with this program; if not, write to the Free Software
+#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#or try this link: http://www.gnu.org/licenses/lgpl.html
+#
+#Contributors:
+#    Martin O. J. Schmitz - initial API and implementation
+#    Stefan A. Tzeggai - additional utility classes
+##########
+# ---------------------------------------------------------------
+# ------ Germal Translations for GUI components            ------
+# ------ in Package de.schmitzm.db.hibernate               ------
+# ---------------------------------------------------------------
+HibernateApplication.db.init.title=Datenbank-Initialisierung
+HibernateApplication.db.init.warn.mess=ACHTUNG! Bei der Initialisierung werden alle Daten gelöscht! Fortfahren?
+HibernateApplication.db.init.confirm.mess=Datenbank wurde neu aufgebaut
+HibernateApplication.db.conn.dialog.title=Datenbank-Anmeldung
+HibernateApplication.db.conn.progress.mess=Datenbank-Verbindung wird aufgebaut...
+



More information about the Schmitzm-commits mailing list