/** * <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: * EReferencePropertyHandler.java,v 1.4 2007/04/07 12:43:51 mtaal Exp $ */ package org.eclipse.emf.teneo.hibernate.mapping.property; import java.lang.reflect.Method; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.emf.common.notify.NotificationChain; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.teneo.extension.ExtensionPoint; import org.eclipse.emf.teneo.hibernate.resource.HibernateResource; import org.eclipse.emf.teneo.util.StoreUtil; import org.hibernate.HibernateException; import org.hibernate.PropertyNotFoundException; import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.engine.SessionImplementor; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.Setter; /** * Implements the getter for an EReference field. Normally uses the eget/eset * methods with bidirectional relations the handling is a bit different using * eInverseRemove and eInverseAdd. This class implements both the getter, setter * and propertyaccessor interfaces. When the getGetter and getSetter methods are * called it returns itself. * * @author <a href="mailto:mtaal@elver.org">Martin Taal</a> * @version $Revision: 1.16 $ */ @SuppressWarnings("unchecked") public class EReferencePropertyHandler implements Getter, Setter, PropertyAccessor, ExtensionPoint { /** * Serial version id */ private static final long serialVersionUID = -3712366809398761331L; /** The logger */ private static Log log = LogFactory.getLog(EReferencePropertyHandler.class); /** The feature */ protected EReference eReference; /** Two way reference */ protected boolean isBidirectional; private int featureId = -1; public void initialize(EReference eReference) { this.eReference = eReference; final EClass eClass = eReference.getEContainingClass(); featureId = eClass.getFeatureID(eReference); isBidirectional = eReference.getEOpposite() != null && !eReference.getEOpposite().isTransient(); log .debug("Created getter/setter for " + StoreUtil.toString(eReference)); } public EReference getEReference() { return eReference; } /* * (non-Javadoc) * * @see org.hibernate.property.PropertyAccessor#getGetter(java.lang.Class, * java.lang.String) */ public Getter getGetter(Class theClass, String propertyName) throws PropertyNotFoundException { return this; } /* * (non-Javadoc) * * @see org.hibernate.property.PropertyAccessor#getSetter(java.lang.Class, * java.lang.String) */ public Setter getSetter(Class theClass, String propertyName) throws PropertyNotFoundException { return this; } /* * (non-Javadoc) * * @see org.hibernate.property.Getter#get(java.lang.Object) */ public Object get(Object owner) throws HibernateException { return ((EObject) owner).eGet(eReference, false); } /* * (non-Javadoc) * * @see org.hibernate.property.Getter#getForInsert(java.lang.Object, * java.util.Map, org.hibernate.engine.SessionImplementor) */ public Object getForInsert(Object owner, Map mergeMap, SessionImplementor session) throws HibernateException { return get(owner); } /* * (non-Javadoc) * * @see org.hibernate.property.Setter#set(java.lang.Object, * java.lang.Object, org.hibernate.engine.SessionFactoryImplementor) */ public void set(Object target, Object value, SessionFactoryImplementor factory) throws HibernateException { final Object curValue = get(target); if (isBidirectional) {// these are handled a bit differently because // the opposite should not be set, this is // done by hb if (curValue != value) { // note that == works fine if the // curValue and value have been read in // the same // pm. // Note that the eInverseRemove is called on the target itself // and the value is // passed // therefore the eReference featureid is passed and not the // opposite if (value == null) { // remove final NotificationChain nots = ((InternalEObject) target) .eInverseRemove((InternalEObject) curValue, featureId, eReference.getEType() .getInstanceClass(), null); if (nots != null) { nots.dispatch(); } } else { final NotificationChain nots = ((InternalEObject) target) .eInverseAdd((InternalEObject) value, featureId, eReference.getEType().getInstanceClass(), null); if (nots != null) { nots.dispatch(); } } } } else { if (curValue == value) { return; // do nothing in this case } final EObject eobj = (EObject) target; eobj.eSet(eReference, value); Resource res = eobj.eResource(); if (value != null && res instanceof HibernateResource && ((EObject) value).eResource() == null) { final boolean loading = ((HibernateResource) res).isLoading(); try { ((HibernateResource) res).setIsLoading(true); ((HibernateResource) res).addToContentOrAttach( (InternalEObject) value, eReference); } finally { ((HibernateResource) res).setIsLoading(loading); } } } // see vbbhttps://bugs.eclipse.org/bugs/show_bug.cgi?id=245634 // container relations should be modeled explicitly in the database or // not at all // see the relevant option in PersistenceOptions. // if (eReference.isContainment() && target instanceof InternalEObject // && value instanceof InternalEObject) { // EContainerRepairControl.setContainer((InternalEObject) target, // (InternalEObject) value, eReference); // } } /* * (non-Javadoc) * * @see org.hibernate.property.Getter#getMethod() */ public Method getMethod() { return null; } /* * (non-Javadoc) * * @see org.hibernate.property.Getter#getMethodName() */ public String getMethodName() { return null; } /* * (non-Javadoc) * * @see org.hibernate.property.Getter#getReturnType() */ public Class getReturnType() { return InternalEObject.class; } }