/*
 * Copyright (c) 2015, 2018 Christian W. Damus and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v20.html
 *
 * Contributors:
 *   Christian W. Damus - Initial API and implementation
 *
 */

package org.eclipse.ocl.examples.pivot.tests;

import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.DiagnosticChain;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.Diagnostician;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.ocl.pivot.internal.delegate.OCLDelegateDomain;
import org.eclipse.ocl.pivot.internal.utilities.GlobalEnvironmentFactory;
import org.eclipse.ocl.pivot.uml.UMLStandaloneSetup;
import org.eclipse.ocl.pivot.uml.internal.es2as.UML2AS;
import org.eclipse.ocl.pivot.utilities.ParserException;
import org.eclipse.uml2.common.util.UML2Util;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.util.UMLUtil;

/**
 * A test case that demonstrates a memory leak in the OCL Validation infrastructure.
 */
public class LeakTests extends PivotTestCaseWithAutoTearDown
{
	/**
	 * This is based on the way Papyrus does validation.
	 */
	static class MyDiagnostician extends Diagnostician
	{
		private boolean validatingStereotype;

		@Override
		public Map<Object, Object> createDefaultContext() {
			Map<Object, Object> context = super.createDefaultContext();
			if (context != null) {
				OCLDelegateDomain.initializePivotOnlyDiagnosticianContext(context);
			}
			return context;
		}

		@Override
		public BasicDiagnostic createDefaultDiagnostic(EObject eObject) {
			ResourceSet resourceSet = eObject.eResource().getResourceSet();
			if (resourceSet != null) {
				OCLDelegateDomain.initializePivotOnlyDiagnosticianResourceSet(resourceSet);
			}
			return super.createDefaultDiagnostic(eObject);
		}

		protected boolean doValidateStereotypeApplications(EObject eObject, DiagnosticChain diagnostics, Map<Object, Object> context) {
			if (validatingStereotype) {
				// this function is called recursively. Avoid trying to obtain stereotype applications, if we are
				// already examining a stereotype
				return true;
			}
			List<EObject> stereotypeApplications = eObject instanceof Element ? ((Element) eObject).getStereotypeApplications() : Collections.<EObject> emptyList();
			if (!stereotypeApplications.isEmpty()) {
				Iterator<EObject> i = stereotypeApplications.iterator();
				boolean result;
				validatingStereotype = true;
				try {
					result = validate(i.next(), diagnostics, context);
					while (i.hasNext() && (result || diagnostics != null)) {
						result &= validate(i.next(), diagnostics, context);
					}
				} finally {
					validatingStereotype = false;
				}
				return result;
			} else {
				return true;
			}
		}

		@Override
		protected boolean doValidateContents(EObject eObject, DiagnosticChain diagnostics, Map<Object, Object> context) {
			boolean result = doValidateStereotypeApplications(eObject, diagnostics, context);
			if (result || diagnostics != null) {
				result &= super.doValidateContents(eObject, diagnostics, context);
			}
			return result;
		}

		@Override
		public boolean validate(EObject eObject, DiagnosticChain diagnostics, Map<Object, Object> context) {
			if (!context.containsKey(this)) {
				// put instance of the UMLDiagnostician into context map to identify first invocation
				// (validate is called recursively)
				context.put(this, null);
				BasicDiagnostic newDiagChain = createDefaultDiagnostic(eObject);
				boolean ok = super.validate(eObject, newDiagChain, context);
				// replace markers here instead of using a validation adapter, see
				// bug 410457 - [Validation] Ghost markers when validating profile constraints
				// bug 410119 - [Validation] markers related to stereotype applications are not updated in diagrams
				// bug 410059 - [Validation] delete subtree does not remove markers associated with stereotypes
				for (Diagnostic d : newDiagChain.getChildren()) {
					Object data[] = d.getData().toArray();
					if (data.length > 0) {
						Object target = data[0];
						if (target instanceof EObject) {
							EObject base = UMLUtil.getBaseElement((EObject) target);
							if (base != null) {
								data[0] = base;
							}
						}
					}
					diagnostics.add(new BasicDiagnostic(d.getSeverity(), d.getSource(), d.getCode(), d.getMessage(), data));
				}
				return ok;
			} else {
				return super.validate(eObject, diagnostics, context);
			}
		}
	}

	/**
	 * A test that demonstrates the memory leak from validation of the model.
	 * @throws ParserException
	 */
	public void testValidateProfileLeak() throws InterruptedException, ParserException {	// Bug 459276
		GlobalEnvironmentFactory.disposeInstance();
		//		PartialModels.PARTIAL_MODELS.setState(true);
		//		UML2AS.CONVERT_RESOURCE.setState(true);
		UMLStandaloneSetup.init();
		ResourceSet resourceSet = new ResourceSetImpl();
		UML2AS.initializeUML(resourceSet);
		URI testModelURI = getTestModelURI("models/uml/Bug459276.uml");
		EClass package1 = UMLPackage.Literals.PACKAGE;
		Package umlModel = UML2Util.load(resourceSet, testModelURI, package1);
		EcoreUtil.resolveAll(resourceSet);
		Profile umlProfile = umlModel.getAppliedProfile("j2ee");
		assertNotNull("No UML Profile for leak test", umlProfile);

		// Validate the model
		Diagnostician diagnostician = new MyDiagnostician();
		diagnostician.validate(umlModel);

		// It doesn't matter what the results of validation are, only that
		// OCL constraints were parsed by the OCL validation delegate

		GlobalEnvironmentFactory globalEnvironmentFactory = GlobalEnvironmentFactory.getInstance();
		org.eclipse.ocl.pivot.Profile asProfile = globalEnvironmentFactory.getASOf(org.eclipse.ocl.pivot.Profile.class, umlProfile);
		assertNotNull("No AS Profile for leak", asProfile);
		WeakReference<org.eclipse.uml2.uml.Profile> umlProfileRef = new WeakReference<org.eclipse.uml2.uml.Profile>(umlProfile);
		WeakReference<org.eclipse.ocl.pivot.Profile> asProfileRef = new WeakReference<org.eclipse.ocl.pivot.Profile>(asProfile);
		assertNotNull("No UML Profile for leak test", umlProfileRef.get());
		assertNotNull("No AS Profile for leak", asProfileRef.get());
		//
		// Eliminate our references
		//
		diagnostician = null; // There is no "dispose" API
		umlModel = null;
		umlProfile = null;
		asProfile = null;
		disposeResourceSet(resourceSet);
		resourceSet = null;
		globalEnvironmentFactory = null;
		//
		// Garbage collect and check that there are no other references
		//
		System.gc();
		assertNull("UML Profile has leaked", umlProfileRef.get());
		assertNull("AS Profile has leaked", asProfileRef.get());
	}
}
