Package de.sub.goobi.metadaten

Source Code of de.sub.goobi.metadaten.MetadatenImagesHelper$GoobiImageFileComparator

package de.sub.goobi.metadaten;

/**
* This file is part of the Goobi Application - a Workflow tool for the support of mass digitization.
*
* Visit the websites for more information.
*         - http://www.goobi.org
*         - http://launchpad.net/goobi-production
*         - http://gdz.sub.uni-goettingen.de
*       - http://www.intranda.com
*       - http://digiverso.com
*
* 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 2 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, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions
* of the GNU General Public License cover the whole combination. As a special exception, the copyright holders of this library give you permission to
* link this library with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and
* conditions of the license of that module. An independent module is a module which is not derived from or based on this library. If you modify this
* library, you may extend this exception to your version of the library, but you are not obliged to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
import java.awt.image.RenderedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.lang.SystemUtils;
import org.apache.log4j.Logger;

import ugh.dl.ContentFile;
import ugh.dl.DigitalDocument;
import ugh.dl.DocStruct;
import ugh.dl.DocStructType;
import ugh.dl.Metadata;
import ugh.dl.MetadataType;
import ugh.dl.Prefs;
import ugh.dl.Reference;
import ugh.dl.RomanNumeral;
import ugh.exceptions.ContentFileNotLinkedException;
import ugh.exceptions.DocStructHasNoTypeException;
import ugh.exceptions.MetadataTypeNotAllowedException;
import ugh.exceptions.TypeNotAllowedAsChildException;
import ugh.exceptions.TypeNotAllowedForParentException;
import de.sub.goobi.beans.Prozess;
import de.sub.goobi.config.ConfigMain;
import de.sub.goobi.helper.Helper;
import de.sub.goobi.helper.exceptions.DAOException;
import de.sub.goobi.helper.exceptions.InvalidImagesException;
import de.sub.goobi.helper.exceptions.SwapException;
import de.unigoettingen.sub.commons.contentlib.exceptions.ImageManagerException;
import de.unigoettingen.sub.commons.contentlib.exceptions.ImageManipulatorException;
import de.unigoettingen.sub.commons.contentlib.imagelib.ImageManager;
import de.unigoettingen.sub.commons.contentlib.imagelib.JpegInterpreter;

public class MetadatenImagesHelper {
    private static final Logger logger = Logger.getLogger(MetadatenImagesHelper.class);
    private Prefs myPrefs;
    private DigitalDocument mydocument;
    private int myLastImage = 0;

    public MetadatenImagesHelper(Prefs inPrefs, DigitalDocument inDocument) {
        this.myPrefs = inPrefs;
        this.mydocument = inDocument;
    }

    /**
     * Markus baut eine Seitenstruktur aus den vorhandenen Images ---------------- Steps - ---------------- Validation of images compare existing
     * number images with existing number of page DocStructs if it is the same don't do anything if DocStructs are less add new pages to
     * physicalDocStruct if images are less delete pages from the end of pyhsicalDocStruct --------------------------------
     *
     * @return null
     * @throws TypeNotAllowedForParentException
     * @throws TypeNotAllowedForParentException
     * @throws InterruptedException
     * @throws IOException
     * @throws InterruptedException
     * @throws IOException
     * @throws DAOException
     * @throws SwapException
     */
    public void createPagination(Prozess inProzess, String directory) throws TypeNotAllowedForParentException, IOException, InterruptedException,
            SwapException, DAOException {
        DocStruct physicaldocstruct = this.mydocument.getPhysicalDocStruct();

        DocStruct log = this.mydocument.getLogicalDocStruct();
        if (log.getType().isAnchor()) {
            if (log.getAllChildren() != null && log.getAllChildren().size() > 0) {
                log = log.getAllChildren().get(0);
            }
        }

        /*--------------------------------
         * der physische Baum wird nur
         * angelegt, wenn er noch nicht existierte
         * --------------------------------*/
        if (physicaldocstruct == null) {
            DocStructType dst = this.myPrefs.getDocStrctTypeByName("BoundBook");
            physicaldocstruct = this.mydocument.createDocStruct(dst);

            /*--------------------------------
             * Probleme mit dem FilePath
             * -------------------------------- */
            MetadataType MDTypeForPath = this.myPrefs.getMetadataTypeByName("pathimagefiles");
            try {
                Metadata mdForPath = new Metadata(MDTypeForPath);
                if (SystemUtils.IS_OS_WINDOWS) {
                    mdForPath.setValue("file:/" + inProzess.getImagesTifDirectory(false));
                } else {
                    mdForPath.setValue("file://" + inProzess.getImagesTifDirectory(false));
                }
                physicaldocstruct.addMetadata(mdForPath);
            } catch (MetadataTypeNotAllowedException e1) {
            } catch (DocStructHasNoTypeException e1) {
            }
            this.mydocument.setPhysicalDocStruct(physicaldocstruct);
        }

        if (directory == null) {
            checkIfImagesValid(inProzess.getTitel(), inProzess.getImagesTifDirectory(true));
        } else {
            checkIfImagesValid(inProzess.getTitel(), inProzess.getImagesDirectory() + directory);
        }

        /*-------------------------------
         * retrieve existing pages/images
         * -------------------------------*/
        DocStructType newPage = this.myPrefs.getDocStrctTypeByName("page");
        List<DocStruct> oldPages = physicaldocstruct.getAllChildrenByTypeAndMetadataType("page", "*");
        if (oldPages == null) {
            oldPages = new ArrayList<DocStruct>();
        }

        /*--------------------------------
         * add new page/images if necessary
         * --------------------------------*/

        if (oldPages.size() == this.myLastImage) {
            return;
        }

        String defaultPagination = ConfigMain.getParameter("MetsEditorDefaultPagination", "uncounted");
        Map<String, DocStruct> assignedImages = new HashMap<String, DocStruct>();
        List<DocStruct> pageElementsWithoutImages = new ArrayList<DocStruct>();
        List<String> imagesWithoutPageElements = new ArrayList<String>();

        if (physicaldocstruct.getAllChildren() != null && !physicaldocstruct.getAllChildren().isEmpty()) {
            for (DocStruct page : physicaldocstruct.getAllChildren()) {
                if (page.getImageName() != null) {
                    File imageFile = null;
                    if (directory == null) {
                        imageFile = new File(inProzess.getImagesTifDirectory(true), page.getImageName());
                    } else {
                        imageFile = new File(inProzess.getImagesDirectory() + directory, page.getImageName());
                    }
                    if (imageFile.exists()) {
                        assignedImages.put(page.getImageName(), page);
                    } else {
                        try {
                            page.removeContentFile(page.getAllContentFiles().get(0));
                            pageElementsWithoutImages.add(page);
                        } catch (ContentFileNotLinkedException e) {
                            logger.error(e);
                        }
                    }
                } else {
                    pageElementsWithoutImages.add(page);

                }
            }

        }
        try {
            List<String> imageNamesInMediaFolder = getDataFiles(inProzess);
            for (String imageName : imageNamesInMediaFolder) {
                if (!assignedImages.containsKey(imageName)) {
                    imagesWithoutPageElements.add(imageName);
                }
            }
        } catch (InvalidImagesException e1) {
            logger.error(e1);
        }

        // handle possible cases

        // case 1: existing pages but no images (some images are removed)
        if (!pageElementsWithoutImages.isEmpty() && imagesWithoutPageElements.isEmpty()) {
            for (DocStruct pageToRemove : pageElementsWithoutImages) {
                physicaldocstruct.removeChild(pageToRemove);
                List<Reference> refs = new ArrayList<Reference>(pageToRemove.getAllFromReferences());
                for (ugh.dl.Reference ref : refs) {
                    ref.getSource().removeReferenceTo(pageToRemove);
                }
            }
        }

        // case 2: no page docs but images (some images are added)
        else if (pageElementsWithoutImages.isEmpty() && !imagesWithoutPageElements.isEmpty()) {
            int currentPhysicalOrder = assignedImages.size();
            for (String newImage : imagesWithoutPageElements) {
                DocStruct dsPage = this.mydocument.createDocStruct(newPage);
                try {
                    // physical page no
                    physicaldocstruct.addChild(dsPage);
                    MetadataType mdt = this.myPrefs.getMetadataTypeByName("physPageNumber");
                    Metadata mdTemp = new Metadata(mdt);
                    mdTemp.setValue(String.valueOf(++currentPhysicalOrder));
                    dsPage.addMetadata(mdTemp);

                    // logical page no
                    mdt = this.myPrefs.getMetadataTypeByName("logicalPageNumber");
                    mdTemp = new Metadata(mdt);

                    if (defaultPagination.equalsIgnoreCase("arabic")) {
                        mdTemp.setValue(String.valueOf(currentPhysicalOrder));
                    } else if (defaultPagination.equalsIgnoreCase("roman")) {
                        RomanNumeral roman = new RomanNumeral();
                        roman.setValue(currentPhysicalOrder);
                        mdTemp.setValue(roman.getNumber());
                    } else {
                        mdTemp.setValue("uncounted");
                    }

                    dsPage.addMetadata(mdTemp);
                    log.addReferenceTo(dsPage, "logical_physical");

                    // image name
                    ContentFile cf = new ContentFile();
                    if (SystemUtils.IS_OS_WINDOWS) {
                        cf.setLocation("file:/" + inProzess.getImagesTifDirectory(false) + newImage);
                    } else {
                        cf.setLocation("file://" + inProzess.getImagesTifDirectory(false) + newImage);
                    }
                    dsPage.addContentFile(cf);

                } catch (TypeNotAllowedAsChildException e) {
                    logger.error(e);
                } catch (MetadataTypeNotAllowedException e) {
                    logger.error(e);
                }
            }
        }

        // case 3: empty page docs and unassinged images
        else {
            for (DocStruct page : pageElementsWithoutImages) {
                if (!imagesWithoutPageElements.isEmpty()) {
                    // assign new image name to page
                    String newImageName = imagesWithoutPageElements.get(0);
                    imagesWithoutPageElements.remove(0);
                    ContentFile cf = new ContentFile();
                    if (SystemUtils.IS_OS_WINDOWS) {
                        cf.setLocation("file:/" + inProzess.getImagesTifDirectory(false) + newImageName);
                    } else {
                        cf.setLocation("file://" + inProzess.getImagesTifDirectory(false) + newImageName);
                    }
                    page.addContentFile(cf);
                } else {
                    // remove page
                    physicaldocstruct.removeChild(page);
                    List<Reference> refs = new ArrayList<Reference>(page.getAllFromReferences());
                    for (ugh.dl.Reference ref : refs) {
                        ref.getSource().removeReferenceTo(page);
                    }
                }
            }
            if (!imagesWithoutPageElements.isEmpty()) {
                // create new page elements

                int currentPhysicalOrder = physicaldocstruct.getAllChildren().size();
                for (String newImage : imagesWithoutPageElements) {
                    DocStruct dsPage = this.mydocument.createDocStruct(newPage);
                    try {
                        // physical page no
                        physicaldocstruct.addChild(dsPage);
                        MetadataType mdt = this.myPrefs.getMetadataTypeByName("physPageNumber");
                        Metadata mdTemp = new Metadata(mdt);
                        mdTemp.setValue(String.valueOf(++currentPhysicalOrder));
                        dsPage.addMetadata(mdTemp);

                        // logical page no
                        mdt = this.myPrefs.getMetadataTypeByName("logicalPageNumber");
                        mdTemp = new Metadata(mdt);

                        if (defaultPagination.equalsIgnoreCase("arabic")) {
                            mdTemp.setValue(String.valueOf(currentPhysicalOrder));
                        } else if (defaultPagination.equalsIgnoreCase("roman")) {
                            RomanNumeral roman = new RomanNumeral();
                            roman.setValue(currentPhysicalOrder);
                            mdTemp.setValue(roman.getNumber());
                        } else {
                            mdTemp.setValue("uncounted");
                        }

                        dsPage.addMetadata(mdTemp);
                        log.addReferenceTo(dsPage, "logical_physical");

                        // image name
                        ContentFile cf = new ContentFile();
                        if (SystemUtils.IS_OS_WINDOWS) {
                            cf.setLocation("file:/" + inProzess.getImagesTifDirectory(false) + newImage);
                        } else {
                            cf.setLocation("file://" + inProzess.getImagesTifDirectory(false) + newImage);
                        }
                        dsPage.addContentFile(cf);

                    } catch (TypeNotAllowedAsChildException e) {
                        logger.error(e);
                    } catch (MetadataTypeNotAllowedException e) {
                        logger.error(e);
                    }
                }

            }
        }
        int currentPhysicalOrder = 1;
        MetadataType mdt = this.myPrefs.getMetadataTypeByName("physPageNumber");
        if (physicaldocstruct.getAllChildrenByTypeAndMetadataType("page", "*") != null) {
            if (physicaldocstruct.getAllChildrenByTypeAndMetadataType("page", "*") != null) {
                for (DocStruct page : physicaldocstruct.getAllChildrenByTypeAndMetadataType("page", "*")) {
                    List<? extends Metadata> pageNoMetadata = page.getAllMetadataByType(mdt);
                    if (pageNoMetadata == null || pageNoMetadata.size() == 0) {
                        currentPhysicalOrder++;
                        break;
                    }
                    for (Metadata pageNo : pageNoMetadata) {
                        pageNo.setValue(String.valueOf(currentPhysicalOrder));
                    }
                    currentPhysicalOrder++;
                }
            }
        }
    }

    /**
     * scale given image file to png using internal embedded content server
     *
     * @throws ImageManagerException
     * @throws IOException
     * @throws ImageManipulatorException
     */
    public void scaleFile(String inFileName, String outFileName, int inSize, int intRotation) throws ImageManagerException, IOException,
            ImageManipulatorException {
        logger.trace("start scaleFile");
        int tmpSize = inSize / 3;
        if (tmpSize < 1) {
            tmpSize = 1;
        }
        logger.trace("tmpSize: " + tmpSize);
        if (ConfigMain.getParameter("goobiContentServerUrl", "").equals("")) {
            logger.trace("api");
            ImageManager im = new ImageManager(new File(inFileName).toURI().toURL());
            logger.trace("im");
            RenderedImage ri = im.scaleImageByPixel(tmpSize, tmpSize, ImageManager.SCALE_BY_PERCENT, intRotation);
            logger.trace("ri");
            JpegInterpreter pi = new JpegInterpreter(ri);
            logger.trace("pi");
            FileOutputStream outputFileStream = new FileOutputStream(outFileName);
            logger.trace("output");
            pi.writeToStream(null, outputFileStream);
            logger.trace("write stream");
            outputFileStream.close();
            logger.trace("close stream");
        } else {
            String cs = ConfigMain.getParameter("goobiContentServerUrl") + inFileName + "&scale=" + tmpSize + "&rotate=" + intRotation + "&format=jpg";
            cs = cs.replace("\\", "/");
            logger.trace("url: " + cs);
            URL csUrl = new URL(cs);
            HttpClient httpclient = new HttpClient();
            GetMethod method = new GetMethod(csUrl.toString());
            logger.trace("get");
            Integer contentServerTimeOut = ConfigMain.getIntParameter("goobiContentServerTimeOut", 60000);
            method.getParams().setParameter("http.socket.timeout", contentServerTimeOut);
            int statusCode = httpclient.executeMethod(method);
            if (statusCode != HttpStatus.SC_OK) {
                return;
            }
            logger.trace("statusCode: " + statusCode);
            InputStream inStream = method.getResponseBodyAsStream();
            logger.trace("inStream");
            BufferedInputStream bis = new BufferedInputStream(inStream);
            logger.trace("BufferedInputStream");
            FileOutputStream fos = new FileOutputStream(outFileName);
            logger.trace("FileOutputStream");
            byte[] bytes = new byte[8192];
            int count = bis.read(bytes);
            while (count != -1 && count <= 8192) {
                fos.write(bytes, 0, count);
                count = bis.read(bytes);
            }
            if (count != -1) {
                fos.write(bytes, 0, count);
            }
            logger.trace("write");
            fos.close();
            bis.close();
        }
        logger.trace("end scaleFile");
    }

    // Add a method to validate the image files

    /**
     * die Images eines Prozesses auf Vollständigkeit prüfen ================================================================
     *
     * @throws DAOException
     * @throws SwapException
     */
    public boolean checkIfImagesValid(String title, String folder) throws IOException, InterruptedException, SwapException, DAOException {
        boolean isValid = true;
        this.myLastImage = 0;

        /*--------------------------------
         * alle Bilder durchlaufen und dafür
         * die Seiten anlegen
         * --------------------------------*/
        File dir = new File(folder);
        if (dir.exists()) {
            String[] dateien = dir.list(Helper.dataFilter);
            if (dateien == null || dateien.length == 0) {
                Helper.setFehlerMeldung("[" + title + "] No objects found");
                return false;
            }

            this.myLastImage = dateien.length;
            if (ConfigMain.getParameter("ImagePrefix", "\\d{8}").equals("\\d{8}")) {
                List<String> filesDirs = Arrays.asList(dateien);
                Collections.sort(filesDirs);
                int counter = 1;
                int myDiff = 0;
                String curFile = null;
                try {
                    for (Iterator<String> iterator = filesDirs.iterator(); iterator.hasNext(); counter++) {
                        curFile = iterator.next();
                        int curFileNumber = Integer.parseInt(curFile.substring(0, curFile.indexOf(".")));
                        if (curFileNumber != counter + myDiff) {
                            Helper.setFehlerMeldung("[" + title + "] expected Image " + (counter + myDiff) + " but found File " + curFile);
                            myDiff = curFileNumber - counter;
                            isValid = false;
                        }
                    }
                } catch (NumberFormatException e1) {
                    isValid = false;
                    Helper.setFehlerMeldung("[" + title + "] Filename of image wrong - not an 8-digit-number: " + curFile);
                }
                return isValid;
            }
            return true;
        }
        Helper.setFehlerMeldung("[" + title + "] No image-folder found");
        return false;
    }

    public static class GoobiImageFileComparator implements Comparator<String> {

        @Override
        public int compare(String s1, String s2) {
            String imageSorting = ConfigMain.getParameter("ImageSorting", "number");
            s1 = s1.substring(0, s1.lastIndexOf("."));
            s2 = s2.substring(0, s2.lastIndexOf("."));

            if (imageSorting.equalsIgnoreCase("number")) {
                try {
                    Integer i1 = Integer.valueOf(s1);
                    Integer i2 = Integer.valueOf(s2);
                    return i1.compareTo(i2);
                } catch (NumberFormatException e) {
                    return s1.compareToIgnoreCase(s2);
                }
            } else if (imageSorting.equalsIgnoreCase("alphanumeric")) {
                return s1.compareToIgnoreCase(s2);
            } else {
                return s1.compareToIgnoreCase(s2);
            }
        }

    }

    /**
     *
     * @param myProzess current process
     * @return sorted list with strings representing images of process
     * @throws InvalidImagesException
     */

    public ArrayList<String> getImageFiles(Prozess myProzess) throws InvalidImagesException {
        File dir;
        try {
            dir = new File(myProzess.getImagesTifDirectory(true));
        } catch (Exception e) {
            throw new InvalidImagesException(e);
        }
        /* Verzeichnis einlesen */
        String[] dateien = dir.list(Helper.imageNameFilter);
        ArrayList<String> dataList = new ArrayList<String>();
        if (dateien != null && dateien.length > 0) {
            for (int i = 0; i < dateien.length; i++) {
                String s = dateien[i];
                dataList.add(s);
            }
            /* alle Dateien durchlaufen */
            if (dataList != null && dataList.size() != 0) {
                Collections.sort(dataList, new GoobiImageFileComparator());
            }
            return dataList;
        } else {
            return null;
        }
    }

    public List<String> getDataFiles(Prozess myProzess) throws InvalidImagesException {
        File dir;
        try {
            dir = new File(myProzess.getImagesTifDirectory(true));
        } catch (Exception e) {
            throw new InvalidImagesException(e);
        }
        /* Verzeichnis einlesen */
        String[] dateien = dir.list(Helper.dataFilter);
        ArrayList<String> dataList = new ArrayList<String>();
        if (dateien != null && dateien.length > 0) {
            for (int i = 0; i < dateien.length; i++) {
                String s = dateien[i];
                dataList.add(s);
            }
            /* alle Dateien durchlaufen */
            if (dataList != null && dataList.size() != 0) {
                Collections.sort(dataList, new GoobiImageFileComparator());
            }
            return dataList;
        } else {
            return null;
        }
    }

    /**
     *
     * @param myProzess current process
     * @param directory current folder
     * @return sorted list with strings representing images of process
     * @throws InvalidImagesException
     */

    public List<String> getImageFiles(Prozess myProzess, String directory) throws InvalidImagesException {
        File dir;
        try {
            dir = new File(myProzess.getImagesDirectory() + directory);
        } catch (Exception e) {
            throw new InvalidImagesException(e);
        }
        /* Verzeichnis einlesen */
        String[] dateien = dir.list(Helper.imageNameFilter);
        List<String> dataList = new ArrayList<String>();
        if (dateien != null && dateien.length > 0) {
            for (int i = 0; i < dateien.length; i++) {
                String s = dateien[i];
                dataList.add(s);
            }
            /* alle Dateien durchlaufen */
        }
        List<String> orderedFilenameList = new ArrayList<String>();
        if (dataList != null && dataList.size() != 0) {
            List<DocStruct> pagesList = mydocument.getPhysicalDocStruct().getAllChildren();
            if (pagesList != null) {
                for (DocStruct page : pagesList) {
                    String filename = page.getImageName();
                    String filenamePrefix = filename.replace(Metadaten.getFileExtension(filename), "");
                    for (String currentImage : dataList) {
                        String currentImagePrefix = currentImage.replace(Metadaten.getFileExtension(currentImage), "");
                        if (currentImagePrefix.equals(filenamePrefix)) {
                            orderedFilenameList.add(currentImage);
                            break;
                        }
                    }
                }
                //                    orderedFilenameList.add(page.getImageName());
            }

            if (orderedFilenameList.size() == dataList.size()) {
                return orderedFilenameList;

            } else {
                Collections.sort(dataList, new GoobiImageFileComparator());
                return dataList;
            }
        } else {
            return null;
        }
    }

    public List<String> getImageFiles(DocStruct physical) {
        List<String> orderedFileList = new ArrayList<String>();
        List<DocStruct> pages = physical.getAllChildren();
        if (pages != null) {
            for (DocStruct page : pages) {
                String filename = page.getImageName();
                if (filename != null) {
                    orderedFileList.add(filename);
                } else {
                    logger.error("cannot find image");
                }
            }
        }
        return orderedFileList;
    }

}
TOP

Related Classes of de.sub.goobi.metadaten.MetadatenImagesHelper$GoobiImageFileComparator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.