/*******************************************************************************
 * Copyright (c) 2003, 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
 *******************************************************************************/
package org.eclipse.jst.j2ee.internal.common;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.emf.common.notify.AdapterFactory;
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.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jem.internal.adapters.jdom.JavaJDOMAdapterFactory;
import org.eclipse.jem.internal.java.adapters.ReadAdaptor;
import org.eclipse.jem.internal.java.adapters.ReflectionAdaptor;
import org.eclipse.jem.java.Field;
import org.eclipse.jem.java.JavaClass;
import org.eclipse.jem.java.JavaVisibilityKind;
import org.eclipse.jem.java.util.NotificationUtil;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jem.util.emf.workbench.nature.EMFNature;
import org.eclipse.jst.j2ee.ejb.CMPAttribute;
import org.eclipse.jst.j2ee.ejb.ContainerManagedEntity;
import org.eclipse.jst.j2ee.ejb.EJBJar;
import org.eclipse.jst.j2ee.ejb.EjbPackage;
import org.eclipse.jst.j2ee.ejb.internal.impl.EjbFactoryImpl;

/**
 * This adapter is used to listen for changes to the ejb class or the primary key class in order to
 * reflect the proper CMP field types and the proper key attributes.
 */
public class CMPJavaChangeSynchronizationAdapter extends AdapterImpl {

	private static final String J2EE_PROJ_MIGRATION_ADAPTER = "J2EEProjectMigration"; //$NON-NLS-1$

	protected static EjbPackage EJB_PACK = EjbFactoryImpl.getPackage();

	private static HashMap enablementMap = new HashMap();

	public static void disable(ContainerManagedEntity cmp) {
		enablementMap.put(cmp, Boolean.FALSE);
	}

	public static void enable(ContainerManagedEntity cmp) {
		enablementMap.put(cmp, Boolean.TRUE);
	}

	public static boolean isEnabled(ContainerManagedEntity cmp) {
		if (!enablementMap.containsKey(cmp))
			return true;
		return ((Boolean) enablementMap.get(cmp)).booleanValue();
	}

	protected Resource cmpResource;

	private List foundKeys = new ArrayList();
	
	/*
	 * This Set is used to avoid reacting to notifications for a notifier while
	 * updating that notifier.
	 */
	private Set updatingSet = new HashSet();

	public CMPJavaChangeSynchronizationAdapter() {
		super();
	} // EJBKeyShapeMaintenanceAdapter

	/**
	 * Notifies if there is change in the key shape.
	 * 
	 * @param Notification
	 *            msg - Message indicates what has changed.
	 */
	public void notifyChanged(Notification msg) {
		if (!isEnabled(getCMP())) {
			enable(getCMP());
			return;
		}
		Object notifier = msg.getNotifier();
		if (!updatingSet.contains(notifier)) {
			try {
				updatingSet.add(notifier);
				switch (msg.getEventType()) {
					case Notification.SET :
						setNotification(msg);
						break;
					case Notification.UNSET :
						unsetNotification(msg);
						break;
					case Notification.REMOVING_ADAPTER :
						removeAdapterNotification(msg);
						break;
					case ReflectionAdaptor.EVENT :
						jemFlushNotification(msg);
						break;
				}
			} finally {
				updatingSet.remove(notifier);
			}
		}
	}

	/**
	 * Use if the there was an set notification.
	 * 
	 * @param Notification
	 *            msg - Message indicates what has changed.
	 */
	protected void setNotification(Notification msg) {
		EStructuralFeature sf = (EStructuralFeature) msg.getFeature();
		if (sf == EJB_PACK.getEnterpriseBean_EjbClass() || sf == EJB_PACK.getEntity_PrimaryKey()) {
			if (!isMigrating()) {
				removeAttributeMaintenanceAdapter((Notifier) msg.getOldValue());
				addAttributeMaintenanceAdapter((Notifier) msg.getNewValue());
				touchKeyShapeAdapter(msg);
			}
		} else if (sf == EJB_PACK.getEntity_PrimaryKey()) {
			removeAttributeMaintenanceAdapter((Notifier) msg.getOldValue());
			if (shouldAddToPrimaryKeyClass((ContainerManagedEntity) getTarget()))
				addAttributeMaintenanceAdapter((Notifier) msg.getNewValue());
		} else {
			jemFlushNotification(msg); //In EMF a TOUCH is a SET.
		}
	} // setNotification

	/**
	 * @return
	 */
	private boolean isMigrating() {
		EJBJar jar = ((ContainerManagedEntity) getTarget()).getEjbJar();
		if (jar != null)
			return EcoreUtil.getExistingAdapter(jar, J2EE_PROJ_MIGRATION_ADAPTER) != null;
		return false;
	}

	// setNotification
	/**
	 * Use if the there was an unset notification.
	 * 
	 * @param Notification
	 *            msg - Message indicates what has changed.
	 */
	protected void unsetNotification(Notification msg) {
		EStructuralFeature sf = (EStructuralFeature) msg.getFeature();
		if ((sf == EJB_PACK.getEnterpriseBean_EjbClass() || sf == EJB_PACK.getEntity_PrimaryKey()) && !isMigrating()) {
			removeAttributeMaintenanceAdapter((Notifier) msg.getOldValue());
		}
	} // unsetNotification

	/**
	 * Use if the there was an touch notification.
	 * 
	 * @param Notification
	 *            msg - Message indicates what has changed.
	 */
	protected void jemFlushNotification(Notification msg) {
		if ((NotificationUtil.isFlushNewEvent(msg) || NotificationUtil.isFlushEvent(msg)) && !isMigrating()) {
			if (msg.getNotifier() == ((ContainerManagedEntity) getTarget()).getEjbClass()) {
				touchBeanAdapter(msg);
			} else if (msg.getNotifier() == ((ContainerManagedEntity) getTarget()).getPrimaryKey()) {
				touchKeyShapeAdapter(msg);
			} // if
			//if the notifier is eq the primary key
			//else ejb bean class flush
		} // if
	} // touchNotification

	protected void removeAdapterNotification(Notification msg) {
		if (msg.getOldValue() == this && msg.getNotifier() instanceof ContainerManagedEntity) {
			ContainerManagedEntity cmp = (ContainerManagedEntity) msg.getNotifier();
			if (cmp.getEjbClass() != null)
				cmp.getEjbClass().eAdapters().remove(this);
			if (cmp.getPrimaryKey() != null)
				cmp.getPrimaryKey().eAdapters().remove(this);
		}
	}

	/**
	 * Adds the key shape adapter
	 * 
	 * @param Notifier
	 *            notifier - The current notifier.
	 */
	protected void addAttributeMaintenanceAdapter(Notifier notifier) {
		if (notifier != null && !notifier.eAdapters().contains(this))
			notifier.eAdapters().add(this);
	}

	/**
	 * Remove the key shape adapter
	 */
	protected void removeAttributeMaintenanceAdapter(Notifier notifier) {
		if (notifier != null)
			notifier.eAdapters().remove(this);
	}

	/**
	 * The key has been touched.
	 * 
	 * @param Notification
	 *            msg - The notification message.
	 */
	protected void touchKeyShapeAdapter(Notification msg) {
		if (msg == null)
			return;
		ContainerManagedEntity cmp = (ContainerManagedEntity) getTarget();
		JavaClass primaryKeyClass = cmp.getPrimaryKey();
		//Synch the two lists.
		synchCMPandKeyAttributes(cmp, primaryKeyClass);
	} // touchKeyShapeAdapter

	/**
	 * The ejb class has been flushed.
	 * 
	 * @param Notification
	 *            msg - The notification message.
	 */
	protected void touchBeanAdapter(Notification msg) {
		if (msg == null)
			return;
		ContainerManagedEntity cmp = (ContainerManagedEntity) getTarget();
		List cmpAttributes = cmp.getPersistentAttributes();
		if (cmpAttributes != null || !cmpAttributes.isEmpty()) {
			boolean modFlag = getCurrentModificationFlag();
			try {
				for (int i = 0; i < cmpAttributes.size(); i++) {
					CMPAttribute cmpAttr = (CMPAttribute) cmpAttributes.get(i);
					if (cmpAttr != null && !cmpAttr.isDerived()) {
						cmpAttr.setEType(null);
					}
				}
			} finally {
				setModificationFlag(modFlag);
			}
		}
		synchCMPandKeyAttributes(cmp, cmp.getPrimaryKey());
	}

	/**
	 * Synchronzies the cmp and primary key class attributes.
	 * 
	 * @param ContainerManagedEntity
	 *            cmp - The cmp.
	 * @param JavaClass
	 *            primaryKeyClass
	 */
	protected void synchCMPandKeyAttributes(ContainerManagedEntity cmp, JavaClass primaryKeyClass) {
		if (cmp == null || primaryKeyClass == null || cmp.getPrimKeyField() != null || primaryKeyClass.getQualifiedName().startsWith("java.lang")) //$NON-NLS-1$
			return;

		// make sure we flush the primary key to get latest updates if no save
		// took place
		flushPrimaryKeyClass(primaryKeyClass);

		List cmpAttributes = cmp.getPersistentAttributes();
		if (cmpAttributes != null || !cmpAttributes.isEmpty()) {
			foundKeys.clear();
			List keyAttributesList = cmp.getKeyAttributes();
			foundKeys.addAll(keyAttributesList);
			boolean modFlag = getCurrentModificationFlag();
			try {
				List keyFields = primaryKeyClass.getFieldsExtended();
				for (int i = 0; i < keyFields.size(); i++) {
					Field field = (Field) keyFields.get(i);
					if (field.getJavaVisibility() != JavaVisibilityKind.PUBLIC_LITERAL)
						continue;
					String fieldName = field.getName();
					if (fieldName != null) {
						CMPAttribute keyAttr = cmp.getKeyAttribute(fieldName);
						if (keyAttr == null)
							cmp.addKeyAttributeName(fieldName);
						else
							foundKeys.remove(keyAttr);
					}
				}
				if (!foundKeys.isEmpty())
					keyAttributesList.removeAll(foundKeys);
			} finally {
				setModificationFlag(modFlag);
			}
		}
	}

	public void setTarget(Notifier newTarget) {
		boolean isChanged = getTarget() != newTarget;
		if (newTarget == null) {
			super.setTarget(newTarget);
			cmpResource = null;
		} else if (newTarget instanceof ContainerManagedEntity) {
			//TODO - uncomment when compile errors are gone
			if (false)/* (EJBCommandCopier.isCodegenCopy(newTarget)) */
				newTarget.eAdapters().remove(this);
			else {
				Resource res = ((ContainerManagedEntity) newTarget).eResource();
				if (res != null && res.getResourceSet() != null) {
					super.setTarget(newTarget);
					if (isChanged)
						initializeTarget();
				}
			}
		}
	}

	/**
	 *  
	 */
	private void initializeTarget() {
		ContainerManagedEntity cmp = (ContainerManagedEntity) getTarget();
		addAttributeMaintenanceAdapter(cmp.getEjbClass());
		if (shouldAddToPrimaryKeyClass(cmp))
			addAttributeMaintenanceAdapter(cmp.getPrimaryKey());
	}

	private boolean shouldAddToPrimaryKeyClass(ContainerManagedEntity cmp) {
		return cmp.getPrimKeyField() == null && cmp.getPrimaryKey() != null && !cmp.getPrimaryKey().getQualifiedName().startsWith("java.lang"); //$NON-NLS-1$
	}

	protected Resource getCMPResource() {
		if (cmpResource == null && getTarget() != null)
			cmpResource = ((EObject) getTarget()).eResource();
		return cmpResource;
	}

	protected boolean getCurrentModificationFlag() {
		return getCMPResource() != null && cmpResource.getContents() != null ? cmpResource.isModified() : false;
	}

	protected void setModificationFlag(boolean aBoolean) {
		if (getCMPResource() != null)
			getCMPResource().setModified(aBoolean);
	}

	public ContainerManagedEntity getCMP() {
		if (getTarget() instanceof ContainerManagedEntity)
			return (ContainerManagedEntity) getTarget();
		return null;
	}

	protected boolean flushPrimaryKeyClass(JavaClass primaryKeyClass) {
		// ensure the primary key class is flushed and reloaded to get latest
		// content
		IProject p = ProjectUtilities.getProject(primaryKeyClass);
		try {
			List natures = EMFNature.getRegisteredRuntimes(p);
			EMFNature nature = null;
			for (int i = 0; i < natures.size(); i++) {
				if (natures.get(i) instanceof EMFNature)
					nature = (EMFNature) natures.get(i);
			}
			List adapterFactories = nature.getResourceSet().getAdapterFactories();
			AdapterFactory factory = EcoreUtil.getAdapterFactory(adapterFactories, ReadAdaptor.TYPE_KEY);
			if (factory instanceof JavaJDOMAdapterFactory) {
				JavaJDOMAdapterFactory javaFactory = (JavaJDOMAdapterFactory) factory;
				javaFactory.flushReflectionNoNotification(primaryKeyClass.getQualifiedName());
				return true;
			}
		} catch (Exception e) {
			// We don't really care what the exception was, we'll just bail out
			// and return false;
		}
		return false;
	}
}
