SessionFactoryAsInstance.java

/***************************************************************************
   Copyright 2014 Emily Estes

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
***************************************************************************/
package net.metanotion.web.concrete;


import net.metanotion.util.Unknown;

import net.metanotion.web.Instance;
import net.metanotion.web.SessionFactory;

/** This class allows a {@link net.metanotion.web.SessionFactory} instance to behave as an
{@link net.metanotion.web.Instance}.
	@param <App> The application backing the SessionFactory.
	@param <Factory> The type of objects the SessionFactory requires to produce a session.
*/
public final class SessionFactoryAsInstance<App,Factory extends SessionFactory<App> & Unknown> implements Instance {
	private final Factory factory;
	private final App app;

	/** Wrap a SessionFactory that also implements Unknown as an Instance with the backing Application.
		@param <A> The type of the application.
		@param <B> The type of the session factory.
		@param factory The session factory that also implements Unknown
		@param app The application.
		@return An instance backed by the session factory and application.
	*/
	public static <A,B extends SessionFactory<A> & Unknown> Instance wrap(final B factory, final A app) {
		return new SessionFactoryAsInstance<A,B>(factory, app);
	}

	private static final class W<A> implements SessionFactory<A>, Unknown {
		private final SessionFactory<A> factory;
		public W(final SessionFactory<A> factory) { this.factory = factory; }
		@Override public Unknown newSession(A app) { return this.factory.newSession(app); }
		@Override public <I> I lookupInterface(final Class<I> theInterface) {
			throw new RuntimeException("no suitable proxy for " + theInterface);
		}
	}

	/** Create an instance backed by the SessionFactory and the Application.
		@param <A> The type of the application.
		@param factory The session factory.
		@param app The application.
		@return An instance backed by the session factory and application.
	*/
	public static <A> Instance create(final SessionFactory<A> factory, final A app) {
		return new SessionFactoryAsInstance<A,W<A>>(new W<A>(factory), app);
	}

	/** Create a new Instance backed by a SessionFactory.
		@param factory The session factory backing the instance.
		@param app The initializer object for the session factory's sessions.
	*/
	private SessionFactoryAsInstance(final Factory factory, final App app) {
		this.factory = factory;
		this.app = app;
	}

	// Instance
	@Override public Unknown newSession() { return this.factory.newSession(app); }
	@Override public <I> I lookupInterface(final Class<I> theInterface) { return this.factory.lookupInterface(theInterface); }
}