de.tudarmstadt.ukp.lmf.transform.UBYHibernateTransformer.java Source code

Java tutorial

Introduction

Here is the source code for de.tudarmstadt.ukp.lmf.transform.UBYHibernateTransformer.java

Source

/*******************************************************************************
 * Copyright 2015
 * Ubiquitous Knowledge Processing (UKP) Lab
 * Technische Universitt Darmstadt
 * 
 * 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 de.tudarmstadt.ukp.lmf.transform;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistryBuilder;

import de.tudarmstadt.ukp.lmf.hibernate.HibernateConnect;
import de.tudarmstadt.ukp.lmf.model.interfaces.IHasParentSpecificTable;
import de.tudarmstadt.ukp.lmf.model.miscellaneous.EVarType;
import de.tudarmstadt.ukp.lmf.transform.UBYLMFClassMetadata.UBYLMFFieldMetadata;

/**
 * Abstract base class for all resource transformations requiring a 
 * Hibernate session (i.e., transformations requring database access).
 * @author Christian M. Meyer
 */
public abstract class UBYHibernateTransformer extends UBYXMLTransformer {

    protected Session session;
    protected Transaction tx;
    protected SessionFactory sessionFactory;

    public UBYHibernateTransformer(final DBConfig dbConfig) {
        super();
        Configuration cfg = HibernateConnect.getConfiguration(dbConfig);
        sessionFactory = cfg.buildSessionFactory(
                new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry());
    }

    /** Adds the given child element to the list (which should be a member of
     *  the specified parent), saves the child, and updates the parent. To 
     *  reduce the memory footprint, the changes are periodically committed, 
     *  and the parent object is cleared. */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected void saveListElement(final Object parent, final List list, final Object child) {
        list.add(child);
        saveCascade(child, parent);
        commitCounter++;
        if (commitCounter % COMMIT_STEP == 0) {
            commit();
            session.clear();
            session.update(parent);
            list.clear();
        }
    }

    /** Saves all elements of the list and updates their parent (in contrast 
     *  to {@link #saveCascade(Object, Object)}, which would also save the 
     *  parent and lead to "element already exists" Hibernate exception). */
    @SuppressWarnings("rawtypes")
    protected void saveList(final Object parent, final List list) {
        for (Object obj : list)
            saveCascade(obj, parent);
        session.update(parent);
    }

    /** Saves the specified object and all its children to the Hibernate session.
     *  For objects implementing the {@link IHasParentSpecificTable} interface,
     *  a parent should be specified, which is used to derive the table name. */
    protected void saveCascade(final Object obj, final Object parent) {
        Class<?> objClass = obj.getClass();
        obj.toString(); // It can happen that a Hibernate object is not initialized properly
        // --> force initialization of object by calling its toString() method

        Class<?> parentClass = objClass;
        if (parent != null) {
            parentClass = parent.getClass();
            parent.toString(); // Force initialization of parent by calling its toString() method
        }

        // Identify dependent child objects and save them.
        UBYLMFClassMetadata classMeta = getClassMetadata(objClass);
        for (UBYLMFFieldMetadata fieldMeta : classMeta.getFields()) {
            EVarType varType = fieldMeta.getVarType();
            if (varType != EVarType.CHILDREN && varType != EVarType.CHILD)
                continue;

            Method getter = fieldMeta.getGetter();
            Object retObj = null;
            try {
                retObj = getter.invoke(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (retObj == null)
                continue;

            if (varType == EVarType.CHILD)
                saveCascade(retObj, obj);
            else if (varType == EVarType.CHILDREN)
                for (Object el : (Iterable<?>) retObj)
                    saveCascade(el, obj);
        }

        try {
            if (obj instanceof IHasParentSpecificTable)
                session.save(objClass.getSimpleName() + "_" + parentClass.getSimpleName(), obj);
            else
                session.save(obj);
        } catch (Exception ex) {
            System.err.println("CAN'T SAVE " + objClass.getSimpleName() + " PARENT: " + parentClass.getSimpleName()
                    + ": " + ex.getMessage());
        }
    }

    /** Shorthand for {@link #saveCascade(Object, Object)} with an empty 
     *  parent (i.e., the second parameter is null). */
    protected void saveCascade(final Object obj) {
        saveCascade(obj, null);
    }

    /** Returns the object of the given class with the specified ID from the 
     *  Hibernate session. */
    protected Object getLmfObjectById(final Class<?> clazz, final String id) {
        return session.get(clazz, id);
    }

    /** Opens a Hibernate session. */
    protected void openSession() {
        session = sessionFactory.openSession();
        tx = session.beginTransaction();
    }

    /** Closes the Hibernate session. */
    protected void closeSession() {
        tx.commit();
        session.close();
    }

    /** Commits changes made to the Hibernate session. */
    protected void commit() {
        System.out.println(new Date(System.currentTimeMillis()) + ": COMMIT " + commitCounter);
        tx.commit();
        tx = session.beginTransaction();
    }

}