buildframework/helium/sf/java/metadata/src/com/nokia/helium/metadata/FactoryManager.java
changeset 628 7c4a911dc066
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/buildframework/helium/sf/java/metadata/src/com/nokia/helium/metadata/FactoryManager.java	Fri Aug 13 14:59:05 2010 +0300
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description:  
+ *
+ */
+package com.nokia.helium.metadata;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.Cache;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceUnitUtil;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.metamodel.Metamodel;
+
+/**
+ * This singleton class is the main entry point to the Metadata framework.
+ * Developer must use it to get access to the EntityManagerFactory from the
+ * JPA framework. 
+ *
+ */
+public final class FactoryManager {
+    private static FactoryManager self = new FactoryManager();
+    private List<EntityManagerFactoryWrapper> wrappers = new ArrayList<EntityManagerFactoryWrapper>();
+    private EntityManagerFactoryCreator factoryManagerCreator = new DerbyFactoryManagerCreator();
+    
+    /**
+     * This class must not be instantiated from outside.
+     */
+    private FactoryManager() {
+    }
+    
+    /**
+     * Get the FactoryManager instance.
+     * @return the FactoryManager instance.
+     */
+    public static FactoryManager getFactoryManager() {
+        return self;
+    }
+    
+    /**
+     * Get the EntityManagerFactory for the database. 
+     * @param database the File object representing the database.
+     * @return an EntityManagerFactory instance.
+     * @throws MetadataException is thrown in case of error.
+     */
+    public synchronized EntityManagerFactory getEntityManagerFactory(File database) throws MetadataException {
+        EntityManagerFactoryWrapper wrapper = null;
+        for (EntityManagerFactoryWrapper wrp : wrappers) {
+            // Found what we wanted so leaving the loop.
+            if (wrp.getDatabase().equals(database)) {
+                wrapper = wrp;
+                break;
+            }
+        }
+        if (wrapper != null) {
+            wrapper.reference();
+            return wrapper;
+        } else {
+            // creating a new one.
+            wrapper = 
+                new EntityManagerFactoryWrapper(factoryManagerCreator.create(database), this, database);
+            wrappers.add(wrapper);
+            return wrapper;
+        }
+    }
+    
+    /**
+     * Removing the wrapper object from the available database, so no one can 
+     * use it anymore. This method is intended to be used by the EntityManagerFactoryWrapper.
+     * @param wrapper
+     */
+    private synchronized void remove(EntityManagerFactoryWrapper wrapper) {
+        wrappers.remove(wrapper);
+    }
+
+    /**
+     * Unload the database when not used anymore.
+     * This method is intended to be used by the EntityManagerFactoryWrapper.
+     * @param database the database to unload.
+     */
+    private void unload(File database) {
+        try {
+            factoryManagerCreator.unload(database);
+        } catch (MetadataException e) {
+            // do nothing in the meantime
+            database = null;
+        }        
+    }
+    
+    /**
+     * Internal Factory wrapper object which implements a custom 
+     * factory lifecycle management. 
+     *
+     */
+    class EntityManagerFactoryWrapper implements EntityManagerFactory {
+        private EntityManagerFactory factory;
+        private FactoryManager factoryManager;
+        private int counter = 1;
+        private File database;
+        
+        /**
+         * Default constructor.
+         * @param factory the factory to delegate to calls to.
+         * @param factoryManager the factory manager used for the lifecycle management.
+         * @param database the database this object is connected to.
+         */
+        public EntityManagerFactoryWrapper(EntityManagerFactory factory,
+                FactoryManager factoryManager, File database) {
+            this.factory = factory;
+            this.factoryManager = factoryManager;
+            this.database = database;
+        }
+
+        /**
+         * Method used by the factoryManager to reference the usage of the 
+         * EntityFactoryManager.
+         */
+        public synchronized void reference() {
+            counter++;
+        }
+
+        /**
+         * {@inheritDoc}
+         * This method overrides the default close implementation, and will
+         * only close the EntityManagerFactory, if all application have stopped
+         * using the EntityManagerFactory.
+         * It interacts with the factoryManager.
+         */
+        public synchronized void close() {
+            counter--;
+            if (counter == 0) {
+                factoryManager.remove(this);
+                factory.close();
+                factoryManager.unload(database);
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public EntityManager createEntityManager() {
+            return factory.createEntityManager();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @SuppressWarnings("unchecked")
+        public EntityManager createEntityManager(Map properties) {
+            return factory.createEntityManager(properties);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Cache getCache() {
+            return factory.getCache();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public CriteriaBuilder getCriteriaBuilder() {
+            return factory.getCriteriaBuilder();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Metamodel getMetamodel() {
+            return factory.getMetamodel();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public PersistenceUnitUtil getPersistenceUnitUtil() {
+            return factory.getPersistenceUnitUtil();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Map<String, Object> getProperties() {
+            return factory.getProperties();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean isOpen() {
+            return factory.isOpen();
+        }
+        
+        /**
+         * {@inheritDoc}
+         */
+        public File getDatabase() {
+            return database;
+        }
+    }
+
+}