...
 
Commits (10)
......@@ -46,7 +46,8 @@
<target name="resolve" description="resolve libraries" depends="clean, copy.pom">
<echo level="info">Resolve jars with maven</echo>
<exec executable="/usr/local/bin/mvn">
<exec executable="/usr/bin/env">
<arg value="mvn" />
<arg value="-f${stage-one.config}/pom.xml" />
<arg value="-Dbuild.directory=${build.cli}" />
<arg value="dependency:copy-dependencies" />
......@@ -311,6 +312,9 @@ mvn -DMCR.AppName=${app.name} ${cmd.value}
<fileset dir="${build.cli.config}" includes="hosts.xml" />
<fileset dir="${build.cli.config}" includes="log4j2.xml" />
</copy>
<copy todir="${build.webapps}/content" overwrite="true">
<fileset dir="documentation" includes="AniHealth_Benutzerdokumentation.pdf" />
</copy>
<copy todir="${build.webapps}/WEB-INF/classes">
<fileset dir="${build.cli.classes}" includes="**/*" />
<fileset dir="${build.cli.config}" includes="*.xml" />
......
#!/usr/bin/env bash
set -e
set -o pipefail
printf "\e[4mPurging OCFL store contents\e[0m\n"
echo "In MyCoRe:"
./build/bin/mycore.sh delete all objects of type anihealth
printf " \e[4mDone\e[0m\n"
echo "In the FS:"
OCFL_REPOOPTION=$(grep 'MCR.Metadata.Store.OCFL.RepoDir=' config/mycore.private.properties)
if [ x"$OCFL_REPOOPTION" == x ]; then
echo " 'MCR.Metadata.Store.OCFL.RepoDir' not found in 'config/mycore.private.properties'!"
sh -c 'exit 1'
fi
OCFL_REPO=$(echo "$OCFL_REPOOPTION" | cut -d'=' -f2)
rm -rf "$OCFL_REPO"/*
printf " \e[4mDone\e[0m\n"
echo "Purging & rebuilding SOLR contents & database classifications"
echo "
DO \$\$ DECLARE
r RECORD;
BEGIN
FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE';
END LOOP;
END \$\$;
" | psql anihealth
ant create.default-rules create.users
./build/bin/mycore.sh reload solr configuration main in core main
sleep 1
./build/bin/mycore.sh clear solr index in core main
sleep 1
ant create.class
sleep 1
./build/bin/mycore.sh rebuild solr metadata and content index in core main
sleep 1
./build/bin/mycore.sh rebuild solr classification index in core main
printf " \e[4mDone\e[0m\n"
......@@ -2,18 +2,26 @@
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>de.uni-leipzig.urz</groupId>
<artifactId>anihealth</artifactId>
<name>Animal Health Application</name>
<version>1.0</version>
<properties>
<mycore.version>2019.06.0-SNAPSHOT</mycore.version>
<java.target.version>11</java.target.version>
<maven.compiler.source>${java.target.version}</maven.compiler.source>
<maven.compiler.target>${java.target.version}</maven.compiler.target>
<maven.compiler.arg>-Werror</maven.compiler.arg>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<uniqueVersion>false</uniqueVersion>
<mycore.version>2019.06.4-SNAPSHOT</mycore.version>
<dptbase.version>2019.06-SNAPSHOT</dptbase.version>
<postgres.version>42.2.5</postgres.version>
<postgres.version>42.2.6</postgres.version>
<servlet.version>3.1.0</servlet.version>
<xmltask.version>1.16</xmltask.version>
<ocfl.version>0.0.2-SNAPSHOT</ocfl.version>
<slf4j.version>1.7.30</slf4j.version>
</properties>
<repositories>
......@@ -300,5 +308,15 @@
<artifactId>postgresql</artifactId>
<version>${postgres.version}</version>
</dependency>
<dependency>
<groupId>edu.wisc.library.ocfl</groupId>
<artifactId>ocfl-java-core</artifactId>
<version>${ocfl.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
</project>
......@@ -1069,11 +1069,9 @@
<p>
<xed:bind xpath="@categid">
<select class="dpt_editor_select-ltr">
<!--
<option value="">
<xed:output i18n="module.dptbase.anihealth.common.editor.choose.required" />
</option>
-->
<option value="">
<xed:output i18n="module.dptbase.anihealth.common.editor.choose.optional" />
</option>
<xed:include
uri="xslStyle:items2options:classification:editor[Text]:-1:children:institutionsList"
cacheable="false" />
......
......@@ -680,6 +680,12 @@
<xsl:with-param name="staticURL" select="$staticURL" />
<xsl:with-param name="bold" select="true()" />
</xsl:call-template>
<!-- Versioning -->
<xsl:call-template name="printValueLineVersion">
<xsl:with-param name="nodes" select="." />
<xsl:with-param name="bold" select="true()" />
</xsl:call-template>
<!-- License -->
......
<?xml version="1.0" encoding="UTF-8"?>
<!-- =================================================================== -->
<!-- Inventory module build file for use with Apache Ant -->
<!-- Inventory module build file for use with Apache Ant -->
<!-- =================================================================== -->
<project name="MyCoReModule - Animal Health Core" basedir="../.." xmlns:mcr="antlib:org.mycore.buildtools">
......@@ -11,10 +11,11 @@
<property file="${stage-one.modules}/core/config/mycore.properties" />
<!-- =================================================================== -->
<!-- Create all XML schema files from the configuration file -->
<!-- Create all XML schema files from the configuration file -->
<!-- =================================================================== -->
<target name="create.schema" depends="init" description="Generates all schema files from the configuration files">
<target name="create.schema" depends="init"
description="Generates all schema files from the configuration files">
<echo level="info"> building ${ant.project.name} schemas </echo>
<copy todir="${build.cli.schema}">
<fileset dir="${stage-one}/modules/core/config" includes="MCRCondition.xsd" />
......@@ -22,16 +23,40 @@
</target>
<!-- =================================================================== -->
<!-- Create global configuration -->
<!-- Compiles all application classes -->
<!-- =================================================================== -->
<target name="javac" depends="init">
<echo>Compiling ${packages}</echo>
<path id="compile.classpath">
<fileset dir="${build.cli.lib}" includes="*.jar" />
<path refid="build.classpath" />
</path>
<javac srcdir="${stage-one.modules}/core/sources" destdir="${build.cli.classes}" includes="${packages}"
classpathref="compile.classpath" debug="${debug}" optimize="${optimize}" target="${javatarget}"
source="${sourcerelease}" encoding="${sourceencoding}" deprecation="${deprecation}">
</javac>
</target>
<target name="compile" description="Compiles all sources under the build directory">
<echo level="info"> compiling ${ant.project.name} classes </echo>
<antcall target="javac">
<param name="packages" value="org/mycore/**" />
</antcall>
</target>
<!-- =================================================================== -->
<!-- Create global configuration -->
<!-- =================================================================== -->
<target name="config" depends="init" description="Copy the configuration files">
<echo level="info"> copy ${ant.project.name} configuration </echo>
<mcr:config propertyfile="${build.cli.config}/mycore.properties" mergeFile="${stage-one}/modules/core/config/mycore.properties" />
<mcr:config propertyfile="${build.cli.config}/mycore.properties"
mergeFile="${stage-one}/modules/core/config/mycore.properties" />
</target>
<!-- =================================================================== -->
<!-- Create scripts in bin like mycore.cmd/.sh a.s.o. -->
<!-- Create scripts in bin like mycore.cmd/.sh a.s.o. -->
<!-- =================================================================== -->
<target name="create.scripts.unix">
......@@ -42,18 +67,18 @@
</target>
<!-- =================================================================== -->
<!-- Load all classifications -->
<!-- Load all classifications -->
<!-- =================================================================== -->
<target name="create.class" depends="init" description="Copy all classifications">
<target name="create.class" depends="init" description="Copy all classifications">
<echo level="info"> run ${ant.project.name} create.class </echo>
<copy todir="${build.content}/classifications" flatten="false" overwrite="true">
<fileset dir="${stage-one.modules}/core/content/classifications" includes="*.xml" />
</copy>
</target>
<!-- =================================================================== -->
<!-- Load default ACL rules -->
<!-- Load default ACL rules -->
<!-- =================================================================== -->
<target name="pre.create.default-rules" depends="init" description="Prepare default ACL rules">
<copy todir="${build.cli.config}" overwrite="true">
......@@ -79,17 +104,19 @@
</target>
<!-- =================================================================== -->
<!-- Integrate the I18N data -->
<!-- Integrate the I18N data -->
<!-- =================================================================== -->
<target name="i18n">
<echo> building ${ant.project.name} i18n </echo>
<copy file="${stage-one}/modules/core/config/messages_local_de.properties" tofile="${build.cli.config}/messages_de.properties" />
<copy file="${stage-one}/modules/core/config/messages_local_en.properties" tofile="${build.cli.config}/messages_en.properties" />
<copy file="${stage-one}/modules/core/config/messages_local_de.properties"
tofile="${build.cli.config}/messages_de.properties" />
<copy file="${stage-one}/modules/core/config/messages_local_en.properties"
tofile="${build.cli.config}/messages_en.properties" />
</target>
<!-- =================================================================== -->
<!-- Build the web application directory and copy webpages -->
<!-- Build the web application directory and copy webpages -->
<!-- =================================================================== -->
<target name="create.webapp" depends="init">
......@@ -105,6 +132,6 @@
</copy>
</target>
<!-- =================================================================== -->
<!-- =================================================================== -->
</project>
\ No newline at end of file
......@@ -9,6 +9,7 @@
MCR.EventHandler.MCRObject.016.Class=
MCR.EventHandler.MCRObject.017.Class=org.mycore.datamodel.common.MCRDptServiceFlagEventHandler
MCR.EventHandler.MCRObject.020.Class=org.mycore.datamodel.common.MCRXMLMetadataEventHandler
#MCR.EventHandler.MCRObject.021.Class=org.mycore.datamodel.common.MCROCFLMetadataEventHandler
MCR.EventHandler.MCRObject.030.Class=org.mycore.datamodel.common.MCRLinkTableEventHandler
MCR.EventHandler.MCRObject.040.Class=
MCR.EventHandler.MCRObject.060.Class=org.mycore.datamodel.metadata.history.MCRMetadataHistoryManager
......@@ -17,6 +18,7 @@
MCR.EventHandler.MCRDerivate.010.Class=org.mycore.access.MCRRemoveAclEventHandler
MCR.EventHandler.MCRDerivate.020.Class=org.mycore.datamodel.common.MCRXMLMetadataEventHandler
#MCR.EventHandler.MCRDerivate.021.Class=org.mycore.datamodel.common.MCROCFLMetadataEventHandler
MCR.EventHandler.MCRDerivate.050.Class=
MCR.EventHandler.MCRDerivate.070.Class=org.mycore.datamodel.metadata.history.MCRMetadataHistoryManager
MCR.EventHandler.MCRDerivate.100.Class=org.mycore.solr.index.MCRSolrIndexEventHandler
......
/*
* This file is part of *** M y C o R e ***
* See http://www.mycore.de/ for details.
*
* This program is free software; you can use it, redistribute it
* and / or modify it under the terms of the GNU General Public License
* (GPL) as published by the Free Software Foundation; either version 3
* of the License or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program, in a file called gpl.txt or license.txt.
* If not, write to the Free Software Foundation Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
*/
package org.mycore.datamodel.common;
import java.io.InputStream;
import java.util.Locale;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mycore.common.MCRException;
import org.mycore.common.MCRUsageException;
import org.mycore.common.content.MCRJDOMContent;
import org.mycore.common.events.MCREvent;
import org.mycore.common.events.MCREventHandlerBase;
import org.mycore.datamodel.metadata.MCRBase;
import org.mycore.datamodel.metadata.MCRDerivate;
import org.mycore.datamodel.metadata.MCRObject;
import edu.wisc.library.ocfl.api.OcflOption;
import edu.wisc.library.ocfl.api.OcflRepository;
import edu.wisc.library.ocfl.api.model.CommitInfo;
import edu.wisc.library.ocfl.api.model.ObjectVersionId;
/**
* This event handler stores MyCoRe object & derivate metadata in an OCFL
* repository.
*
* @author Christoph Neidahl (OPNA2608)
*/
public class MCROCFLMetadataEventHandler extends MCREventHandlerBase {
private static final Logger LOGGER = LogManager.getLogger();
@Override
protected final void handleObjectCreated(MCREvent evt, MCRObject obj) {
LOGGER.debug(evt.getEventType(), evt.getObjectType());
handleCreated((MCRBase) obj);
}
@Override
protected final void handleObjectUpdated(MCREvent evt, MCRObject obj) {
LOGGER.debug(evt.getEventType(), evt.getObjectType());
handleUpdated((MCRBase) obj);
}
@Override
protected void handleObjectDeleted(MCREvent evt, MCRObject obj) {
LOGGER.debug(evt.getEventType(), evt.getObjectType());
handleDeleted((MCRBase) obj);
}
@Override
protected void handleDerivateCreated(MCREvent evt, MCRDerivate der) {
LOGGER.debug(evt.getEventType(), evt.getObjectType());
handleCreated((MCRBase) der);
}
@Override
protected void handleDerivateUpdated(MCREvent evt, MCRDerivate der) {
LOGGER.debug(evt.getEventType(), evt.getObjectType());
handleUpdated((MCRBase) der);
}
@Override
protected void handleDerivateDeleted(MCREvent evt, MCRDerivate der) {
LOGGER.debug(evt.getEventType(), evt.getObjectType());
handleDeleted((MCRBase) der);
}
private static void handleCreated(MCRBase obj) {
OcflRepository repo = MCROCFLRepositoryHandler.instance().getRepository();
String objName = obj.getId().toString();
if (repo.containsObject(objName)) {
throw new MCRException("Refusing to recreate already existing object!");
}
try {
InputStream objectAsStream = new MCRJDOMContent(obj.createXML()).getInputStream();
repo.updateObject(ObjectVersionId.head(objName), new CommitInfo().setMessage(
"Init on " + MCRISO8601Date.now().format("yyyy-MM-dd HH:mm:ss", Locale.GERMAN)), init -> {
init.writeFile(objectAsStream, objName + ".xml");
});
} catch (Exception e) {
throw new MCRException("Error while creating object in OCFL store!", e);
}
}
private static void handleUpdated(MCRBase obj) {
OcflRepository repo = MCROCFLRepositoryHandler.instance().getRepository();
String objName = obj.getId().toString();
if (!repo.containsObject(objName)) {
LOGGER.debug("Object does not exist yet, will create it instead!");
handleCreated(obj);
} else {
try {
InputStream objectAsStream = new MCRJDOMContent(obj.createXML()).getInputStream();
repo.updateObject(ObjectVersionId.head(objName),
new CommitInfo().setMessage(
"Update on " + MCRISO8601Date.now().format("yyyy-MM-dd HH:mm:ss", Locale.GERMAN)),
init -> {
init.writeFile(objectAsStream, objName + ".xml", OcflOption.OVERWRITE);
});
} catch (Exception e) {
throw new MCRException("Error while updating object in OCFL store!", e);
}
}
}
private static void handleDeleted(MCRBase obj) {
OcflRepository repo = MCROCFLRepositoryHandler.instance().getRepository();
String objName = obj.getId().toString();
if (!repo.containsObject(objName)) {
throw new MCRUsageException("Refusing to delete non-existent object: " + objName);
} else {
try {
if (MCROCFLRepositoryHandler.instance().getAbsoluteDelete()) {
repo.purgeObject(objName);
} else {
if (!repo.describeObject(objName).getHeadVersion().containsFile(objName + ".xml")) {
throw new MCRUsageException("Object does not exist (anymore?): " + objName);
} else {
repo.updateObject(ObjectVersionId.head(objName), new CommitInfo().setMessage(
"Delete on " + MCRISO8601Date.now().format("yyyy-MM-dd HH:mm:ss", Locale.GERMAN)),
init -> {
init.removeFile(objName + ".xml");
});
}
}
} catch (Exception e) {
throw new MCRException("Error while creating object in OCFL store!", e);
}
}
}
}
package org.mycore.datamodel.common;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mycore.common.config.MCRConfiguration;
import org.mycore.common.config.MCRConfigurationException;
import org.mycore.datamodel.ocfl.MCROCFLAbstractRepo;
import org.mycore.datamodel.ocfl.MCROCFLDefaultRepo;
import edu.wisc.library.ocfl.api.OcflRepository;
public class MCROCFLRepositoryHandler {
private static final Logger LOGGER = LogManager.getLogger();
private static final MCRConfiguration CONFIG = MCRConfiguration.instance();
private static MCROCFLRepositoryHandler handler = new MCROCFLRepositoryHandler();
// TODO: discuss
protected final Boolean opinionated = CONFIG.getBoolean("MCR.Metadata.Store.OCFL.Opinionated", false);
protected final Boolean absoluteDelete = CONFIG.getBoolean("MCR.Metadata.Store.OCFLDeletionIsAbsolute", false);
protected final MCROCFLAbstractRepo repoClass = CONFIG.<MCROCFLAbstractRepo>getInstanceOf(
"MCR.Metadata.Store.OCFL.RepoClass", MCROCFLDefaultRepo.class.getName());
protected final Path dirRepo, dirWork;
protected final OcflRepository repo;
private MCROCFLRepositoryHandler() {
LOGGER.debug("Initializing OCFL store.");
String strRepo = CONFIG.getString("MCR.Metadata.Store.OCFL.RepoDir");
dirRepo = Paths.get(strRepo);
checkPath(dirRepo, "repo", this.opinionated);
String strWork = CONFIG.getString("MCR.Metadata.Store.OCFL.WorkDir");
dirWork = Paths.get(strWork);
checkPath(dirWork, "work", this.opinionated);
try {
repo = repoClass.configure(dirRepo, dirWork);
} catch (Exception e) {
throw new MCRConfigurationException("Exception while configuring the OCFL metadata store from class "
+ this.repoClass.getClass().getCanonicalName() + ".", e);
}
};
private void checkPath(Path path, String type, Boolean attemptCreation) {
if (Files.notExists(path)) {
if (attemptCreation) {
try {
if (!Files.exists(Files.createDirectories(path))) {
throw new MCRConfigurationException("The OCFL metadata store " + type + " directory "
+ path.toAbsolutePath() + " does not exist.");
}
} catch (Exception e) {
throw new MCRConfigurationException("Exception while creating OCFL metadata store " + type
+ " directory " + path.toAbsolutePath(), e);
}
} else
throw new MCRConfigurationException("The OCFL metadata store " + type + " directory "
+ path.toAbsolutePath() + " does not exist, will not attempt to create it myself.");
} else {
if (!Files.isDirectory(path)) {
throw new MCRConfigurationException("The OCFL metadata store " + type + " directory "
+ path.toAbsolutePath() + " is a file, not a directory");
} else if (!Files.isReadable(path)) {
throw new MCRConfigurationException(
"The OCFL metadata store " + type + " directory " + path.toAbsolutePath() + " is not readable");
} else if (!Files.isWritable(path)) {
throw new MCRConfigurationException("The OCFL metadata store " + type + " directory "
+ path.toAbsolutePath() + " is not writeable");
}
}
}
public static MCROCFLRepositoryHandler instance() {
LOGGER.debug("Instance of OCFL store requested.");
return handler;
}
public OcflRepository getRepository() {
return this.repo;
}
public Path getRepositoryPath() {
return this.dirRepo;
}
public Path getWorkPath() {
return this.dirWork;
}
public Boolean getAbsoluteDelete() {
return this.absoluteDelete;
}
}
/*
* This file is part of *** M y C o R e ***
* See http://www.mycore.de/ for details.
*
* MyCoRe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MyCoRe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MyCoRe. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mycore.datamodel.ifs2;
import java.io.IOException;
import java.util.Date;
import java.util.stream.Stream;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import org.jdom2.JDOMException;
import org.mycore.common.MCRUsageException;
import org.mycore.common.content.MCRByteContent;
import org.mycore.common.content.MCRContent;
import org.mycore.common.content.streams.MCRByteArrayOutputStream;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.io.SVNRepository;
/**
* Provides information about a stored version of metadata and allows to
* retrieve that version from SVN
*
* @author Frank Lützenkirchen
*/
@XmlRootElement(name = "revision")
@XmlAccessorType(XmlAccessType.FIELD)
public class MCRMetadataVersion {
protected enum Type {
created(MCRMetadataVersion.CREATED), modified(MCRMetadataVersion.UPDATED), deleted(MCRMetadataVersion.DELETED);
protected final char charValue;
Type(char a) {
this.charValue = a;
}
public static Type fromValue(char a) {
return Stream.of(values()).filter(t -> t.charValue == a)
.findAny()
.orElseThrow(IllegalArgumentException::new);
}
}
/**
* The metadata document this version belongs to
*/
@XmlTransient
private MCRVersionedMetadata vm;
/**
* The revision number of this version
*/
@XmlAttribute(name = "r")
private long revision;
/**
* The user that created this version
*/
@XmlAttribute
private String user;
/**
* The date this version was created
*/
@XmlAttribute
private Date date;
/**
* Was this version result of a create, update or delete?
*/
@XmlAttribute()
private Type type;
/**
* A version that was created in store
*/
public static final char CREATED = 'A';
/**
* A version that was updated in store
*/
public static final char UPDATED = 'M';
/**
* A version that was deleted in store
*/
public static final char DELETED = 'D';
protected MCRMetadataVersion() {
//required for JAXB serialization
}
/**
* Creates a new metadata version info object
*
* @param vm
* the metadata document this version belongs to
* @param logEntry
* the log entry from SVN holding data on this version
* @param type
* the type of commit
*/
MCRMetadataVersion(MCRVersionedMetadata vm, SVNLogEntry logEntry, char type) {
this.vm = vm;
revision = logEntry.getRevision();
user = logEntry.getAuthor();
date = logEntry.getDate();
this.type = Type.fromValue(type);
}
/**
* Returns the metadata object this version belongs to
*
* @return the metadata object this version belongs to
*/
public MCRVersionedMetadata getMetadataObject() {
return vm;
}
/**
* Returns the type of operation this version comes from
*
* @see #CREATED
* @see #UPDATED
* @see #DELETED
*/
public char getType() {
return type.charValue;
}
/**
* Returns the SVN revision number of this version
*
* @return the SVN revision number of this version
*/
public long getRevision() {
return revision;
}
/**
* Returns the user that created this version
*
* @return the user that created this version
*/
public String getUser() {
return user;
}
/**
* Returns the date and time this version was created
*
* @return the date and time this version was created
*/
public Date getDate() {
return date;
}
/**
* Retrieves this version of the metadata
*
* @return the metadata document as it was in this version
* @throws MCRUsageException
* if this is a deleted version, which can not be retrieved
*/
public MCRContent retrieve() throws IOException {
if (type == Type.deleted) {
String msg = "You can not retrieve a deleted version, retrieve a previous version instead";
throw new MCRUsageException(msg);
}
try {
SVNRepository repository = vm.getStore().getRepository();
MCRByteArrayOutputStream baos = new MCRByteArrayOutputStream();
repository.getFile(vm.getStore().getSlotPath(vm.getID()), revision, null, baos);
baos.close();
return new MCRByteContent(baos.getBuffer(), 0, baos.size(), getDate().getTime());
} catch (SVNException e) {
throw new IOException(e);
}
}
/**
* Replaces the current version of the metadata object with this version,
* which means that a new version is created that is identical to this old
* version. The stored metadata document is updated to this old version of
* the metadata.
*/
public void restore() throws IOException, JDOMException {
vm.update(retrieve());
}
}
/*
* This file is part of *** M y C o R e ***
* See http://www.mycore.de/ for details.
*
* MyCoRe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MyCoRe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MyCoRe. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mycore.datamodel.ifs2;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Date;
import java.util.stream.Stream;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jdom2.JDOMException;
import org.mycore.common.MCRUsageException;
import org.mycore.common.content.MCRByteContent;
import org.mycore.common.content.MCRContent;
import edu.wisc.library.ocfl.api.OcflRepository;
import edu.wisc.library.ocfl.api.model.VersionDetails;
import edu.wisc.library.ocfl.api.model.VersionId;
/**
* Provides information about a stored version of metadata and allows to
* retrieve that version from SVN
*
* @author Christoph Neidahl
*/
@XmlRootElement(name = "revision")
@XmlAccessorType(XmlAccessType.FIELD)
public class MCROCFLMetadataVersion extends MCRMetadataVersion {
/**
* The logger
*/
protected static final Logger LOGGER = LogManager.getLogger();
/**
* The metadata document this version belongs to
*/
@XmlTransient
private MCROCFLVersionedMetadata vm;
/**
* The revision number of this version
*/
@XmlAttribute(name = "r")
private long revision;
/**
* The user that created this version
*/
@XmlAttribute
private String user;
/**
* The date this version was created
*/
@XmlAttribute
private Date date;
/**
* Was this version result of a create, update or delete?
*/
@XmlAttribute()
private Type type;
/**
* A version that was created in store
*/
public static final char CREATED = 'A';
/**
* A version that was updated in store
*/
public static final char UPDATED = 'M';
/**
* A version that was deleted in store
*/
public static final char DELETED = 'D';
/**
* Creates a new metadata version info object
*
* @param vm the metadata document this version belongs to
* @param version the version entry from OCFL identifying this version
* @param type the type of commit
*/
public MCROCFLMetadataVersion(MCROCFLVersionedMetadata vm, VersionDetails version, char type) {
this (vm, version, vm.getRevision(), type);
}
/**
* Creates a new metadata version info object
*
* @param vm the metadata document this version belongs to
* @param logEntry the log entry from SVN holding data on this version
* @param type the type of commit
*/
public MCROCFLMetadataVersion(MCROCFLVersionedMetadata vm, VersionDetails version, long revision, char type) {
this.vm = vm;
this.revision = revision;
user = "system";
date = Date.from(version.getCreated().toInstant());
this.type = Type.fromValue(type);
}
/**
* Returns the metadata object this version belongs to
*
* @return the metadata object this version belongs to
*/
@Override
public MCRVersionedMetadata getMetadataObject() {
return vm;
}
/**
* Returns the type of operation this version comes from
*
* @see #CREATED
* @see #UPDATED
* @see #DELETED
*/
public char getType() {
return type.charValue;
}
/**
* Returns the SVN revision number of this version
*
* @return the SVN revision number of this version
*/
public long getRevision() {
return revision;
}
/**
* Returns the user that created this version
*
* @return the user that created this version
*/
public String getUser() {
return user;
}
/**
* Returns the date and time this version was created
*
* @return the date and time this version was created
*/
public Date getDate() {
return date;
}
/**
* Retrieves this version of the metadata
*
* @return the metadata document as it was in this version
* @throws MCRUsageException if this is a deleted version, which can not be
* retrieved
*/
public MCRContent retrieve() throws IOException {
if (type == Type.deleted) {
String msg = "You can not retrieve a deleted version, retrieve a previous version instead";
throw new MCRUsageException(msg);
}
try {
OcflRepository repository = vm.getStoreOCFL().getOCFLRepository();
String objName = vm.getStoreOCFL().getID() + "_" + vm.getStoreOCFL().idLeadingZeroes(vm.getID());
LOGGER.warn("Requested retrieval of {}", objName);
File versionFile = Paths
.get(vm.getStoreOCFL().getOCFLRepositoryPath().toString(), repository.describeObject(objName)
.getVersion(new VersionId(revision)).getFile(objName + ".xml").getStorageRelativePath())
.toFile();
LOGGER.warn(versionFile.getAbsolutePath());
byte[] versionBytes = new byte[(int) versionFile.length()];
LOGGER.warn("Size of metadata: {}", versionFile.length());
FileInputStream versionContent = new FileInputStream(versionFile);
versionContent.read(versionBytes);
versionContent.close();
return new MCRByteContent(versionBytes, 0, versionBytes.length, getDate().getTime());
} catch (Exception e) {
throw new IOException(e);
}
}
/**
* Replaces the current version of the metadata object with this version, which
* means that a new version is created that is identical to this old version.
* The stored metadata document is updated to this old version of the metadata.
*/
public void restore() throws IOException, JDOMException {
vm.update(retrieve());
}
}
/*
* This file is part of *** M y C o R e ***
* See http://www.mycore.de/ for details.
*
* MyCoRe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MyCoRe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MyCoRe. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mycore.datamodel.ifs2;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.NumberFormat;
import java.util.Iterator;
import java.util.Locale;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jdom2.JDOMException;
import org.mycore.common.MCRException;
import org.mycore.common.MCRPersistenceException;
import org.mycore.common.MCRUsageException;
import org.mycore.common.content.MCRContent;
import org.mycore.datamodel.common.MCRISO8601Date;
import org.mycore.datamodel.common.MCROCFLRepositoryHandler;
import org.tmatesoft.svn.core.io.SVNRepository;
import edu.wisc.library.ocfl.api.OcflRepository;
import edu.wisc.library.ocfl.api.model.CommitInfo;
import edu.wisc.library.ocfl.api.model.ObjectVersionId;
/**
* Stores metadata objects both in a local filesystem structure and in a
* Subversion repository. Changes can be tracked and restored. To enable
* versioning, configure the repository URL, for example
*
* MCR.IFS2.Store.DocPortal_document.SVNRepositoryURL=file:///foo/svnroot/
*
* @author Frank Lützenkirchen
*/
public class MCROCFLVersioningMetadataStore extends MCRVersioningMetadataStore {
protected static final Logger LOGGER = LogManager.getLogger();
protected OcflRepository repo;
@Override
protected void init(String type) {
super.init(type);
checkRepo();
}
@Override
protected void init(MCRStoreConfig config) {
super.init(config);
checkRepo();
}
protected void setupSVN(String type) {
LOGGER.warn ("Unsupported: void setupSVN(String type)");
}
protected void checkRepo() {
LOGGER.info("Testing if OCFL repository is configured correctly.");
repo = MCROCFLRepositoryHandler.instance().getRepository();
}
/**
* The SVN store was configurable in whether or not it should touch the
* modification date on commits. The OCFL repository handler is only capable of
* writing the metadata from the object straight to the target.
*
* This method is only kept for compatibility purposes.
*
* @return true, if last modified of file should be same as timestamp of OCFL
* commit (always)
*/
public static boolean shouldSyncLastModifiedOnSVNCommit() {
return true;
}
@Override
public SVNRepository getRepository() {
throw new MCRException ("Unsupported: SVNRepository getRepository()");
}
/**
* Returns the OCFL repository used to manage metadata versions in this store.
*
* @return the OCFL repository used to manage metadata versions in this store.
*/
public OcflRepository getOCFLRepository() {
return MCROCFLRepositoryHandler.instance().getRepository();
}
/**
* Returns the path of the OCFL repository used to manage metadata versions in
* this store.
*
* @return the path of the OCFL repository used to manage metadata versions in
* this store.
*/
public Path getOCFLRepositoryPath() {
return MCROCFLRepositoryHandler.instance().getRepositoryPath();
}
/**
* Used to check the local SVN repository for errors
*
* Kept for compatibility reasons with existing code, OCFL repository does this
* on its own.
*
* @throws MCRPersistenceException if 'svn verify' fails (doesn't apply anymore)
*/
public void verify() throws MCRPersistenceException {
LOGGER.warn("Unsupported: void verify()");
}
@Override
public MCROCFLVersionedMetadata create(MCRContent xml, int id) throws IOException, JDOMException {
if (id <= 0) {
throw new MCRException("ID of metadata object must be a positive integer!");
}
String objName = getID() + "_" + idLeadingZeroes(id);
if (getOCFLRepository().containsObject(objName)) {
throw new MCRException("Metadata object " + objName + " already exists in store!");
}
MCROCFLVersionedMetadata meta = buildMetadataObject(id);
meta.create(xml);
return meta;
}
@Override
public MCROCFLVersionedMetadata create(MCRContent xml) throws IOException, JDOMException {
return (MCROCFLVersionedMetadata) super.create(xml);
}
/**
* Returns the metadata stored under the given ID, or null. Note that this
* metadata may not exist currently in the store, it may be a deleted version,
* which can be restored then.
*
* @param id the ID of the XML document
* @return the metadata stored under that ID, or null when there is no such
* metadata object
*/
@Override
public MCRVersionedMetadata retrieve(int id) throws IOException {
LOGGER.debug("Retrieving {}_{} ({}).", getID(), idLeadingZeroes(id), id);
MCROCFLVersionedMetadata requestedMetadata = new MCROCFLVersionedMetadata(this, getSlot(id), id, super.forceDocType,
false);
LOGGER.debug("Retrieved metadata object: {}", requestedMetadata);
LOGGER.debug("Contained metadata: {}", requestedMetadata.getMetadata().asString());
return requestedMetadata;
}
@Override
public void delete(int id) throws IOException {
delete(getID() + "_" + idLeadingZeroes(id));
}
public void delete(String objName) {
if (!repo.containsObject(objName)) {
throw new MCRUsageException("Refusing to delete non-existent object: " + objName);
} else if (MCROCFLRepositoryHandler.instance().getAbsoluteDelete()) {
repo.purgeObject(objName);
} else {
if (!repo.describeObject(objName).getHeadVersion().containsFile(objName + ".xml")) {
throw new MCRUsageException("Object does not exist (anymore?): " + objName);
} else {
repo.updateObject(ObjectVersionId.head(objName),
new CommitInfo().setMessage(
"Delete on " + MCRISO8601Date.now().format("yyyy-MM-dd HH:mm:ss", Locale.GERMAN)),
init -> {
init.removeFile(objName + ".xml");
});
}
}
}
/**
* Returns true if data for the given ID is existing in the store.
*
* @param id the ID of the data
* @return true, if data for the given ID is existing in the store.
*/
@Override
public boolean exists(final int id) throws IOException {
return repo.containsObject(getID() + "_" + idLeadingZeroes(id));
}
protected MCROCFLVersionedMetadata buildMetadataObject(int id) {
return new MCROCFLVersionedMetadata(this, null, id, super.forceDocType, false);
}
@Override
protected MCROCFLVersionedMetadata buildMetadataObject(Path fo, int id) {
return buildMetadataObject(id);
}
public String idLeadingZeroes(int id) {
NumberFormat formatter = NumberFormat.getIntegerInstance(Locale.ROOT);
formatter.setMinimumIntegerDigits(getIDLength());
formatter.setGroupingUsed(false);
return formatter.format(id);
}
}
package org.mycore.datamodel.ocfl;
import java.nio.file.Path;
import edu.wisc.library.ocfl.api.OcflRepository;
import edu.wisc.library.ocfl.core.OcflRepositoryBuilder;
public abstract class MCROCFLAbstractRepo extends OcflRepositoryBuilder {
public MCROCFLAbstractRepo() {
super();
}
public abstract OcflRepository configure(Path dirRepo, Path dirWork);
}
package org.mycore.datamodel.ocfl;
import java.nio.file.Path;
import edu.wisc.library.ocfl.api.OcflRepository;
import edu.wisc.library.ocfl.core.extension.layout.config.DefaultLayoutConfig;
import edu.wisc.library.ocfl.core.storage.filesystem.FileSystemOcflStorage;
public class MCROCFLDefaultRepo extends MCROCFLAbstractRepo {
@Override
public OcflRepository configure(Path dirRepo, Path dirWork) {
return this.layoutConfig(DefaultLayoutConfig.nTupleHashConfig())
.storage(FileSystemOcflStorage.builder().repositoryRoot(dirRepo).build())
.workDir(dirWork)
.build();
}
}
......@@ -10,7 +10,7 @@
Begleitend zum Projekt wird eine Dokumentation erstellt. Sie wird <a href="https://git.sc.uni-leipzig.de/mycore_applications/collection/anihealth/blob/master/documentation_anihealth.pdf" target="_blank">hier</a> auffindbar sein. (in Bearbeitung)
</p>
<p>
Eine Benutzerdokumentation für Anwender befindet sich <a href="https://git.sc.uni-leipzig.de/mycore_applications/collection/anihealth/blob/master/documentation/AniHealth_Benutzerdokumentation.pdf" target="_blank">hier</a>.
Eine Benutzerdokumentation für Anwender befindet sich <a href="/content/AniHealth_Benutzerdokumentation.pdf" target="_blank">hier</a>.
</p>
</div>
</section>
......@@ -22,7 +22,7 @@
The project is accompanied by a documentation. It will be available <a href="https://git.sc.uni-leipzig.de/mycore_applications/collection/anihealth/blob/master/documentation_anihealth.pdf" target="_blank">here</a>. (WIP)
</p>
<p>
You can find the user documentation <a href="https://git.sc.uni-leipzig.de/mycore_applications/collection/anihealth/blob/master/documentation/AniHealth_Benutzerdokumentation.pdf" target="_blank">here (German)</a>.
You can find the user documentation <a href="/content/AniHealth_Benutzerdokumentation.pdf" target="_blank">here (German)</a>.
</p>
</div>
</section>
......
......@@ -28,19 +28,18 @@
<link href="{$WebApplicationBaseURL}favicon.ico" REL="SHORTCUT ICON" />
<link href="{$WebApplicationBaseURL}css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<link href="{$WebApplicationBaseURL}css/fontawesome.min.css" rel="stylesheet" type="text/css" />
<link href="{$WebApplicationBaseURL}css/dptbase-common.css" rel="stylesheet" type="text/css" />
<link href="{$WebApplicationBaseURL}css/application_layout.css" rel="stylesheet" type="text/css" />
<link href="{$WebApplicationBaseURL}css/my_layout.css" rel="stylesheet" type="text/css" />
<!-- jQuery -->
<script type="text/javascript" language="javascript" src="{$WebApplicationBaseURL}js/jquery.min.js"></script>
<script type="text/javascript" language="javascript" src="{$WebApplicationBaseURL}js/jquery-ui.min.js"></script>
<link href="/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<link href="/css/fontawesome.min.css" rel="stylesheet" type="text/css" />
<link href="/css/dptbase-common.css" rel="stylesheet" type="text/css" />
<link href="/css/application_layout.css" rel="stylesheet" type="text/css" />
<link href="/css/my_layout.css" rel="stylesheet" type="text/css" />
<!-- jQeury -->
<script type="text/javascript" language="javascript" src="/js/jquery.min.js"></script>
<script type="text/javascript" language="javascript" src="/js/jquery-ui.min.js"></script>
<!-- bootstrap -->
<script type="text/javascript" language="javascript" src="{$WebApplicationBaseURL}js/popper.min.js"></script>
<script type="text/javascript" language="javascript" src="{$WebApplicationBaseURL}js/bootstrap.min.js"></script>
<script type="text/javascript" language="javascript" src="/js/bootstrap.bundle.min.js"></script>
</head>
......
#!/usr/bin/env bash
export INSTALL_HOME=$ANIHEALTH_HOME
......