package org.pentaho.platform.engine.core.system.objfac.references;
import org.pentaho.platform.api.engine.IObjectCreator;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.engine.ObjectFactoryException;
import org.pentaho.platform.engine.core.system.PentahoSessionHolder;
import java.util.Map;
import java.util.WeakHashMap;
/**
* Session-aware Reference. An internal weak-map is maintained to keep track of instances by IPentahoSession.
* <p/>
* Created by nbaker on 4/15/14.
*/
public class SessionBoundPentahoObjectReference<T> extends AbstractPentahoObjectReference<T> {
private final IObjectCreator<T> creator;
private static WeakHashMap<IPentahoSession, Map<Class<?>, Object>> cache =
new WeakHashMap<IPentahoSession, Map<Class<?>, Object>>();
public SessionBoundPentahoObjectReference( Class<T> type, IObjectCreator<T> creator, Map<String, Object> attributes,
Integer priority ) {
super( type, attributes, priority );
this.creator = creator;
}
@SuppressWarnings( "unchecked" )
@Override protected T createObject() throws ObjectFactoryException {
final IPentahoSession session = PentahoSessionHolder.getSession();
Map<Class<?>, Object> classObjectMap = cache.get( session );
if ( classObjectMap == null ) {
classObjectMap = new WeakHashMap<Class<?>, Object>();
cache.put( session, classObjectMap );
}
if ( classObjectMap.containsKey( this.getObjectClass() ) ) {
return (T) classObjectMap.get( this.getObjectClass() );
}
T newObject = creator.create( session );
classObjectMap.put( this.getObjectClass(), newObject );
return newObject;
}
/**
* workaround for inheritance in Builders. Ideas taken from: https://weblogs.java
* .net/blog/emcmanus/archive/2010/10/25/using-builder-pattern-subclasses
*/
private abstract static class BuilderBase<T, B extends BuilderBase<T, B>>
extends AbstractPentahoObjectReference.Builder<T, B> {
IObjectCreator<T> creator;
public B creator( IObjectCreator<T> creator ) {
this.creator = creator;
return self();
}
@Override public SessionBoundPentahoObjectReference<T> build() {
return new SessionBoundPentahoObjectReference<T>( this.type, this.creator, this.attributes, this.priority );
}
}
/**
* Public builder, implementation specific methods should be in BuilderBase, only self() should be defined here
*/
public static class Builder<T> extends BuilderBase<T, Builder<T>> {
public Builder( Class<T> type ) {
type( type );
}
@Override public Builder<T> self() {
return this;
}
}
}