/* * Copyright (C) 2012 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.custom; import cz.cas.lib.proarc.common.mods.custom.ArrayMapper.ItemMapper; import cz.cas.lib.proarc.common.mods.custom.ClassificationMapper.ClassificationItem.Type; import cz.cas.lib.proarc.mods.ClassificationDefinition; import cz.cas.lib.proarc.mods.ModsDefinition; import cz.cas.lib.proarc.mods.ObjectFactory; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Set; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; /** * UDC, DDC mapper. * * <pre>{@code <classification authority="ddc">123</classification> <classification authority="udc">321</classification> }</pre> * This should fetch pairs of DDC and UDC classifications in arbitrary order. * * @author Jan Pokorsky */ final class ClassificationMapper { private final ArrayMapper<ClassificationDefinition, ClassificationItem> classificationMap = new ArrayMapper<>(new ClassificationItemMapper()); public List<ClassificationPair> mapPairs(ModsDefinition mods) { List<ClassificationItem> items = map(mods); return toPairs(items); } public ModsDefinition mapPairs(ModsDefinition mods, List<ClassificationPair> pairs) { pairs = MapperUtils.noNull(pairs); List<ClassificationItem> items = map(mods); List<ClassificationItem> others = filter(items, true, Type.OTHER); List<ClassificationItem> newItems = toItems(pairs); newItems.addAll(others); map(mods, newItems); return mods; } public List<ClassificationItem> map(ModsDefinition mods) { List<ClassificationDefinition> classifications = mods.getClassification(); return classificationMap.map(classifications); } public ModsDefinition map(ModsDefinition mods, List<ClassificationItem> items) { List<ClassificationDefinition> oldies = mods.getClassification(); List<ClassificationDefinition> news = classificationMap.map(items, oldies); oldies.clear(); oldies.addAll(news); return mods; } static List<ClassificationItem> toItems(List<ClassificationPair> pairs) { List<ClassificationItem> items = new ArrayList<>(2 * pairs.size()); for (ClassificationPair pair : pairs) { items.add(new ClassificationItem(pair.getDdcIndex(), Type.DDC, pair.getDdc())); items.add(new ClassificationItem(pair.getUdcIndex(), Type.UDC, pair.getUdc())); } return items; } static List<ClassificationPair> toPairs(List<ClassificationItem> items) { List<ClassificationPair> pairs = new ArrayList<>(); ClassificationPair pair = null; Type previousType = null; for (ClassificationItem item : items) { if (previousType == item.getType()) { pair = null; } switch (item.getType()) { case DDC: if (pair == null) { pair = new ClassificationPair(); pair.setDdc(item.getValue()); pair.setDdcIndex(item.getArrayIndex()); pairs.add(pair); } else { pair.setDdc(item.getValue()); pair.setDdcIndex(item.getArrayIndex()); pair = null; } break; case UDC: if (pair == null) { pair = new ClassificationPair(); pair.setUdc(item.getValue()); pair.setUdcIndex(item.getArrayIndex()); pairs.add(pair); } else { pair.setUdc(item.getValue()); pair.setUdcIndex(item.getArrayIndex()); pair = null; } break; default: pair = null; } previousType = item.getType(); } return pairs; } static List<ClassificationItem> filter(List<ClassificationItem> items, boolean include, Type first, Type... rest) { return filter(items, EnumSet.of(first, rest), include); } static List<ClassificationItem> filter(List<ClassificationItem> items, Set<Type> filter, boolean include) { List<ClassificationItem> result = new ArrayList<>(); for (ClassificationItem name : items) { boolean contains = filter.contains(name.getType()); if ((include == true && include == contains) || (include == false && include == contains)) { result.add(name); } } return result; } @XmlAccessorType(XmlAccessType.FIELD) public static class ClassificationPair { @XmlElement(name = ModsConstants.FIELD_CLASSIFICATION_DDC) private String ddc; @XmlElement(name = ModsConstants.FIELD_CLASSIFICATION_UDC) private String udc; private Integer ddcIndex; private Integer udcIndex; public ClassificationPair() { } ClassificationPair(String ddc, Integer ddcIndex, String udc, Integer udcIndex) { this.ddc = ddc; this.udc = udc; this.ddcIndex = ddcIndex; this.udcIndex = udcIndex; } public String getDdc() { return ddc; } public void setDdc(String ddc) { this.ddc = ddc; } public Integer getDdcIndex() { return ddcIndex; } public void setDdcIndex(Integer ddcIndex) { this.ddcIndex = ddcIndex; } public String getUdc() { return udc; } public void setUdc(String udc) { this.udc = udc; } public Integer getUdcIndex() { return udcIndex; } public void setUdcIndex(Integer udcIndex) { this.udcIndex = udcIndex; } @Override public String toString() { return String.format("ClassificationPair{ddc:[v: %s, i: %s], udc:[v: %s, i: %s]}", ddc, ddcIndex, udc, udcIndex); } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final ClassificationPair other = (ClassificationPair) obj; if ((this.ddc == null) ? (other.ddc != null) : !this.ddc.equals(other.ddc)) { return false; } if ((this.udc == null) ? (other.udc != null) : !this.udc.equals(other.udc)) { return false; } if (this.ddcIndex != other.ddcIndex && (this.ddcIndex == null || !this.ddcIndex.equals(other.ddcIndex))) { return false; } if (this.udcIndex != other.udcIndex && (this.udcIndex == null || !this.udcIndex.equals(other.udcIndex))) { return false; } return true; } } private static final class ClassificationItemMapper implements ItemMapper<ClassificationDefinition, ClassificationItem> { private final ObjectFactory factory = new ObjectFactory(); @Override public ClassificationItem map(ClassificationDefinition source) { ClassificationItem result = new ClassificationItem(); Type type = Type.from(source.getAuthority()); result.setType(type); if (type != Type.OTHER) { result.setValue(source.getValue()); } return result; } @Override public ClassificationDefinition map(ClassificationItem item, ClassificationDefinition origin) { if (item.getType() == Type.OTHER) { return origin; } ClassificationDefinition source = origin; if (origin == null) { source = factory.createClassificationDefinition(); source.setAuthority(item.getType().getText()); } source.setValue(item.getValue()); return source; } } public static class ClassificationItem implements ArrayMapper.ArrayItem { private String value; private Type type; private Integer index; public ClassificationItem() { } public ClassificationItem(Integer index, Type type, String value) { this.value = value; this.type = type; this.index = index; } public Type getType() { return type; } public void setType(Type type) { this.type = type; } public String getValue() { return value; } public void setValue(String value) { this.value = MapperUtils.normalize(value); } @Override public Integer getArrayIndex() { return index; } @Override public void setArrayIndex(Integer index) { this.index = index; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final ClassificationItem other = (ClassificationItem) obj; if ((this.value == null) ? (other.value != null) : !this.value.equals(other.value)) { return false; } if ((this.type == null) ? (other.type != null) : !this.type.equals(other.type)) { return false; } if (this.index != other.index && (this.index == null || !this.index.equals(other.index))) { return false; } return true; } @Override public String toString() { return String.format("ClassificationItem{type: %s, value: %s, index: %s}", type, value, index); } public enum Type { DDC("ddc"), UDC("udc"), OTHER("ClassificationItem.OTHER"); private String text; private Type(String text) { this.text = text; } public String getText() { return text; } public static Type from(String s) { for (Type type : values()) { if (type.getText().equals(s)) { return type; } } return OTHER; } } } }