/*******************************************************************************
 * Copyright (c) 2009, 2010 Cloudsmith Inc. 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:
 *     Cloudsmith Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.p2.tests.ql;

import java.io.File;
import java.net.URI;
import java.util.*;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.equinox.internal.p2.director.QueryableArray;
import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.expression.*;
import org.eclipse.equinox.p2.publisher.PublisherInfo;
import org.eclipse.equinox.p2.publisher.PublisherResult;
import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.artifact.*;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
import org.eclipse.equinox.p2.tests.TestActivator;
import org.osgi.framework.Filter;

public class EvaluatorTest extends AbstractProvisioningTest {
	private static final IExpressionParser parser = ExpressionUtil.getParser();
	private static final IExpressionFactory factory = ExpressionUtil.getFactory();

	public void testArguments() throws Exception {
		IExpression expr = parser.parse("'a' == $0 && 'b' == $1 && 'c' == $2");
		assertEquals(Boolean.TRUE, expr.evaluate(factory.createContext("a", "b", "c")));
	}

	public void testAnonymousMember() throws Exception {
		IExpression expr = parser.parse("$0.class == $1");
		assertEquals(Boolean.TRUE, expr.evaluate(factory.createContext("a", String.class)));
	}

	public void testInstanceOf() throws Exception {
		// Explicit instanceof when rhs is a class
		IExpression expr = parser.parse("$0 ~= $1");
		assertEquals(Boolean.TRUE, expr.evaluate(factory.createContext(new Integer(4), Number.class)));
	}

	public void testArray() throws Exception {
		IExpression expr = parser.parse("['a', 'b', 'c'].exists(x | x == 'b') && ['a', 'b', 'c'].all(x | 'd' > x)");
		IEvaluationContext ctx = factory.createContext();
		assertEquals(Boolean.TRUE, expr.evaluate(ctx));
		expr = parser.parse("['d', 'e', 'f'].exists(x | ['a', 'b', 'c'].exists(y | x > y))");
		assertEquals(Boolean.TRUE, expr.evaluate(ctx));
		expr = parser.parse("[['d', 'e', 'f'], ['h', 'i', 'j']].exists(x | x.all(y | ['a', 'b', 'c'].all(z | y > z)))");
		assertEquals(Boolean.TRUE, expr.evaluate(ctx));
		expr = parser.parse("[['d', 'e', 'f'], ['h', '3', 'j']].exists(x | x.all(y | ['a', 'b', 'c'].exists(z | y > z)))");
		assertEquals(Boolean.TRUE, expr.evaluate(ctx));
		expr = parser.parse("[['d', 'e', 'f'], ['h', 'i', 'j']].all(x | x.all(y | ['a', 'b', 'c'].all(z | y > z)))");
		assertEquals(Boolean.TRUE, expr.evaluate(ctx));
		expr = parser.parse("[['d', 'e', 'f'], ['h', '3', 'j']].all(x | x.all(y | ['a', 'b', 'c'].all(z | y > z)))");
		assertEquals(Boolean.FALSE, expr.evaluate(ctx)); // 3 < 'b'
	}

	public void testLatest() throws Exception {
		IMetadataRepository repo = getMDR("/testData/metadataRepo/multipleversions1");
		IQueryResult result = repo.query(QueryUtil.createQuery("latest(x | x.id == $0)", "test.bundle"), new NullProgressMonitor());
		assertTrue(queryResultSize(result) == 1);
	}

	public void testRange() throws Exception {
		IMetadataRepository repo = getMDR("/testData/metadataRepo/multipleversions1");
		IQueryResult result = repo.query(QueryUtil.createMatchQuery("version ~= $0", new VersionRange("2.0.0")), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 2);
	}

	public void testProperty() throws Exception {
		IMetadataRepository repo = getMDR("/testData/metadataRepo/multipleversions1");

		IQueryResult result = repo.query(QueryUtil.createMatchQuery("properties.exists(p | boolean(p.value))"), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 3);

		result = repo.query(QueryUtil.createMatchQuery("boolean(properties['org.eclipse.equinox.p2.type.group'])"), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 3);

		Filter filter = TestActivator.context.createFilter("(org.eclipse.equinox.p2.type.group=true)");
		result = repo.query(QueryUtil.createMatchQuery("properties ~= $0", filter), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 3);
	}

	public void testToString() throws Exception {
		String exprString = "select(x | x.id == $0 && (x.version == $1 || x.version == $2)).traverse(set(), _, {requirementsCache, parent | select(" + //
				"parent.requirerements.unique(requirementsCache).select(rc | rc.filter == null || $2 ~= filter(rc.filter)), _, " + //
				"{rcs, child | rcs.exists(rc | child ~= rc)})}).limit(10)";

		IContextExpression expr = factory.contextExpression(parser.parseQuery(exprString));
		System.out.println(expr.toString());
		assertEquals(exprString, expr.toString());
	}

	public void testSomeAPI() throws Exception {
		// Create some expressions. Note the use of identifiers instead of
		// indexes for the parameters

		IExpression item = factory.variable("item");
		IExpression cmp1 = factory.equals(factory.member(item, "id"), factory.indexedParameter(0));
		IExpression cmp2 = factory.equals(factory.at(factory.member(item, "properties"), factory.indexedParameter(1)), factory.indexedParameter(2));

		IExpression lambda = factory.lambda(item, factory.and(cmp1, cmp2));
		IExpression latest = factory.latest(factory.select(factory.variable("everything"), lambda));

		// Create the query
		IContextExpression<IInstallableUnit> e3 = factory.contextExpression(latest, "test.bundle", "org.eclipse.equinox.p2.type.group", "true");
		IMetadataRepository repo = getMDR("/testData/metadataRepo/multipleversions1");
		IQueryResult result = repo.query(QueryUtil.createQuery(e3), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 1);
	}

	public void testPatch() throws Exception {
		IRequirement[][] applicability = new IRequirement[2][2];
		applicability[0][0] = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "javax.wsdl", null, null, false, false);
		applicability[0][1] = MetadataFactory.createRequirement("org.eclipse.equinox.p2.eclipse.type", "bundle", null, null, false, false);
		applicability[1][0] = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "tooling.source.default", null, null, false, false);
		applicability[1][1] = MetadataFactory.createRequirement("org.eclipse.equinox.p2.flavor", "tooling", null, null, false, false);

		IMetadataRepository repo = getMDR("/testData/metadataRepo/wsdlTestRepo");
		IQueryResult result = repo.query(QueryUtil.createMatchQuery("$0.exists(rcs | rcs.all(rc | this ~= rc))", (Object) applicability), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 3);
	}

	public void testPattern() throws Exception {
		IProvidedCapability pc = MetadataFactory.createProvidedCapability("org.eclipse.equinox.p2.eclipse.type", "source", null);
		IMetadataRepository repo = getMDR("/testData/metadataRepo/wsdlTestRepo");
		IQueryResult result = repo.query(QueryUtil.createMatchQuery("id ~= /tooling.*.default/", pc), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 3);
	}

	public void testLimit() throws Exception {
		IMetadataRepository repo = getMDR("/testData/metadataRepo/wsdlTestRepo");
		IQueryResult result = repo.query(QueryUtil.createQuery("select(x | x.id ~= /tooling.*/).limit(1)"), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 1);

		result = repo.query(QueryUtil.createQuery("select(x | x.id ~= /tooling.*/).limit($0)", new Integer(2)), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 2);
	}

	public void testNot() throws Exception {
		IMetadataRepository repo = getMDR("/testData/metadataRepo/wsdlTestRepo");
		IQueryResult result = repo.query(QueryUtil.createMatchQuery("!(id ~= /tooling.*/)"), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 4);
	}

	public void testArtifactQuery() throws Exception {
		URI artifactRepo = getTestData("1.1", "/testData/artifactRepo/simple").toURI();

		IArtifactRepositoryManager artifactManager = getArtifactRepositoryManager();
		assertNotNull(artifactManager);

		IArtifactRepository repo = artifactManager.loadRepository(artifactRepo, new NullProgressMonitor());
		IQueryResult result = repo.query(QueryUtil.createMatchQuery(IArtifactKey.class, "classifier ~= /*/"), new NullProgressMonitor());
		assertTrue(queryResultSize(result) > 1);
		Iterator itor = result.iterator();
		while (itor.hasNext())
			assertTrue(itor.next() instanceof IArtifactKey);

		result = repo.descriptorQueryable().query(QueryUtil.createMatchQuery(IArtifactDescriptor.class, "artifactKey.classifier ~= /*/"), new NullProgressMonitor());
		assertTrue(queryResultSize(result) > 1);
		itor = result.iterator();
		while (itor.hasNext())
			assertTrue(itor.next() instanceof IArtifactDescriptor);
	}

	public void testClassConstructor() throws Exception {
		IMetadataRepository repo = getMDR("/testData/metadataRepo/wsdlTestRepo");
		IQueryResult result = repo.query(QueryUtil.createQuery(//
				"select(x | x ~= class('org.eclipse.equinox.p2.metadata.IInstallableUnitFragment'))"), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 4);
		repo = getMDR("/testData/galileoM7");
	}

	public void testTouchpoints() throws Exception {
		IMetadataRepository repo = getMDR("/testData/galileoM7");
		IQueryResult result = repo.query(QueryUtil.createMatchQuery(//
				"touchpointType != null && touchpointType.id == 'org.eclipse.equinox.p2.osgi' && touchpointData.exists(t | t.instructions.exists(entry | entry.key == 'zipped'))"), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 616);
	}

	public void testTraverse() throws Exception {
		IMetadataRepository repo = getMDR("/testData/galileoM7");
		IQueryResult result = repo.query(QueryUtil.createQuery(//
				"select(x | x.id == $0 && x.version == $1).traverse(parent | parent.requirements.collect(rc | select(iu | iu ~= rc)).flatten())", //
				"org.eclipse.sdk.feature.group", Version.create("3.5.0.v20090423-7Q7bA7DPR-wM38__Q4iRsmx9z0KOjbpx3AbyvXd-Uq7J2")), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 463);
	}

	public void testTraverseWithFilter() throws Exception {
		// Add some filtering of requirements
		Map env = new Hashtable();
		env.put("osgi.os", "linux");
		env.put("osgi.ws", "gtk");
		env.put("osgi.arch", "x86");
		IInstallableUnit envIU = InstallableUnit.contextIU(env);

		IContextExpression<IInstallableUnit> expr = factory.contextExpression(parser.parseQuery("" + //
				"select(x | x.id == $0 && x.version == $1).traverse(parent |" + //
				"parent.requirements.select(rc | rc.filter == null || $2 ~= rc.filter).collect(rc | select(iu | iu ~= rc)).flatten())"), "org.eclipse.sdk.feature.group", Version.create("3.5.0.v20090423-7Q7bA7DPR-wM38__Q4iRsmx9z0KOjbpx3AbyvXd-Uq7J2"), envIU);

		IQuery<IInstallableUnit> query = QueryUtil.createQuery(expr);
		IMetadataRepository repo = getMDR("/testData/galileoM7");
		IQueryResult<IInstallableUnit> result = repo.query(query, new NullProgressMonitor());
		assertEquals(queryResultSize(result), 411);
	}

	public void testCommonRequirements() throws Exception {
		// Add some filtering of requirements

		IMetadataRepository repo = getMDR("/testData/galileoM7");
		IInstallableUnit envIU = InstallableUnit.contextIU("gtk", "linux", "x86");
		IContextExpression<IInstallableUnit> expr = factory.contextExpression(parser.parseQuery("" + //
				"select(x | x.id == $0 && x.version == $1).traverse(parent |" + //
				"parent.requirements.select(rc | rc.filter == null || $4 ~= rc.filter).collect(rc | select(iu | iu ~= rc)).flatten()).intersect(" + //
				"select(x | x.id == $2 && x.version == $3).traverse(parent |" + //
				"parent.requirements.select(rc | rc.filter == null || $4 ~= rc.filter).collect(rc | select(iu | iu ~= rc)).flatten()))"), //
				"org.eclipse.pde.feature.group", //
				Version.create("3.5.0.v20090123-7Z7YF8NFE-z0VXhWU26Hu8gY"), //
				"org.eclipse.gmf.feature.group", //
				Version.create("1.1.1.v20090114-0940-7d8B0FXwkKwFanGNHeHHq8ymBgZ"), //
				envIU);

		IQuery<IInstallableUnit> query = QueryUtil.createQuery(expr);
		IQueryResult<IInstallableUnit> result = repo.query(query, new NullProgressMonitor());
		assertEquals(queryResultSize(result), 184);
	}

	public void testMatchQueryInjectionInPredicate() throws Exception {
		IMetadataRepository repo = getMDR("/testData/galileoM7");
		IMatchExpression<IInstallableUnit> expr = factory.matchExpression(parser.parse("iquery($0) || iquery($1)"), new MatchQuery() {
			@Override
			public boolean isMatch(Object candidate) {
				return "true".equals(((IInstallableUnit) candidate).getProperty("org.eclipse.equinox.p2.type.category"));
			}
		}, new MatchQuery() {
			@Override
			public boolean isMatch(Object candidate) {
				return "true".equals(((IInstallableUnit) candidate).getProperty("org.eclipse.equinox.p2.type.group"));
			}
		});
		IQueryResult<IInstallableUnit> result = repo.query(QueryUtil.createMatchQuery(expr), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 497);
	}

	static class MyObject {
		String id;
		Map properties = new HashMap();

		public MyObject(String id, String key, String value) {
			this.id = id;
			this.properties.put(key, value);
		}

		public String getId() {
			return this.id;
		}

		public Map getProperties() {
			return this.properties;
		}
	}

	public void testRootVariableSerialization() throws Exception {
		List items = new ArrayList();

		items.add(new MyObject("ian bull", "foo", "true"));

		// Create some expressions. Note the use of identifiers instead of
		// indexes for the parameters
		IExpression item = factory.variable("item");

		IExpression cmp1 = factory.equals(factory.member(item, "id"), factory.indexedParameter(0));

		IExpression everything = factory.variable("everything");
		IExpression lambda = factory.lambda(item, cmp1);

		IContextExpression e3 = factory.contextExpression(factory.select(everything, lambda));

		IContextExpression<Object> contextExpression = factory.contextExpression(parser.parseQuery(e3.toString()), "ian bull");
		IQuery<Object> query = QueryUtil.createQuery(Object.class, contextExpression);
		System.out.println(e3);

		IQueryResult<Object> queryResult = query.perform(items.iterator());
		Iterator iterator = queryResult.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}

	}

	public void testMatchQueryInjectionInContext() throws Exception {
		IMetadataRepository repo = getMDR("/testData/galileoM7");
		IContextExpression<IInstallableUnit> expr = factory.contextExpression(parser.parseQuery("select(x | iquery($0, x) || iquery($1, x)).latest()"), new MatchQuery() {
			@Override
			public boolean isMatch(Object candidate) {
				return "true".equals(((IInstallableUnit) candidate).getProperty("org.eclipse.equinox.p2.type.category"));
			}
		}, new MatchQuery() {
			@Override
			public boolean isMatch(Object candidate) {
				return "true".equals(((IInstallableUnit) candidate).getProperty("org.eclipse.equinox.p2.type.group"));
			}
		});
		IQueryResult result = repo.query(QueryUtil.createQuery(expr), new NullProgressMonitor());
		assertEquals(queryResultSize(result), 497);
	}

	public void testTranslations() {
		File foo_fragment = new File(TestActivator.getTestDataFolder(), "FragmentPublisherTest/foo.fragment");//$NON-NLS-1$
		File foo = new File(TestActivator.getTestDataFolder(), "FragmentPublisherTest/foo");//$NON-NLS-1$
		BundlesAction bundlesAction = new BundlesAction(new File[] {foo_fragment});
		PublisherInfo info = new PublisherInfo();
		PublisherResult results = new PublisherResult();

		bundlesAction.perform(info, results, new NullProgressMonitor());
		Collection ius = results.getIUs(null, null);
		assertEquals("1.0", 1, ius.size());

		info = new PublisherInfo();
		results = new PublisherResult();
		bundlesAction = new BundlesAction(new File[] {foo});
		bundlesAction.perform(info, results, new NullProgressMonitor());

		bundlesAction = new BundlesAction(new File[] {foo_fragment});
		bundlesAction.perform(info, results, new NullProgressMonitor());
		ius = results.getIUs(null, null);
		assertEquals("2.0", 3, ius.size());
		QueryableArray queryableArray = new QueryableArray((IInstallableUnit[]) ius.toArray(new IInstallableUnit[ius.size()]));
		IQueryResult result = queryableArray.query(QueryUtil.createIUQuery("foo"), null);
		assertEquals("2.1", 1, queryResultSize(result));
		IQuery<IInstallableUnit> lq = QueryUtil.createMatchQuery("translatedProperties[$0] ~= /German*/", new KeyWithLocale("org.eclipse.equinox.p2.name", Locale.GERMAN));
		Iterator itr = queryableArray.query(lq, new NullProgressMonitor()).iterator();
		assertTrue(itr.hasNext());
		assertEquals("2.8", "foo", ((IInstallableUnit) itr.next()).getId());
		assertFalse(itr.hasNext());
	}

	private IMetadataRepository getMDR(String uri) throws Exception {
		URI metadataRepo = getTestData("1.1", uri).toURI();

		IMetadataRepositoryManager metadataManager = (IMetadataRepositoryManager) getAgent().getService(IMetadataRepositoryManager.SERVICE_NAME);
		assertNotNull(metadataManager);

		return metadataManager.loadRepository(metadataRepo, new NullProgressMonitor());
	}

	public void testConsistency() throws Exception {
		IMetadataRepository repo = getMDR("/testData/metadataRepo/qltest");

		IQuery<IInstallableUnit> query1 = QueryUtil.createIUGroupQuery();
		IQuery<IInstallableUnit> query2 = QueryUtil.createQuery("select(iu2 | iu2.requirements.exists(r | r != null) || exists(iu | iu.requirements.exists(r | iu2 ~= r)))");

		IQueryResult<IInstallableUnit> rt2 = repo.query(QueryUtil.createPipeQuery(query1, query2), null);

		IQueryResult<IInstallableUnit> rt = repo.query(query1, null);
		IQueryResult<IInstallableUnit> rt1 = rt.query(QueryUtil.createQuery("select(iu2 | iu2.requirements.exists(r | r != null))"), null);
		rt = rt.query(QueryUtil.createQuery("select(iu | $0.exists(i | i.requirements.exists(r | iu ~= r)))", (Object) rt1.toArray(IInstallableUnit.class)), null);
		/**
		 * should use below line to replace above two lines,
		 * but it throws an unsupported operation exception
		 */
		//		rt = rt.query(query2, null);
		Set set = rt.toSet();
		set.addAll(rt1.toSet());

		assertTrue("Query results are inconsistent.", set.size() == rt2.toSet().size());
	}
}
