org.clothocad.hibernate.HibernateConnection.java Source code

Java tutorial

Introduction

Here is the source code for org.clothocad.hibernate.HibernateConnection.java

Source

/*
Copyright (c) 2009 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
    
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
    
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 */
package org.clothocad.hibernate;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import javax.swing.filechooser.FileFilter;
import org.clothocore.api.data.ObjBase.ObjBaseDatum;
import org.clothocad.hibernate.data.*;
import org.clothocore.api.plugin.ClothoConnection;
import org.clothocore.api.data.*;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Restrictions;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;

/**
 *
 * @author Bing Xia
 */
public class HibernateConnection implements ClothoConnection {

    public HibernateConnection() {
    }

    @Override
    public boolean connect() {
        return false;
    }

    @Override
    public boolean isAClothoDatabase() {
        return true;
    }

    public static List<FileObject> getDefaultMappings() {
        FileObject mappingDir = FileUtil.getConfigFile("data/private/org.clothocad.hibernate");
        return Arrays.asList(mappingDir.getChildren());
    }

    public boolean connect(URL hibernateXML, List<URL> mappings) {
        // Create a new configuration and configures it.
        Configuration config = new Configuration();
        for (URL map : mappings) {
            config.addURL(map);
        }

        try {
            // Attempt to create a session factory from the configuration.
            // As long as this session factory is active, the connection is
            // defined as active.
            config.configure(hibernateXML);
            fac = config.buildSessionFactory();
            HibernateConnection.connection = this;
            return true;
        } catch (Throwable e) {
            System.err.println(e);
            e.printStackTrace();
            fac = null;
            return false;
        }
    }

    @Override
    public boolean disconnect() {
        try {
            fac.close();
            return true;
        } catch (Throwable e) {
            e.printStackTrace();
            System.err.println(e);
            return false;
        } finally {
            fac = null;
        }
    }

    @Override
    public boolean isConnected() {
        return fac != null;
    }

    @Override
    public boolean save(ObjBase obj) {
        SearchtagTable.updateSearchTags(obj); //JCA:  Relays to save search tags for object
        if (obj.getType() == ObjType.PART) {
            //TODO: figure out a better way...if there is one
            return savePart((Part) obj);
        }
        Session session = null;
        Transaction transaction = null;
        try {
            session = fac.openSession();
            Object toSave = getHibernateDatum(obj, session); //This will instantiate the objbaseTable constructor
            if (toSave == null) {
                return false;
            }

            //Do the save from the hibernateDatum constructor
            transaction = session.beginTransaction();
            hibernateDatum d = (hibernateDatum) toSave;
            System.out.println(
                    "hibernateconnectionplugin will save" + d.toString() + "  " + d.getName() + " " + d.getUUID()); // FIXME: remove in final version
            session.saveOrUpdate(toSave);
            transaction.commit();

            //Do any secondary processing saves for new objBase's xrefs
            if (d.needsSecondaryProcessing()) {
                transaction = session.beginTransaction();
                d.runSecondaryProcessing(obj);
                session.saveOrUpdate(toSave);
                transaction.commit();
            }

            session.close();
            activeSession = null;
            return true;
        } catch (RuntimeException e) {
            e.printStackTrace();
            System.err.println("Commit failed!");
            if (transaction != null && transaction.isActive()) {
                try {
                    transaction.rollback();
                } catch (HibernateException e1) {
                    System.err.println("Rollback failed");
                }
            }
        }
        return false;
    }

    /**
     * For saving a Part, since the order of operations for this save
     * doesn't fit well into the normal save method.
     * @param pt
     * @return
     */
    boolean savePart(Part pt) {
        Session s = null;
        Transaction t = null;
        try {
            List<String> newXrefs = pt.getComposition();
            s = fac.openSession();

            if (pt.getPartType() == Part.partType.Composite) {

                PartTable existingPart = (PartTable) getHibernateDatum(ObjType.PART, pt.getUUID(), s);

                if (existingPart != null) {
                    // Part already exists
                    // Check if all the xrefs match perfectly
                    boolean changed = false;
                    Set<CompositeXref> curXrefs = existingPart.getCompositeXrefsForChildPart();

                    System.out.println(curXrefs.size() + " " + newXrefs.size());
                    if (curXrefs.size() == newXrefs.size()) {
                        String[] curXrefUUIDs = new String[curXrefs.size()];
                        for (CompositeXref xr : curXrefs) {
                            String parentUUID = xr.getPartTableByParentPart().getUUID();
                            curXrefUUIDs[xr.getPosition()] = parentUUID;
                        }

                        for (int i = 0; i < curXrefUUIDs.length; i++) {
                            if (!newXrefs.get(i).equals(curXrefUUIDs[i])) {
                                changed = true;
                            }
                        }
                    } else {
                        changed = true;
                    }

                    if (changed) {
                        System.out.println("changed");
                        for (CompositeXref xr : curXrefs) {
                            System.out.println("deleting " + xr);
                            t = s.beginTransaction();
                            s.delete(xr);
                            t.commit();
                        }

                        for (int i = 0; i < newXrefs.size(); i++) {
                            String uuid = newXrefs.get(i);
                            CompositeXref cxr = new CompositeXref(UUID.randomUUID().toString(), new PartTable(uuid),
                                    existingPart, i);
                            t = s.beginTransaction();
                            s.save(cxr);
                            t.commit();
                        }
                    }
                } else {
                    // Part doesn't exist yet...have to save it, then save the xrefs
                    t = s.beginTransaction();
                    PartTable toSave = new PartTable(pt);
                    s.save(toSave);
                    t.commit();

                    // Save the xrefs

                    for (int i = 0; i < newXrefs.size(); i++) {
                        CompositeXref xr = new CompositeXref(UUID.randomUUID().toString(),
                                new PartTable(newXrefs.get(i)), toSave, i);
                        t = s.beginTransaction();
                        s.save(xr);
                        t.commit();
                    }
                }

            } else {
                // Not a composite, can save much more simply
                PartTable toSave = new PartTable(pt);
                t = s.beginTransaction();
                s.saveOrUpdate(toSave);
                t.commit();
            }
            s.close();

            return true;
        } catch (RuntimeException e) {
            e.printStackTrace();
            System.err.println("Commit failed!");
            if (t != null && t.isActive()) {
                try {
                    t.rollback();
                } catch (HibernateException e1) {
                    System.err.println("Rollback failed");
                }
            }
        }

        return false;
    }

    public boolean saveDatum(Object toSave) {
        Session s = null;
        Transaction t = null;
        try {
            s = fac.openSession();
            t = s.beginTransaction();
            if (toSave != null) {
                s.saveOrUpdate(toSave);
            } else {
                return false;
            }
            t.commit();
            s.close();
            return true;
        } catch (RuntimeException e) {
            e.printStackTrace();
            System.err.println("Commit failed!");
            if (t != null && t.isActive()) {
                try {
                    t.rollback();
                } catch (HibernateException e1) {
                    System.err.println("Rollback failed");
                }
            }
        }
        return false;
    }

    public boolean deleteDatum(Object toDelete) {
        Session s = null;
        Transaction t = null;
        try {
            boolean startedsession = false;
            ;
            if (activeSession != null) {
                s = activeSession;
            } else {
                s = fac.openSession();
                startedsession = true;
            }
            t = s.beginTransaction();
            if (toDelete != null) {
                s.delete(toDelete);
            } else {
                return false;
            }
            t.commit();
            if (startedsession) {
                s.close();
            }
            return true;
        } catch (RuntimeException e) {
            e.printStackTrace();
            System.err.println("Commit failed!");
            if (t != null && t.isActive()) {
                try {
                    t.rollback();
                } catch (HibernateException e1) {
                    System.err.println("Rollback failed");
                }
            }
        }
        return false;
    }

    @Override
    public int save(Collection<ObjBase> objs) {
        Session session = null;
        Transaction transaction = null;
        int succeeded = 0;
        try {
            session = fac.openSession();
            for (ObjBase obj : objs) {
                hibernateDatum toSave = getHibernateDatum(obj, session);
                if (toSave != null) {
                    transaction = session.beginTransaction();
                    System.out.println("hibernateconnectionplugin will save" + toSave.toString() + "  "
                            + toSave.getName() + " " + toSave.getUUID());
                    session.saveOrUpdate(toSave);
                    succeeded++;
                    transaction.commit();
                }
            }
            session.close();
        } catch (RuntimeException e) {
            e.printStackTrace();
            System.err.println("Commit failed!");
            if (transaction != null && transaction.isActive()) {
                try {
                    transaction.rollback();
                    return 0;
                } catch (HibernateException e1) {
                    session.close();
                    System.err.println("Rollback failed");
                }
            }
        }
        return succeeded;
    }

    @Override
    public ObjBaseDatum getDatum(ObjType type, String uuid) {
        Session s = fac.openSession();
        hibernateDatum data = getHibernateDatum(type, uuid, s);
        ObjBaseDatum out = null;
        if (data != null) {
            out = data.getObjBaseDatum();
        } else {
            out = null;
        }
        s.close();
        return out;
    }

    @Override
    public boolean delete(ObjBase obj) {
        System.out.println("Delete got called");
        if (obj == null) {
            System.out.println("Delete but ObjBase is null");
            return false;
        }

        //Query for any CollectionXref links and delete them
        String query = "from Collectionxref where objectId='" + obj.getType() + "'";
        Iterator xrefs = query(query);
        while (xrefs.hasNext()) {
            Object xr = xrefs.next();
            Collectionxref csr = (Collectionxref) xr;
            System.out.println("Delete found an xref, and its deleting it");
            HibernateConnection.connection.deleteDatum(csr);
        }

        Session s = null;
        Transaction t = null;
        try {
            System.out.println("Delete doing a transaction");
            s = fac.openSession();
            t = s.beginTransaction();
            if (obj != null) {
                s.delete(getEmptyDatum(obj));
            } else {
                return false;
            }
            t.commit();
            s.close();
            System.out.println("Delete returning true");
            return true;
        } catch (RuntimeException e) {
            e.printStackTrace();
            System.err.println("Commit failed!");
            if (t != null && t.isActive()) {
                try {
                    t.rollback();
                } catch (HibernateException e1) {
                    System.err.println("Rollback failed");
                }
            }
        }
        System.out.println("Delete returning false");
        return false;
    }

    @Override
    public int delete(Collection<ObjBase> objs) {
        Session session = null;
        Transaction transaction = null;
        int succeeded = 0;
        try {
            session = fac.openSession();
            transaction = session.beginTransaction();
            for (ObjBase obj : objs) {
                Object toDelete = getEmptyDatum(obj);
                if (toDelete != null) {
                    session.delete(toDelete);
                    succeeded++;
                }
            }
            transaction.commit();
            session.close();
        } catch (RuntimeException e) {
            e.printStackTrace();
            System.err.println("Commit failed!");
            if (transaction != null && transaction.isActive()) {
                try {
                    transaction.rollback();
                    return 0;
                } catch (HibernateException e1) {
                    session.close();
                    System.err.println("Rollback failed");
                }
            }
        }
        return succeeded;
    }

    /**
     * Retrieves an ObjBase object from the database using a uuid
     * @param type
     * @param uuid
     * @return
     */
    @Override
    public ObjBase get(ObjType type, String uuid) {
        Session s = fac.openSession();
        hibernateDatum d = getHibernateDatum(type, uuid, s);
        ObjBase result = null;
        if (d != null) {
            result = d.getObject();
            SearchtagTable.pullSearchTags(result);
        }
        s.close();
        return result;
    }

    @Override
    public Collection<ObjBase> get(String hibQuery) {
        Collection<ObjBase> objs = new ArrayList<ObjBase>();
        Session s = fac.openSession();

        Transaction transaction = s.beginTransaction();
        Query q = s.createQuery(hibQuery);
        Iterator<hibernateDatum> results = q.iterate();
        while (results.hasNext()) {
            hibernateDatum d = results.next();
            ObjBase obj = d.getObject();
            SearchtagTable.pullSearchTags(obj);
            objs.add(obj);
        }
        transaction.commit();
        return objs;
    }

    @Override
    public ArrayList<ObjLink> getAllLinks(ObjType type) {
        ArrayList<ObjLink> out = new ArrayList<ObjLink>();
        System.out.println("********* Getting all " + type.toString() + ":");

        Iterator collIT = findAll(type);
        while (collIT.hasNext()) {
            hibernateDatum datum = (hibernateDatum) collIT.next();

            String name = datum.getName();
            String uuid = datum.getUUID();

            out.add(new ObjLink(uuid, type, name));
        }
        return out;
    }

    @Override
    public String[][] getTableAsArray(ObjType type) {
        ArrayList<String[]> templist = new ArrayList<String[]>();

        Iterator collIT = findAll(type);
        while (collIT.hasNext()) {
            hibernateDatum datum = (hibernateDatum) collIT.next();

            String[] aline = new String[3];
            aline[0] = datum.getUUID();
            aline[1] = datum.getName();

            switch (type) {
            case FEATURE:
                FeatureTable ft = (FeatureTable) datum;
                aline[2] = ft.getNucseqTable().getSequence();
                break;
            default:
                aline[2] = "";
            }

            templist.add(aline);
        }

        String[][] out = new String[templist.size()][3];
        for (int i = 0; i < templist.size(); i++) {
            out[i] = templist.get(i);
        }

        return out;
    }

    /**
     * Returns all the objects of the given type.
     * @param type - Object keyword
     * @return - Iterator giving results
     */
    private Iterator<hibernateDatum> findAll(ObjType type) {
        Session session = null;
        Transaction transaction = null;
        session = fac.openSession();
        Transaction t = session.beginTransaction();
        String tabletoprobe = getObjectTranslation(type);
        System.out.println("Probing " + tabletoprobe);

        Query q = session.createQuery("from " + tabletoprobe);
        Iterator<hibernateDatum> it = q.iterate();

        t.commit();
        return it;
    }

    /**
     * JCA added this.  Used for queries within the connection.
     * @param hibQuery
     * @return
     */
    public Iterator query(String hibQuery) {
        Session session = null;
        Transaction transaction = null;
        session = fac.openSession();
        activeSession = session;
        Transaction t = session.beginTransaction();
        Query q = session.createQuery(hibQuery);
        Iterator it = q.iterate();
        t.commit();
        return it;
    }

    @Override
    public void init() {
        // In the future, add preference loading and such
    }

    public void configure() {
        //        _configurationViewer = new ConfigurationView( this );
        //        _configurationViewer.setVisible( true );
    }

    @Override
    public Date getTimeModified(ObjBase obj) {
        String query = "";

        //JCA:  I have this if here since there is a typo in the field name of nucseq.  Worth fixing eventually.
        if (obj.getType().equals(ObjType.NUCSEQ)) {
            query = "select lastmodified from " + getObjectTranslation(obj.getType()) + " where id='"
                    + obj.getUUID() + "'";
        } else {
            query = "select lastModified from " + getObjectTranslation(obj.getType()) + " where id='"
                    + obj.getUUID() + "'";
        }

        Session session = null;
        Transaction transaction = null;
        try {
            session = fac.openSession();

            transaction = session.beginTransaction();
            Date lastMod = (Date) session.createQuery(query).uniqueResult();
            transaction.commit();
            session.close();
            return lastMod;
        } catch (RuntimeException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public ClothoConnection.ClothoQuery createQuery(ObjType type) {
        return new HibernateQuery(type);
    }

    /**
     * Use this to get a datum object built from a given ObjBase object. The
     * resulting hibernateDatum object can be saved using hibernate. There should be one
     * case here for each API type that is valid.
     * @param obj
     * @return
     */
    hibernateDatum getHibernateDatum(ObjBase obj, Session s) {
        if (obj == null) {
            return null;
        }
        switch (obj.getType()) {
        case ANNOTATION:
            return new NucseqAnnotation((Annotation) obj);
        case ATTACHMENT:
            return new AttachmentTable((Attachment) obj);
        case COLLECTION:
            return new CollectionTable((org.clothocore.api.data.Collection) obj);
        case CONTAINER:
            return new ContainerTable((Container) obj);
        case FACTOID:
            return new FactoidTable((Factoid) obj);
        case FAMILY:
            return new FamilyTable((Family) obj);
        case FEATURE:
            return new FeatureTable((Feature) obj);
        case FLEX_FIELD:
            return new FlexfieldTable((FlexField) obj);
        case FORMAT:
            return new FormatTable((Format) obj);
        case GRAMMAR:
            return new GrammarTable((Grammar) obj);
        case INSTITUTION:
            return new InstitutionTable((Institution) obj);
        case LAB:
            return new LabTable((Lab) obj);
        case NUCSEQ:
            return new NucseqTable((NucSeq) obj);
        case NOTE:
            return new NoteTable((Note) obj);
        case OLIGO:
            return new OligoTable((Oligo) obj);
        case PART:
            // ASSERT: never reached, because parts are handled differently
            return new PartTable((Part) obj);
        case PERSON:
            return new PersonTable((Person) obj);
        case PLASMID:
            return new PlasmidTable((Plasmid) obj);
        case PLATE:
            return new PlateTable((Plate) obj);
        case PLATE_TYPE:
            return new PlateTypeTable((PlateType) obj);
        case SAMPLE:
            return new SampleTable((Sample) obj);
        case SAMPLE_DATA:
            return new SampleDataTable((SampleData) obj);
        case STRAIN:
            return new StrainTable((Strain) obj);
        case WIKITEXT:
            return new WikitextTable((WikiText) obj);
        case VECTOR:
            return new VectorTable((Vector) obj);
        default:
            return null;
        }
    }

    /**
     * Use this to create an empty hibernateDatum object for the purpose of deleting or
     * saving a link. The returned hibernateDatum will be of the right type and only
     * have its UUID field filled in.
     * @param obj
     * @return
     */
    hibernateDatum getEmptyDatum(ObjBase obj) {
        if (obj == null) {
            return null;
        }
        switch (obj.getType()) {
        case ANNOTATION:
            return new NucseqAnnotation(obj.getUUID());
        case ATTACHMENT:
            return new AttachmentTable(obj.getUUID());
        case COLLECTION:
            return new CollectionTable(obj.getUUID());
        case CONTAINER:
            return new ContainerTable(obj.getUUID());
        case FACTOID:
            return new FactoidTable(obj.getUUID());
        case FAMILY:
            return new FamilyTable(obj.getUUID());
        case FEATURE:
            return new FeatureTable(obj.getUUID());
        case FLEX_FIELD:
            return new FlexfieldTable(obj.getUUID());
        case FORMAT:
            return new FormatTable(obj.getUUID());
        case GRAMMAR:
            return new GrammarTable(obj.getUUID());
        case INSTITUTION:
            return new InstitutionTable(obj.getUUID());
        case LAB:
            return new LabTable(obj.getUUID());
        case NUCSEQ:
            return new NucseqTable(obj.getUUID());
        case NOTE:
            return new NoteTable(obj.getUUID());
        case OLIGO:
            return new OligoTable(obj.getUUID());
        case PART:
            return new PartTable(obj.getUUID());
        case PERSON:
            return new PersonTable(obj.getUUID());
        case PLASMID:
            return new PlasmidTable(obj.getUUID());
        case PLATE:
            return new PlateTable(obj.getUUID());
        case PLATE_TYPE:
            return new PlateTypeTable(obj.getUUID());
        case SAMPLE:
            return new SampleTable(obj.getUUID());
        case SAMPLE_DATA:
            return new SampleDataTable(obj.getUUID());
        case STRAIN:
            return new StrainTable(obj.getUUID());
        case WIKITEXT:
            return new WikitextTable(obj.getUUID());
        case VECTOR:
            return new VectorTable(obj.getUUID());
        default:
            return null;
        }
    }

    /**
     * Use this to get the datum object of the given type from the database. The
     * resulting object can be used to create an ObjBase object to return, or to
     * update an existing ObjBase object.
     *
     * openSession specifies whether this method needs to open a session, or whether
     * a session has already been opened outside this method.
     * @param type
     * @param uuid
     * @param openSession
     * @return
     */
    hibernateDatum getHibernateDatum(ObjType type, String uuid, Session session) {
        try {
            boolean openedSession = false;
            if (session == null) {
                session = fac.openSession();
                openedSession = true;
            }
            Transaction transaction = session.beginTransaction();
            Query q = session.createQuery("from " + getObjectTranslation(type) + " where id='" + uuid + "'");
            hibernateDatum d = (hibernateDatum) q.uniqueResult();
            transaction.commit();
            if (openedSession) {
                session.close();
            }
            return d;
        } catch (Throwable e) {
            System.err.println(e); // TODO: do some error output
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Returns a select query for the given ObjBase, assuming its in the database.
     * Uses the uuid of the given object along with its type to build the query.
     * @param obj
     * @return
     */
    String getSelectQuery(ObjBase obj) {
        String uuid = obj.getUUID();
        if (uuid == null) {
            return null;
        }
        String typeTranslation = getObjectTranslation(obj.getType());
        if (typeTranslation == null) {
            return null;
        }
        return "from " + typeTranslation + " where id='" + uuid + "'";

    }

    /**
     * Returns the database translation for the given type
     * @param type
     * @return
     */
    @Override
    public String getObjectTranslation(ObjType type) {
        switch (type) {
        case ANNOTATION:
            return "NucseqAnnotation";
        case ATTACHMENT:
            return "AttachmentTable";
        case COLLECTION:
            return "CollectionTable";
        case CONTAINER:
            return "ContainerTable";
        case FACTOID:
            return "FactoidTable";
        case FAMILY:
            return "FamilyTable";
        case FEATURE:
            return "FeatureTable";
        case FLEX_FIELD:
            return "FlexFieldTable";
        case FORMAT:
            return "FormatTable";
        case GRAMMAR:
            return "GrammarTable";
        case INSTITUTION:
            return "InstitutionTable";
        case LAB:
            return "LabTable";
        case NUCSEQ:
            return "NucseqTable";
        case NOTE:
            return "NoteTable";
        case OLIGO:
            return "OligoTable";
        case PART:
            return "PartTable";
        case PERSON:
            return "PersonTable";
        case PLASMID:
            return "PlasmidTable";
        case PLATE:
            return "PlateTable";
        case PLATE_TYPE:
            return "PlateTypeTable";
        case SAMPLE:
            return "SampleTable";
        case SAMPLE_DATA:
            return "SampleDataTable";
        case STRAIN:
            return "StrainTable";
        case VECTOR:
            return "VectorTable";
        case WIKITEXT:
            return "WikitextTable";
        default:
            return null;
        }
    }

    /**
     * Returns the field name of the given field type of the given object type.
     * This isn'transaction needed except for the HibernateQuery type searching of the database.
     * @param type
     * @param field
     * @return
     */
    @Override
    public String getFieldTranslation(ObjType type, Enum field) {
        String translation = null;
        System.out.println("getfieldTranslation of " + type + field);
        switch (type) {
        case ANNOTATION:
            translation = NucseqAnnotation.translate(field);
            break;
        case ATTACHMENT:
            translation = AttachmentTable.translate(field);
            break;
        case COLLECTION:
            translation = CollectionTable.translate(field);
            break;
        case CONTAINER:
            translation = ContainerTable.translate(field);
            break;
        case FACTOID:
            translation = FactoidTable.translate(field);
            break;
        case FAMILY:
            translation = FamilyTable.translate(field);
            break;
        case FEATURE:
            translation = FeatureTable.translate(field);
            break;
        case FLEX_FIELD:
            translation = FlexfieldTable.translate(field);
            break;
        case FORMAT:
            translation = FormatTable.translate(field);
            break;
        case GRAMMAR:
            translation = GrammarTable.translate(field);
            break;
        case INSTITUTION:
            translation = InstitutionTable.translate(field);
            break;
        case LAB:
            translation = LabTable.translate(field);
            break;
        case NOTE:
            translation = NoteTable.translate(field);
            break;
        case NUCSEQ:
            translation = NucseqTable.translate(field);
            break;
        case OLIGO:
            translation = OligoTable.translate(field);
            break;
        case PART:
            translation = PartTable.translate(field);
            break;
        case PERSON:
            translation = PersonTable.translate(field);
            break;
        case PLASMID:
            translation = PlasmidTable.translate(field);
            break;
        case PLATE:
            translation = PlateTable.translate(field);
            break;
        case PLATE_TYPE:
            translation = PlateTypeTable.translate(field);
            break;
        case SAMPLE:
            translation = SampleTable.translate(field);
            break;
        case SAMPLE_DATA:
            translation = SampleDataTable.translate(field);
            break;
        case STRAIN:
            translation = StrainTable.translate(field);
            break;
        case VECTOR:
            translation = VectorTable.translate(field);
            break;
        case WIKITEXT:
            translation = WikitextTable.translate(field);
            break;
        default:
            translation = null;
        }

        if (translation == null) {
            // TODO: signal an error somehow, but this should never happen
        }

        return translation;
    }

    public ObjType getFieldType(ObjType type, Enum field) {
        switch (type) {
        case ANNOTATION:
            return NucseqAnnotation.getType(field);
        case ATTACHMENT:
            return AttachmentTable.getType(field);
        case COLLECTION:
            return CollectionTable.getType(field);
        case CONTAINER:
            return ContainerTable.getType(field);
        case FACTOID:
            return FactoidTable.getType(field);
        case FAMILY:
            return FamilyTable.getType(field);
        case FEATURE:
            return FeatureTable.getType(field);
        case FLEX_FIELD:
            return FlexfieldTable.getType(field);
        case FORMAT:
            return FormatTable.getType(field);
        case GRAMMAR:
            return GrammarTable.getType(field);
        case INSTITUTION:
            return InstitutionTable.getType(field);
        case LAB:
            return LabTable.getType(field);
        case NOTE:
            return NoteTable.getType(field);
        case NUCSEQ:
            return NucseqTable.getType(field);
        case OLIGO:
            return OligoTable.getType(field);
        case PART:
            return PartTable.getType(field);
        case PERSON:
            return PersonTable.getType(field);
        case PLASMID:
            return PlasmidTable.getType(field);
        case PLATE:
            return PlateTable.getType(field);
        case PLATE_TYPE:
            return PlateTypeTable.getType(field);
        case SAMPLE:
            return SampleTable.getType(field);
        case SAMPLE_DATA:
            return SampleDataTable.getType(field);
        case STRAIN:
            return StrainTable.getType(field);
        case VECTOR:
            return VectorTable.getType(field);
        case WIKITEXT:
            return WikitextTable.getType(field);
        default:
            return null;
        }
    }

    /**************** PRIVATE VARIABLES ****************/
    private SessionFactory fac;
    private Session activeSession = null;
    private static FileFilter configFileFilter = new FileFilter() {

        public boolean accept(File pathname) {
            return pathname.getName().endsWith(".cfg.xml");
        }

        @Override
        public String getDescription() {
            return "Filters for Hibernate Configuration Files";
        }
    };
    public static HibernateConnection connection;

    /* Preference enums */
    public enum PreferenceKeys {

        CONFIG_DIRECTORY,
    }

    /***************************************************************************
     ***************************** Inner Class **********************************
     ***************************************************************************/
    class HibernateQuery implements ClothoConnection.ClothoQuery {

        private Criteria criteria;
        private ObjType type;
        private Session session;

        HibernateQuery(ObjType type) {
            session = fac.openSession();
            this.type = type;
            switch (type) {
            case ATTACHMENT:
                criteria = session.createCriteria(AttachmentTable.class);
                break;
            case COLLECTION:
                criteria = session.createCriteria(CollectionTable.class);
                break;
            case CONTAINER:
                criteria = session.createCriteria(ContainerTable.class);
                break;
            case FACTOID:
                criteria = session.createCriteria(FactoidTable.class);
                break;
            case FAMILY:
                criteria = session.createCriteria(FamilyTable.class);
                break;
            case FEATURE:
                criteria = session.createCriteria(FeatureTable.class);
                break;
            case FLEX_FIELD:
                criteria = session.createCriteria(FlexfieldTable.class);
                break;
            case FORMAT:
                criteria = session.createCriteria(FormatTable.class);
                break;
            case GRAMMAR:
                criteria = session.createCriteria(GrammarTable.class);
                break;
            case INSTITUTION:
                criteria = session.createCriteria(InstitutionTable.class);
                break;
            case LAB:
                criteria = session.createCriteria(LabTable.class);
                break;
            case NOTE:
                criteria = session.createCriteria(NoteTable.class);
                break;
            case NUCSEQ:
                criteria = session.createCriteria(NucseqTable.class);
                break;
            case OLIGO:
                criteria = session.createCriteria(OligoTable.class);
                break;
            case PART:
                criteria = session.createCriteria(PartTable.class);
                break;
            case PERSON:
                criteria = session.createCriteria(PersonTable.class);
                break;
            case PLASMID:
                criteria = session.createCriteria(PlasmidTable.class);
                break;
            case PLATE:
                criteria = session.createCriteria(PlateTable.class);
                break;
            case PLATE_TYPE:
                criteria = session.createCriteria(PlateTypeTable.class);
                break;
            case SAMPLE:
                criteria = session.createCriteria(SampleTable.class);
                break;
            case SAMPLE_DATA:
                criteria = session.createCriteria(SampleDataTable.class);
                break;
            case STRAIN:
                criteria = session.createCriteria(StrainTable.class);
                break;
            case VECTOR:
                criteria = session.createCriteria(VectorTable.class);
                break;
            case WIKITEXT:
                criteria = session.createCriteria(WikitextTable.class);
                break;
            default:
                System.err.println("Unrecognized type"); // TODO: Change this to a warning dialog
            }
        }

        private HibernateQuery(ObjType t, Criteria crit) {
            type = t;
            criteria = crit;
        }

        @Override
        public ClothoConnection.ClothoQuery setMaxResults(int max) {
            criteria = criteria.setMaxResults(max);
            return this;
        }

        @Override
        public ClothoConnection.ClothoQuery between(Enum field, Object hi, Object lo) {
            criteria = criteria.add(Restrictions.between(getFieldTranslation(type, field), lo, hi));
            return this;
        }

        @Override
        public ClothoConnection.ClothoQuery lessThan(Enum field, Object hi) {
            criteria = criteria.add(Restrictions.lt(getFieldTranslation(type, field), hi));
            return this;
        }

        @Override
        public ClothoConnection.ClothoQuery greaterThan(Enum field, Object lo) {
            criteria = criteria.add(Restrictions.gt(getFieldTranslation(type, field), lo));
            return this;
        }

        @Override
        public ClothoConnection.ClothoQuery equal(Enum field, Object value) {
            criteria = criteria.add(Restrictions.eq(getFieldTranslation(type, field), value));
            return this;
        }

        @Override
        public ClothoConnection.ClothoQuery eq(Enum field, Object value) {
            return equal(field, value);
        }

        @Override
        public ClothoConnection.ClothoQuery notEqual(Enum field, Object value) {
            criteria = criteria.add(Restrictions.ne(getFieldTranslation(type, field), value));
            return this;
        }

        @Override
        public ClothoConnection.ClothoQuery neq(Enum field, Object value) {
            return notEqual(field, value);
        }

        @Override
        public ClothoConnection.ClothoQuery isNull(Enum field) {
            criteria = criteria.add(Restrictions.isNull(getFieldTranslation(type, field)));
            return this;
        }

        @Override
        public ClothoConnection.ClothoQuery isNotNull(Enum field) {
            criteria = criteria.add(Restrictions.isNotNull(getFieldTranslation(type, field)));
            return this;
        }

        @Override
        public ClothoConnection.ClothoQuery matches(Enum field, String value, boolean caseSensitive) {
            if (caseSensitive) {
                criteria = criteria.add(Restrictions.like(getFieldTranslation(type, field), value));
            } else {
                criteria = criteria.add(Restrictions.ilike(getFieldTranslation(type, field), value));
            }
            return this;
        }

        @Override
        public ClothoConnection.ClothoQuery contains(Enum field, String value, boolean caseSensitive) {
            if (value.charAt(0) != '%') {
                value = "%" + value;
            }
            if (value.charAt(value.length() - 1) != '%') {
                value = value + "%";
            }
            if (caseSensitive) {
                criteria = criteria.add(Restrictions.like(getFieldTranslation(type, field), value));
            } else {
                criteria = criteria.add(Restrictions.ilike(getFieldTranslation(type, field), value));
            }
            return this;
        }

        @Override
        public List<ObjBase> getResults() {
            if (!session.isOpen()) {
                System.out.println("HibernateConnectionPlugin returning null since session isn't open");
                return null; // This method should only be called once!
            }
            List<ObjBase> results = new ArrayList<ObjBase>();
            List<hibernateDatum> datums = criteria.list();

            for (hibernateDatum d : datums) {
                ObjBase obj = d.getObject();
                SearchtagTable.pullSearchTags(obj);
                results.add(obj);
            }
            session.close();

            return results;
        }

        @Override
        public ClothoConnection.ClothoQuery add(ClothoConnection.ClothoCriterion crit) {
            if (crit != null && crit.getClass().equals(HibernateCriterion.class)) {
                criteria = criteria.add(((HibernateCriterion) crit)._myCriterion);
            }
            return this;
        }

        @Override
        public ClothoConnection.ClothoCriterion or(Collection<ClothoConnection.ClothoCriterion> criteria) {
            Iterator<ClothoConnection.ClothoCriterion> it = criteria.iterator();

            Disjunction d = Restrictions.disjunction();
            while (it.hasNext()) {
                ClothoConnection.ClothoCriterion cc = it.next();
                if (it.getClass().equals(HibernateCriterion.class)) {
                    d.add(((HibernateCriterion) cc)._myCriterion);
                }
            }
            return new HibernateCriterion(d);
        }

        @Override
        public ClothoConnection.ClothoCriterion or(ClothoConnection.ClothoCriterion a,
                ClothoConnection.ClothoCriterion b) {
            if (!a.getClass().equals(HibernateCriterion.class) || !b.getClass().equals(HibernateCriterion.class)) {
                return null;
            }

            HibernateCriterion ha = (HibernateCriterion) a, hb = (HibernateCriterion) b;

            Disjunction d = Restrictions.disjunction();
            d.add(ha._myCriterion).add(hb._myCriterion);
            return new HibernateCriterion(d);
        }

        @Override
        public ClothoConnection.ClothoCriterion and(Collection<ClothoConnection.ClothoCriterion> criteria) {
            Iterator<ClothoConnection.ClothoCriterion> it = criteria.iterator();

            Conjunction d = Restrictions.conjunction();
            while (it.hasNext()) {
                ClothoConnection.ClothoCriterion cc = it.next();
                if (it.getClass().equals(HibernateCriterion.class)) {
                    d.add(((HibernateCriterion) cc)._myCriterion);
                }
            }
            return new HibernateCriterion(d);
        }

        @Override
        public ClothoConnection.ClothoCriterion and(ClothoConnection.ClothoCriterion a,
                ClothoConnection.ClothoCriterion b) {
            if (a == null || b == null || !a.getClass().equals(HibernateCriterion.class)
                    || !b.getClass().equals(HibernateCriterion.class)) {
                return null;
            }

            HibernateCriterion ha = (HibernateCriterion) a, hb = (HibernateCriterion) b;

            Conjunction d = Restrictions.conjunction();
            d.add(ha._myCriterion).add(hb._myCriterion);
            return new HibernateCriterion(d);
        }

        @Override
        public ClothoConnection.ClothoCriterion not(ClothoConnection.ClothoCriterion c) {
            if (c != null && c.getClass().equals(HibernateCriterion.class)) {
                return new HibernateCriterion(Restrictions.not(((HibernateCriterion) c)._myCriterion));
            }
            return null;
        }

        @Override
        public ClothoConnection.ClothoCriterion getBetweenCrit(Enum field, Object hi, Object lo) {
            String f = getFieldTranslation(type, field);

            Criterion c = Restrictions.between(f, lo, hi);

            return new HibernateCriterion(c);
        }

        @Override
        public ClothoConnection.ClothoCriterion getLessThanCrit(Enum field, Object hi) {
            String f = getFieldTranslation(type, field);

            Criterion c = Restrictions.lt(f, hi);

            return new HibernateCriterion(c);
        }

        @Override
        public ClothoConnection.ClothoCriterion getGreaterThanCrit(Enum field, Object lo) {
            String f = getFieldTranslation(type, field);

            Criterion c = Restrictions.gt(f, lo);

            return new HibernateCriterion(c);
        }

        @Override
        public ClothoConnection.ClothoCriterion getEqualCrit(Enum field, Object value) {
            String f = getFieldTranslation(type, field);

            Criterion c = Restrictions.eq(f, value);

            return new HibernateCriterion(c);
        }

        @Override
        public ClothoConnection.ClothoCriterion getNotEqualCrit(Enum field, Object value) {
            String f = getFieldTranslation(type, field);

            Criterion c = Restrictions.ne(f, value);

            return new HibernateCriterion(c);
        }

        @Override
        public ClothoConnection.ClothoCriterion getIsNullCrit(Enum field) {
            String f = getFieldTranslation(type, field);

            Criterion c = Restrictions.isNull(f);

            return new HibernateCriterion(c);
        }

        @Override
        public ClothoConnection.ClothoCriterion getIsNotNullCrit(Enum field) {
            String f = getFieldTranslation(type, field);

            Criterion c = Restrictions.isNotNull(f);

            return new HibernateCriterion(c);
        }

        @Override
        public ClothoConnection.ClothoCriterion getMatchesCrit(Enum field, Object value) {
            String f = getFieldTranslation(type, field);

            Criterion c = Restrictions.ilike(f, value);

            return new HibernateCriterion(c);
        }

        @Override
        public ObjType getType() {
            return type;
        }

        @Override
        public ClothoQuery createAssociationQuery(Enum field) {
            return new HibernateQuery(getFieldType(type, field),
                    criteria.createCriteria(getFieldTranslation(type, field)));
        }
    }

    class HibernateCriterion extends ClothoConnection.ClothoCriterion {

        Criterion _myCriterion;

        protected HibernateCriterion(Criterion c) {
            _myCriterion = c;
        }
    }
}