Java tutorial
/* * (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.metadata.display.helper; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; 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.kitodo.config.enums.KitodoConfigFile; import org.kitodo.production.metadata.display.Item; import org.kitodo.production.metadata.display.enums.DisplayType; public final class ConfigDisplayRules { private static ConfigDisplayRules instance; private XMLConfiguration config; private final Map<String, Map<String, Map<String, Map<String, List<Item>>>>> allValues = new HashMap<>(); private static final String BIND = "bind"; private static final String CONTEXT = "context"; private static final String ITEM = "item"; private static final String LABEL = "label"; private static final String RULESET = "ruleSet"; private static final String RULESET_CONTEXT = RULESET + "." + CONTEXT; private static final String VALUE = "value"; /** * Reads given xml file into XMLConfiguration. */ private ConfigDisplayRules() { String configPath = KitodoConfigFile.METADATA_DISPLAY_RULES.getAbsolutePath(); 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() { if (Objects.equals(instance, null)) { synchronized (ConfigDisplayRules.class) { if (Objects.equals(instance, null)) { instance = new ConfigDisplayRules(); } } } 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++) { Map<String, Map<String, List<Item>>> itemsByType = new HashMap<>(); Map<String, Map<String, Map<String, List<Item>>>> bindState = new HashMap<>(); String projectName = config .getString(RULESET + "(" + i + ")." + CONTEXT + "(" + j + ")[@projectName]"); String bind = config.getString(RULESET + "(" + i + ")." + CONTEXT + "(" + j + ")." + BIND); itemsByType.put(DisplayType.SELECT1.getTitle(), getSelectOneItems(i, j, projectName, bind)); itemsByType.put(DisplayType.SELECT.getTitle(), getSelectItems(i, j, projectName, bind)); itemsByType.put(DisplayType.INPUT.getTitle(), getInputItems(i, j, projectName, bind)); itemsByType.put(DisplayType.TEXTAREA.getTitle(), getTextAreaItems(i, j, projectName, bind)); itemsByType.put(DisplayType.READONLY.getTitle(), 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 Map<String, List<Item>> getSelectOneItems(int i, int j, String projectName, String bind) { int countAnotherSelect = getAmountOfElements(i, j, DisplayType.SELECT1.getTitle()); Map<String, List<Item>> selectOne = new HashMap<>(); for (int k = 0; k <= countAnotherSelect; k++) { String elementName = getElementName(i, j, k, DisplayType.SELECT1.getTitle()); List<Item> items = getSelectOneByElementName(projectName, bind, elementName); selectOne.put(elementName, items); } return selectOne; } private Map<String, List<Item>> getSelectItems(int i, int j, String projectName, String bind) { int countSelect = getAmountOfElements(i, j, DisplayType.SELECT.getTitle()); HashMap<String, List<Item>> select = new HashMap<>(); for (int k = 0; k <= countSelect; k++) { String elementName = getElementName(i, j, k, DisplayType.SELECT.getTitle()); List<Item> items = getSelectByElementName(projectName, bind, elementName); select.put(elementName, items); } return select; } private Map<String, List<Item>> getInputItems(int i, int j, String projectName, String bind) { int countInput = getAmountOfElements(i, j, DisplayType.INPUT.getTitle()); Map<String, List<Item>> input = new HashMap<>(); for (int k = 0; k <= countInput; k++) { String elementName = getElementName(i, j, k, DisplayType.INPUT.getTitle()); List<Item> items = getInputByElementName(projectName, bind, elementName); input.put(elementName, items); } return input; } private Map<String, List<Item>> getTextAreaItems(int i, int j, String projectName, String bind) { int countTextArea = getAmountOfElements(i, j, DisplayType.TEXTAREA.getTitle()); Map<String, List<Item>> textarea = new HashMap<>(); for (int k = 0; k <= countTextArea; k++) { String elementName = getElementName(i, j, k, DisplayType.TEXTAREA.getTitle()); List<Item> items = getTextareaByElementName(projectName, bind, elementName); textarea.put(elementName, items); } return textarea; } private Map<String, List<Item>> getReadOnlyItems(int i, int j, String projectName, String bind) { int countReadOnly = getAmountOfElements(i, j, DisplayType.READONLY.getTitle()); Map<String, List<Item>> readOnly = new HashMap<>(); for (int k = 0; k <= countReadOnly; k++) { String elementName = getElementName(i, j, k, DisplayType.READONLY.getTitle()); List<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 int getAmountOfElements(int i, String label) { return config.getMaxIndex(RULESET_CONTEXT + "(" + i + ")." + 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 List<Item> getSelectOneByElementName(String project, String bind, String elementName) { return getSelectByElementName(project, bind, elementName, DisplayType.SELECT1.getTitle()); } /** * 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 List<Item> getSelectByElementName(String project, String bind, String elementName) { return getSelectByElementName(project, bind, elementName, DisplayType.SELECT.getTitle()); } private List<Item> getSelectByElementName(String project, String bind, String elementName, String select) { List<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)) { String key = RULESET_CONTEXT + "(" + i + ")." + select + "(" + j + ")." + ITEM; int item = config.getMaxIndex(key); listOfItems.addAll(getItems(item, key)); } } } } return listOfItems; } private List<Item> getItems(int item, String key) { List<Item> items = new ArrayList<>(); for (int k = 0; k <= item; k++) { Item currentItem = new Item( // the displayed value config.getString(key + "(" + k + ")." + LABEL), // the internal value, which will be taken if label is selected config.getString(key + "(" + k + ")." + VALUE), // indicated whether given item is preselected or not config.getBoolean(key + "(" + k + ")[@tns:selected]")); items.add(currentItem); } return items; } /** * 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 List<Item> getInputByElementName(String project, String bind, String elementName) { return getListOfItems(project, bind, elementName, DisplayType.INPUT.getTitle()); } /** * 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 List<Item> getTextareaByElementName(String project, String bind, String elementName) { return getListOfItems(project, bind, elementName, DisplayType.TEXTAREA.getTitle()); } private List<Item> getReadOnlyByElementName(String project, String bind, String elementName) { return getListOfItems(project, bind, elementName, DisplayType.READONLY.getTitle()); } private List<Item> getListOfItems(String project, String bind, String elementName, String label) { List<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 List<Item> getListOfItems(int i, String elementName, String label) { List<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); } /** * 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; } Map<String, Map<String, Map<String, List<Item>>>> bind = this.allValues.get(myproject); if (bind == null) { return DisplayType.TEXTAREA; } Map<String, Map<String, List<Item>>> itemsByType = bind.get(mybind); if (itemsByType == null) { return DisplayType.TEXTAREA; } Set<String> itemTypes = itemsByType.keySet(); for (String type : itemTypes) { Map<String, List<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; } Map<String, Map<String, Map<String, List<Item>>>> bind = this.allValues.get(myproject); if (bind.isEmpty()) { values.add(new Item(myelementName, "", false)); return values; } Map<String, Map<String, List<Item>>> itemsByType = bind.get(mybind); if (itemsByType.isEmpty()) { values.add(new Item(myelementName, "", false)); return values; } Map<String, List<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(); } } } }