Coverage Summary for Class: ProcessSelectMetadata (org.kitodo.production.forms.createprocess)

Class Method, % Line, %
ProcessSelectMetadata 62,5% (10/16) 47,1% (33/70)
ProcessSelectMetadata$1 0% (0/1) 0% (0/1)
Total 58,8% (10/17) 46,5% (33/71)


 /*
  * (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.forms.createprocess;
 
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.function.BiConsumer;
 
 import javax.faces.model.SelectItem;
 
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.kitodo.api.MdSec;
 import org.kitodo.api.Metadata;
 import org.kitodo.api.MetadataEntry;
 import org.kitodo.api.dataeditor.rulesetmanagement.Domain;
 import org.kitodo.api.dataeditor.rulesetmanagement.SimpleMetadataViewInterface;
 import org.kitodo.api.dataformat.Division;
 import org.kitodo.exceptions.InvalidMetadataValueException;
 import org.kitodo.exceptions.NoSuchMetadataFieldException;
 
 public class ProcessSelectMetadata extends ProcessSimpleMetadata implements Serializable {
     private static final Logger logger = LogManager.getLogger(ProcessSelectMetadata.class);
 
     private final boolean dependent;
 
     /**
      * Converts the select items map to the select items type required by JSF to
      * display the select lists.
      *
      * @param selectItems
      *            items as map key to label
      * @return list of select item objects
      */
     private static List<SelectItem> toItems(Map<String, String> selectItems) {
         ArrayList<SelectItem> items = new ArrayList<>(selectItems.entrySet().size());
         for (Entry<String, String> entry : selectItems.entrySet()) {
             items.add(new SelectItem(entry.getKey(), entry.getValue()));
         }
         return items;
     }
 
     /**
      * Elements the user can choose from.
      */
     private final List<SelectItem> items;
 
     /**
      * Elements selected by the user.
      */
     private List<String> selectedItems = new ArrayList<>();
 
     ProcessSelectMetadata(ProcessFieldedMetadata container, SimpleMetadataViewInterface settings,
             Collection<MetadataEntry> selected, boolean dependent) {
         super(container, settings, settings.getLabel());
         List<Map<MetadataEntry, Boolean>> leadingMetadataFields = container.getListForLeadingMetadataFields();
         this.items = toItems(settings.getSelectItems(leadingMetadataFields));
         container.markLeadingMetadataFields(leadingMetadataFields);
         if (selected.isEmpty()) {
             selectedItems.addAll(settings.getDefaultItems());
         } else {
             for (MetadataEntry entry : selected) {
                 selectedItems.add(entry.getValue());
             }
         }
         this.dependent = dependent;
     }
 
     private ProcessSelectMetadata(ProcessSelectMetadata template) {
         super(template.container, template.settings, template.label);
         this.items = template.items;
         this.selectedItems = new ArrayList<>(template.selectedItems);
         this.dependent = template.dependent;
     }
 
     @Override
     ProcessSelectMetadata getClone() {
         return new ProcessSelectMetadata(this);
     }
 
     /**
      * Whether the list is multi-select or not can be told from this.
      */
     @Override
     public String getInput() {
         switch (settings.getInputType()) {
             case MULTIPLE_SELECTION:
                 return "manyMenu";
             case MULTI_LINE_SINGLE_SELECTION:
                 return "oneRadio";
             case ONE_LINE_SINGLE_SELECTION:
                 return "oneMenu";
             default:
                 return "";
         }
     }
 
     /**
      * Returns the select item objects required to display the list.
      *
      * @return the select item objects
      */
     public List<SelectItem> getItems() {
         return items;
     }
 
     @Override
     public Collection<Metadata> getMetadataWithFilledValues() throws InvalidMetadataValueException {
         return getMetadata(true);
     }
 
     @Override
     public Collection<Metadata> getMetadata(boolean skipEmpty) throws InvalidMetadataValueException {
         int items = selectedItems.size();
         Collection<Metadata> metadata = new HashSet<>((int) Math.ceil(items / .75));
         String key = settings.getId();
         MdSec domain = DOMAIN_TO_MDSEC.get(settings.getDomain().orElse(Domain.DESCRIPTION));
         selectedItems.removeAll(Collections.singletonList(""));
         selectedItems.removeAll(Collections.singletonList(null));
         for (String selectedItem : selectedItems) {
             if (!settings.isValid(selectedItem, container.getListForLeadingMetadataFields())) {
                 /*
                  * If this selection field is dependent on another metadata
                  * field and is not valid, then this is because the user has
                  * changed a field it depends on. In that case we can safely
                  * skip saving the value.
                  */
                 if (dependent) {
                     logger.debug("{} \"{}\" moved out of scope, forgetting.", key, selectedItem);
                     continue;
                 }
                 throw new InvalidMetadataValueException(label, selectedItem);
             }
             MetadataEntry entry = new MetadataEntry();
             entry.setKey(key);
             entry.setDomain(domain);
             entry.setValue(selectedItem);
             metadata.add(entry);
         }
         if (!skipEmpty && metadata.isEmpty()) {
             MetadataEntry entry = new MetadataEntry();
             entry.setKey(key);
             entry.setDomain(domain);
             metadata.add(entry);
             metadata.add(entry);
         }
         return metadata;
     }
 
     /**
      * Returns the keys which io selected in single-select scenario.
      *
      * @return identifier of selected element
      */
     public String getSelectedItem() {
         return selectedItems.isEmpty() ? "" : selectedItems.get(0);
     }
 
     /**
      * Returns the list of keys which are selected in multi-select scenario.
      *
      * @return identifiers of selected elements
      */
     public List<String> getSelectedItems() {
         return selectedItems;
     }
 
     @Override
     Pair<BiConsumer<Division<?>, String>, String> getStructureFieldValue()
             throws InvalidMetadataValueException, NoSuchMetadataFieldException {
         if (settings.getDomain().orElse(Domain.DESCRIPTION).equals(Domain.METS_DIV)) {
             String value = String.join(" ", selectedItems);
             if (!settings.isValid(value, container.getListForLeadingMetadataFields())) {
                 throw new InvalidMetadataValueException(label, value);
             }
             return Pair.of(super.getStructureFieldSetters(settings), value);
         } else {
             return null;
         }
     }
 
     @Override
     public boolean isValid() {
         for (String selectedItem : selectedItems) {
             if (!settings.isValid(selectedItem, container.getListForLeadingMetadataFields())) {
                 return false;
             }
         }
         return true;
     }
 
     /**
      * Setter to set the selected elements in multi-select scenario.
      *
      * @param selectedItems
      *            selected items to set
      */
     public void setSelectedItems(List<String> selectedItems) {
         this.selectedItems = selectedItems;
     }
 
     /**
      * Setter to set the one selected element in single-select scenario.
      *
      * @param selectedItem
      *            selected item to set
      */
     public void setSelectedItem(String selectedItem) {
         this.selectedItems = selectedItem.isEmpty() ? Collections.emptyList() : Collections.singletonList(selectedItem);
     }
 
     @Override
     public String getMetadataID() {
         return settings.getId();
     }
 }