/*
 Copyright (C) 2007 Richard Gomes

 This source code is release under the BSD License.

 This file is part of JQuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://jquantlib.org/

 JQuantLib is free software: you can redistribute it and/or modify it
 under the terms of the JQuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 . The license is also available online at
 .

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the license for more details.

 JQuantLib is based on QuantLib. http://quantlib.org/
 When applicable, the original copyright notice follows this notice.
 */

package org.jquantlib.testsuite.patterns;

import static org.junit.Assert.fail;

import org.jquantlib.QL;
import org.jquantlib.util.PolymorphicVisitable;
import org.jquantlib.util.PolymorphicVisitor;
import org.jquantlib.util.Visitor;
import org.junit.Test;

/**
 *
 * @author Richard Gomes
 */
public class VisitorTest {

	public VisitorTest() {
		QL.info("::::: "+this.getClass().getSimpleName()+" :::::");
	}

	@Test
	public void testPolymorphicVisitorPattern() {

		final NumberPolymorphicVisitable  numberPolymorphicVisitable  = new NumberPolymorphicVisitable();
		final DoublePolymorphicVisitable  doublePolymorphicVisitable  = new DoublePolymorphicVisitable();
		final IntegerPolymorphicVisitable integerPolymorphicVisitable = new IntegerPolymorphicVisitable();

		final NumberPolymorphicVisitor  numberPolymorphicVisitor  = new NumberPolymorphicVisitor();
		final DoublePolymorphicVisitor  doublePolymorphicVisitor  = new DoublePolymorphicVisitor();
		final IntegerPolymorphicVisitor integerPolymorphicVisitor = new IntegerPolymorphicVisitor();

		// these tests must pass
		numberPolymorphicVisitable.accept(numberPolymorphicVisitor);
		doublePolymorphicVisitable.accept(numberPolymorphicVisitor);
		doublePolymorphicVisitable.accept(doublePolymorphicVisitor);
		integerPolymorphicVisitable.accept(numberPolymorphicVisitor);
		integerPolymorphicVisitable.accept(integerPolymorphicVisitor);

		// the following must fail
		try {
			numberPolymorphicVisitable.accept(doublePolymorphicVisitor);
			fail("numberPolymorphicVisitable.accept(doublePolymorphicVisitor) should fail!");
		} catch (final Exception e) {
			// OK, as expected
		}

		// the following must fail
		try {
			numberPolymorphicVisitable.accept(integerPolymorphicVisitor);
			fail("numberPolymorphicVisitable.accept(integerPolymorphicVisitor) should fail");
		} catch (final Exception e) {
			// OK, as expected
		}

		// the following must fail
		try {
			doublePolymorphicVisitable.accept(integerPolymorphicVisitor);
			fail("doublePolymorphicVisitable.accept(integerPolymorphicVisitor) should fail");
		} catch (final Exception e) {
			// OK, as expected
		}

		// the following must fail
		try {
			integerPolymorphicVisitable.accept(doublePolymorphicVisitor);
			fail("integerPolymorphicVisitable.accept(doublePolymorphicVisitor) should fail");
		} catch (final Exception e) {
			// OK, as expected
		}

	}

	private class NumberPolymorphicVisitable implements PolymorphicVisitable {
		@Override
		public void accept(final PolymorphicVisitor pv) {
			final Visitor v = (pv!=null) ? pv.visitor(Number.class) : null;
			if (v!=null)
				v.visit(1.0);
			else
				throw new IllegalArgumentException("not a Number visitor");
		}
	}


	private class DoublePolymorphicVisitable extends NumberPolymorphicVisitable  /* implements PolymorphicVisitable */ {
		private final double data = 5.6;

		@Override
		public void accept(final PolymorphicVisitor pv) {
			final Visitor v = (pv!=null) ? pv.visitor(Double.class) : null;
			if (v!=null)
				v.visit(data);
			else
				super.accept(pv);
		}
	}


	private class IntegerPolymorphicVisitable extends NumberPolymorphicVisitable  /* implements PolymorphicVisitable */ {
		private final int data = 3456;

		@Override
		public void accept(final PolymorphicVisitor pv) {
			final Visitor v = (pv!=null) ? pv.visitor(Integer.class) : null;
			if (v!=null)
				v.visit(data);
			else
				super.accept(pv);
		}
	}



	//
	// declare PolymorphicVisitors and corresponding Visitors
	//

	private static class NumberPolymorphicVisitor implements PolymorphicVisitor {

		@Override
		public  Visitor visitor(final Class klass) {
			return (Visitor) ((klass==java.lang.Number.class) ? numberVisitor : null);
		}

		//
		// composition pattern to an inner Visitor
		//

		private final NumberVisitor numberVisitor = new NumberVisitor();

		private static class NumberVisitor implements Visitor {
			@Override
			public void visit(final Number o) {
				QL.info("Number :: "+o);
			}
		}
	}


	private static class DoublePolymorphicVisitor extends NumberPolymorphicVisitor {

		@Override
		public  Visitor visitor(final Class klass) {
			return (Visitor) ((klass==Double.class) ? doubleVisitor : null);
		}

		//
		// composition pattern to an inner Visitor
		//

		private final DoubleVisitor doubleVisitor = new DoubleVisitor();

		private static class DoubleVisitor implements Visitor {
			@Override
			public void visit(final Number o) {
				final double obj = (Double)o;
				QL.info("Double :: "+obj);
			}
		}
	}

	private static class IntegerPolymorphicVisitor extends NumberPolymorphicVisitor {

		@Override
		public  Visitor visitor(final Class klass) {
			return (Visitor) ((klass==Integer.class) ? integerVisitor : null);
		}

		//
		// composition pattern to an inner Visitor
		//

		private final IntegerVisitor integerVisitor = new IntegerVisitor();

		private static class IntegerVisitor implements Visitor {
			@Override
			public void visit(final Number o) {
				final Integer obj = (Integer)o;
				QL.info("Integer :: "+obj);
			}
		}
	}

}

 

Ads help maintain this website.