/*
* 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.ArrayItem;
import cz.cas.lib.proarc.mods.ObjectFactory;
import cz.cas.lib.proarc.mods.StringPlusLanguage;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
/**
* Helper to handle arrays of the same XML element. The helper is necessary
* in order to update existing objects properly without loss of data
* that are not part of edited (mapped) objects.
*
* @author Jan Pokorsky
*/
final class ArrayMapper<S, T extends ArrayItem> {
private final ItemMapper<S, T> itemMapper;
public ArrayMapper(ItemMapper<S, T> mapper) {
this.itemMapper = mapper;
}
public List<T> map(List<S> l) {
List<T> result = new ArrayList<>(l.size());
int index = 0;
for (S source : l) {
T target = itemMapper.map(source);
target.setArrayIndex(index++);
result.add(target);
}
return result;
}
public List<S> map(List<T> newValues, List<? extends S> oldValues) {
newValues = MapperUtils.noNull(newValues);
oldValues = MapperUtils.noNull(oldValues);
List<S> result = new ArrayList<>(newValues.size());
for (T item : newValues) {
Integer index = item.getArrayIndex();
S origin = null;
if (index != null && index >= 0) {
origin = oldValues.get(index);
}
S source = itemMapper.map(item, origin);
result.add(source);
}
return result;
}
public static ArrayMapper<String, StringItem> stringMapper() {
return new ArrayMapper<>(new StringMapper());
}
public static List<StringItem> toStringItemList(List<String> strings) {
strings = MapperUtils.noNull(strings);
ArrayList<StringItem> items = new ArrayList<>(strings.size());
for (String s : strings) {
items.add(new StringItem(s));
}
return items;
}
public static List<String> toStringList(List<StringItem> items) {
items = MapperUtils.noNull(items);
ArrayList<String> strings = new ArrayList<>(items.size());
for (StringItem item : items) {
strings.add(item.getValue());
}
return strings;
}
public static List<StringPlusLanguage> toStringPlusLanguageList(List<StringItem> items) {
items = MapperUtils.noNull(items);
ArrayList<StringPlusLanguage> strings = new ArrayList<>(items.size());
ObjectFactory factory = new ObjectFactory();
for (StringItem item : items) {
StringPlusLanguage s = factory.createStringPlusLanguage();
s.setValue(item.getValue());
strings.add(s);
}
return strings;
}
public static List<StringItem> toStringPlusLanguageItemList(List<StringPlusLanguage> strings) {
strings = MapperUtils.noNull(strings);
ArrayList<StringItem> items = new ArrayList<>(strings.size());
for (StringPlusLanguage s : strings) {
items.add(new StringItem(s.getValue()));
}
return items;
}
public interface ArrayItem {
Integer getArrayIndex();
void setArrayIndex(Integer index);
}
public interface ItemMapper<S, T extends ArrayItem> {
T map(S source);
S map(T item, S origin);
}
@XmlAccessorType(XmlAccessType.FIELD)
public static final class StringItem implements ArrayItem {
@XmlElement(name = ModsConstants.FIELD_STRING_VALUE)
private String value;
private Integer index;
public StringItem(String value, Integer index) {
this.value = value;
this.index = index;
}
public StringItem(String value) {
this(value, null);
}
public StringItem() {
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public Integer getArrayIndex() {
return index;
}
@Override
public void setArrayIndex(Integer index) {
this.index = index;
}
@Override
public String toString() {
return String.format("StringItem{value=%s, index=%s}", value, index);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final StringItem other = (StringItem) obj;
return Objects.equals(this.value, other.value)
&& Objects.equals(this.index, other.index);
}
}
private static final class StringMapper implements ItemMapper<String, StringItem> {
@Override
public StringItem map(String source) {
return new StringItem(source);
}
@Override
public String map(StringItem item, String origin) {
return item.getValue();
}
}
}