    001    package com.hammurapi.reasoning.impl;
    002
    003    import java.util.Collection;
    004    import java.util.List;
    005    import java.util.Map;
    006    import java.util.Set;
    007
    008    import org.apache.commons.pool.KeyedObjectPool;
    009    import org.apache.commons.pool.KeyedPoolableObjectFactory;
    010
    011    import com.hammurapi.config.bootstrap.ConfigurationException;
    012    import com.hammurapi.config.bootstrap.Destroyable;
    013    import com.hammurapi.reasoning.Derivation;
    014    import com.hammurapi.reasoning.ExceptionHandler;
    015    import com.hammurapi.reasoning.ForwardReasoningSession;
    016    import com.hammurapi.reasoning.ForwardReasoningSessionFactory;
    017    import com.hammurapi.reasoning.Handle;
    018    import com.hammurapi.reasoning.InferenceListener;
    019    import com.hammurapi.reasoning.ReasoningException;
    020
    021    /**
    022     * Implements session pooling, uses properties as the key.
    023     * @author Pavel Vlasov
    024     *
    025     * @param <F>
    026     */
    027    public class PoolingForwardReasoningSessionFactory<F> implements ForwardReasoningSessionFactory<F>, Destroyable {
    028
    029            private ForwardReasoningSessionFactory<F> master;
    030
    031            protected KeyedObjectPool pool;
    032
    033            private class PoolableForwardReasoningSession implements ForwardReasoningSession<F> {
    034
    035                    private ForwardReasoningSession<F> master;
    036                    private Object key;
    037
    038                    PoolableForwardReasoningSession(ForwardReasoningSession<F> master, Object key) {
    039                            this.master = master;
    040                            this.key = key;
    041                    }
    042
    043                    public void close() throws ReasoningException {
    044                            master.reset();
    045                            master.setInferenceListener(null);
    046                            master.setExceptionHandler(null);
    047                            try {
    048                                    pool.returnObject(key, this);
    049                            } catch (Exception e) {
    050                                    throw new ReasoningException("Failed to return session to pool: "+e, e);
    051                            }
    052                    }
    053
    054                    public boolean contains(Handle<F> handle) throws ReasoningException {
    055                            return master.contains(handle);
    056                    }
    057
    058                    public boolean contains(Object fact) throws ReasoningException {
    059                            return master.contains(fact);
    060                    }
    061
    062                    public void executeRules() throws ReasoningException {
    063                            master.executeRules();
    064                    }
    065
    066                    public F get(Handle<F> handle) throws ReasoningException {
    067                            return master.get(handle);
    068                    }
    069
    070                    public Map<Class<F>, Set<Class<F>>> getConclusionMap() {
    071                            return master.getConclusionMap();
    072                    }
    073
    074                    public Collection<Derivation<F>> getDerivations(F obj) throws ReasoningException {
    075                            return master.getDerivations(obj);
    076                    }
    077
    078                    public Collection<Derivation<F>> getDerivations(Handle<F> handle) throws ReasoningException {
    079                            return master.getDerivations(handle);
    080                    }
    081
    082                    public String getDescription() {
    083                            return master.getDescription();
    084                    }
    085
    086                    public ExceptionHandler getExceptionHandler() throws ReasoningException {
    087                            return master.getExceptionHandler();
    088                    }
    089
    090                    public Handle<F> getHandle(Object fact) {
    091                            return master.getHandle(fact);
    092                    }
    093
    094                    public Collection<Handle<F>> getHandles() throws ReasoningException {
    095                            return master.getHandles();
    096                    }
    097
    098                    public InferenceListener<F> getInferenceListener() throws ReasoningException {
    099                            return master.getInferenceListener();
    100                    }
    101
    102                    public String getName() {
    103                            return master.getName();
    104                    }
    105
    106                    public Collection<? extends F> getObjects() throws ReasoningException {
    107                            return master.getObjects();
    108                    }
    109
    110                    public Handle<F> put(F fact) throws ReasoningException {
    111                            return master.put(fact);
    112                    }
    113
    114                    public Handle<F>[] putAll(F... facts) throws ReasoningException {
    115                            return master.putAll(facts);
    116                    }
    117
    118                    public List<Handle<F>> putAll(List<? extends F> facts)
    119                                    throws ReasoningException {
    120                            return master.putAll(facts);
    121                    }
    122
    123                    public void remove(F fact, boolean strict) throws ReasoningException {
    124                            master.remove(fact, strict);
    125                    }
    126
    127                    public void remove(Handle<F> handle, boolean strict) throws ReasoningException {
    128                            master.remove(handle, strict);
    129                    }
    130
    131                    public void reset() throws ReasoningException {
    132                            master.reset();
    133                    }
    134
    135                    public void setExceptionHandler(ExceptionHandler handler) throws ReasoningException {
    136                            master.setExceptionHandler(handler);
    137                    }
    138
    139                    public void setInferenceListener(InferenceListener<F> listener)   throws ReasoningException {
    140                            master.setInferenceListener(listener);
    141                    }
    142
    143                    public void updateObject(Handle<F> handle, F obj) throws ReasoningException {
    144                            master.updateObject(handle, obj);
    145                    }
    146
    147            }
    148
    149            private KeyedPoolableObjectFactory poolFactory = new KeyedPoolableObjectFactory() {
    150
    151                    @Override
    152                    public boolean validateObject(Object key, Object obj) {
    153                            return true; // No way to validate, assume always valid.
    154                    }
    155
    156                    @Override
    157                    public void passivateObject(Object key, Object obj) throws Exception {
    158                            // Nothing to do here, passivation handled by the session wrapper.
    159
    160                    }
    161
    162                    @Override
    163                    public Object makeObject(Object key) throws Exception {
    164                            return new PoolableForwardReasoningSession(master.createSession((Map<?, ?>) (key==NULL_KEY ? null : key)), key);
    165                    }
    166
    167                    @Override
    168                    public void destroyObject(Object key, Object obj) throws Exception {
    169                            ((PoolableForwardReasoningSession) obj).master.close();
    170                    }
    171
    172                    @Override
    173                    public void activateObject(Object key, Object obj) throws Exception {
    174                            // Nothing to do here.
    175                    }
    176            };
    177
    178            public PoolingForwardReasoningSessionFactory(ForwardReasoningSessionFactory<F> master, KeyedObjectPool pool) {
    179                    this.master = master;
    180                    this.pool = pool;
    181                    pool.setFactory(poolFactory);
    182            }
    183
    184            private static final Object NULL_KEY = new Object();
    185
    186            private static Object toKey(Map<?, ?> keyCandidate) {
    187                    return keyCandidate==null ? NULL_KEY : keyCandidate;
    188            }
    189
    190            @SuppressWarnings("unchecked")
    191            @Override
    192            public ForwardReasoningSession<F> createSession(Map<?, ?> properties) throws ReasoningException {
    193                    try {
    194                            return (ForwardReasoningSession<F>) pool.borrowObject(toKey(properties));
    195                    } catch (Exception e) {
    196                            throw new ReasoningException(e);
    197                    }
    198            }
    199
    200            /**
    201             * Closes the pool.
    202             */
    203            @Override
    204            public void destroy() throws ConfigurationException {
    205                    if (pool!=null) {
    206                            try {
    207                                    pool.close();
    208                            } catch (ConfigurationException e) {
    209                                    throw e;
    210                            } catch (Exception e) {
    211                                    throw new ConfigurationException(e);
    212                            }
    213                    }
    214            }
    215
    216    }