/*
* Copyright (C) 2014 Jan Pokorsky
*
* This program 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.
*
* 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. If not, see <http://www.gnu.org/licenses/>.
*/
package cz.cas.lib.proarc.common.mods.ndk;
import com.fasterxml.jackson.databind.ObjectMapper;
import cz.cas.lib.proarc.common.mods.ModsUtils;
import cz.cas.lib.proarc.common.mods.custom.ModsCutomEditorType;
import static cz.cas.lib.proarc.common.mods.ndk.MapperUtils.*;
import cz.cas.lib.proarc.common.object.DigitalObjectHandler;
import cz.cas.lib.proarc.common.object.ndk.NdkMetadataHandler.ModsWrapper;
import cz.cas.lib.proarc.common.object.ndk.NdkPlugin;
import cz.cas.lib.proarc.mods.IdentifierDefinition;
import cz.cas.lib.proarc.mods.ModsDefinition;
import cz.cas.lib.proarc.mods.TitleInfoDefinition;
import cz.cas.lib.proarc.oaidublincore.ElementType;
import cz.cas.lib.proarc.oaidublincore.OaiDcType;
import java.io.IOException;
import java.util.List;
/**
* Subclass to implement transformations of MODS data in NDK flavor
* to various formats for given digital object model.
*
* @author Jan Pokorsky
*/
public abstract class NdkMapper {
/**
* Gets a NDK mapper for the given model ID.
* @param modelId model ID
* @return the mapper
* @deprecated Replaced with {@link NdkMapperFactory#get}.
*/
@Deprecated
public static NdkMapper get(String modelId) {
NdkMapper mapper;
if (NdkPlugin.MODEL_PAGE.equals(modelId)
|| ModsCutomEditorType.EDITOR_PAGE.equals(modelId)) {
mapper = new NdkPageMapper();
} else if (NdkPlugin.MODEL_PERIODICAL.equals(modelId)) {
mapper = new NdkPeriodicalMapper();
} else if (NdkPlugin.MODEL_PERIODICALVOLUME.equals(modelId)) {
mapper = new NdkPeriodicalVolumeMapper();
} else if (NdkPlugin.MODEL_PERIODICALISSUE.equals(modelId)) {
mapper = new NdkPeriodicalIssueMapper();
} else if (NdkPlugin.MODEL_PERIODICALSUPPLEMENT.equals(modelId)) {
mapper = new NdkPeriodicalSupplementMapper();
} else if (NdkPlugin.MODEL_ARTICLE.equals(modelId)) {
mapper = new NdkArticleMapper();
} else if (NdkPlugin.MODEL_PICTURE.equals(modelId)) {
mapper = new NdkPictureMapper();
} else if (NdkPlugin.MODEL_MONOGRAPHTITLE.equals(modelId)) {
mapper = new NdkMonographTitleMapper();
} else if (NdkPlugin.MODEL_MONOGRAPHVOLUME.equals(modelId)) {
mapper = new NdkMonographVolumeMapper();
} else if (NdkPlugin.MODEL_MONOGRAPHSUPPLEMENT.equals(modelId)) {
mapper = new NdkMonographSupplementMapper();
} else if (NdkPlugin.MODEL_CHAPTER.equals(modelId)) {
mapper = new NdkChapterMapper();
} else if (NdkPlugin.MODEL_CARTOGRAPHIC.equals(modelId)) {
mapper = new NdkCartographicMapper();
} else if (NdkPlugin.MODEL_SHEETMUSIC.equals(modelId)) {
mapper = new NdkSheetMusicMapper();
} else {
throw new IllegalStateException("Unsupported model: " + modelId);
}
return mapper;
}
/**
* Updates missing required attribute and elements to comply with the NDK specification.
*/
public void createMods(ModsDefinition mods, Context ctx) {
mods.setVersion(ModsUtils.VERSION);
addPid(mods, ctx.getPid());
}
/**
* Transforms MODS to DC.
*/
public final OaiDcType toDc(ModsDefinition mods, Context ctx) {
return createDc(mods, ctx);
}
/**
* Override to provide own view of MODS for a JSON editor.
* @param mods persisted MODS
* @param ctx context
* @return the serializable object
*/
public ModsWrapper toJsonObject(ModsDefinition mods, Context ctx) {
return new ModsWrapper(mods);
}
/**
* Reads MODS from JSON. Use subclass of {@link ModsWrapper} to read a customized MODS.
* @param jsMapper
* @param json
* @param ctx
* @return MODS
* @throws IOException failure
*/
public ModsDefinition fromJsonObject(ObjectMapper jsMapper, String json, Context ctx) throws IOException {
return jsMapper.readValue(json, ModsWrapper.class).getMods();
}
/**
* Adds identifiers.
*/
protected OaiDcType createDc(ModsDefinition mods, Context ctx) {
OaiDcType dc = new OaiDcType();
List<ElementType> identifiers = dc.getIdentifiers();
for (IdentifierDefinition identifier : mods.getIdentifier()) {
String idVal = toValue(identifier.getValue());
if (idVal == null) {
continue;
}
String idType = toValue(identifier.getType());
if (idType != null) {
idVal = idType + ':' + idVal;
}
identifiers.add(new ElementType(idVal, null));
}
return dc;
}
/**
* Transforms MODS to Fedora digital object label.
*/
public final String toLabel(ModsDefinition mods) {
String label = createObjectLabel(mods);
if (label == null) {
label = "?";
} else {
label = label.trim();
label = label.isEmpty() ? "?" : label;
int threshold = 2000;
if (label.length() > threshold) {
label = label.substring(0, threshold);
}
}
return label;
}
/**
* The default implementation creates label from titleInfo subelements.
* @return label or {@code null}
*/
protected String createObjectLabel(ModsDefinition mods) {
for (TitleInfoDefinition ti : mods.getTitleInfo()) {
if (toValue(ti.getType()) != null) {
continue;
}
return createTitleString(ti);
}
return null;
}
public static class Context {
private DigitalObjectHandler handler;
private String pid;
public Context(DigitalObjectHandler handler) {
this.handler = handler;
}
/**
* Use this just in case there is no handler to provide.
*/
public Context(String pid) {
this.pid = pid;
}
public String getPid() {
return handler == null ? pid: handler.getFedoraObject().getPid();
}
public DigitalObjectHandler getHandler() {
return handler;
}
}
}