/***********************************************************************
 * 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.ArrayList;
import java.util.Collection;
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"); //$NON-NLS-1$
		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) {
		if (listeners == null)
			return;
		listenersLock.lock();
		try {
			IModelProviderListener[] backup = listeners.toArray(new IModelProviderListener[listeners.size()]);
			notifyListeners(backup, event);
			backup = null;
		} finally {
			listenersLock.unlock();
		}
	}

	/**
	 * 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 IModelProviderListener[] aListeners, final IModelProviderEvent event) {
		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);
				}
			});
		}
	}

	/**
	 * @return the currently registered listeners.
	 */
	protected Collection<IModelProviderListener> getListeners() {
		if (listeners == null) {
			listeners = new ArrayList<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(IModelProviderEvent.UNLOADED_RESOURCE);
		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
	 *            subclasses should "fill" modelEvent with information about the
	 *            change that has happened. This event will be propagated to
	 *            model provided listeners.
	 * @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
	 *            subclasses should "fill" modelEvent with information about the
	 *            change that has happened. This event will be propagated to
	 *            model provided listeners.
	 * @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
	 *            subclasses should "fill" modelEvent with information about the
	 *            change that has happened. This event will be propagated to
	 *            model provided listeners.
	 * @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)) {
						modelEvent
								.setEventCode(IModelProviderEvent.KNOWN_RESOURCES_CHANGED | modelEvent.getEventCode());
						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);

	}
}
