org.goobi.api.display.helper.ConfigDisplayRules.java Source code

Java tutorial

Introduction

Here is the source code for org.goobi.api.display.helper.ConfigDisplayRules.java

Source

/*
 * (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.goobi.api.display.helper;

import de.sub.goobi.config.ConfigCore;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.goobi.api.display.Item;
import org.goobi.api.display.enums.DisplayType;
import org.goobi.production.constants.FileNames;

public final class ConfigDisplayRules {

    private static ConfigDisplayRules instance = new ConfigDisplayRules();
    private static XMLConfiguration config;
    private final HashMap<String, HashMap<String, HashMap<String, HashMap<String, ArrayList<Item>>>>> allValues = new HashMap<>();
    private static final String CONTEXT = "context";
    private static final String INPUT = "input";
    private static final String READ_ONLY = "readonly";
    private static final String RULESET = "ruleSet";
    private static final String RULESET_CONTEXT = RULESET + "." + CONTEXT;
    private static final String SELECT = "select";
    private static final String SELECT_ONE = "select1";
    private static final String TEXTAREA = "textarea";

    /**
     * Reads given xml file into XMLConfiguration.
     */
    private ConfigDisplayRules() {
        String configPath = ConfigCore.getKitodoConfigDirectory() + FileNames.METADATA_DISPLAY_RULES_FILE;
        try {
            config = new XMLConfiguration(configPath);
            config.setReloadingStrategy(new FileChangedReloadingStrategy());
            getDisplayItems();
        } catch (ConfigurationException e) {
            /*
             * no configuration file found, default configuration (textarea) will be used,
             * nothing to do here
             */
        }
    }

    /**
     * Get instance of ConfigDisplayRules.
     * 
     * @return instance of ConfigDisplayRules
     */
    public static ConfigDisplayRules getInstance() {
        return instance;
    }

    /**
     * Creates hierarchical HashMap with values for each element of given data.
     */
    private synchronized void getDisplayItems() {
        if (this.allValues.isEmpty() && config != null) {
            int countRuleSet = config.getMaxIndex(RULESET);
            for (int i = 0; i <= countRuleSet; i++) {
                int projectContext = config.getMaxIndex(RULESET + "(" + i + ")." + CONTEXT);
                for (int j = 0; j <= projectContext; j++) {
                    HashMap<String, HashMap<String, ArrayList<Item>>> itemsByType = new HashMap<>();
                    HashMap<String, HashMap<String, HashMap<String, ArrayList<Item>>>> bindState = new HashMap<>();
                    String projectName = config
                            .getString(RULESET + "(" + i + ")." + CONTEXT + "(" + j + ")[@projectName]");
                    String bind = config.getString(RULESET + "(" + i + ")." + CONTEXT + "(" + j + ").bind");

                    itemsByType.put(SELECT_ONE, getSelectOneItems(i, j, projectName, bind));
                    itemsByType.put(SELECT, getSelectItems(i, j, projectName, bind));
                    itemsByType.put(INPUT, getInputItems(i, j, projectName, bind));
                    itemsByType.put(TEXTAREA, getTextAreaItems(i, j, projectName, bind));
                    itemsByType.put(READ_ONLY, getReadOnlyItems(i, j, projectName, bind));
                    if (this.allValues.get(projectName) == null) {
                        bindState.put(bind, itemsByType);
                        this.allValues.put(projectName, bindState);
                    } else {
                        bindState = this.allValues.get(projectName);
                        bindState.put(bind, itemsByType);
                    }
                }
            }
        }
    }

    private HashMap<String, ArrayList<Item>> getSelectOneItems(int i, int j, String projectName, String bind) {
        int countAnotherSelect = getAmountOfElements(i, j, SELECT_ONE);
        HashMap<String, ArrayList<Item>> selectOne = new HashMap<>();

        for (int k = 0; k <= countAnotherSelect; k++) {
            String elementName = getElementName(i, j, k, SELECT_ONE);
            ArrayList<Item> items = getSelectOneByElementName(projectName, bind, elementName);
            selectOne.put(elementName, items);
        }

        return selectOne;
    }

    private HashMap<String, ArrayList<Item>> getSelectItems(int i, int j, String projectName, String bind) {
        int countSelect = getAmountOfElements(i, j, SELECT);
        HashMap<String, ArrayList<Item>> select = new HashMap<>();

        for (int k = 0; k <= countSelect; k++) {
            String elementName = getElementName(i, j, k, SELECT);
            ArrayList<Item> items = getSelectByElementName(projectName, bind, elementName);
            select.put(elementName, items);
        }

        return select;
    }

    private HashMap<String, ArrayList<Item>> getInputItems(int i, int j, String projectName, String bind) {
        int countInput = getAmountOfElements(i, j, INPUT);
        HashMap<String, ArrayList<Item>> input = new HashMap<>();

        for (int k = 0; k <= countInput; k++) {
            String elementName = getElementName(i, j, k, INPUT);
            ArrayList<Item> items = getInputByElementName(projectName, bind, elementName);
            input.put(elementName, items);
        }

        return input;
    }

    private HashMap<String, ArrayList<Item>> getTextAreaItems(int i, int j, String projectName, String bind) {
        int countTextArea = getAmountOfElements(i, j, TEXTAREA);
        HashMap<String, ArrayList<Item>> textarea = new HashMap<>();

        for (int k = 0; k <= countTextArea; k++) {
            String elementName = getElementName(i, j, k, TEXTAREA);
            ArrayList<Item> items = getTextareaByElementName(projectName, bind, elementName);
            textarea.put(elementName, items);
        }

        return textarea;
    }

    private HashMap<String, ArrayList<Item>> getReadOnlyItems(int i, int j, String projectName, String bind) {
        int countReadOnly = getAmountOfElements(i, j, READ_ONLY);
        HashMap<String, ArrayList<Item>> readOnly = new HashMap<>();

        for (int k = 0; k <= countReadOnly; k++) {
            String elementName = getElementName(i, j, k, READ_ONLY);
            ArrayList<Item> items = getReadOnlyByElementName(projectName, bind, elementName);
            readOnly.put(elementName, items);
        }
        return readOnly;
    }

    private int getAmountOfElements(int i, int j, String label) {
        return config.getMaxIndex(RULESET + "(" + i + ")." + CONTEXT + "(" + j + ")." + label);
    }

    private String getElementName(int i, int j, int k, String label) {
        return config
                .getString(RULESET + "(" + i + ")." + CONTEXT + "(" + j + ")." + label + "(" + k + ")[@tns:ref]");
    }

    /**
     * Get by element name for 'select1' parameter.
     * 
     * @param project
     *            name of project as String
     * @param bind
     *            create or edit
     * @param elementName
     *            name of the select1 element
     * @return ArrayList with all items and its values of given select1 element.
     */
    private ArrayList<Item> getSelectOneByElementName(String project, String bind, String elementName) {
        return getSelectByElementName(project, bind, elementName, SELECT_ONE);
    }

    /**
     * Get by element name for 'select' parameter.
     * 
     * @param project
     *            name of project as String
     * @param bind
     *            create or edit
     * @param elementName
     *            name of the select element
     * @return ArrayList with all items and its values of given select element.
     */
    private ArrayList<Item> getSelectByElementName(String project, String bind, String elementName) {
        return getSelectByElementName(project, bind, elementName, SELECT);
    }

    private ArrayList<Item> getSelectByElementName(String project, String bind, String elementName, String select) {
        ArrayList<Item> listOfItems = new ArrayList<>();
        int count = config.getMaxIndex(RULESET_CONTEXT);
        for (int i = 0; i <= count; i++) {
            String myProject = getProject(i);
            String myBind = getBind(i);
            if (myProject.equals(project) && myBind.equals(bind)) {
                int type = getAmountOfElements(i, select);
                for (int j = 0; j <= type; j++) {
                    String myElementName = config
                            .getString(RULESET_CONTEXT + "(" + i + ")." + select + "(" + j + ")[@tns:ref]");
                    if (myElementName.equals(elementName)) {
                        int item = config
                                .getMaxIndex(RULESET_CONTEXT + "(" + i + ")." + select + "(" + j + ").item");
                        for (int k = 0; k <= item; k++) {
                            Item myItem = new Item(
                                    // the displayed value
                                    config.getString(RULESET_CONTEXT + "(" + i + ")." + select + "(" + j + ").item("
                                            + k + ").label"),
                                    // the internal value, which will be taken if label is selected
                                    config.getString(RULESET_CONTEXT + "(" + i + ")." + select + "(" + j + ").item("
                                            + k + ").value"),
                                    // indicated wheter given item is preselected or not
                                    config.getBoolean(RULESET_CONTEXT + "(" + i + ")." + select + "(" + j
                                            + ").item(" + k + ")[@tns:selected]"));
                            listOfItems.add(myItem);
                        }
                    }
                }
            }
        }
        return listOfItems;
    }

    /**
     * Get by element name for 'input' parameter.
     * 
     * @param project
     *            name of project as String
     * @param bind
     *            create or edit
     * @param elementName
     *            name of the input element
     * @return item of given input element.
     */
    private ArrayList<Item> getInputByElementName(String project, String bind, String elementName) {
        return getListOfItems(project, bind, elementName, INPUT);
    }

    /**
     * Get by element name for 'textarea' parameter.
     * 
     * @param project
     *            name of project as String
     * @param bind
     *            create or edit
     * @param elementName
     *            name of the textarea element
     * @return item of given textarea element.
     */
    private ArrayList<Item> getTextareaByElementName(String project, String bind, String elementName) {
        return getListOfItems(project, bind, elementName, TEXTAREA);
    }

    private ArrayList<Item> getReadOnlyByElementName(String project, String bind, String elementName) {
        return getListOfItems(project, bind, elementName, READ_ONLY);
    }

    private ArrayList<Item> getListOfItems(String project, String bind, String elementName, String label) {
        ArrayList<Item> listOfItems = new ArrayList<>();
        int count = config.getMaxIndex(RULESET_CONTEXT);
        for (int i = 0; i <= count; i++) {
            String myProject = getProject(i);
            String myBind = getBind(i);
            if (myProject.equals(project) && myBind.equals(bind)) {
                listOfItems = getListOfItems(i, elementName, label);
            }
        }
        return listOfItems;
    }

    private ArrayList<Item> getListOfItems(int i, String elementName, String label) {
        ArrayList<Item> listOfItems = new ArrayList<>();
        int type = getAmountOfElements(i, label);
        for (int j = 0; j <= type; j++) {
            String readElementName = config
                    .getString(RULESET_CONTEXT + "(" + i + ")." + label + "(" + j + ")[@tns:ref]");
            if (readElementName.equals(elementName)) {
                // the displayed value
                // TODO: here two times label is read - why?
                Item item = new Item(
                        config.getString(RULESET_CONTEXT + "(" + i + ")." + label + "(" + j + ").label"),
                        config.getString(RULESET_CONTEXT + "(" + i + ")." + label + "(" + j + ").label"), false);
                listOfItems.add(item);
            }
        }
        return listOfItems;
    }

    private String getProject(int i) {
        return config.getString(RULESET_CONTEXT + "(" + i + ")[@projectName]");
    }

    private String getBind(int i) {
        return config.getString(RULESET_CONTEXT + "(" + i + ").bind");
    }

    private int getAmountOfElements(int i, String label) {
        return config.getMaxIndex(RULESET_CONTEXT + "(" + i + ")." + label);
    }

    /**
     * Get element type by name.
     *
     * @param myproject
     *            project of element
     * @param mybind
     *            create or edit
     * @param myelementName
     *            name of element
     * @return type of element
     */
    public DisplayType getElementTypeByName(String myproject, String mybind, String myelementName) {
        synchronized (this.allValues) {
            if (this.allValues.isEmpty() && config != null) {
                getDisplayItems();
            } else if (config == null) {
                return DisplayType.TEXTAREA;
            }
            HashMap<String, HashMap<String, HashMap<String, ArrayList<Item>>>> bind = this.allValues.get(myproject);
            if (bind == null) {
                return DisplayType.TEXTAREA;
            }
            HashMap<String, HashMap<String, ArrayList<Item>>> itemsByType = bind.get(mybind);
            if (itemsByType == null) {
                return DisplayType.TEXTAREA;
            }
            Set<String> itemTypes = itemsByType.keySet();
            for (String type : itemTypes) {
                HashMap<String, ArrayList<Item>> typeList = itemsByType.get(type);
                Set<String> names = typeList.keySet();
                for (String name : names) {
                    if (name.equals(myelementName)) {
                        return DisplayType.getByTitle(type);
                    }
                }
            }
        }
        return DisplayType.TEXTAREA;
    }

    /**
     * Get items by name and type.
     *
     * @param myproject
     *            name of project as String
     * @param mybind
     *            create or edit
     * @param myelementName
     *            name of the element
     * @param mydisplayType
     *            type of the element
     * @return ArrayList with all values of given element
     */
    public List<Item> getItemsByNameAndType(String myproject, String mybind, String myelementName,
            DisplayType mydisplayType) {
        List<Item> values = new ArrayList<>();
        synchronized (this.allValues) {
            if (this.allValues.isEmpty() && config != null) {
                getDisplayItems();
            } else if (config == null) {
                values.add(new Item(myelementName, "", false));
                return values;
            }
            HashMap<String, HashMap<String, HashMap<String, ArrayList<Item>>>> bind = this.allValues.get(myproject);
            if (bind.isEmpty()) {
                values.add(new Item(myelementName, "", false));
                return values;
            }
            HashMap<String, HashMap<String, ArrayList<Item>>> itemsByType = bind.get(mybind);
            if (itemsByType.isEmpty()) {
                values.add(new Item(myelementName, "", false));
                return values;
            }
            HashMap<String, ArrayList<Item>> typeList = itemsByType.get(mydisplayType.getTitle());
            if (typeList.isEmpty()) {
                values.add(new Item(myelementName, "", false));
                return values;
            }
            values = typeList.get(myelementName);
            if (values.isEmpty()) {
                values.add(new Item(myelementName, "", false));
                return values;
            }
        }
        return values;
    }

    /**
     * refreshes the hierarchical HashMap with values from xml file. If HashMap is
     * used by another thread, the function will wait until.
     */
    public void refresh() {
        if (config != null && !this.allValues.isEmpty()) {
            synchronized (this.allValues) {
                this.allValues.clear();
                getDisplayItems();
            }
        }
    }
}