Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catalog config importer #5313

Merged
merged 17 commits into from
Oct 6, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public enum SearchInterfaceType {
".//*[local-name()='diagnostic']/*[local-name()='message']/text()"),
OAI("oai", "http://www.openarchives.org/OAI/2.0/", "record", null, null,
null, null, null, ".//*[local-name()='error']/text()"),
FTP("ftp", null, null, null, null,null, null, null,
null);
FTP("ftp", null, null, null, null,null, null, null, null),
CUSTOM("custom", null, null, null, null, null, null, null, null);

private final String typeString;
private final String namespace;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public enum MetadataFormat {
MODS,
MARC,
PICA,
OTHER,
KITODO;

/**
Expand All @@ -36,4 +37,42 @@ public static MetadataFormat getMetadataFormat(String formatString) {
throw new UnknownFormatConversionException("Unable to find MetadataFormat for given String '"
+ formatString + "'!");
}

/**
* Get default record ID XPath for given format.
*
* @param format MetadataFormat
* @return default record ID XPath for given format
*/
public static String getDefaultRecordIdXpath(String format) {
switch (format) {
case "MODS":
return ".//*[local-name()='recordInfo']/*[local-name()='recordIdentifier']/text()";
case "MARC":
return ".//*[local-name()='datafield'][@tag='245']/*[local-name()='subfield'][@code='a']/text()";
case "PICA":
return ".//*[local-name()='datafield'][@tag='003@']/*[local-name()='subfield'][@code='0']/text()";
default:
return "";
}
}

/**
* Get default record title XPath for given format.
*
* @param format MetadataFormat
* @return default record title XPath for given format
*/
public static String getDefaultRecordTitleXpath(String format) {
switch (format) {
case "MODS":
return ".//*[local-name()='titleInfo']/*[local-name()='title']/text()";
case "MARC":
return ".//*[local-name()='controlfield'][@tag='001']/text()";
case "PICA":
return ".//*[local-name()='datafield'][@tag='021A']/*[local-name()='subfield'][@code='a']/text()";
default:
return "";
}
}
}
153 changes: 136 additions & 17 deletions Kitodo-API/src/main/java/org/kitodo/config/OPACConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.stream.Collectors;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.ConversionException;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.apache.commons.configuration.tree.ConfigurationNode;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.kitodo.api.externaldatamanagement.SearchInterfaceType;
import org.kitodo.config.enums.KitodoConfigFile;
import org.kitodo.exceptions.ConfigException;
import org.kitodo.exceptions.MandatoryParameterMissingException;
import org.kitodo.exceptions.ParameterNotFoundException;

/**
Expand All @@ -39,13 +39,19 @@
* NOTE: the class is not removed because it will be used to create an "OPAC configuration importer"
* that converts existing "kitodo_opac.xml" files to the new format saved to the database.
*/
@SuppressWarnings("unused")
public class OPACConfig {
private static final Logger logger = LogManager.getLogger(OPACConfig.class);
private static XMLConfiguration config;
private static final String TRUE = "true";
private static final String DEFAULT = "[@default]";
private static final int DEFAULT_IMPORT_DEPTH = 2;
private static final String DEFAULT_RETURN_FORMAT = "XML";
private static final String DESCRIPTION = "description";
private static final String NOT_AVAILABLE = "N/A";
private static final String HOST = "host";
private static final String SCHEME = "scheme";
private static final String PATH = "path";
private static final String PORT = "port";

/**
* Private constructor.
Expand Down Expand Up @@ -103,15 +109,80 @@ public static SearchInterfaceType getInterfaceType(String catalogName) {
return null;
}

/**
* Retrieve the "description" of the catalog identified by its title.
* @param catalogName String identifying the catalog by title
* @return String description for catalog's "config"
*/
public static String getOPACDescription(String catalogName) {
HierarchicalConfiguration catalogConfiguration = getCatalog(catalogName);
List<ConfigurationNode> descriptionAttributes = catalogConfiguration.getRoot().getAttributes(DESCRIPTION);
if (descriptionAttributes.isEmpty()) {
return NOT_AVAILABLE;
} else {
return descriptionAttributes.stream().map(cn -> cn.getValue().toString())
.collect(Collectors.joining(System.lineSeparator()));
}
}

/**
* Retrieve the "config" of the catalog identified by its title.
* @param catalogName String identifying the catalog by title
* @return HierarchicalConfiguration for catalog's "config"
*/
public static HierarchicalConfiguration getOPACConfiguration(String catalogName) {
private static HierarchicalConfiguration getOPACConfiguration(String catalogName) {
return getCatalog(catalogName).configurationAt("config");
}

private static String getUrlConfigPart(String catalogName, String parameter)
throws MandatoryParameterMissingException {
HierarchicalConfiguration config = getOPACConfiguration(catalogName);
if (Objects.nonNull(config)) {
for (HierarchicalConfiguration param : config.configurationsAt("param")) {
if (parameter.equals(param.getString("[@name]"))) {
return param.getString("[@value]");
}
}
}
throw new MandatoryParameterMissingException(parameter);
}

/**
* Get host parameter of catalog configuration with name 'catalogName'.
* @param catalogName name of catalog configuration
* @return host value as String
*/
public static String getHost(String catalogName) throws MandatoryParameterMissingException {
return getUrlConfigPart(catalogName, HOST);
}

/**
* Get scheme parameter of catalog configuration with name 'catalogName'.
* @param catalogName name of catalog configuration
* @return scheme value as String
*/
public static String getScheme(String catalogName) throws MandatoryParameterMissingException {
return getUrlConfigPart(catalogName, SCHEME);
}

/**
* Get path parameter of catalog configuration with name 'catalogName'.
* @param catalogName name of catalog configuration
* @return path value as String
*/
public static String getPath(String catalogName) throws MandatoryParameterMissingException {
return getUrlConfigPart(catalogName, PATH);
}

/**
* Get port parameter of catalog configuration with name 'catalogName'.
* @param catalogName name of catalog configuration
* @return port value as Integer
*/
public static String getPort(String catalogName) throws MandatoryParameterMissingException {
return getUrlConfigPart(catalogName, PORT);
}

/**
* Retrieve the "searchFields" of the catalog identified by its title.
* @param catalogName String identifying the catalog by title
Expand Down Expand Up @@ -162,6 +233,31 @@ public static HierarchicalConfiguration getUrlParameters(String catalogName) {
return getCatalog(catalogName).configurationAt("urlParameters");
}

private static String getUrlParameter(String catalogName, String parameter)
throws MandatoryParameterMissingException {
HierarchicalConfiguration urlParameters = getCatalog(catalogName).configurationAt("urlParameters");
if (Objects.nonNull(urlParameters)) {
for (HierarchicalConfiguration param : urlParameters.configurationsAt("param")) {
if (parameter.equals(param.getString("[@name]"))) {
return param.getString("[@value]");
}
}
}
throw new MandatoryParameterMissingException(parameter);
}

public static String getSruVersion(String catalogName) throws MandatoryParameterMissingException {
return getUrlParameter(catalogName, "version");
}

public static String getSruRecordSchema(String catalogName) throws MandatoryParameterMissingException {
return getUrlParameter(catalogName, "recordSchema");
}

public static String getOaiMetadataPrefix(String catalogName) throws MandatoryParameterMissingException {
return getUrlParameter(catalogName, "metadataPrefix");
}

/**
* Retrieve the "fileUpload" configuration of the catalog identified by its title.
* @param catalogName String identifying the catalog by its title
Expand Down Expand Up @@ -274,7 +370,7 @@ public static String getExemplarFieldXPath(String catalogName) {
* @return String XPath for owner information about an exemplar record
*/
public static String getExemplarFieldOwnerXPath(String catalogName) {
return getCatalog(catalogName).getString("exemplarField[@ownerSubPath]");
return getCatalog(catalogName).getString("exemplarField[@ownerSubPath]", null);
}

/**
Expand Down Expand Up @@ -340,11 +436,25 @@ public static boolean isParentInRecord(String catalogName) {
* @return default import depth of catalog
*/
public static int getDefaultImportDepth(String catalogName) {
try {
return getCatalog(catalogName).getInt("defaultImportDepth");
} catch (NoSuchElementException | ConversionException e) {
return DEFAULT_IMPORT_DEPTH;
}
return getCatalog(catalogName).getInt("defaultImportDepth", DEFAULT_IMPORT_DEPTH);
}

/**
* Return 'returnFormat' of catalog 'catalogName' if configured. Return DEFAULT_RETURN_FORMAT "XML" otherwise.
* @param catalogName name of catalog
* @return 'returnFormat' of catalog
*/
public static String getReturnFormat(String catalogName) {
return getCatalog(catalogName).getString("returnFormat", DEFAULT_RETURN_FORMAT);
}

/**
* Return 'metadataFormat' of catalog 'catalogName.
* @param catalogName name of catalog
* @return 'metadataFormat' of catalog
*/
public static String getMetadataFormat(String catalogName) {
return getCatalog(catalogName).getString("metadataFormat");
}

/**
Expand All @@ -365,7 +475,7 @@ public static List<String> getCatalogs() {
* @param catalogName String identifying the catalog by attribute "title"
* @return HierarchicalConfiguration for single catalog
*/
private static HierarchicalConfiguration getCatalog(String catalogName) {
public static HierarchicalConfiguration getCatalog(String catalogName) {
XMLConfiguration conf = getConfig();
int countCatalogues = conf.getMaxIndex("catalogue");
HierarchicalConfiguration catalog = null;
Expand All @@ -386,13 +496,8 @@ private static XMLConfiguration getConfig() {
if (config != null) {
return config;
}
KitodoConfigFile kitodoConfigOpacFile = KitodoConfigFile.OPAC_CONFIGURATION;
if (!kitodoConfigOpacFile.exists()) {
String message = "File not found: " + kitodoConfigOpacFile.getAbsolutePath();
throw new ConfigException(message, new FileNotFoundException(message));
}
try {
config = new XMLConfiguration(kitodoConfigOpacFile.getFile());
config = getKitodoOpacConfiguration();
} catch (ConfigurationException e) {
logger.error(e);
config = new XMLConfiguration();
Expand All @@ -401,4 +506,18 @@ private static XMLConfiguration getConfig() {
config.setReloadingStrategy(new FileChangedReloadingStrategy());
return config;
}

/**
* Retrieve and return the XML configuration of Kitodo OPACs from the 'kitodo_opac.xml' file.
* @return XMLConfiguration containing the catalog configurations of the 'kitodo_opac.xml' file
* @throws ConfigurationException if 'kitodo_opac.xml' file does not exist
*/
public static XMLConfiguration getKitodoOpacConfiguration() throws ConfigurationException {
KitodoConfigFile kitodoConfigOpacFile = KitodoConfigFile.OPAC_CONFIGURATION;
if (!kitodoConfigOpacFile.exists()) {
String message = "File not found: " + kitodoConfigOpacFile.getAbsolutePath();
throw new ConfigException(message, new FileNotFoundException(message));
}
return new XMLConfiguration(kitodoConfigOpacFile.getFile());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* (c) Kitodo. Key to digital objects e. V. <[email protected]>
*
* 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.exceptions;

/**
* This exception is thrown during the import of catalog configurations from 'kitodo_opac.xml' when
* a mandatory XML configuration element like "interfaceType" is missing.
*/
public class MandatoryParameterMissingException extends Exception {

/**
* Constructor with given parameter name.
* @param parameterName name of missing parameter
*/
public MandatoryParameterMissingException(String parameterName) {
super("Mandatory XML parameter '" + parameterName + "' missing!");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

Expand All @@ -38,7 +39,7 @@ public class MappingFile extends BaseBean {
@Column(name = "prestructured_import")
private Boolean prestructuredImport = false;

@ManyToMany(mappedBy = "mappingFiles", cascade = CascadeType.PERSIST)
@ManyToMany(mappedBy = "mappingFiles", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private List<ImportConfiguration> importConfigurations;

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--
-- (c) Kitodo. Key to digital objects e. V. <[email protected]>
--
-- 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.
--
-- Migration: change 'identifier_metadata', 'metadata_record_id_xpath' and 'metadata_record_title_xpath' columns
-- to be nullable
ALTER TABLE importconfiguration MODIFY identifier_metadata varchar(255) NULL DEFAULT 'CatalogIDDigital';
ALTER TABLE importconfiguration MODIFY metadata_record_id_xpath varchar(255) NULL;
ALTER TABLE importconfiguration MODIFY metadata_record_title_xpath varchar(255) NULL;
Loading