blob: b04238c84e1bd6c082a01a6e5e19faf9301c0177 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2005 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
/*
* Created on Oct 24, 2003
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package org.eclipse.jst.j2ee.ejb.internal.util;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jem.java.Field;
import org.eclipse.jem.java.JavaClass;
import org.eclipse.jem.java.JavaVisibilityKind;
import org.eclipse.jst.j2ee.ejb.CMPAttribute;
import org.eclipse.jst.j2ee.ejb.ContainerManagedEntity;
import org.eclipse.jst.j2ee.ejb.EjbFactory;
import org.eclipse.jst.j2ee.ejb.EjbPackage;
import org.eclipse.jst.j2ee.ejb.internal.impl.ContainerManagedEntityImpl;
/**
* @author jlanuti
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class CMPKeySynchronizationAdapter extends AdapterImpl {
public static final String ADAPTER_TYPE = CMPKeySynchronizationAdapter.class.getName();
private boolean initialized = false;
protected ContainerManagedEntity cmp = null;
private boolean isUpdating = false;
private boolean isEnabled = true;
/**
* Default constructor
*/
public CMPKeySynchronizationAdapter(ContainerManagedEntity cmp) {
super();
this.cmp = cmp;
}
/**
* If the keyAttributes list is empty, try to reflect
* the keyAttributes from the fields of the primaryKey class.
*/
public void initializeKeyAttributes() {
if(cmp == null || initialized)
return;
Resource res = cmp.eResource();
if(res == null)
return;
boolean cachedIsModified = res.isModified();
try {
// Handle primkeyfield scenario
if (cmp.getPrimKeyField()!=null)
initializeForPrimKey();
// Handle compound key scenario
else
initializeForCompoundKey();
} finally {
res.setModified(cachedIsModified);
}
initialized = true;
}
protected void initializeForPrimKey() {
// Ensure the key attributes list contains only the primKeyField attribute
if (!(getKeyAttributes().size()==1 && getKeyAttributes().contains(cmp.getPrimKeyField())))
primKeyFieldChanged(cmp.getPrimKeyField());
}
protected void initializeForCompoundKey() {
List keys = getKeyAttributes();
// clear key list
keys.clear();
//ensure the key class is not null
JavaClass keyClass = cmp.getPrimaryKey();
if (keyClass == null)
return;
keyClass.eAdapters().add(this);
// reflect key fields into key attributes list
List keyFields = keyClass.getFieldsExtended();
for (int i = 0; i < keyFields.size(); i++) {
Field field = (Field) keyFields.get(i);
if (field.getJavaVisibility() == JavaVisibilityKind.PUBLIC_LITERAL) { //only public fields
CMPAttribute keyAttribute = cmp.getPersistentAttribute(field.getName());
if (keyAttribute != null)
keys.add(keyAttribute);
}
}
}
public void notifyChanged(Notification notification) {
if (isUpdating || !isEnabled) return; //we don't want to react to our own changes
try {
isUpdating = true;
EClass featureClass = ((EObject)notification.getNotifier()).eClass();
if (EjbPackage.eINSTANCE.getContainerManagedEntity().equals(featureClass)) {
switch (notification.getFeatureID(ContainerManagedEntity.class)) {
// handle if cmp attribute is updated, added, removed
case EjbPackage.CONTAINER_MANAGED_ENTITY__PERSISTENT_ATTRIBUTES : {
handleCMPAttributeEvent(notification);
break;
}
// handle the key attributes list is updated programatically
case EjbPackage.CONTAINER_MANAGED_ENTITY__KEY_ATTRIBUTES : {
handleCMPAttributeEvent(notification);
break;
}
// handle if the key class is changed,added, removed
case EjbPackage.CONTAINER_MANAGED_ENTITY__PRIMARY_KEY : {
handleKeyClassEvent(notification);
break;
}
// handle prim key field sets, adds, removes
case EjbPackage.CONTAINER_MANAGED_ENTITY__PRIM_KEY_FIELD : {
handlePrimKeyFieldEvent(notification);
break;
}
}
} else if (EjbPackage.eINSTANCE.getCMPAttribute().equals(featureClass)) {
switch (notification.getFeatureID(CMPAttribute.class)) {
// handle a set or change of an attribute name
case (EjbPackage.CMP_ATTRIBUTE__NAME) : {
handleCMPAttributeRenameEvent((CMPAttribute)notification.getNotifier(), notification.getOldValue());
break;
}
}
}
} finally {
// restore initial notification state
isUpdating = false;
}
}
/**
* @param attribute
*/
private void handleCMPAttributeRenameEvent(CMPAttribute attribute, Object oldValue) {
// if renamed attribute was in key and is not anymore, remove it from key list
if (getKeyAttributes().contains(attribute)) {
if (!isAttributeKeyClassField(attribute.getName()))
removeKeyAttribute(attribute,(String)oldValue);
}
// if renamed attribute is now part of the key, add it to the key list
else
attributeAdded(attribute);
}
/**
* @param notification
*/
private void handlePrimKeyFieldEvent(Notification notification) {
EObject newPrimKeyField = (EObject)notification.getNewValue();
cmp.setPrimKeyField((CMPAttribute)newPrimKeyField);
// if primKeyField is removed or a proxy, recompute key attributes based on key class
if (newPrimKeyField == null || newPrimKeyField.eIsProxy()) {
CMPAttribute primField = (CMPAttribute)newPrimKeyField;
if (primField!=null && primField.getName() == null) {
primField.setName(((InternalEObject)primField).eProxyURI().toString());
makePrimKeyFieldProxy(primField.getName());
}
removeAllKeyAttributes();
initialized = false;
initializeKeyAttributes();
}
// Ensure the key attributes list contains only the primKeyField attribute
else if (!(getKeyAttributes().size()==1 && getKeyAttributes().contains(newPrimKeyField))) {
primKeyFieldChanged(newPrimKeyField);
}
}
/**
* @param notification
*/
private void handleKeyClassEvent(Notification notification) {
// if primkey null or proxy, clear key fields and reinitialize if key class not null
if (cmp.getPrimKeyField()==null || cmp.getPrimKeyField().eIsProxy()) {
keyClassChanged();
}
// if primkey is not null, then do nothing
}
/**
* @param notification
*/
private void handleCMPAttributeEvent(Notification notification) {
int eventType = notification.getEventType();
// handle a CMPAttribute added
if (eventType == Notification.ADD) {
attributeAdded((CMPAttribute)notification.getNewValue());
}
// handle a CMPAttribute removed
else if (eventType == Notification.REMOVE) {
CMPAttribute attribute = (CMPAttribute)notification.getOldValue();
// remove this adapter from the deleted attribute
attribute.eAdapters().remove(this);
removeKeyAttribute(attribute, attribute.getName());
}
}
protected void removeKeyAttribute(CMPAttribute attribute, String oldName) {
// if attribute was a key attribute it will be removed, otherwise do nothing
getKeyAttributes().remove(attribute);
// if it is the prim key attribute, then make the prim key attribute a proxy
if (cmp.getPrimKeyField()!=null && cmp.getPrimKeyField().equals(attribute)) {
makePrimKeyFieldProxy(oldName);
}
}
public void makePrimKeyFieldProxy(String oldName) {
if (cmp.getPrimKeyField() == null) return;
cmp.setPrimKeyField(EjbFactory.eINSTANCE.createCMPAttribute());
cmp.getPrimKeyField().setName(oldName);
((InternalEObject)cmp.getPrimKeyField()).eSetProxyURI(URI.createURI(oldName));
}
protected void removeAllKeyAttributes() {
// clear key attributes list on cmp
getKeyAttributes().clear();
}
protected void addKeyAttribute(CMPAttribute attribute) {
CMPAttribute primKeyField = cmp.getPrimKeyField();
// if prim key is null add attribute to key list
if (primKeyField==null || primKeyField.eIsProxy()) {
if (!getKeyAttributes().contains(attribute))
getKeyAttributes().add(attribute);
// if att is only key att, and type is the key class type, set the prim key field
if (getKeyAttributes().size()==1 && attribute.getType().equals(cmp.getPrimaryKey()))
cmp.setPrimKeyField(attribute);
}
// if primkey set + primkeyfield is the new attribute ensure its the only one
else if (primKeyField.equals(attribute)) {
if (!(getKeyAttributes().size()==1 && getKeyAttributes().contains(attribute))) {
getKeyAttributes().clear();
getKeyAttributes().add(attribute);
}
}
// if primkey set,new attribute not prim key, key atts > 1, remove primkey field
else {
cmp.setPrimKeyField(null);
if (!getKeyAttributes().contains(attribute))
getKeyAttributes().add(attribute);
}
}
protected void attributeAdded(CMPAttribute attribute) {
//Make sure cmp key adapters are initialized if needed
cmp.getKeyAttributes();
// add this as a listener to name changes on this attribute
if (!attribute.eAdapters().contains(this))
attribute.eAdapters().add(this);
if (attribute.getName() ==null) return;
// add it to the key list if applicable and sort the key list
if (isAttributeKeyClassField(attribute.getName())) {
addKeyAttribute(attribute);
sortKeyAttributeList();
}
// if new attribute name is now prim key name, fix up prim key field
else if (cmp.getPrimKeyField()!=null && cmp.getPrimKeyField().eIsProxy() && attribute.getName().equals(cmp.getPrimKeyField().getName())) {
cmp.setPrimKeyField(attribute);
primKeyFieldChanged(attribute);
}
}
/**
* Is the cmp attribute also a field in the key class?
*/
protected boolean isAttributeKeyClassField(String attributeName) {
// ensure key class is not null
JavaClass keyClass = cmp.getPrimaryKey();
if (keyClass == null)
return false;
// see if the attribute name matchs any of the reflected key class public field names
List keyFields = keyClass.getFieldsExtended();
for (int i = 0; i < keyFields.size(); i++) {
Field field = (Field) keyFields.get(i);
if (field.getJavaVisibility() == JavaVisibilityKind.PUBLIC_LITERAL) {
if (field.getName().equals(attributeName))
return true;
}
}
return false;
}
/**
* Sort the list of the key attributes to match the order of the key class
*/
private void sortKeyAttributeList() {
List result = new ArrayList();
JavaClass keyClass = cmp.getPrimaryKey();
if (keyClass == null) return;
List keyFields = keyClass.getFieldsExtended();
List currentKeys = getKeyAttributes();
// create a new list of the attributes in order of key class fields.
for (int i = 0; i < keyFields.size(); i++) {
Field field = (Field) keyFields.get(i);
if (field.getJavaVisibility() == JavaVisibilityKind.PUBLIC_LITERAL) { //only public fields
for (int j=0; j<currentKeys.size(); j++) {
CMPAttribute attribute = (CMPAttribute) currentKeys.get(j);
if (field.getName().equals(attribute.getName()))
result.add(attribute);
}
}
}
//clear list and set the new key attribute order on the cmp
getKeyAttributes().clear();
getKeyAttributes().addAll(result);
}
protected void keyClassChanged() {
JavaClass key = cmp.getPrimaryKey();
if (key !=null)
key.eAdapters().remove(this);
// if not prim key class, clear key attribute list
removeAllKeyAttributes();
initialized = false;
initializeKeyAttributes();
}
protected void primKeyFieldChanged(EObject primKeyField) {
// if a primKeyField is added, do a remove all and an add
removeAllKeyAttributes();
if (primKeyField != null && !primKeyField.eIsProxy()) {
if (!primKeyField.eAdapters().contains(this))
primKeyField.eAdapters().add(this);
getKeyAttributes().add(primKeyField);
}
}
private EList getKeyAttributes() {
return ((ContainerManagedEntityImpl)cmp).getKeyAttributesGen();
}
/* (non-Javadoc)
* @see org.eclipse.emf.common.notify.impl.AdapterImpl#setTarget(org.eclipse.emf.common.notify.Notifier)
*/
public void setTarget(Notifier newTarget) {
super.setTarget(newTarget);
}
/* (non-Javadoc)
* @see org.eclipse.emf.common.notify.impl.AdapterImpl#isAdapterForType(java.lang.Object)
*/
public boolean isAdapterForType(Object type) {
return ADAPTER_TYPE.equals(type);
}
//To turn sync on or off
public void setEnabled(boolean enabled){
isEnabled = enabled;
}
}