com.chingo247.structureapi.plan.schematic.SchematicManager.java Source code

Java tutorial

Introduction

Here is the source code for com.chingo247.structureapi.plan.schematic.SchematicManager.java

Source

/*
 * Copyright (C) 2014 Chingo247
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.chingo247.structureapi.plan.schematic;

import com.chingo247.structureapi.QSchematicData;
import com.chingo247.structureapi.SchematicData;
import com.chingo247.structureapi.StructureAPI;
import com.chingo247.structureapi.persistence.hibernate.HibernateUtil;
import com.chingo247.structureapi.persistence.service.AbstractService;
import com.chingo247.structureapi.plan.StructurePlan;
import com.mysema.query.jpa.JPQLQuery;
import com.mysema.query.jpa.hibernate.HibernateQuery;
import com.sk89q.worldedit.data.DataException;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 *
 * @author Chingo
 */
public class SchematicManager {

    private final Map<Long, Schematic> schematics = Collections.synchronizedMap(new HashMap<Long, Schematic>());
    private final ExecutorService executor;
    private final StructureAPI structureAPI;

    public SchematicManager(StructureAPI structureAPI, ExecutorService executorService) {
        this.executor = executorService;
        this.structureAPI = structureAPI;
    }

    /**
     * Loads the file only if there is no cached version available. New schematics will be cached
     * @param schematic The schematic file
     * @return The schematic for this file
     * @throws IOException
     * @throws DataException 
     */
    public Schematic load(File schematic) throws IOException, DataException {
        long checksum = FileUtils.checksumCRC32(schematic);
        Schematic s = schematics.get(checksum);
        if (s != null) {
            return s;
        }
        s = Schematic.load(schematic);
        schematics.put(checksum, s);

        return s;
    }

    public List<Schematic> getSchematics() {
        return new LinkedList<>(schematics.values());
    }

    public boolean hasSchematic(long checksum) {
        return schematics.get(checksum) != null;
    }

    public boolean hasSchematic(StructurePlan plan) throws IOException {
        long checkskum = FileUtils.checksumCRC32(plan.getSchematic());
        return hasSchematic(checkskum);
    }

    /**
     * Loads all schematics
     */
    public void load() {
        List<File> schms = new LinkedList<>();
        for (StructurePlan plan : structureAPI.getStructurePlanManager().getPlans()) {
            schms.add(plan.getSchematic());
        }
        filter(schms);
        save(schms);
    }

    private void filter(final List<File> schematics) {
        Set<Long> checksums = new HashSet<>();
        Iterator<File> it = schematics.iterator();
        while (it.hasNext()) {
            File file = it.next();
            try {
                long checksum = FileUtils.checksumCRC32(file);
                QSchematicData qsd = QSchematicData.schematicData;
                if (exists(checksum) || checksums.contains(checksum)) {
                    it.remove();
                } else {
                    checksums.add(checksum);
                }

            } catch (IOException ex) {
                Logger.getLogger(SchematicManager.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private boolean exists(long checksum) throws IOException {
        Session session = HibernateUtil.getSession();
        JPQLQuery query = new HibernateQuery(session);
        QSchematicData qsd = QSchematicData.schematicData;
        boolean exists = query.from(qsd).where(qsd.checksum.eq(checksum)).exists();
        session.close();
        return exists;
    }

    private void save(final List<File> schematics) {

        final List<SchematicData> data = new LinkedList<>();
        List<Future> tasks = new LinkedList<>();

        for (final File file : schematics) {
            tasks.add(executor.submit(new Runnable() {

                @Override
                public void run() {
                    try {
                        data.add(SchematicData.load(file));
                    } catch (IOException | DataException ex) {
                        Logger.getLogger(SchematicManager.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }));
        }

        for (Future task : tasks) {
            try {
                task.get();
            } catch (InterruptedException | ExecutionException ex) {
                Logger.getLogger(SchematicManager.class.getName()).log(Level.SEVERE, null, ex);
                for (Future f : tasks) {
                    f.cancel(true);
                }
            }
        }

        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtil.getSession();
            tx = session.beginTransaction();
            for (SchematicData schematicData : data) {
                session.merge(schematicData);
            }
            tx.commit();
        } catch (HibernateException e) {
            try {
                tx.rollback();
            } catch (HibernateException rbe) {
                Logger.getLogger(AbstractService.class.getName()).log(Level.SEVERE,
                        "Couldnt roll back transaction", rbe);
            }
            throw e;
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    /**
     * Gets data about the schematic, doesn't contain the CuboidClipboard
     * @param checksum The checksum
     * @return The schematicData
     */
    public SchematicData getData(long checksum) {
        Session session = HibernateUtil.getSession();
        QSchematicData qsd = QSchematicData.schematicData;
        SchematicData cachedEntry = (SchematicData) session.get(SchematicData.class, checksum);
        if (cachedEntry != null) {
            session.close();
            return cachedEntry;
        }
        JPQLQuery query = new HibernateQuery(session);
        SchematicData data = query.from(qsd).where(qsd.checksum.eq(checksum)).uniqueResult(qsd);
        session.close();
        return data;
    }

}