edu.upenn.cis.ppod.model.PPodVersionInfoInterceptor.java Source code

Java tutorial

Introduction

Here is the source code for edu.upenn.cis.ppod.model.PPodVersionInfoInterceptor.java

Source

/*
 * Copyright (C) 2009 Trustees of the University of Pennsylvania
 *
 * 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 edu.upenn.cis.ppod.model;

import static edu.upenn.cis.ppod.util.CollectionsUtil.newConcurrentHashMap;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentMap;

import org.hibernate.EmptyInterceptor;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.classic.Session;
import org.hibernate.type.Type;

import com.google.inject.Inject;
import com.google.inject.Provider;

import edu.upenn.cis.ppod.dao.IVersionInfoDAO;
import edu.upenn.cis.ppod.dao.hibernate.HibernateDAOFactory;
import edu.upenn.cis.ppod.imodel.IVersioned;

/**
 * Assign a new {@link PPodVersionInfo} to any {@code PPodEntity}s that are
 * marked as being newly saved or modified and to any {@code null} members of
 * {@link CharacterStateMatrix#getColumnPPodVersionInfos()}
 * <p>
 * {@code PPodEntity}s are marked for a new {@link PPodVersionInfo} by having a
 * {@code null} {@code pPodVersionInfo} field.
 * 
 * @author Sam Donnelly
 */
public class PPodVersionInfoInterceptor extends EmptyInterceptor {

    private static final long serialVersionUID = 1L;

    private SessionFactory sessionFactory;

    private final transient HibernateDAOFactory.IFactory hibernateDAOFactoryFactory;

    private final transient Provider<PPodVersionInfo> pPodVersionInfoProvider;

    private final ConcurrentMap<Session, PPodVersionInfo> pPodVersionInfosBySession = newConcurrentHashMap();

    @Inject
    PPodVersionInfoInterceptor(final Provider<PPodVersionInfo> pPodVersionInfoProvider,
            final HibernateDAOFactory.IFactory hibernateDAOFactoryFactory) {
        this.pPodVersionInfoProvider = pPodVersionInfoProvider;
        this.hibernateDAOFactoryFactory = hibernateDAOFactoryFactory;
    }

    @Override
    public void afterTransactionCompletion(final Transaction tx) {
        pPodVersionInfosBySession.remove(sessionFactory.getCurrentSession());
    }

    /**
     * In a temporary session, grab the next available pPOD version number,
     * increment it, assign it to a {@code sessionFactory.getCurrentSession()}
     * and {@code PPodVersionInfo} in {@link #pPodVersionInfosBySession}, and
     * save (but not commit) it to the database.
     */
    private void initializePPodVersionInfo() {
        if (pPodVersionInfosBySession.containsKey(sessionFactory.getCurrentSession())) {
            // Already been called.
            return;
        }
        // there's no alternative to the deprecated method yet - see its
        // javadoc: it says "TBD".
        @SuppressWarnings("deprecation")
        final Session tempSession = sessionFactory.openSession(sessionFactory.getCurrentSession().connection(),
                EmptyInterceptor.INSTANCE);
        final IPPodVersionInfoDAO pPodVersionInfoDAO = hibernateDAOFactoryFactory.create(tempSession)
                .getPPodVersionInfoDAO();
        pPodVersionInfosBySession.put(sessionFactory.getCurrentSession(), pPodVersionInfoProvider.get()
                .setPPodVersion(pPodVersionInfoDAO.getMaxPPodVersion() + 1).setCreated(new Date()));
        tempSession.save(pPodVersionInfosBySession.get(sessionFactory.getCurrentSession()));
        tempSession.flush();
    }

    /**
     * Equivalent to {@code setPPodVersionInfoIfAppropriate(entity,
     * propertyNames, state)}.
     */
    @Override
    public boolean onSave(final Object entity, final Serializable id, final Object[] state,
            final String[] propertyNames, final Type[] types) {
        return setPPodVersionInfoIfAppropriate(entity, propertyNames, state);
    }

    /**
     * This method does two things:
     * <ol>
     * <li>
     * If {@code entity} is an {@link IPPodEntity} and has {@code
     * "pPodVersionInfo".equals(properyNames[n])} with {@code currentState[n] ==
     * null}, then assign {@link PPodVersionInfoInterceptor#pPodVersionInfo} to
     * {@code currentState[n]}.
     * <li>
     * If an {@code entity} is a {@link CharacterStateMatrix} then assign all
     * {@link CharacterStateMatrix#getColumnPPodVersionInfos()} w/ a {@code
     * null} value to {@link PPodVersionInfoInterceptor#pPodVersionInfo}. It
     * does this by picking out {@code
     * "columnPPodVersionInfos".equals(propertyNames[n])} and operating on
     * {@code (List<PPodVersionInfo>) currentState[n]}.
     * </ol>
     * 
     * @param entity being saved or updated
     * @param propertyNames property names of the entity
     * @param currentState the about to be saved or updated
     * @return {@code true} if we modify {@code currentState}, {@code false}
     *         otherwise
     */
    private boolean setPPodVersionInfoIfAppropriate(final Object entity, final String[] propertyNames,
            final Object[] currentState) {
        boolean modified = false;
        if (entity instanceof IPPodVersioned) {
            if (!((IPPodVersioned) entity).getAllowPersist()) {
                throw new IllegalArgumentException(
                        "entity is marked do not persist. Entity is " + entity.toString());
            }
            initializePPodVersionInfo();
            if (((IPPodVersioned) entity).isInNeedOfNewPPodVersionInfo()) {
                for (int i = 0; i < propertyNames.length; i++) {
                    if (PPodVersionInfo.PPOD_VERSION_INFO_FIELD.equals(propertyNames[i])) {
                        currentState[i] = pPodVersionInfosBySession.get(sessionFactory.getCurrentSession());
                        ((IPPodVersioned) entity).setPPodVersionInfo(
                                pPodVersionInfosBySession.get(sessionFactory.getCurrentSession()));
                        // ((IPPodVersioned) entity)
                        // .unsetInNeedOfNewPPodVersionInfo();
                        modified = true;
                    }
                }
            }
        }
        if (entity instanceof CharacterStateMatrix) {
            for (int i = 0; i < propertyNames.length; i++) {
                if ("columnPPodVersionInfos".equals(propertyNames[i])) {
                    @SuppressWarnings("unchecked")
                    final List<PPodVersionInfo> columnPPodVersionInfos = (List<PPodVersionInfo>) currentState[i];
                    for (int j = 0; j < columnPPodVersionInfos.size(); j++) {
                        if (columnPPodVersionInfos.get(j) == null) {
                            columnPPodVersionInfos.set(j,
                                    pPodVersionInfosBySession.get(sessionFactory.getCurrentSession()));
                            modified = true;
                        }
                    }
                    currentState[i] = columnPPodVersionInfos;
                }
            }
        }
        return modified;
    }

    /**
     * Set the session factory for this interceptor to use.
     * 
     * @param sessionFactory the session factory
     * @return this
     */
    public PPodVersionInfoInterceptor setSessionFactory(final SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
        return this;
    }
}