/***********************************************************************
 * Copyright (c) 2008 by SAP AG, Walldorf. 
 * 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:
 *     SAP AG - initial API and implementation
 ***********************************************************************/
package org.eclipse.jst.jee.model.internal.common;

import java.util.Collection;
import java.util.HashSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jst.j2ee.model.IModelProvider;
import org.eclipse.jst.j2ee.model.IModelProviderEvent;
import org.eclipse.jst.j2ee.model.IModelProviderListener;
import org.eclipse.jst.javaee.core.JavaEEObject;
import org.eclipse.jst.javaee.core.SecurityRole;
import org.eclipse.jst.javaee.core.SecurityRoleRef;
import org.eclipse.jst.javaee.ejb.SessionBean;
import org.eclipse.jst.jee.JEEPlugin;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;

/**
 * Base implementation for model providers based on annotations in java files.
 * 
 * Listeners can be registered with {@link #addListener(IModelProviderListener)}
 * 
 * @author Kiril Mitov k.mitov@sap.com
 * 
 */
public abstract class AbstractAnnotationModelProvider<T> implements IElementChangedListener, IModelProvider {

	private static final String JAVA_EXTENSION = "java"; //$NON-NLS-1$

	/**
	 * Find the security role with the given name in the given assembly
	 * descriptor.
	 * 
	 * @param assembly
	 * @param name
	 * @return <code>null</code> if a security role with this name can not be
	 *         found
	 */
	private static SecurityRole findRole(Collection<SecurityRole> securityRoles, String name) {
		for (SecurityRole role : securityRoles) {
			if (role.getRoleName().equals(name))
				return role;
		}
		return null;
	}

	protected T modelObject;

	private Collection<IModelProviderListener> listeners;

	private Lock listenersLock = new ReentrantLock();

	protected IFacetedProject facetedProject;

	private ManyToOneRelation<SecurityRoleRef, SecurityRole> rolesToRolesRef = new ManyToOneRelation<SecurityRoleRef, SecurityRole>();

	/**
	 * Constructs a new AnnotationReader for this faceted project. An illegal
	 * argument if a project with value <code>null</code> is passed. No loading
	 * is done in this constructor. Loading the model is made on demand when
	 * calling {@link #getModelObject()}.
	 * 
	 * @param project
	 *            the ejb project. Can not be <code>null</code>
	 */
	public AbstractAnnotationModelProvider(IFacetedProject project) {
		if (project == null)
			throw new IllegalArgumentException("The project argument can not be null");
		this.facetedProject = project;
	}

	public T getConcreteModel() {
		if (modelObject == null) {
			preLoad();
			try {
				loadModel();
				/*
				 * Adding the resource change listener after loading the model.
				 * No resource change event are acceptable while loading the
				 * model.
				 */
				postLoad();
			} catch (CoreException e) {
				log(e.getStatus());
				return null;
			}
		}
		return modelObject;
	}

	public Object getModelObject() {
		return getConcreteModel();
	}

	public Object getModelObject(IPath modelPath) {
		return getConcreteModel();
	}

	protected abstract void loadModel() throws CoreException;

	protected void preLoad() {
	}

	protected void postLoad() {
		JavaCore.addElementChangedListener(this);
	}

	/**
	 * Notifies the currently registered listeners with this model event. If the
	 * {@link IModelProviderEvent#getChangedResources()} is empty or
	 * <code>null</code> the method returns immediately.
	 * 
	 * @param event
	 *            the event that should be send to the listeners
	 */
	protected void notifyListeners(final IModelProviderEvent event) {
		notifyListeners(listeners, event);
	}

	/**
	 * Clears the list of listeners. No notifications can occur while clearing
	 * the listeners.
	 */
	protected void clearListeners() {
		if (listeners == null)
			return;
		try {
			listenersLock.lock();
			listeners.clear();
			listeners = null;
		} finally {
			listenersLock.unlock();
		}
	}

	private void notifyListeners(final Collection<IModelProviderListener> aListeners, final IModelProviderEvent event) {
		if (listeners == null)
			return;
		listenersLock.lock();
		try {
			if (event.getChangedResources() == null || event.getChangedResources().isEmpty())
				return;
			for (final IModelProviderListener listener : aListeners) {
				SafeRunner.run(new ISafeRunnable() {
					public void handleException(Throwable exception) {
					}

					public void run() throws Exception {
						listener.modelsChanged(event);
					}
				});
			}
		} finally {
			listenersLock.unlock();
		}

	}

	/**
	 * @return the currently registered listeners.
	 */
	protected Collection<IModelProviderListener> getListeners() {
		if (listeners == null) {
			listeners = new HashSet<IModelProviderListener>();
		}
		return listeners;
	}

	/**
	 * Adds a listener to this instance. No listeners can be added during
	 * notifying the current listeners.
	 * 
	 * @param listener
	 */
	public void addListener(IModelProviderListener listener) {
		listenersLock.lock();
		try {
			getModelObject();
			getListeners().add(listener);
		} finally {
			listenersLock.unlock();
		}
	}

	/**
	 * Removes the listener from this instance. Has no effect if an identical
	 * listener is not registered.
	 * 
	 * @param listener
	 *            the listener to be removed.
	 */
	public void removeListener(IModelProviderListener listener) {
		listenersLock.lock();
		try {
			getListeners().remove(listener);
		} finally {
			listenersLock.unlock();
		}

	}

	/**
	 * @param javaProject
	 * @return true if the given project contains resources that are relative to
	 *         the model. This method returns <code>true</code> for the
	 *         ejbProject on which this instance is working a <code>true</code>
	 *         for its client project.
	 */
	protected boolean isProjectRelative(IJavaProject javaProject) {
		if (javaProject == null || facetedProject == null)
			return false;
		else if (javaProject.getProject().equals(facetedProject.getProject()))
			return true;
		return false;
	}

	/**
	 * Dispose the current instance. The actual dispose may occur in another
	 * thread. Use {@link #addListener(IModelProviderListener)} to register a
	 * listener that will be notified when the instance is disposed. After all
	 * the listeners are notified the list of listeners is cleared.
	 */
	public void dispose() {
		IModelProviderEvent modelEvent = createModelProviderEvent();
		modelEvent.addResource(facetedProject.getProject());
		modelEvent.setEventCode(modelEvent.getEventCode() | IModelProviderEvent.PRE_DISPOSE);
		JavaCore.removeElementChangedListener(this);
		modelObject = null;
		notifyListeners(modelEvent);
		clearListeners();
	}

	/**
	 * Process a unit as "removed". The method is allowed not to make checks
	 * whether the unit was added/removed/change. It is processing the unit as
	 * "removed".
	 * 
	 * If no model object depends on the given file "modelEvent" is not changed.
	 * 
	 * @see #processAddedCompilationUnit(IModelProviderEvent, ICompilationUnit)
	 * @param modelEvent
	 * @param file
	 *            the file to be removed.
	 * @throws CoreException
	 *             if there was an error during parsing the file
	 */
	protected abstract void processRemovedCompilationUnit(IModelProviderEvent modelEvent, ICompilationUnit unit)
			throws CoreException;

	/**
	 * Process a unit as "added". The method is allowed not to make checks
	 * whether the unit was added/removed/change. It is processing the file as
	 * "added". It is the responsibility of the caller to make sure the
	 * processing of the file as added will not leave the model in a wrong
	 * state.
	 * 
	 * modelEvent is changed to contain information about the added modelObject.
	 * 
	 * @see #processRemovedCompilationUnit(IModelProviderEvent,
	 *      ICompilationUnit)
	 * @param modelEvent
	 * @param file
	 *            the file that was added
	 * @throws CoreException
	 */
	protected abstract void processAddedCompilationUnit(IModelProviderEvent modelEvent, ICompilationUnit file)
			throws CoreException;

	/**
	 * Process a unit as "changed". The method is allowed not to make checks
	 * whether the unit was added/removed/change. It is processing the unit as
	 * "changed". It is the responsibility of the caller to make sure the
	 * processing of the file as "changed" will not leave the model in a wrong
	 * state.
	 * 
	 * @see #processAddedCompilationUnit(IModelProviderEvent, ICompilationUnit)
	 * @see #processRemovedCompilationUnit(IModelProviderEvent,
	 *      ICompilationUnit)
	 * @param modelEvent
	 * @param unit
	 *            the unti that was changed
	 * @throws CoreException
	 */
	protected abstract void processChangedCompilationUnit(IModelProviderEvent modelEvent, ICompilationUnit file)
			throws CoreException;

	protected void log(IStatus status) {
	}

	protected MyModelProviderEvent createModelProviderEvent() {
		return new MyModelProviderEvent(0, null, facetedProject.getProject());
	}

	// ---------------SECURITY ROLES ---------------------------//
	protected abstract Collection<SecurityRole> getSecurityRoles();

	protected abstract Collection<SecurityRoleRef> getSecurityRoleRefs(JavaEEObject target);

	/**
	 * Deletes the connection maintained by the given bean and the security
	 * roles defined in the bean. If this is the only bean in which the role is
	 * defined, the role will also be deleted. Calling this method makes sense
	 * only if the bean and the security role and the bean were connected with
	 * {@link #connectWithRole(SecurityRole, SessionBean)}
	 * 
	 * <p>
	 * If the bean is not of type org.eclipse.jst.javaee.ejb.SessionBean the
	 * method returns immediately.
	 * </p>
	 * 
	 * @see #connectWithRole(SecurityRole, SessionBean)
	 * @see #rolesToRolesRef
	 * @param bean
	 */
	protected void disconnectFromRoles(JavaEEObject target) {
		Collection<SecurityRole> roles = getSecurityRoles();
		if (roles == null)
			return;
		Collection<SecurityRoleRef> refs = getSecurityRoleRefs(target);
		if (refs == null)
			return;
		for (SecurityRoleRef ref : refs) {
			SecurityRole role = rolesToRolesRef.getTarget(ref);
			rolesToRolesRef.disconnectSource(ref);
			if (!rolesToRolesRef.containsTarget(role)) {
				getSecurityRoles().remove(role);
			}
		}
	}

	/**
	 * A security role was found in the given file. Add this security role to
	 * the assembly descriptor. If the ejbJar does not have an assembly
	 * descriptor a new one is created.
	 * 
	 * @see #connectRoleWithBean(SecurityRole, SessionBean)s
	 * @param file
	 * @param securityRole
	 */
	protected void securityRoleFound(JavaEEObject object, SecurityRole securityRole) {
		connectWithRole(securityRole, object);
	}

	/**
	 * A security role can be defined in more the one bean. A bean can define
	 * more then one security role. This means we have a many-to-many relation
	 * between sessionBeans and securityRoles.
	 * 
	 * <p>
	 * Luckily a sessionBean contains a list of securityRoleRefs. This method
	 * creates a connection between the securityRole contained in the assembly
	 * descriptor and the security role ref contained in the bean.
	 * 
	 * If a security role is define only in one bean, deleting the bean means
	 * deleting the security role. But if the security role is defined in two
	 * beans only deleting both beans will result in deleting the security role.
	 * </p>
	 * 
	 * @see #disconnectFromRoles(JavaEEObject)
	 * @see #rolesToRolesRef
	 * @param securityRole
	 * @param target
	 */
	private void connectWithRole(SecurityRole securityRole, JavaEEObject target) {
		Collection<SecurityRole> roles = getSecurityRoles();
		if (roles == null)
			return;
		Collection<SecurityRoleRef> refs = getSecurityRoleRefs(target);
		if (refs == null)
			return;
		/*
		 * If there is a security role with this name use the existing security
		 * role.
		 */
		SecurityRole role = findRole(roles, securityRole.getRoleName());
		if (role == null) {
			roles.add(securityRole);
			role = securityRole;
		}
		for (SecurityRoleRef ref : refs) {
			if (ref.getRoleName().equals(role.getRoleName()))
				rolesToRolesRef.connect(ref, role);
		}
	}

	public void elementChanged(final ElementChangedEvent javaEvent) {
		if (javaEvent.getType() == ElementChangedEvent.POST_RECONCILE)
			internalPostReconcile(javaEvent);
		else if (javaEvent.getType() == ElementChangedEvent.POST_CHANGE)
			internalPostChange(javaEvent);
	}

	private void internalPostChange(ElementChangedEvent javaEvent) {
		IModelProviderEvent modelEvent = createModelProviderEvent();
		// handles ElementChangedEvent.POST_CHANGE - the case when the
		// compilation unit has been changed
		for (IJavaElementDelta child : javaEvent.getDelta().getAffectedChildren()) {
			if (child.getElement() instanceof IJavaProject) {
				processChangedProject(modelEvent, child);
				notifyListeners(modelEvent);
			}
		}
	}

	private void internalPostReconcile(final ElementChangedEvent javaEvent) {
		IModelProviderEvent modelEvent = createModelProviderEvent();
		if (javaEvent.getDelta().getElement() instanceof ICompilationUnit) {
			recursevilyProcessCompilationUnits(modelEvent, javaEvent.getDelta());
			notifyListeners(modelEvent);
		}
	}

	protected void processChangedProject(IModelProviderEvent event, IJavaElementDelta projectDelta) {
		if (!isProjectRelative(projectDelta.getElement().getJavaProject())) {
			return;
		}
		Assert.isTrue(projectDelta.getElement() instanceof IJavaProject,
				"An invalid change notification has occured. Element is <" + projectDelta.getElement() + ">"); //$NON-NLS-1$//$NON-NLS-2$
		if (((projectDelta.getFlags() & IJavaElementDelta.F_OPENED) != 0)
				|| projectDelta.getKind() == IJavaElementDelta.ADDED) {
			try {
				loadModel();
			} catch (CoreException e) {
				JEEPlugin.getDefault().getLog().log(
						new Status(IStatus.ERROR, JEEPlugin.getDefault().getPluginID(), e.getMessage(), e));
			}
		}

		if (((projectDelta.getFlags() & IJavaElementDelta.F_CLOSED) != 0)
				|| projectDelta.getKind() == IJavaElementDelta.REMOVED) {
			dispose();
		}

		processChangedProjectChildren(event, projectDelta);
	}

	protected void processChangedProjectChildren(IModelProviderEvent event, IJavaElementDelta projectDelta) {
		for (IJavaElementDelta childDelta : projectDelta.getAffectedChildren()) {
			if (!(childDelta.getElement() instanceof IPackageFragmentRoot)) {
				continue;
			}
			if ((childDelta.getFlags() & IJavaElementDelta.F_CHILDREN) != 0) {
				recursevilyProcessPackages(event, childDelta);
			}
		}
	}

	public void recursevilyProcessPackages(IModelProviderEvent modelEvent, IJavaElementDelta delta) {
		if (delta.getElement() instanceof IPackageFragment) {
			try {
				IPackageFragment fragment = (IPackageFragment) delta.getElement();
				if (delta.getKind() == IJavaElementDelta.ADDED) {
					for (ICompilationUnit unit : fragment.getCompilationUnits()) {
						processAddedCompilationUnit(modelEvent, unit);
					}
				} else if (delta.getKind() == IJavaElementDelta.REMOVED) {
					if (delta.getKind() == IJavaElementDelta.REMOVED) {
						processRemovedPackage(modelEvent, delta);
					}
				} else if (delta.getKind() == IJavaElementDelta.CHANGED) {
					recursevilyProcessCompilationUnits(modelEvent, delta);
				}
			} catch (CoreException e) {
				JEEPlugin.getDefault().getLog().log(
						new Status(IStatus.ERROR, JEEPlugin.getDefault().getPluginID(), e.getMessage(), e));
			}
		} else {
			for (IJavaElementDelta childDelta : delta.getAffectedChildren()) {
				recursevilyProcessPackages(modelEvent, childDelta);
			}
		}
	}

	protected abstract void processRemovedPackage(IModelProviderEvent modelEvent, IJavaElementDelta delta)
			throws CoreException;

	public void recursevilyProcessCompilationUnits(IModelProviderEvent modelEvent, IJavaElementDelta delta) {
		if (delta.getElement() instanceof ICompilationUnit) {
			if (!isProjectRelative(delta.getElement().getJavaProject()))
				return;
			try {
				final ICompilationUnit unit = (ICompilationUnit) delta.getElement();

				if (delta.getKind() == IJavaElementDelta.ADDED) {
					processAddedCompilationUnit(modelEvent, unit);
				}
				if (delta.getKind() == IJavaElementDelta.REMOVED) {
					processRemovedCompilationUnit(modelEvent, unit);
				}
				if (delta.getKind() == IJavaElementDelta.CHANGED) {
					if (((delta.getFlags() & IJavaElementDelta.F_PRIMARY_RESOURCE) == 0)
							|| ((delta.getFlags() & IJavaElementDelta.F_PRIMARY_WORKING_COPY) == 0)) {
						processChangedCompilationUnit(modelEvent, unit);
					}
				}
			} catch (CoreException e) {
				JEEPlugin.getDefault().getLog().log(
						new Status(IStatus.ERROR, JEEPlugin.getDefault().getPluginID(), e.getMessage(), e));
			}
		} else {
			for (IJavaElementDelta childDelta : delta.getAffectedChildren()) {
				recursevilyProcessCompilationUnits(modelEvent, childDelta);
			}
		}
	}

	protected void visitJavaFiles(final Collection<ICompilationUnit> javaFiles, final IPackageFragmentRoot root)
			throws CoreException {
		if (root.getKind() != IPackageFragmentRoot.K_SOURCE)
			return;
		root.getCorrespondingResource().accept(new IResourceProxyVisitor() {
			public boolean visit(IResourceProxy proxy) throws CoreException {
				if (proxy.getType() == IResource.FILE) {
					if (proxy.getName().endsWith("." + JAVA_EXTENSION)) { //$NON-NLS-1$
						IFile file = (IFile) proxy.requestResource();
						if (!root.getJavaProject().isOnClasspath(file))
							return false;
						if (!file.isSynchronized(IResource.DEPTH_ONE))
							return false;
						javaFiles.add(JavaCore.createCompilationUnitFrom(file));
					}
					return false;
				}
				return true;
			}
		}, IContainer.NONE);

	}
}
