Java tutorial
/** * <copyright> * * Copyright (c) 2005, 2006, 2007, 2008 Springsite BV (The Netherlands) and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Martin Taal * </copyright> * * $Id: HibernatePersistableFeatureMap.java,v 1.15 2009/11/02 10:24:50 mtaal Exp $ */ package org.eclipse.emf.teneo.hibernate.mapping.elist; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.FeatureMap; import org.eclipse.emf.teneo.EContainerRepairControl; import org.eclipse.emf.teneo.extension.ExtensionPoint; import org.eclipse.emf.teneo.hibernate.HbMapperException; import org.eclipse.emf.teneo.hibernate.SessionWrapper; import org.eclipse.emf.teneo.hibernate.resource.HibernateResource; import org.eclipse.emf.teneo.mapping.elist.PersistableFeatureMap; import org.eclipse.emf.teneo.resource.StoreResource; import org.eclipse.emf.teneo.util.AssertUtil; import org.hibernate.Session; import org.hibernate.collection.AbstractPersistentCollection; import org.hibernate.collection.PersistentBag; import org.hibernate.collection.PersistentCollection; import org.hibernate.collection.PersistentList; /** * Implements the hibernate persistable elist. * * @author <a href="mailto:mtaal@elver.org">Martin Taal</a> * @version $Revision: 1.15 $ */ public class HibernatePersistableFeatureMap extends PersistableFeatureMap implements ExtensionPoint { /** * Serial Version ID */ private static final long serialVersionUID = -1916994464446630140L; /** The logger */ private static Log log = LogFactory.getLog(HibernatePersistableFeatureMap.class); /** Constructor */ public HibernatePersistableFeatureMap(InternalEObject owner, EStructuralFeature feature, List<FeatureMap.Entry> list) { super(owner, feature, list); if (isLoaded()) { for (Entry entry : getDelegate()) { final HibernateFeatureMapEntry fme = (HibernateFeatureMapEntry) entry; if (!fme.belongsToFeatureMap(this)) { fme.setFeatureMap(this); } } } } /** Returns the element type to be used */ @Override protected Class<? extends FeatureMap.Entry> determineElementType() { return HibernateFeatureMapEntry.class; } /** OVerridden to create the correct featuremap entry */ @Override protected FeatureMap.Entry createEntry(EStructuralFeature eStructuralFeature, Object value) { final HibernateFeatureMapEntry entry = new HibernateFeatureMapEntry(); entry.setFeatureValue(eStructuralFeature, value, this); return entry; } /** Shortcut to replace entries */ protected FeatureMap.Entry replaceEntry(Object entry) { if (entry instanceof HibernateFeatureMapEntry && ((HibernateFeatureMapEntry) entry).belongsToFeatureMap(this)) { return (HibernateFeatureMapEntry) entry; } final FeatureMap.Entry emfEntry = (FeatureMap.Entry) entry; final HibernateFeatureMapEntry fme = new HibernateFeatureMapEntry(); fme.setFeatureValue(emfEntry.getEStructuralFeature(), emfEntry.getValue(), this); return fme; } /** If the delegate has been initialized */ public boolean isInitialized() { return ((PersistentCollection) delegate).wasInitialized(); } /** * Override isLoaded to check if the delegate lists was not already loaded by hibernate behind the scenes, this * happens with eagerly loaded lists. */ @Override public boolean isLoaded() { if (delegate instanceof AbstractPersistentCollection) { if (((AbstractPersistentCollection) delegate).wasInitialized()) { // delegate is loaded in case of subselect or eager loading if (isLoading()) { // probably are we doing this already return return false; } if (log.isDebugEnabled()) { log.debug("Persistentlist already initialized, probably eagerly loaded: " + getLogString()); } try { setIsLoading(true); // do load to load the resource doLoad(); setIsLoaded(true); } finally { setIsLoading(false); } } } return super.isLoaded(); } /** Do the actual load can be overridden, called from the subclass */ @Override protected synchronized void doLoad() { AssertUtil.assertTrue("EList " + logString, !isLoaded()); SessionWrapper sessionWrapper = null; boolean controlsSession = false; boolean err = true; try { final Resource res = owner.eResource(); if (res != null && res instanceof HibernateResource) { sessionWrapper = ((HibernateResource) res).getSessionWrapper(); if (res.isLoaded()) { // resource is loaded reopen transaction if (!sessionWrapper.isTransactionActive()) { if (log.isDebugEnabled()) { log.debug("Reconnecting session to read a lazy collection, Featuremap: " + logString); } controlsSession = true; sessionWrapper.beginTransaction(); sessionWrapper.setFlushModeManual(); } else if (log.isDebugEnabled()) { log.debug("Resource session is still active, using it"); } } else if (log.isDebugEnabled()) { log.debug("Featuremap uses session from resource, " + logString); } } else if (log.isDebugEnabled()) { log.debug("EList is not loaded in session context"); } Object[] objs = delegate.toArray(); // this forces the load // set the owner of the feature map entries // set the econtainer for (Object element : objs) { final HibernateFeatureMapEntry fme = (HibernateFeatureMapEntry) element; fme.setFeatureMap(this); if (fme.getEStructuralFeature() instanceof EReference && ((EReference) fme.getEStructuralFeature()).isContainment()) { final InternalEObject eobj = (InternalEObject) fme.getValue(); if (eobj != null) { EContainerRepairControl.setContainer(owner, eobj, fme.getEStructuralFeature()); if (res != null && res instanceof StoreResource && fme.getEStructuralFeature() instanceof EReference) { ((StoreResource) res).addToContentOrAttach((InternalEObject) fme.getValue(), (EReference) fme.getEStructuralFeature()); } } } } err = false; if (log.isDebugEnabled()) { log.debug("Loaded " + objs.length + " from backend store for " + logString); } } finally { if (controlsSession) { if (err) { sessionWrapper.rollbackTransaction(); sessionWrapper.restorePreviousFlushMode(); } else { // a bit rough but delete from the persitence context // otherwise // hibernate will think that this collection is not attached // to anything and // will delete me // getSession().getPersistenceContext().getCollectionEntries().remove(this); sessionWrapper.commitTransaction(); sessionWrapper.restorePreviousFlushMode(); } } } } /** Overridden because general list type is not supported as a replacement */ @Override public void replaceDelegate(List<FeatureMap.Entry> newDelegate) { if (newDelegate instanceof PersistentList) { AssertUtil.assertTrue( "This elist " + logString + " contains a different list than the " + " passed list", ((PersistentList) newDelegate).isWrapper(delegate)); super.replaceDelegate(newDelegate); } else if (newDelegate instanceof PersistentBag) { AssertUtil.assertTrue( "This elist " + logString + " contains a different list than the " + " passed list", ((PersistentBag) newDelegate).isWrapper(delegate)); super.replaceDelegate(newDelegate); } else { throw new HbMapperException("Type " + newDelegate.getClass().getName() + " can not be " + " used as a replacement for elist " + logString); } } /** Returns true if the wrapped list is a persistency layer specific list */ @Override public boolean isPersistencyWrapped() { return delegate instanceof PersistentCollection; } @Override protected Entry delegateRemove(int index) { final Entry old = super.delegateRemove(index); if (old.getEStructuralFeature() instanceof EReference && getDelegate() instanceof PersistentList) { final PersistentList pl = (PersistentList) getDelegate(); final EReference eref = (EReference) old.getEStructuralFeature(); if (eref.isContainment()) { ((Session) pl.getSession()).delete(old.getValue()); } } return old; } @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone(); } }