de.iai.ilcd.model.dao.SourceDao.java Source code

Java tutorial

Introduction

Here is the source code for de.iai.ilcd.model.dao.SourceDao.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Karlsruhe Institute of Technology (KIT) - Institute for
 * Applied Computer Science (IAI).
 * 
 * This file is part of soda4LCA - the Service-Oriented Life Cycle Data Store.
 * 
 * soda4LCA 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.
 * 
 * soda4LCA 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 soda4LCA. If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package de.iai.ilcd.model.dao;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.velocity.tools.generic.ValueParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.fzk.iai.ilcd.service.model.ISourceListVO;
import de.fzk.iai.ilcd.service.model.ISourceVO;
import de.fzk.iai.ilcd.service.model.enums.PublicationTypeValue;
import de.iai.ilcd.model.common.DigitalFile;
import de.iai.ilcd.model.source.Source;
import de.iai.ilcd.persistence.PersistenceUtil;
import de.schlichtherle.io.File;

/**
 * Data access object for {@link Source sources}
 */
public class SourceDao extends DataSetDao<Source, ISourceListVO, ISourceVO> {

    private static final Logger logger = LoggerFactory.getLogger(SourceDao.class);

    public SourceDao() {
        super("Source", Source.class, ISourceListVO.class, ISourceVO.class);
    }

    protected String getDataStockField() {
        return "sources";
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void preCheckAndPersist(Source source) {
        // nothing to do
    }

    /**
     * Concrete implementation required for saving of digital files
     */
    @Override
    public boolean checkAndPersist(Source source, PersistType pType, PrintWriter out) {
        EntityManager em = PersistenceUtil.getEntityManager();

        Source existingSource = this.getByUuid(source.getUuid().getUuid());
        if (existingSource != null) {
            if (pType == PersistType.ONLYNEW) {
                out.println(
                        "Warning: source data set with this uuid already exists in database; will ignore this data set");
                return false;
            }
        }

        EntityTransaction t = em.getTransaction();
        try {
            t.begin();
            if (existingSource != null && (pType == PersistType.MERGE)) {
                // delete first the existing one, we will use the new one
                if (out != null) {
                    out.println(
                            "Notice: source data set with this uuid already exists in database; will merge this data set");
                }
                em.remove(existingSource);
                this.deleteDigitalFiles(source);
            }

            em.persist(source);

            t.commit();

            if (!super.setMostRecentVersionFlags(source.getUuidAsString())) {
                return false;
            }

            if (source != null && source.getId() != null) {
                if (!this.saveDigitalFiles(source, out)) {
                    if (out != null) {
                        out.println(
                                "Warning: couldn't save all files of this source data set into database file directory: see messages above");
                    }
                }
            }
            return true;

        } catch (Exception e) {
            if (out != null) {
                out.println("Can't save source data file to database because of: " + e.getMessage());
            }
            t.rollback();
            return false;
        }
    }

    private boolean saveDigitalFiles(Source source, PrintWriter out) {
        EntityManager em = PersistenceUtil.getEntityManager();

        File directory = null;
        EntityTransaction t = em.getTransaction();
        try {

            // OK, now let's handle the files if any
            if ((source.getFiles().size() > 0) && (source.getId() > 0)) { // we have files and the source has a valid
                // id
                // first let's check if the source has already a file directory to save binary files
                String directoryPath = source.getFilesDirectory();
                directory = new File(directoryPath);

                if (!directory.exists()) {
                    directory.mkdirs(); // OK, create the directory and all parents
                } // OK, now that we verified that we have a directory, let's copy the files to the directory
                for (DigitalFile digitalFile : source.getFiles()) {
                    String sourcePath = digitalFile.getFileName();
                    logger.info("have to save digital file {}", sourcePath);
                    File file = new File(sourcePath);
                    if (file.canRead()) {
                        // copy file only if we have a real file and not only a URL
                        File dest = new File(directory, file.getName());
                        if (!file.copyTo(dest)) {
                            if (out != null) {
                                out.println("cannot copy file " + file.getName() + " of source data set "
                                        + source.getName().getDefaultValue() + " to database file firectory");
                            }
                            logger.error("cannot copy digital file {} to source directory {}", file.getName(),
                                    directoryPath);
                        }
                        // now, replace name in digitalFile with just the name of the file
                        digitalFile.setFileName(FilenameUtils.getName(sourcePath));
                    } else {
                        if (!file.getName().startsWith("http:") || !file.getName().startsWith("https:")) {
                            // there are sometimes URL refs in source which don't have http:// prepended
                            if (!file.getName().matches(".+\\....") && file.getName().contains(".")) {
                                // looks like a URL with no http:// in front; try to fix that
                                digitalFile.setFileName("http://" + file.getName());
                            } else {
                                // we have a file which we cannot find
                                digitalFile.setFileName(FilenameUtils.getName(sourcePath));
                                out.println("warning: digital file " + FilenameUtils.getName(sourcePath)
                                        + " of source data set " + source.getName().getDefaultValue()
                                        + " cannot be found in external_docs directory");
                                logger.warn(
                                        "warning: digital file {} of source data set {} cannot be found in external_docs directory; will be ignored",
                                        file.getName(), source.getName().getDefaultValue());
                            }
                        }
                    }
                    t.begin();
                    em.persist(digitalFile);
                    t.commit();
                }
            }
        } catch (Exception e) {
            // OK, let's delete the digital files and rollback the whole transaction to remove database items
            logger.error("cannot save digital file", e);
            if (t.isActive()) {
                t.rollback();
            }
            this.deleteDigitalFiles(source);
            return false;
        }
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Source remove(Source source) throws DeleteDataSetException {
        if (source == null || source.getId() == null) {
            return null;
        }
        Source tmp = super.remove(source);
        this.deleteDigitalFiles(tmp);
        return tmp;
    }

    private void deleteDigitalFiles(Source source) {
        File directory = null;
        if (source == null) {
            return;
        }
        if ((source.getFiles().size() > 0) && (source.getId() > 0)) { // we have files and the source has a valid id
            // first let's check if the source has already a file directory to save binary files
            String directoryPath = source.getFilesDirectory();
            directory = new File(directoryPath);

            if (directory != null && directory.exists()) {
                try {
                    FileUtils.deleteDirectory(directory);
                } catch (IOException ex) {
                    // we will ignore this because we tried the best to delete everything
                }
            }
        }
        return;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void addWhereClausesAndNamedParamesForQueryStringJpql(String typeAlias, ValueParser params,
            List<String> whereClauses, Map<String, Object> whereParamValues) {
        String type = params.getString("type");
        if (type != null && (type.length() > 3) && (!type.equals("select option"))) {
            PublicationTypeValue typeValue = null;
            try {
                typeValue = PublicationTypeValue.valueOf(type);
            } catch (Exception e) {
                // ignore it as we do not have a parsable value
            }
            if (typeValue != null) {
                whereClauses.add(typeAlias + ".type=:typeOfSrc");
                whereParamValues.put("typeOfSrc", typeValue);
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getQueryStringOrderJpql(String typeAlias, String sortString) {
        if ("classification.classHierarchyAsString".equals(sortString)) {
            return typeAlias + ".classificationCache";
        } else if ("publicationType.value".equals(sortString)) {
            return typeAlias + ".publicationType";
        } else {
            return typeAlias + ".nameCache";
        }
    }

    /*
     * ================================================== == DEPRECATED METHODS / BACKWARDS COMPATIBILITY ==
     * ==================================================
     */
    /**
     * Get list of all sources
     * 
     * @return list of all sources
     * @deprecated still exists for internal backwards compatibility, may be removed in future releases. Use
     *             {@link #getAll()}.
     * @see #getAll()
     */
    @Deprecated
    public List<Source> getSources() {
        return this.getAll();
    }

    /**
     * Get a source by UUID
     * 
     * @param uuid
     *            UUID of flow to get
     * @return source with provided UUID
     * @deprecated still exists for internal backwards compatibility, may be removed in future releases. Use
     *             {@link #getByUuid(String)}.
     * @see #getByUuid(String)
     */
    @Deprecated
    public Source getSource(String uuid) {
        return this.getByUuid(uuid);
    }

    /**
     * Get the source with the provided JPA id
     * 
     * @param datasetId
     *            JPA id
     * @return source with the provided JPA id
     * @deprecated still exists for internal backwards compatibility, may be removed in future releases. Use
     *             {@link #getByDataSetId(long)}.
     * @see #getByDataSetId(long)
     */
    @Deprecated
    public Source getSource(long datasetId) {
        return this.getByDataSetId(datasetId);
    }

    /**
     * Get the source with the provided JPA id
     * 
     * @param id
     *            JPA id as string
     * @return source with the provided JPA id
     * @deprecated still exists for internal backwards compatibility, may be removed in future releases. Use
     *             {@link #getByDataSetId(String)}.
     * @see #getByDataSetId(String)
     */
    @Deprecated
    public Source getSourceById(String id) {
        return this.getByDataSetId(id);
    }

    /**
     * Get the source with the provided JPA id
     * 
     * @param id
     *            JPA id
     * @return source with the provided JPA id
     * @deprecated still exists for internal backwards compatibility, may be removed in future releases. Use
     *             {@link #getByDataSetId(long)}.
     * @see #getByDataSetId(long)
     */
    @Deprecated
    public Source getSourceById(Long id) {
        return this.getByDataSetId(id);
    }

    /**
     * Get sources by main class
     * 
     * @param mainClass
     *            main class to get source by
     * @return matched data sets
     * @deprecated still exists for internal backwards compatibility, may be removed in future releases. Use
     *             {@link #getByClass(String)}.
     * @see #getByClass(String)
     */
    @Deprecated
    public List<Source> getSourcesByClass(String mainClass) {
        return this.getByClass(mainClass);
    }

    /**
     * Get the number of sources by main class
     * 
     * @param mainClass
     *            main class to get source by
     * @return the number of matched data sets
     * @deprecated still exists for internal backwards compatibility, may be removed in future releases. Use
     *             {@link #getByClass(String)}.
     * @see #getNumberByClass(String)
     */
    @Deprecated
    public long getNumberOfSources(String mainClass) {
        return this.getNumberByClass(mainClass);
    }

    /**
     * Get sources by main and sub class
     * 
     * @param mainClass
     *            main class to get source by
     * @param subClass
     *            sub class to get source by
     * @return matched data sets
     * @deprecated still exists for internal backwards compatibility, may be removed in future releases. Use
     *             {@link #getByClass(String,String)}.
     * @see #getByClass(String,String)
     */
    @Deprecated
    public List<Source> getSourcesByClass(String mainClass, String subClass) {
        return this.getByClass(mainClass, subClass);
    }

    /**
     * Get number of sources by main and sub class
     * 
     * @param mainClass
     *            main class to get source by
     * @param subClass
     *            sub class to get source by
     * @return number of matched data sets
     * @deprecated still exists for internal backwards compatibility, may be removed in future releases. Use
     *             {@link #getByClass(String,String)}.
     * @see #getNumberByClass(String,String)
     */
    @Deprecated
    public long getNumberOfSources(String mainClass, String subClass) {
        return this.getNumberByClass(mainClass, subClass);
    }
}