add plain map join in parsing from maps, add UTF-8 encoding to compiler and javadoc
This commit is contained in:
parent
3bf648324c
commit
0037857591
4 changed files with 104 additions and 7 deletions
|
@ -1,5 +1,5 @@
|
|||
group = org.xbib
|
||||
name = marc
|
||||
version = 2.9.1
|
||||
version = 2.9.2
|
||||
|
||||
org.gradle.warning.mode = ALL
|
||||
|
|
|
@ -37,8 +37,10 @@ artifacts {
|
|||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << '-Xlint:all'
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
javadoc {
|
||||
tasks.withType(Javadoc) {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
|
@ -30,6 +30,8 @@ import java.util.Set;
|
|||
import java.util.TreeMap;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
|
@ -484,19 +486,27 @@ public class MarcRecord implements Map<String, Object> {
|
|||
if (!prefix.isEmpty()) {
|
||||
key.addLast(prefix);
|
||||
}
|
||||
List<Map.Entry<String, Object>> list = new LinkedList<>();
|
||||
LinkedList<Map.Entry<String, Object>> list = new LinkedList<>();
|
||||
source.forEach((k, v) -> {
|
||||
if (v instanceof Map) {
|
||||
parseMap((Map<String, Object>) v, k, key, consumer);
|
||||
} else if (v instanceof Collection) {
|
||||
Collection<Object> collection = (Collection<Object>) v;
|
||||
// join into a single map if we have a collection of plain maps
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
for (Object object : collection) {
|
||||
if (object instanceof Map) {
|
||||
parseMap((Map<String, Object>) object, k, key, consumer);
|
||||
Map<String, Object> m = (Map<String, Object>) object;
|
||||
if (!join(map, m)) {
|
||||
parseMap(m, k, key, consumer);
|
||||
}
|
||||
} else {
|
||||
list.add(Map.entry(k, object));
|
||||
}
|
||||
}
|
||||
if (!map.isEmpty()) {
|
||||
parseMap(map, k, key, consumer);
|
||||
}
|
||||
} else {
|
||||
list.add(Map.entry(k, v));
|
||||
}
|
||||
|
@ -508,4 +518,46 @@ public class MarcRecord implements Map<String, Object> {
|
|||
key.removeLast();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static boolean join(Map<String, Object> map1, Map<String, Object> map2) {
|
||||
if (isPlainMap(map2)) {
|
||||
String key2 = map2.keySet().iterator().next();
|
||||
Object value2 = map2.values().iterator().next();
|
||||
// collapse values into a single key
|
||||
if (map1.containsKey(key2)) {
|
||||
Object value1 = map1.get(key2);
|
||||
Collection<Object> collection;
|
||||
if (value1 instanceof Collection) {
|
||||
collection = (Collection<Object>) value1;
|
||||
collection.add(value2);
|
||||
} else {
|
||||
collection = new LinkedList<>();
|
||||
collection.add(value1);
|
||||
collection.add(value2);
|
||||
}
|
||||
map1.put(key2, collection);
|
||||
} else {
|
||||
map1.put(key2, value2);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A "plain" map is a map with exactly one element where the element value is not a map or a collection.
|
||||
* This technique is used in Elasticsearch for repeating values with (possibly) the same key.
|
||||
* @param map the map to be tested
|
||||
* @return true if map is a plain map
|
||||
*/
|
||||
private static boolean isPlainMap(Map<String, Object> map) {
|
||||
if (map.size() == 1) {
|
||||
Object object = map.values().iterator().next();
|
||||
return !(object instanceof Map) && !(object instanceof Collection<?>);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,8 +38,6 @@ import java.util.Map;
|
|||
import java.util.TreeMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class MarcRecordTest {
|
||||
|
@ -222,6 +220,7 @@ public class MarcRecordTest {
|
|||
|
||||
@Test
|
||||
public void testMarcRecordFromMapNested() {
|
||||
// test if we can have more than one map in a list
|
||||
Map<String, Object> map = Map.of("001", "123",
|
||||
"100", Map.of("_", Map.of("a", "Hello World")),
|
||||
"016", Map.of("7_", List.of(Map.of("2", "DE-101", "a", "010000151"), Map.of("2", "DE-600", "a", "23-1"))));
|
||||
|
@ -243,6 +242,50 @@ public class MarcRecordTest {
|
|||
assertTrue(match.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMarcRecordFromMapsWithJoinedPlainMaps() {
|
||||
// test if we can collapse "plain" subfield maps into a common MARC field
|
||||
// 016=[{7_=[{2=DE-101}, {a=010000151}]}, {7_=[{2=DE-600}, {a=23-1}]}]
|
||||
Map<String, Object> f1 = Map.of("7_", List.of(Map.of("2", "DE-101"), Map.of("a", "010000151")));
|
||||
Map<String, Object> f2 = Map.of("7_", List.of(Map.of("2", "DE-600"), Map.of("a", "23-1")));
|
||||
Map<String, Object> map = Map.of("016", List.of(f1, f2));
|
||||
MarcRecord marcRecord = MarcRecord.from(map);
|
||||
List<MarcField> list = new LinkedList<>();
|
||||
marcRecord.all(f -> "016".equals(f.getTag()), list::add);
|
||||
assertEquals(2, list.size());
|
||||
AtomicBoolean match = new AtomicBoolean();
|
||||
marcRecord.all(f -> "016".equals(f.getTag()) && "7 ".equals(f.getIndicator()), f -> {
|
||||
if ("DE-600".equals(f.getFirstSubfieldValue("2"))) {
|
||||
match.set("23-1".equals(f.getFirstSubfieldValue("a")));
|
||||
}
|
||||
});
|
||||
assertTrue(match.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMarcRecordFromMapsWithSameSubfieldId() {
|
||||
// 016=[{7_=[{a=foo}, {a=bar}}]
|
||||
Map<String, Object> f1 = Map.of("7_", List.of(Map.of("a", "foo"), Map.of("a", "bar")));
|
||||
Map<String, Object> map = Map.of("016", List.of(f1));
|
||||
MarcRecord marcRecord = MarcRecord.from(map);
|
||||
// we must have a single 016 field
|
||||
List<MarcField> list = new LinkedList<>();
|
||||
marcRecord.all(f -> "016".equals(f.getTag()), list::add);
|
||||
assertEquals(1, list.size());
|
||||
// we count for occurences of "foo" and "bar", both must exist
|
||||
AtomicInteger count = new AtomicInteger();
|
||||
marcRecord.all(f -> "016".equals(f.getTag()) && "7 ".equals(f.getIndicator()), f ->
|
||||
f.getSubfield("a").forEach(sf -> {
|
||||
if ("foo".equals(sf.getValue())) {
|
||||
count.incrementAndGet();
|
||||
}
|
||||
if ("bar".equals(sf.getValue())) {
|
||||
count.incrementAndGet();
|
||||
}
|
||||
}));
|
||||
assertEquals(2, count.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMarcRecordFromMapAsMap() throws IOException {
|
||||
Map<String, Object> map = new TreeMap<>(Map.of("001", "123",
|
||||
|
|
Loading…
Reference in a new issue