/*******************************************************************************
 * Copyright (c) 2009, 2010 Oracle. 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:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.utility.tests.internal.synchronizers;

import org.eclipse.jpt.utility.Command;
import org.eclipse.jpt.utility.internal.CompositeException;
import org.eclipse.jpt.utility.internal.ConsumerThreadCoordinator;
import org.eclipse.jpt.utility.internal.ReflectionTools;
import org.eclipse.jpt.utility.internal.synchronizers.AsynchronousSynchronizer;
import org.eclipse.jpt.utility.internal.synchronizers.Synchronizer;
import org.eclipse.jpt.utility.tests.internal.MultiThreadedTestCase;

@SuppressWarnings("nls")
public class AsynchronousSynchronizerTests
	extends MultiThreadedTestCase
{
	PrimaryModel1 primaryModel1;
	SecondaryModel1 secondaryModel1;
	Command command1;
	Synchronizer synchronizer1;

	PrimaryModel2 primaryModel2;
	SecondaryModel2 secondaryModel2;
	Command command2;
	Synchronizer synchronizer2;

	public AsynchronousSynchronizerTests(String name) {
		super(name);
	}

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		this.primaryModel1 = new PrimaryModel1();
		this.secondaryModel1 = new SecondaryModel1(this.primaryModel1);
		this.command1 = new SynchronizeSecondaryModelCommand1(this.secondaryModel1);
		this.synchronizer1 = new AsynchronousSynchronizer(this.command1, this.buildThreadFactory());
		this.primaryModel1.setSynchronizer(this.synchronizer1);

		this.primaryModel2 = new PrimaryModel2();
		this.secondaryModel2 = new SecondaryModel2(this.primaryModel2);
		this.command2 = new SynchronizeSecondaryModelCommand2(this.primaryModel2, this.secondaryModel2);
		this.synchronizer2 = new AsynchronousSynchronizer(this.command2, this.buildThreadFactory());
		this.primaryModel2.setSynchronizer(this.synchronizer2);
	}

	@Override
	protected void tearDown() throws Exception {
		this.synchronizer1.stop();
		this.synchronizer2.stop();
		super.tearDown();
	}

	public void testInitialization() {
		assertEquals(4, this.secondaryModel1.getDoubleCount());
	}

	public void testToString() {
		assertNotNull(this.synchronizer1.toString());
	}

	public void testChange() throws Exception {
		assertEquals(4, this.secondaryModel1.getDoubleCount());
		this.primaryModel1.setCount(7);

		this.sleep(TICK);
		this.synchronizer1.stop();
		this.sleep(TICK);

		assertEquals(14, this.secondaryModel1.getDoubleCount());

		// re-start so tear-down works
		this.synchronizer1.start();
	}

	public void testStart() throws Exception {
		assertEquals(4, this.secondaryModel1.getDoubleCount());
		this.primaryModel1.setSynchronizer(Synchronizer.Null.instance());
		this.primaryModel1.setCount(7);
		assertEquals(4, this.secondaryModel1.getDoubleCount());
		this.primaryModel1.setSynchronizer(this.synchronizer1);
		// the async synchronizer does not synchronize at start-up
		assertEquals(4, this.secondaryModel1.getDoubleCount());

		this.primaryModel1.setCount(8);

		this.sleep(TICK);
		this.synchronizer1.stop();
		this.sleep(TICK);

		assertEquals(16, this.secondaryModel1.getDoubleCount());

		// re-start so tear-down works
		this.synchronizer1.start();
	}

	public void testStop() throws Exception {
		assertEquals(4, this.secondaryModel1.getDoubleCount());
		this.primaryModel1.dispose();
		this.primaryModel1.setCount(7);
		assertEquals(4, this.secondaryModel1.getDoubleCount());

		// re-start so tear-down works
		this.synchronizer1.start();
	}

	public void testDoubleStart() throws Exception {
		assertEquals(4, this.secondaryModel1.getDoubleCount());
		boolean exCaught = false;
		try {
			this.primaryModel1.startSynchronizer();
			fail();
		} catch (IllegalStateException ex) {
			exCaught = true;
		}
		assertTrue(exCaught);
		this.primaryModel1.setCount(7);

		this.sleep(TICK);
		this.synchronizer1.stop();
		this.sleep(TICK);

		assertEquals(14, this.secondaryModel1.getDoubleCount());

		// re-start so tear-down works
		this.synchronizer1.start();
	}

	public void testDoubleStop() throws Exception {
		assertEquals(4, this.secondaryModel1.getDoubleCount());
		this.primaryModel1.dispose();
		boolean exCaught = false;
		try {
			this.primaryModel1.dispose();
			fail();
		} catch (IllegalStateException ex) {
			exCaught = true;
		}
		assertTrue(exCaught);
		this.primaryModel1.setCount(7);
		assertEquals(4, this.secondaryModel1.getDoubleCount());

		// re-start so tear-down works
		this.synchronizer1.start();
	}

	public void testRecursiveChange() throws Exception {
		assertEquals(4, this.secondaryModel2.getDoubleCount());
		this.primaryModel2.setCount(7);

		this.sleep(TICK);
		assertEquals(10, this.primaryModel2.getCountPlus3());
		assertEquals(14, this.secondaryModel2.getDoubleCount());

		this.sleep(TICK);
		assertEquals(20, this.secondaryModel2.getDoubleCountPlus3());
	}

	public void testNullCommand() {
		boolean exCaught = false;
		try {
			Synchronizer s = new AsynchronousSynchronizer(null, this.buildThreadFactory());
			fail("bogus: " + s);
		} catch (NullPointerException ex) {
			exCaught = true;
		}
		assertTrue(exCaught);
	}

	public void testThreadName() {
		Synchronizer s = new AsynchronousSynchronizer(this.command1, this.buildThreadFactory(), "sync");
		s.start();
		ConsumerThreadCoordinator ctc = (ConsumerThreadCoordinator) ReflectionTools.getFieldValue(s, "consumerThreadCoordinator");
		Thread t = (Thread) ReflectionTools.getFieldValue(ctc, "thread");
		assertEquals("sync", t.getName());
		s.stop();
	}

	public void testSynchronizeCalledBeforeStart() throws Exception {
		SimpleCommand command = new SimpleCommand();
		Synchronizer synchronizer = new AsynchronousSynchronizer(command, this.buildThreadFactory());

		synchronizer.synchronize();
		synchronizer.start();
		this.sleep(TICK);
		synchronizer.stop();
		assertEquals(1, command.count);
	}

	public class SimpleCommand implements Command {
		int count = 0;
		public void execute() {
			this.count++;
		}
	}

	public void testException() throws Exception {
		BogusCommand command = new BogusCommand();
		Synchronizer synchronizer = new AsynchronousSynchronizer(command, this.buildThreadFactory());
		synchronizer.start();

		synchronizer.synchronize();
		this.sleep(TICK);

		synchronizer.synchronize();
		this.sleep(TICK);

		boolean exCaught = false;
		try {
			synchronizer.stop();
			fail();
		} catch (CompositeException ex) {
			assertEquals(2, ex.getExceptions().length);
			exCaught = true;
		}
		assertTrue(exCaught);
		assertEquals(2, command.count);
	}

	public class BogusCommand implements Command {
		int count = 0;
		public void execute() {
			this.count++;
			throw new NullPointerException();
		}
	}


	// ********** synchronize commands **********
	public static class SynchronizeSecondaryModelCommand1 implements Command {
		private final SecondaryModel1 secondaryModel;

		public SynchronizeSecondaryModelCommand1(SecondaryModel1 secondaryModel) {
			super();
			this.secondaryModel = secondaryModel;
		}

		public void execute() {
			this.secondaryModel.synchronize();
		}

	}

	/**
	 * the primary model (subclass) has to synchronize with itself (superclass)
	 */
	public static class SynchronizeSecondaryModelCommand2 extends SynchronizeSecondaryModelCommand1 {
		private final PrimaryModel2 primaryModel;

		public SynchronizeSecondaryModelCommand2(PrimaryModel2 primaryModel, SecondaryModel2 secondaryModel) {
			super(secondaryModel);
			this.primaryModel = primaryModel;
		}

		@Override
		public void execute() {
			super.execute();
			this.primaryModel.synchronize();
		}

	}

	// ********** primary models **********
	/**
	 * this object will call the synchronizer whenever its count changes,
	 * allowing interested parties to synchronize with the change
	 */
	public static class PrimaryModel1 {
		protected Synchronizer synchronizer;
		protected int count = 2;

		public PrimaryModel1() {
			super();
			this.setSynchronizer_(Synchronizer.Null.instance());
		}

		public int getCount() {
			return this.count;
		}
		public void setCount(int count) {
			if (count != this.count) {
				this.count = count;
				this.stateChanged();
			}
		}

		protected void stateChanged() {
			this.synchronizer.synchronize();
		}

		public void setSynchronizer(Synchronizer synchronizer) {
			if (synchronizer == null) {
				throw new NullPointerException();
			}
			this.synchronizer.stop();
			this.setSynchronizer_(synchronizer);
		}
			
		protected void setSynchronizer_(Synchronizer synchronizer) {
			this.synchronizer = synchronizer;
			this.synchronizer.start();
		}

		public void startSynchronizer() {
			this.synchronizer.start();  // this should cause an exception
		}
		public void dispose() {
			this.synchronizer.stop();
		}

		@Override
		public String toString() {
			StringBuilder sb = new StringBuilder();
			sb.append(this.getClass().getSimpleName());
			sb.append('(');
			this.toString(sb);
			sb.append(')');
			return sb.toString();
		}
		public void toString(StringBuilder sb) {
			sb.append("count=");
			sb.append(this.count);
		}

	}

	/**
	 * This model synchronizes with itself, triggering a recursive synchronization
	 * with the change. Whenever the [inherited] 'count' changes, 'countPlus3'
	 * is updated appropriately and another synchronize is initiated if appropriate.
	 */
	public static class PrimaryModel2 extends PrimaryModel1 {
		private int countPlus3 = 0;

		public PrimaryModel2() {
			super();
			this.countPlus3 = this.count + 3;
		}

		public int getCountPlus3() {
			return this.countPlus3;
		}
		protected void setCountPlus3(int countPlus3) {
			if (countPlus3 != this.countPlus3) {
				this.countPlus3 = countPlus3;
				this.stateChanged();
			}
		}

		// synchronize with itself, so to speak
		public void synchronize() {
			this.setCountPlus3(this.count + 3);
		}

		@Override
		public void toString(StringBuilder sb) {
			super.toString(sb);
			sb.append(", countPlus3=");
			sb.append(this.countPlus3);
		}

	}

	// ********** secondary models **********
	/**
	 * This dependent object updates its 'doubleCount' whenever the
	 * PrimaryModel1's 'count' changes, via the 'synchronizer'.
	 */
	public static class SecondaryModel1 {
		protected final PrimaryModel1 primaryModel;
		protected int doubleCount = 0;

		public SecondaryModel1(PrimaryModel1 primaryModel) {
			super();
			this.primaryModel = primaryModel;
			this.synchronize();
		}

		public void synchronize() {
			this.doubleCount = this.primaryModel.getCount() * 2;
		}

		public int getDoubleCount() {
			return this.doubleCount;
		}

		@Override
		public String toString() {
			StringBuilder sb = new StringBuilder();
			sb.append(this.getClass().getSimpleName());
			sb.append('(');
			this.toString(sb);
			sb.append(')');
			return sb.toString();
		}
		public void toString(StringBuilder sb) {
			sb.append("doubleCount=");
			sb.append(this.doubleCount);
		}

	}

	public static class SecondaryModel2 extends SecondaryModel1 {
		private int doubleCountPlus3 = 0;

		public SecondaryModel2(PrimaryModel2 extendedPrimaryModel) {
			super(extendedPrimaryModel);
		}

		protected PrimaryModel2 getExtendedPrimaryModel() {
			return (PrimaryModel2) this.primaryModel;
		}

		@Override
		public void synchronize() {
			super.synchronize();
			int temp = this.getExtendedPrimaryModel().getCountPlus3() * 2;
			if (this.doubleCountPlus3 != temp) {
				this.doubleCountPlus3 = temp;
			}
		}

		public int getDoubleCountPlus3() {
			return this.doubleCountPlus3;
		}

		@Override
		public void toString(StringBuilder sb) {
			super.toString(sb);
			sb.append(", doubleCountPlus3=");
			sb.append(this.doubleCountPlus3);
		}

	}

}
