Coverage Summary for Class: MetsService (org.kitodo.production.services.dataformat)

Class Class, % Method, % Line, %
MetsService 100% (1/1) 81,8% (9/11) 78,6% (33/42)


 /*
  * (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
  *
  * This file is part of the Kitodo project.
  *
  * It is licensed under GNU General Public License version 3 or later.
  *
  * For the full copyright and license information, please read the
  * GPL3-License.txt file that was distributed with this source code.
  */
 
 package org.kitodo.production.services.dataformat;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URI;
 import java.util.Objects;
 
 import javax.xml.transform.Result;
 import javax.xml.transform.Source;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.kitodo.api.MetadataEntry;
 import org.kitodo.api.dataformat.LogicalDivision;
 import org.kitodo.api.dataformat.Workpiece;
 import org.kitodo.api.dataformat.mets.MetsXmlElementAccessInterface;
 import org.kitodo.production.services.ServiceManager;
 import org.kitodo.serviceloader.KitodoServiceLoader;
 import org.w3c.dom.Document;
 
 public class MetsService {
     private static final Logger logger = LogManager.getLogger(MetsService.class);
 
     private static volatile MetsService instance = null;
     private final MetsXmlElementAccessInterface metsXmlElementAccess;
 
     /**
      * Return singleton variable of type MetsService.
      *
      * @return unique instance of MetsService
      */
     public static MetsService getInstance() {
         MetsService localReference = instance;
         if (Objects.isNull(localReference)) {
             synchronized (MetsService.class) {
                 localReference = instance;
                 if (Objects.isNull(localReference)) {
                     localReference = new MetsService();
                     instance = localReference;
                 }
             }
         }
         return localReference;
     }
 
     private MetsService() {
         metsXmlElementAccess = (MetsXmlElementAccessInterface) new KitodoServiceLoader<>(
                 MetsXmlElementAccessInterface.class).loadModule();
     }
 
     /**
      * Returns the type of the top element of the logical structure, and thus the
      * type of the workpiece.
      *
      * @param uri
      *            Address of the METS file of the workpiece
      * @return the type of root element of the logical structure of the workpiece
      * @throws IOException
      *             if the file cannot be read (for example, because the file was
      *             not found)
      */
     public String getBaseType(URI uri) throws IOException {
         return getBaseType(loadWorkpiece(uri));
 
     }
 
     /**
      * Returns the type of the top element of the logical structure, and thus the
      * type of the workpiece.
      *
      * @param workpiece
      *            the workpiece
      * @return the type of root element of the logical structure of the workpiece
      */
     public String getBaseType(Workpiece workpiece) {
         LogicalDivision logicalDivision = workpiece.getLogicalStructure();
         String type = logicalDivision.getType();
         while (Objects.isNull(type) && !logicalDivision.getChildren().isEmpty()) {
             logicalDivision = logicalDivision.getChildren().get(0);
             type = logicalDivision.getType();
         }
         return type;
     }
 
     /**
      * Function for loading METS files from URI.
      *
      * @param uri
      *            address of the file to be loaded
      * @return loaded file
      * @throws IOException
      *             if reading is not working (disk broken, ...)
      */
     public Workpiece loadWorkpiece(URI uri) throws IOException {
         try (InputStream inputStream = ServiceManager.getFileService().read(uri)) {
             logger.info("Reading {}", uri.toString());
             return metsXmlElementAccess.read(inputStream);
         }
     }
 
     /**
      * Create and return Workpiece from given Document 'document'.
      *
      * @param document Document from which a Workpiece is created
      * @return Workpiece created from given Document
      * @throws TransformerException
      *          thrown when XML transformation fails
      * @throws IOException
      *          thrown when unable to read inputStream
      */
     public Workpiece loadWorkpiece(Document document) throws TransformerException, IOException {
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
         Source xmlSource = new DOMSource(document);
         Result outputTarget = new StreamResult(outputStream);
         TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
         InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
         return metsXmlElementAccess.read(inputStream);
     }
 
     /**
      * Function for writing METS files to URI. (URI target must allow writing
      * operation.)
      *
      * @param workpiece
      *            data to be written
      * @param uri
      *            address where should be written
      * @throws IOException
      *             if writing does not work (partition full, or is generally not
      *             supported, ...)
      */
     public void saveWorkpiece(Workpiece workpiece, URI uri) throws IOException {
         try (OutputStream outputStream = ServiceManager.getFileService().write(uri)) {
             logger.info("Saving {}", uri.toString());
             save(workpiece, outputStream);
         }
     }
 
     public void save(Workpiece workpiece, OutputStream outputStream) throws IOException {
         metsXmlElementAccess.save(workpiece, outputStream);
     }
 
     /**
      * Counts the logical metadata tags in the workpiece.
      * @param workpiece the workpiece to count tags.
      * @return the number of tags
      */
     public static int countLogicalMetadata(Workpiece workpiece) {
         return Math.toIntExact(Workpiece.treeStream(workpiece.getLogicalStructure())
                 .flatMap(logicalDivision -> logicalDivision.getMetadata().parallelStream())
                 .filter(metadata -> !(metadata instanceof MetadataEntry)
                         || Objects.nonNull(((MetadataEntry) metadata).getValue())
                                 && !((MetadataEntry) metadata).getValue().isEmpty())
                 .mapToInt(metadata -> 1).count());
     }
 }