Merge branch 'master' of https://code.google.com/p/plexi
diff --git a/src/com/google/enterprise/adaptor/CommandStreamParser.java b/src/com/google/enterprise/adaptor/CommandStreamParser.java
index b505b8d..23aec8c 100644
--- a/src/com/google/enterprise/adaptor/CommandStreamParser.java
+++ b/src/com/google/enterprise/adaptor/CommandStreamParser.java
@@ -277,13 +277,13 @@
private boolean notFound;
private DocId docId;
private String mimeType;
- private Map<String, String> metadata;
+ private Metadata metadata;
private byte[] contents;
- RetrieverInfo(DocId docId, Map<String, String> metadata, byte[] contents, boolean upToDate,
+ RetrieverInfo(DocId docId, Metadata metadata, byte[] contents, boolean upToDate,
String mimeType, boolean notFound) {
this.docId = docId;
- this.metadata = Collections.unmodifiableMap(metadata);
+ this.metadata = metadata.unmodifiableView();
this.contents = contents;
this.upToDate = upToDate;
this.mimeType = mimeType;
@@ -306,7 +306,8 @@
return docId;
}
- public Map<String, String> getMetadata() {
+ /** Returns unmodifiable view of Metadata. */
+ public Metadata getMetadata() {
return metadata;
}
@@ -406,7 +407,7 @@
public RetrieverInfo readFromRetriever() throws IOException {
- Map<String, String> metadata = new HashMap<String, String>();
+ Metadata metadata = new Metadata();
byte[] content = null;
boolean upToDate = false;
boolean notFound = false;
@@ -435,7 +436,7 @@
if (command == null || command.getOperation() != Operation.META_VALUE) {
throw new IOException("meta-name must be immediately followed by meta-value");
}
- metadata.put(metaName, command.getArgument());
+ metadata.add(metaName, command.getArgument());
break;
case UP_TO_DATE:
upToDate = true;
diff --git a/src/com/google/enterprise/adaptor/DocumentHandler.java b/src/com/google/enterprise/adaptor/DocumentHandler.java
index 304bd66..ffb1ee3 100644
--- a/src/com/google/enterprise/adaptor/DocumentHandler.java
+++ b/src/com/google/enterprise/adaptor/DocumentHandler.java
@@ -14,6 +14,8 @@
package com.google.enterprise.adaptor;
+import static java.util.Map.Entry;
+
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpsExchange;
@@ -278,9 +280,9 @@
/**
* Format the GSA-specific metadata header value for crawl-time metadata.
*/
- static String formMetadataHeader(Map<String, String> metadata) {
+ static String formMetadataHeader(Metadata metadata) {
StringBuilder sb = new StringBuilder();
- for (Map.Entry<String, String> item : metadata.entrySet()) {
+ for (Entry<String, String> item : metadata) {
percentEncodeMapEntryPair(sb, item.getKey(), item.getValue());
}
return (sb.length() == 0) ? "" : sb.substring(0, sb.length() - 1);
@@ -446,7 +448,7 @@
private OutputStream os;
private CountingOutputStream countingOs;
private String contentType;
- private Map<String, String> metadata = Collections.emptyMap();
+ private Metadata metadata = new Metadata();
private Acl acl = Acl.EMPTY;
private List<URI> anchorUris = new ArrayList<URI>();
private List<String> anchorTexts = new ArrayList<String>();
@@ -522,17 +524,11 @@
}
@Override
- public void setMetadata(Map<String, String> metadata) {
+ public void addMetadata(String key, String value) {
if (state != State.SETUP) {
throw new IllegalStateException("Already responded");
}
- setMetadataInternal(metadata);
- }
-
- private void setMetadataInternal(Map<String, String> metadata) {
- // TODO(ejona): check for valid keys and values.
- this.metadata = Collections.unmodifiableMap(
- new TreeMap<String, String>(metadata));
+ metadata.add(key, value);
}
@Override
@@ -664,16 +660,14 @@
private ByteArrayOutputStream transform(byte[] content) throws IOException {
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
- Map<String, String> metadataCopy = new HashMap<String, String>(metadata);
Map<String, String> params = new HashMap<String, String>();
params.put("DocId", docId.getUniqueId());
params.put("Content-Type", contentType);
try {
- transform.transform(content, contentOut, metadataCopy, params);
+ transform.transform(content, contentOut, metadata, params);
} catch (TransformException e) {
throw new IOException(e);
}
- setMetadataInternal(metadataCopy);
contentType = params.get("Content-Type");
return contentOut;
}
diff --git a/src/com/google/enterprise/adaptor/DocumentTransform.java b/src/com/google/enterprise/adaptor/DocumentTransform.java
index 0dcacfc..3d3249f 100644
--- a/src/com/google/enterprise/adaptor/DocumentTransform.java
+++ b/src/com/google/enterprise/adaptor/DocumentTransform.java
@@ -38,7 +38,7 @@
*/
public void transform(ByteArrayOutputStream contentIn,
OutputStream contentOut,
- Map<String, String> metadata,
+ Metadata metadata,
Map<String, String> params)
throws TransformException, IOException;
diff --git a/src/com/google/enterprise/adaptor/Metadata.java b/src/com/google/enterprise/adaptor/Metadata.java
new file mode 100644
index 0000000..520c5e7
--- /dev/null
+++ b/src/com/google/enterprise/adaptor/Metadata.java
@@ -0,0 +1,259 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.enterprise.adaptor;
+
+import static java.util.AbstractMap.SimpleImmutableEntry;
+import static java.util.Map.Entry;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ * Allows storing multiple metadata values to a single key.
+ * <p>
+ * Null keys are invalid as arguments. Null values are
+ * invalid as arguments.
+ * <p>
+ * This class is mutable and not thread-safe.
+ */
+public class Metadata implements Iterable<Entry<String, String>> {
+ private Map<String, Set<String>> mappings
+ = new TreeMap<String, Set<String>>();
+
+ /** Create empty instance. */
+ public Metadata() {
+ }
+
+ /** Duplicate. */
+ public Metadata(Iterable<Entry<String, String>> m) {
+ for (Entry<String, String> e : m) {
+ add(e.getKey(), e.getValue());
+ }
+ }
+
+ /** Make v be only value associated with key. */
+ public void set(String k, String v) {
+ if (null == k) {
+ throw new NullPointerException();
+ }
+ if (null == v) {
+ throw new NullPointerException();
+ }
+ TreeSet<String> single = new TreeSet<String>();
+ single.add(v);
+ mappings.put(k, single);
+ }
+
+ /** Throws NullPointerException if a null is found. */
+ private static void assureNoNulls(Set<String> items) {
+ if (items.contains(null)) {
+ throw new NullPointerException();
+ }
+ }
+
+ /** Make copy of v be the values associated with key. */
+ public void set(String k, Set<String> v) {
+ if (null == k) {
+ throw new NullPointerException();
+ }
+ if (null == v) {
+ throw new NullPointerException();
+ }
+ assureNoNulls(v);
+ if (v.isEmpty()) {
+ mappings.remove(k);
+ } else {
+ v = new TreeSet<String>(v);
+ mappings.put(k, v);
+ }
+ }
+
+ /** Increases values mapped to k with v. */
+ public void add(String k, String v) {
+ if (null == k) {
+ throw new NullPointerException();
+ }
+ if (null == v) {
+ throw new NullPointerException();
+ }
+ Set<String> found = mappings.get(k);
+ if (null == found) {
+ set(k, v);
+ } else {
+ found.add(v);
+ }
+ }
+
+ /** Replaces entries inside of this metadata with provided ones. */
+ public void set(Iterable<Entry<String, String>> it) {
+ mappings.clear();
+ for (Entry<String, String> e : it) {
+ add(e.getKey(), e.getValue());
+ }
+ }
+
+ /** Gives unmodifiable reference to inserted values for key, empty if none. */
+ public Set<String> getAllValues(String key) {
+ Set<String> found = mappings.get(key);
+ if (null == found) {
+ found = Collections.emptySet();
+ }
+ return Collections.unmodifiableSet(found);
+ }
+
+ /** One of the inserted values, or null if none. */
+ public String getOneValue(String key) {
+ Set<String> found = mappings.get(key);
+ String first = null;
+ if (null != found) {
+ if (found.isEmpty()) {
+ throw new AssertionError();
+ }
+ first = found.iterator().next();
+ }
+ return first;
+ }
+
+ /** Get modifiable set of all keys with at least one value. */
+ public Set<String> getKeys() {
+ return mappings.keySet();
+ }
+
+ /**
+ * Provides every key and value in immutable entries sorted
+ * alphabetically, first by key, and secondly by value.
+ * <p>
+ * Behaviour is undefined if backing Metadata instance is modified
+ * during iteration.
+ * <p>
+ * remove() is unsupported on returned iterator.
+ */
+ public Iterator<Entry<String, String>> iterator() {
+ return new EntriesIterator();
+ }
+
+ /** Loops through keys and for each key all values. */
+ private class EntriesIterator implements Iterator<Entry<String, String>> {
+ private Iterator<Entry<String, Set<String>>> byKey
+ = mappings.entrySet().iterator();
+ private String currentKey;
+ private Iterator<String> currentValues
+ = Collections.<String>emptyList().iterator();
+
+ @Override
+ public boolean hasNext() {
+ if (currentValues.hasNext()) {
+ return true;
+ }
+ if (!byKey.hasNext()) {
+ return false;
+ }
+ Entry<String, Set<String>> currentEntry = byKey.next();
+ currentKey = currentEntry.getKey();
+ currentValues = currentEntry.getValue().iterator();
+ return hasNext();
+ }
+
+ @Override
+ public Entry<String, String> next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ String k = currentKey, v = currentValues.next();
+ return new SimpleImmutableEntry<String, String>(k, v);
+ }
+
+ /** Not supported. */
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /** True if exactly the same key-values are represented. */
+ public boolean equals(Object o) {
+ if (!(o instanceof Metadata)) {
+ return false;
+ }
+ if (this == o) {
+ return true;
+ }
+ Metadata other = (Metadata) o;
+ return mappings.equals(other.mappings);
+ }
+
+ /** True with 0 entries. */
+ public boolean isEmpty() {
+ return mappings.isEmpty();
+ }
+
+ /** Contains every key and value pair; useful for debugging. */
+ public String toString() {
+ String sep = ", ";
+ StringBuilder builder = new StringBuilder();
+ for (Entry<String, String> e : this) {
+ builder.append(sep);
+ builder.append(e.getKey()).append("=").append(e.getValue());
+ }
+ String body = "";
+ if (0 != builder.length()) {
+ body = builder.substring(sep.length());
+ }
+ return "[" + body + "]";
+ }
+
+ /** Does not allow any mutating operations. */
+ private static class ReadableMetadata extends Metadata {
+ @Override
+ public void set(String k, String v) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void set(String k, Set<String> v) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void add(String k, String v) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void set(Iterable<Entry<String, String>> it) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Set<String> getKeys() {
+ return Collections.unmodifiableSet(super.getKeys());
+ }
+ };
+
+ /** Get a reference to an unmodifiable view of this object. */
+ public Metadata unmodifiableView() {
+ Metadata unmodifiable = new ReadableMetadata();
+ // Extra precaution against mappings use, but not against moding
+ // sets that are values inside it.
+ unmodifiable.mappings = Collections.unmodifiableMap(this.mappings);
+ return unmodifiable;
+ }
+}
diff --git a/src/com/google/enterprise/adaptor/Response.java b/src/com/google/enterprise/adaptor/Response.java
index 34182ab..599d2de 100644
--- a/src/com/google/enterprise/adaptor/Response.java
+++ b/src/com/google/enterprise/adaptor/Response.java
@@ -16,7 +16,6 @@
import java.io.*;
import java.net.URI;
-import java.util.Map;
/**
* Interface provided to {@link Adaptor#getDocContent} for performing the
@@ -72,12 +71,14 @@
public void setContentType(String contentType);
/**
- * Provide metadata that applies to the document.
+ * Add metadata element that applies to the document.
*
- * @throws IllegalArgumentException if metadata contains {@code null} or empty
- * keys or {@code null} values
+ * @param key the key of metadata element
+ * @param value the value of metadata element
+ * @throws NullPointerException if {@code key} or {@code value}
+ * is {@code null}
*/
- public void setMetadata(Map<String, String> metadata);
+ public void addMetadata(String key, String value);
/**
* Provide the document's ACLs for early-binding security on the GSA.
diff --git a/src/com/google/enterprise/adaptor/TransformPipeline.java b/src/com/google/enterprise/adaptor/TransformPipeline.java
index c4edb19..c187e9d 100644
--- a/src/com/google/enterprise/adaptor/TransformPipeline.java
+++ b/src/com/google/enterprise/adaptor/TransformPipeline.java
@@ -50,7 +50,7 @@
*/
public void transform(byte[] contentIn,
OutputStream contentOut,
- Map<String, String> metadata,
+ Metadata metadata,
Map<String, String> params) throws TransformException, IOException {
if (transformList.isEmpty()) {
contentOut.write(contentIn);
@@ -59,23 +59,19 @@
ByteArrayOutputStream contentInTransit = new ByteArrayOutputStream(contentIn.length);
ByteArrayOutputStream contentOutTransit = new ByteArrayOutputStream(contentIn.length);
- Map<String, String> metadataInTransit = Collections.checkedMap(
- new HashMap<String, String>(metadata.size() * 2), String.class, String.class);
- Map<String, String> metadataOutTransit = Collections.checkedMap(
- new HashMap<String, String>(metadata.size() * 2), String.class, String.class);
+ Metadata metadataInTransit = new Metadata(metadata);
Map<String, String> paramsInTransit = Collections.checkedMap(
new HashMap<String, String>(params.size() * 2), String.class, String.class);
Map<String, String> paramsOutTransit = Collections.checkedMap(
new HashMap<String, String>(params.size() * 2), String.class, String.class);
contentInTransit.write(contentIn);
- metadataInTransit.putAll(metadata);
paramsInTransit.putAll(params);
for (DocumentTransform transform : transformList) {
contentOutTransit.reset();
- metadataOutTransit.clear();
- metadataOutTransit.putAll(metadataInTransit);
+ // Invariant: metadataInTransit changes after good transform only.
+ Metadata metadataOutTransit = new Metadata(metadataInTransit);
paramsOutTransit.clear();
paramsOutTransit.putAll(paramsInTransit);
@@ -93,20 +89,18 @@
continue;
}
}
+ metadataInTransit = metadataOutTransit;
+ metadataOutTransit = null;
// Swap input and output. The input is reused as the output for effeciency.
ByteArrayOutputStream tmp = contentInTransit;
contentInTransit = contentOutTransit;
contentOutTransit = tmp;
- Map<String, String> tmpMap = metadataInTransit;
- metadataInTransit = metadataOutTransit;
- metadataOutTransit = tmpMap;
- tmpMap = paramsInTransit;
+ Map<String, String> tmpMap = paramsInTransit;
paramsInTransit = paramsOutTransit;
paramsOutTransit = tmpMap;
}
contentInTransit.writeTo(contentOut);
- metadata.clear();
- metadata.putAll(metadataInTransit);
+ metadata.set(metadataInTransit);
params.clear();
params.putAll(paramsInTransit);
}
diff --git a/src/com/google/enterprise/adaptor/WrapperAdaptor.java b/src/com/google/enterprise/adaptor/WrapperAdaptor.java
index 0314d04..ad7d6a1 100644
--- a/src/com/google/enterprise/adaptor/WrapperAdaptor.java
+++ b/src/com/google/enterprise/adaptor/WrapperAdaptor.java
@@ -119,8 +119,8 @@
}
@Override
- public void setMetadata(Map<String, String> m) {
- response.setMetadata(m);
+ public void addMetadata(String key, String value) {
+ response.addMetadata(key, value);
}
@Override
@@ -185,7 +185,7 @@
public static class GetContentsResponse implements Response {
private OutputStream os;
private String contentType;
- private Map<String, String> metadata;
+ private Metadata metadata = new Metadata();
private Acl acl;
private List<URI> anchorUris = new ArrayList<URI>();
private List<String> anchorTexts = new ArrayList<String>();
@@ -219,9 +219,8 @@
}
@Override
- public void setMetadata(Map<String, String> m) {
- this.metadata = Collections.unmodifiableMap(
- new HashMap<String, String>(m));
+ public void addMetadata(String key, String value) {
+ this.metadata.add(key, value);
}
@Override
@@ -254,7 +253,8 @@
return contentType;
}
- public Map<String, String> getMetadata() {
+ /** Returns reference to modifiable accumulated metadata. */
+ public Metadata getMetadata() {
return metadata;
}
diff --git a/src/com/google/enterprise/adaptor/examples/AdaptorWithCrawlTimeMetadataTemplate.java b/src/com/google/enterprise/adaptor/examples/AdaptorWithCrawlTimeMetadataTemplate.java
index e28c14f..b830160 100644
--- a/src/com/google/enterprise/adaptor/examples/AdaptorWithCrawlTimeMetadataTemplate.java
+++ b/src/com/google/enterprise/adaptor/examples/AdaptorWithCrawlTimeMetadataTemplate.java
@@ -56,12 +56,10 @@
str = "Document 1001 says hello and apple orange";
List<String> users1001 = Arrays.asList("peter", "bart", "simon");
List<String> groups1001 = Arrays.asList("support", "sales");
- Map<String, String> metadata = new HashMap<String, String>();
// Add custom meta items.
- metadata.put("my-special-key", "my-custom-value");
- metadata.put("date", "not soon enough");
+ resp.addMetadata("my-special-key", "my-custom-value");
+ resp.addMetadata("date", "not soon enough");
// Must set metadata before getting OutputStream
- resp.setMetadata(metadata);
resp.setAcl(new Acl.Builder()
// Add user ACL.
.setPermitUsers(users1001)
@@ -70,9 +68,8 @@
.build());
} else if ("1002".equals(id.getUniqueId())) {
str = "Document 1002 says hello and banana strawberry";
- // Must set metadata before getting OutputStream
- resp.setMetadata(
- Collections.singletonMap("date", "better never than late"));
+ // Must add metadata before getting OutputStream
+ resp.addMetadata("date", "never than late");
} else {
resp.respondNotFound();
return;
diff --git a/src/com/google/enterprise/adaptor/examples/CalaisNERTransform.java b/src/com/google/enterprise/adaptor/examples/CalaisNERTransform.java
index bc73c59..ecc759c 100644
--- a/src/com/google/enterprise/adaptor/examples/CalaisNERTransform.java
+++ b/src/com/google/enterprise/adaptor/examples/CalaisNERTransform.java
@@ -15,6 +15,7 @@
package com.google.enterprise.adaptor.examples;
import com.google.enterprise.adaptor.AbstractDocumentTransform;
+import com.google.enterprise.adaptor.Metadata;
import com.google.enterprise.adaptor.TransformException;
import mx.bigdata.jcalais.CalaisClient;
@@ -82,7 +83,7 @@
*/
@Override
public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
- Map<String, String> metadata, Map<String, String> params)
+ Metadata metadata, Map<String, String> params)
throws TransformException, IOException {
String apiKey = params.get("OpenCalaisApiKey");
if (apiKey == null) {
diff --git a/src/com/google/enterprise/adaptor/examples/MetaTaggerTransform.java b/src/com/google/enterprise/adaptor/examples/MetaTaggerTransform.java
index ee77d20..ce7bd56 100644
--- a/src/com/google/enterprise/adaptor/examples/MetaTaggerTransform.java
+++ b/src/com/google/enterprise/adaptor/examples/MetaTaggerTransform.java
@@ -15,6 +15,7 @@
package com.google.enterprise.adaptor.examples;
import com.google.enterprise.adaptor.AbstractDocumentTransform;
+import com.google.enterprise.adaptor.Metadata;
import com.google.enterprise.adaptor.TransformException;
import java.io.ByteArrayOutputStream;
@@ -45,7 +46,7 @@
@Override
public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
- Map<String, String> metadata, Map<String, String> params)
+ Metadata metadata, Map<String, String> params)
throws TransformException, IOException {
String content = contentIn.toString();
StringBuilder sb = new StringBuilder();
diff --git a/src/com/google/enterprise/adaptor/examples/TableGeneratorTransform.java b/src/com/google/enterprise/adaptor/examples/TableGeneratorTransform.java
index f05d372..038205d 100644
--- a/src/com/google/enterprise/adaptor/examples/TableGeneratorTransform.java
+++ b/src/com/google/enterprise/adaptor/examples/TableGeneratorTransform.java
@@ -15,6 +15,7 @@
package com.google.enterprise.adaptor.examples;
import com.google.enterprise.adaptor.AbstractDocumentTransform;
+import com.google.enterprise.adaptor.Metadata;
import com.google.enterprise.adaptor.TransformException;
import au.com.bytecode.opencsv.CSVReader;
@@ -49,7 +50,7 @@
@Override
public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
- Map<String, String> metadata, Map<String, String> params)
+ Metadata metadata, Map<String, String> params)
throws TransformException, IOException {
String csv = contentIn.toString();
List<String[]> records = new CSVReader(new StringReader(csv)).readAll();
diff --git a/src/com/google/enterprise/adaptor/prebuilt/CommandLineAdaptor.java b/src/com/google/enterprise/adaptor/prebuilt/CommandLineAdaptor.java
index cb15b9d..7dfdc0b 100644
--- a/src/com/google/enterprise/adaptor/prebuilt/CommandLineAdaptor.java
+++ b/src/com/google/enterprise/adaptor/prebuilt/CommandLineAdaptor.java
@@ -35,6 +35,7 @@
import java.util.Date;
import java.util.List;
import java.util.Map;
+import java.util.logging.Level;
import java.util.logging.Logger;
/**
@@ -194,9 +195,11 @@
resp.setContentType(retrieverInfo.getMimeType());
}
if (retrieverInfo.getMetadata() != null) {
- log.finest("Retriever: " + id.getUniqueId() + " has metadata "
- + retrieverInfo.getMetadata());
- resp.setMetadata(retrieverInfo.getMetadata());
+ log.log(Level.FINEST, "Retriever: {0} has metadata {1}",
+ new Object[] {id.getUniqueId(), retrieverInfo.getMetadata()});
+ for (Map.Entry<String, String> e : retrieverInfo.getMetadata()) {
+ resp.addMetadata(e.getKey(), e.getValue());
+ }
}
if (retrieverInfo.getContents() != null) {
resp.getOutputStream().write(retrieverInfo.getContents());
diff --git a/src/com/google/enterprise/adaptor/prebuilt/CommandLineTransform.java b/src/com/google/enterprise/adaptor/prebuilt/CommandLineTransform.java
index 217130b..39507f4 100644
--- a/src/com/google/enterprise/adaptor/prebuilt/CommandLineTransform.java
+++ b/src/com/google/enterprise/adaptor/prebuilt/CommandLineTransform.java
@@ -14,8 +14,11 @@
package com.google.enterprise.adaptor.prebuilt;
+import static java.util.AbstractMap.SimpleEntry;
+
import com.google.enterprise.adaptor.AbstractDocumentTransform;
import com.google.enterprise.adaptor.IOHelper;
+import com.google.enterprise.adaptor.Metadata;
import com.google.enterprise.adaptor.TransformException;
import java.io.*;
@@ -80,7 +83,7 @@
@Override
public void transform(ByteArrayOutputStream contentIn,
OutputStream contentOut,
- Map<String, String> metadata,
+ Metadata metadata,
Map<String, String> params)
throws TransformException, IOException {
if (transformCommand == null) {
@@ -91,7 +94,7 @@
try {
String[] commandLine;
if (commandAcceptsParameters) {
- metadataFile = writeMapToTempFile(metadata);
+ metadataFile = writeIterableToTempFile(metadata);
paramsFile = writeMapToTempFile(params);
commandLine = new String[transformCommand.size() + 2];
@@ -125,8 +128,7 @@
contentOut.write(command.getStdout());
if (commandAcceptsParameters) {
- metadata.clear();
- metadata.putAll(readMapFromFile(metadataFile));
+ metadata.set(readSetFromFile(metadataFile));
params.clear();
params.putAll(readMapFromFile(paramsFile));
}
@@ -142,8 +144,13 @@
private File writeMapToTempFile(Map<String, String> map)
throws IOException, TransformException {
+ return writeIterableToTempFile(map.entrySet());
+ }
+
+ private File writeIterableToTempFile(Iterable<Map.Entry<String, String>> it)
+ throws IOException, TransformException {
StringBuilder sb = new StringBuilder();
- for (Map.Entry<String, String> me : map.entrySet()) {
+ for (Map.Entry<String, String> me : it) {
if (me.getKey().contains("\0")) {
throw new TransformException("Key cannot contain the null character: "
+ me.getKey());
@@ -158,7 +165,7 @@
return IOHelper.writeToTempFile(sb.toString(), charset);
}
- private Map<String, String> readMapFromFile(File file) throws IOException {
+ private List<Map.Entry<String, String>> readListFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
String str;
try {
@@ -168,9 +175,23 @@
}
String[] list = str.split("\0");
- Map<String, String> map = new HashMap<String, String>(list.length);
+ List<Map.Entry<String, String>> all = new ArrayList<Map.Entry<String, String>>();
for (int i = 0; i + 1 < list.length; i += 2) {
- map.put(list[i], list[i + 1]);
+ all.add(new SimpleEntry<String, String>(list[i], list[i + 1]));
+ }
+ return all;
+ }
+
+ private Set<Map.Entry<String, String>> readSetFromFile(File file) throws IOException {
+ List<Map.Entry<String, String>> all = readListFromFile(file);
+ Set<Map.Entry<String, String>> set = new HashSet<Map.Entry<String, String>>(all);
+ return set;
+ }
+
+ private Map<String, String> readMapFromFile(File file) throws IOException {
+ Map<String, String> map = new HashMap<String, String>();
+ for (Map.Entry<String, String> e : readListFromFile(file)) {
+ map.put(e.getKey(), e.getValue());
}
return map;
}
diff --git a/test/com/google/enterprise/adaptor/CommandStreamParserTest.java b/test/com/google/enterprise/adaptor/CommandStreamParserTest.java
index c875567..d63e05d 100644
--- a/test/com/google/enterprise/adaptor/CommandStreamParserTest.java
+++ b/test/com/google/enterprise/adaptor/CommandStreamParserTest.java
@@ -30,7 +30,9 @@
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
/**
* Tests for {@link CommandStreamParser}.
@@ -163,9 +165,35 @@
assertEquals("123", info.getDocId().getUniqueId());
assertTrue(info.isUpToDate());
assertArrayEquals("2468".getBytes(), info.getContents());
- Map<String, String> metadata = info.getMetadata();
- assertEquals(1, metadata.size());
- assertEquals("plexi", metadata.get("project"));
+ Metadata metadata = info.getMetadata();
+ assertEquals(1, metadata.getKeys().size());
+ assertEquals("plexi", metadata.getOneValue("project"));
+ }
+
+ @Test
+ public void testRetrieverMultipleMetadataValuesSameKey() throws IOException {
+ String source = "GSA Adaptor Data Version 1 [\n]\n" +
+ "id=123\n" +
+ "up-to-date\n" +
+ "UNKNOWN_COMMAND=abcdefghi\n" +
+ "meta-name=project\nmeta-value=plexi\n" +
+ "meta-name=project\nmeta-value=klexa\ncontent\n2468";
+
+ InputStream inputStream = new ByteArrayInputStream(source.getBytes("UTF-8"));
+ CommandStreamParser parser = new CommandStreamParser(inputStream);
+ int version = parser.getVersionNumber();
+ assertEquals(1, version);
+
+ CommandStreamParser.RetrieverInfo info = parser.readFromRetriever();
+ assertEquals("123", info.getDocId().getUniqueId());
+ assertTrue(info.isUpToDate());
+ assertArrayEquals("2468".getBytes(), info.getContents());
+ Metadata metadata = info.getMetadata();
+ assertEquals(1, metadata.getKeys().size());
+ Set<String> projectNames = new HashSet<String>();
+ projectNames.add("plexi");
+ projectNames.add("klexa");
+ assertEquals(projectNames, metadata.getAllValues("project"));
}
@Test
@@ -216,7 +244,7 @@
@Test
public void testRepositoryUnavailable() throws IOException {
- String source = "GSA Adaptor Data Version 1 [\n]\nrepository-unavailable" ;
+ String source = "GSA Adaptor Data Version 1 [\n]\nrepository-unavailable";
InputStream inputStream = new ByteArrayInputStream(source.getBytes("UTF-8"));
CommandStreamParser parser = new CommandStreamParser(inputStream);
diff --git a/test/com/google/enterprise/adaptor/DocumentHandlerTest.java b/test/com/google/enterprise/adaptor/DocumentHandlerTest.java
index b2c3aea..63bad29 100644
--- a/test/com/google/enterprise/adaptor/DocumentHandlerTest.java
+++ b/test/com/google/enterprise/adaptor/DocumentHandlerTest.java
@@ -337,12 +337,12 @@
@Override
public void transform(ByteArrayOutputStream contentIn,
OutputStream contentOut,
- Map<String, String> metadata,
+ Metadata metadata,
Map<String, String> params) throws IOException {
assertArrayEquals(mockAdaptor.documentBytes, contentIn.toByteArray());
contentOut.write(golden);
- metadata.put(key, metadata.get(key).toUpperCase());
- metadata.put("docid", params.get("DocId"));
+ metadata.set(key, metadata.getOneValue(key).toUpperCase());
+ metadata.set("docid", params.get("DocId"));
}
});
TransformPipeline transform = new TransformPipeline(transforms);
@@ -350,7 +350,7 @@
@Override
public void getDocContent(Request request, Response response)
throws IOException {
- response.setMetadata(Collections.singletonMap(key, "testing value"));
+ response.addMetadata(key, "testing value");
super.getDocContent(request, response);
}
};
@@ -375,7 +375,7 @@
@Override
public void transform(ByteArrayOutputStream contentIn,
OutputStream contentOut,
- Map<String, String> metadata,
+ Metadata metadata,
Map<String, String> params) throws IOException {
// This is not the content we are looking for.
contentOut.write(new byte[] {2, 3, 4});
@@ -588,7 +588,7 @@
public void getDocContent(Request request, Response response)
throws IOException {
response.getOutputStream();
- response.setMetadata(Collections.<String, String>emptyMap());
+ response.addMetadata("not", "important");
}
};
DocumentHandler handler = createDefaultHandlerForAdaptor(adaptor);
@@ -704,7 +704,7 @@
return;
}
response.setContentType("text/plain");
- response.setMetadata(Collections.<String, String>emptyMap());
+ response.addMetadata("not", "important");
response.setAcl(Acl.EMPTY);
response.getOutputStream();
// It is free to get it multiple times
@@ -739,7 +739,7 @@
@Override
public void getDocContent(Request request, Response response)
throws IOException {
- response.setMetadata(Collections.singletonMap("test", "ing"));
+ response.addMetadata("test", "ing");
response.setAcl(new Acl.Builder()
.setInheritFrom(new DocId("testing")).build());
response.addAnchor(URI.create("http://test/"), null);
@@ -777,7 +777,7 @@
@Override
public void getDocContent(Request request, Response response)
throws IOException {
- response.setMetadata(Collections.singletonMap("test", "ing"));
+ response.addMetadata("test", "ing");
response.setAcl(new Acl.Builder()
.setInheritFrom(new DocId("testing")).build());
response.getOutputStream();
@@ -802,18 +802,17 @@
@Test
public void testFormMetadataHeader() {
- Map<String, String> metadata = new HashMap<String, String>();
- metadata.put("test", "ing");
- metadata.put("another", "item");
- metadata.put("equals=", "==");
+ Metadata metadata = new Metadata();
+ metadata.add("test", "ing");
+ metadata.add("another", "item");
+ metadata.add("equals=", "==");
String result = DocumentHandler.formMetadataHeader(metadata);
assertEquals("another=item,equals%3D=%3D%3D,test=ing", result);
}
@Test
public void testFormMetadataHeaderEmpty() {
- String header = DocumentHandler.formMetadataHeader(
- Collections.<String, String>emptyMap());
+ String header = DocumentHandler.formMetadataHeader(new Metadata());
assertEquals("", header);
}
diff --git a/test/com/google/enterprise/adaptor/GsaCommunicationHandlerTest.java b/test/com/google/enterprise/adaptor/GsaCommunicationHandlerTest.java
index 249c985..a10f1e3 100644
--- a/test/com/google/enterprise/adaptor/GsaCommunicationHandlerTest.java
+++ b/test/com/google/enterprise/adaptor/GsaCommunicationHandlerTest.java
@@ -312,7 +312,7 @@
@Override
public void transform(ByteArrayOutputStream contentIn,
OutputStream contentOut,
- Map<String, String> metadata,
+ Metadata metadata,
Map<String, String> params) throws IOException {
contentIn.writeTo(contentOut);
}
diff --git a/test/com/google/enterprise/adaptor/MetadataTest.java b/test/com/google/enterprise/adaptor/MetadataTest.java
new file mode 100644
index 0000000..d882058
--- /dev/null
+++ b/test/com/google/enterprise/adaptor/MetadataTest.java
@@ -0,0 +1,419 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.enterprise.adaptor;
+
+import static java.util.AbstractMap.SimpleEntry;
+import static java.util.Map.Entry;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.junit.rules.ExpectedException;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.HashSet;
+import java.util.Set;
+
+/** Test cases for {@link Metadata}. */
+public class MetadataTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testInitiallyEmpty() {
+ Metadata m = new Metadata();
+ assertTrue(m.isEmpty());
+ assertTrue(m.getKeys().isEmpty());
+ assertFalse(m.iterator().hasNext());
+ }
+
+ @Test
+ public void testDupConstructor() {
+ Metadata m1 = new Metadata();
+ m1.add("foo", "home");
+ m1.add("bar", "far");
+ Metadata m2 = new Metadata(m1);
+ assertEquals(m1, m2);
+ m1.set("shoes", makeSet("bing", "bongo"));
+ m2 = new Metadata(m1);
+ assertEquals(m1, m2);
+ // New values.
+ m1.set("shoes", makeSet("bongo", "bing"));
+ assertEquals(m1, m2);
+ }
+
+ @Test
+ public void testSingleSetAndGet() {
+ Metadata m = new Metadata();
+ assertEquals(null, m.getOneValue("foo"));
+ m.set("foo", "bar");
+ assertEquals("bar", m.getOneValue("foo"));
+ m.set("foo", "foo");
+ assertEquals("foo", m.getOneValue("foo"));
+ m.set("foo", "bar");
+ assertEquals("bar", m.getOneValue("foo"));
+ }
+
+ @Test
+ public void testSingleSetNullValue() {
+ Metadata m = new Metadata();
+ thrown.expect(NullPointerException.class);
+ m.set("foo", (String) null);
+ }
+
+ @Test
+ public void testSingleSetNullKey() {
+ Metadata m = new Metadata();
+ thrown.expect(NullPointerException.class);
+ m.set(null, "bar");
+ }
+
+ @Test
+ public void testSingleSetEffectOnKeys() {
+ Metadata m = new Metadata();
+ assertEquals(0, m.getKeys().size());
+ m.set("foo", "bar");
+ assertEquals(1, m.getKeys().size());
+ m.set("foo", "bar");
+ assertEquals(1, m.getKeys().size());
+ m.set("bar", "foo");
+ assertEquals(2, m.getKeys().size());
+ }
+
+ private static Set<String> makeSet(String ... s) {
+ return new HashSet<String>(Arrays.asList(s));
+ }
+
+ @Test
+ public void testMultipleSetAndGet() {
+ Metadata m = new Metadata();
+ assertEquals(null, m.getOneValue("foo"));
+ m.set("foo", makeSet("bar", "home"));
+ assertTrue(makeSet("bar", "home").contains(m.getOneValue("foo")));
+ assertEquals(makeSet("bar", "home"), m.getAllValues("foo"));
+ assertEquals(makeSet("home", "bar"), m.getAllValues("foo"));
+ m.set("foo", makeSet("foo"));
+ assertEquals("foo", m.getOneValue("foo"));
+ assertEquals(makeSet("foo"), m.getAllValues("foo"));
+ m.set("foo", makeSet("barf", "floor"));
+ assertTrue(makeSet("barf", "floor").contains(m.getOneValue("foo")));
+ assertEquals(makeSet("barf", "floor"), m.getAllValues("foo"));
+ }
+
+ @Test
+ public void testMultipleGetNoKey() {
+ Metadata m = new Metadata();
+ assertEquals(makeSet(), m.getAllValues("foo"));
+ }
+
+ @Test
+ public void testMultipleSetEmptySetRemoves() {
+ Metadata m = new Metadata();
+ m.set("foo", makeSet("bar", "home"));
+ assertFalse(m.isEmpty());
+ m.set("foo", makeSet());
+ assertTrue(m.isEmpty());
+ }
+
+ @Test
+ public void testMultipleSetNullValue() {
+ Metadata m = new Metadata();
+ assertTrue(m.isEmpty());
+ Set<String> nullSet = null;
+ thrown.expect(NullPointerException.class);
+ m.set("foo", nullSet);
+ }
+
+ @Test
+ public void testMultipleSetEmptySet() {
+ Metadata m = new Metadata();
+ assertTrue(m.isEmpty());
+ Set<String> emptySet = makeSet();
+ m.set("foo", emptySet);
+ assertTrue(m.isEmpty());
+ m.set("bar", makeSet("bar"));
+ assertEquals(1, m.getKeys().size());
+ m.set("foo", emptySet);
+ assertEquals(1, m.getKeys().size());
+ m.set("bar", emptySet);
+ assertTrue(m.isEmpty());
+ }
+
+ @Test
+ public void testSetEntriesIterable() {
+ HashSet<Entry<String, String>> e1 = new HashSet<Entry<String, String>>();
+ HashSet<Entry<String, String>> e2 = new HashSet<Entry<String, String>>();
+ e1.add(new SimpleEntry<String, String>("a", "b"));
+ e1.add(new SimpleEntry<String, String>("b", "q"));
+ e2.add(new SimpleEntry<String, String>("a", "b"));
+ e2.add(new SimpleEntry<String, String>("b", "q"));
+ Metadata m1 = new Metadata();
+ m1.set(e1);
+ Metadata m2 = new Metadata();
+ m2.set(e2);
+ assertEquals(m1, m2);
+ }
+
+ @Test
+ public void testSetEntriesNull() {
+ Metadata m = new Metadata();
+ thrown.expect(NullPointerException.class);
+ m.set(null);
+ }
+
+ @Test
+ public void testSetMetadata() {
+ Metadata m1 = new Metadata();
+ Metadata m2 = new Metadata();
+ m1.set("foo", makeSet("home", "floor"));
+ m2.set(m1);
+ assertEquals(m1, m2);
+ m1.set("foo", makeSet("home", "floor"));
+ assertEquals(m1, m2);
+ Set<String> vals = new HashSet<String>();
+ vals.add("pigeon");
+ vals.add("eagle");
+ m1.set("foo", vals);
+ m2.set(m1);
+ assertTrue(m1.equals(m2));
+ // Should not change m2.
+ m1.add("foo", "bird");
+ assertFalse(m1.equals(m2));
+ }
+
+ @Test
+ public void testReturningUnmodifiableSetsA() {
+ Metadata m = new Metadata();
+ m.set("foo", makeSet("bar", "home", "villa"));
+ Set<String> all = m.getAllValues("foo");
+ thrown.expect(UnsupportedOperationException.class);
+ all.add("newnew");
+ }
+
+ @Test
+ public void testReturningUnmodifiableSetsB() {
+ Metadata m = new Metadata();
+ m.set("foo", makeSet("bar", "home", "villa"));
+ Set<String> all = m.getAllValues("foo");
+ thrown.expect(UnsupportedOperationException.class);
+ all.remove("bar");
+ }
+
+ @Test
+ public void testEasyToWriteModificationLoopOverValues() {
+ Metadata m = new Metadata();
+ m.set("foo", makeSet("bar", "home", "villa"));
+ // End setup.
+ // Loop should be idiomatic to write.
+ Set<String> dest = new HashSet<String>();
+ for (String v : m.getAllValues("foo")) {
+ dest.add(v.toUpperCase());
+ }
+ m.set("foo", dest);
+ // Double check function.
+ assertEquals(makeSet("BAR", "HOME", "VILLA"), m.getAllValues("foo"));
+ }
+
+ @Test
+ public void testReturningRemovalKeys() {
+ Metadata m = new Metadata();
+ m.set("foo", makeSet("bar", "home"));
+ m.set("sna", makeSet("fu"));
+ Set<String> keys = m.getKeys();
+ assertEquals(2, keys.size());
+ keys.remove("sna");
+ assertEquals(1, keys.size());
+ assertEquals(1, m.getKeys().size());
+ assertEquals(keys, m.getKeys());
+ }
+
+ @Test
+ public void testIteratingOverImmutableEntries() {
+ Metadata m = new Metadata();
+ m.set("foo", makeSet("bar", "home"));
+ thrown.expect(UnsupportedOperationException.class);
+ m.iterator().next().setValue("HOME");
+ }
+
+ private static Entry<String, String> ne(String k, String v) {
+ return new SimpleEntry<String, String>(k, v);
+ }
+
+ @Test
+ public void testEntriesGivenSorted() {
+ Metadata m = new Metadata();
+ m.set("foo", makeSet("home", "bar"));
+ m.set("early", makeSet("bird"));
+ m.set("cleary", makeSet("obfuscated"));
+ m.set("dearly", makeSet("beloved"));
+ m.set("badly", makeSet("traversed", "implied"));
+ Iterator<Entry<String, String>> it = m.iterator();
+ assertEquals(ne("badly", "implied"), it.next());
+ assertEquals(ne("badly", "traversed"), it.next());
+ assertEquals(ne("cleary", "obfuscated"), it.next());
+ assertEquals(ne("dearly", "beloved"), it.next());
+ assertEquals(ne("early", "bird"), it.next());
+ assertEquals(ne("foo", "bar"), it.next());
+ assertEquals(ne("foo", "home"), it.next());
+ assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void testEmptyIterator() {
+ Metadata m = new Metadata();
+ assertFalse(m.iterator().hasNext());
+ }
+
+ @Test
+ public void testNormalAdd() {
+ Metadata m = new Metadata();
+ m.add("foo", "home");
+ assertEquals("home", m.getOneValue("foo"));
+ m.add("foo", "bar");
+ assertTrue(makeSet("bar", "home").contains(m.getOneValue("foo")));
+ assertEquals(makeSet("home", "bar"), m.getAllValues("foo"));
+ assertEquals(1, m.getKeys().size());
+ m.add("foo", "few");
+ assertEquals(1, m.getKeys().size());
+ m.add("bar", "mor");
+ assertEquals(makeSet("mor"), m.getAllValues("bar"));
+ m.add("bar", "far");
+ assertEquals(2, m.getKeys().size());
+ assertEquals(makeSet("far", "mor"), m.getAllValues("bar"));
+ m.add("bar", "far");
+ assertEquals(makeSet("far", "mor"), m.getAllValues("bar"));
+ m.add("bar", "mor");
+ assertEquals(makeSet("far", "mor"), m.getAllValues("bar"));
+ }
+
+ @Test
+ public void testNullAddA() {
+ Metadata m = new Metadata();
+ thrown.expect(NullPointerException.class);
+ m.add("foo", null);
+ }
+
+ @Test
+ public void testNullAddB() {
+ Metadata m = new Metadata();
+ m.add("foo", "bar");
+ thrown.expect(NullPointerException.class);
+ m.add("foo", null);
+ }
+
+ @Test
+ public void testNullKeysNotAllowedInAdd() {
+ Metadata m = new Metadata();
+ thrown.expect(NullPointerException.class);
+ m.add(null, "can-no-add");
+ }
+
+ @Test
+ public void testEquals() {
+ Metadata m1 = new Metadata();
+ m1.add("foo", "home");
+ Metadata m2 = new Metadata();
+ m2.add("foo", "home");
+ assertEquals(m1, m2);
+
+ m1.add("foo", "bar");
+ m2.add("foo", "bar");
+ assertEquals(m1, m2);
+
+ m1.set("foo", "high");
+ m2.set("foo", "low");
+ assertFalse(m1.equals(m2));
+
+ m2.set("foo", "high");
+ assertEquals(m1, m2);
+
+ m1.set("bar", makeSet("floor", "door"));
+ m2.set("bar", makeSet("floor", "door"));
+ assertEquals(m1, m2);
+
+ m1.set("bar", makeSet("near", "far"));
+ assertFalse(m1.equals(m2));
+ m2.set("bar", makeSet("near", "far"));
+ assertEquals(m1, m2);
+ }
+
+ @Test
+ public void testUnmodifiableSetSingle() {
+ Metadata m = new Metadata().unmodifiableView();
+ thrown.expect(UnsupportedOperationException.class);
+ m.set("foo", "bar");
+ }
+
+ @Test
+ public void testUnmodifiableSetMultiple() {
+ Metadata m = new Metadata().unmodifiableView();
+ thrown.expect(UnsupportedOperationException.class);
+ m.set("foo", makeSet("bar", "home"));
+ }
+
+ @Test
+ public void testUnmodifiableAdd() {
+ Metadata m = new Metadata().unmodifiableView();
+ thrown.expect(UnsupportedOperationException.class);
+ m.add("foo", "bar");
+ }
+
+ @Test
+ public void testUnmodifiableSetIterable() {
+ Metadata m = new Metadata().unmodifiableView();
+ thrown.expect(UnsupportedOperationException.class);
+ m.set(new Metadata());
+ }
+ @Test
+ public void testUnmodifiableSetSingleB() {
+ Metadata m = new Metadata().unmodifiableView();
+ thrown.expect(UnsupportedOperationException.class);
+ m.set("foo", (String) null);
+ }
+
+ @Test
+ public void testUnmodifiableSetMultipleB() {
+ Metadata m = new Metadata().unmodifiableView();
+ thrown.expect(UnsupportedOperationException.class);
+ m.set("foo", (Set<String>) null);
+ }
+
+ @Test
+ public void testUnmodifiableAddB() {
+ Metadata m = new Metadata().unmodifiableView();
+ thrown.expect(UnsupportedOperationException.class);
+ m.add("foo", null);
+ }
+
+ @Test
+ public void testUnmodifiableSetIterableB() {
+ Metadata m = new Metadata().unmodifiableView();
+ thrown.expect(UnsupportedOperationException.class);
+ m.set(null);
+ }
+
+ @Test
+ public void testUnmodifiableDoesNotAllowKeyRemoval() {
+ Metadata m = new Metadata();
+ m.set("foo", makeSet("bar", "home"));
+ m.set("sna", makeSet("fu"));
+ m = m.unmodifiableView();
+ Set<String> keys = m.getKeys();
+ assertEquals(2, keys.size());
+ thrown.expect(UnsupportedOperationException.class);
+ keys.remove("sna");
+ }
+}
diff --git a/test/com/google/enterprise/adaptor/TransformPipelineTest.java b/test/com/google/enterprise/adaptor/TransformPipelineTest.java
index 0d66e15..c60b293 100644
--- a/test/com/google/enterprise/adaptor/TransformPipelineTest.java
+++ b/test/com/google/enterprise/adaptor/TransformPipelineTest.java
@@ -35,12 +35,12 @@
public void testNoOpEmpty() throws IOException, TransformException {
TransformPipeline pipeline = new TransformPipeline(Collections.<DocumentTransform>emptyList());
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
+ Metadata metadata = new Metadata();
Map<String, String> params = new HashMap<String, String>();
pipeline.transform(new byte[0], contentOut, metadata, params);
assertEquals(0, contentOut.size());
- assertEquals(Collections.emptyMap(), metadata);
+ assertEquals(new Metadata(), metadata);
assertEquals(Collections.emptyMap(), params);
}
@@ -48,216 +48,58 @@
public void testNoOpWithInput() throws IOException, TransformException {
TransformPipeline pipeline = new TransformPipeline(Collections.<DocumentTransform>emptyList());
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
- metadata.put("key1", "value1");
+ Metadata metadata = new Metadata();
+ metadata.add("key1", "value1");
Map<String, String> params = new HashMap<String, String>();
params.put("key2", "value2");
String testString = "Here is some input";
pipeline.transform(testString.getBytes(), contentOut, metadata, params);
assertEquals(testString, contentOut.toString());
- assertEquals(Collections.singletonMap("key1", "value1"), metadata);
+ Metadata goldenMetadata = new Metadata();
+ goldenMetadata.add("key1", "value1");
+ assertEquals(goldenMetadata, metadata);
assertEquals(Collections.singletonMap("key2", "value2"), params);
}
@Test
public void testAddMetadataAndParams() throws IOException, TransformException {
- Map<String, String> metadata = new HashMap<String, String>();
- metadata.put("key1", "value1");
+ Metadata metadata = new Metadata();
+ metadata.add("key1", "value1");
Map<String, String> params = new HashMap<String, String>();
params.put("key2", "value2");
List<DocumentTransform> transforms = new ArrayList<DocumentTransform>();
transforms.add(new AbstractDocumentTransform() {
@Override
- public void transform(ByteArrayOutputStream cIn, OutputStream cOut, Map<String, String> m,
+ public void transform(ByteArrayOutputStream cIn, OutputStream cOut, Metadata m,
Map<String, String> p) throws TransformException, IOException {
- m.put("newMeta", "metaValue");
+ m.set("newMeta", "metaValue");
p.put("newKey", "newValue");
}
});
TransformPipeline pipeline = new TransformPipeline(transforms);
pipeline.transform(new byte[0], new ByteArrayOutputStream(), metadata, params);
- assertEquals("value1", metadata.get("key1"));
- assertEquals("metaValue", metadata.get("newMeta"));
- assertEquals(2, metadata.size());
+ assertEquals("value1", metadata.getOneValue("key1"));
+ assertEquals("metaValue", metadata.getOneValue("newMeta"));
+ assertEquals(2, metadata.getKeys().size());
assertEquals("value2", params.get("key2"));
assertEquals("newValue", params.get("newKey"));
assertEquals(2, params.size());
}
- @Test
- public void testTransform() throws IOException, TransformException {
- TransformPipeline pipeline = new TransformPipeline(Arrays.asList(new IncrementTransform()));
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
- metadata.put("int", "0");
- Map<String, String> params = new HashMap<String, String>();
- params.put("int", "1");
-
- pipeline.transform(new byte[] {1, 2, 3}, out, metadata, params);
-
- assertArrayEquals(new byte[] {2, 3, 4}, out.toByteArray());
- assertEquals(Collections.singletonMap("int", "1"), metadata);
- assertEquals(Collections.singletonMap("int", "2"), params);
- }
-
- @Test
- public void testMultipleTransforms() throws IOException, TransformException {
- TransformPipeline pipeline = new TransformPipeline(Arrays.asList(
- new IncrementTransform(), new ProductTransform(2)));
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
- metadata.put("int", "0");
- Map<String, String> params = new HashMap<String, String>();
- params.put("int", "1");
-
- pipeline.transform(new byte[] {1, 2, 3}, out, metadata, params);
-
- assertArrayEquals(new byte[] {4, 6, 8}, out.toByteArray());
- assertEquals(Collections.singletonMap("int", "2"), metadata);
- assertEquals(Collections.singletonMap("int", "4"), params);
- }
-
- @Test
- public void testNotLastTransformError() throws IOException, TransformException {
- TransformPipeline pipeline = new TransformPipeline(Arrays.asList(
- new IncrementTransform(), new ErroringTransform(false)));
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
- metadata.put("int", "0");
- Map<String, String> params = new HashMap<String, String>();
- params.put("int", "1");
-
- pipeline.transform(new byte[] {1, 2, 3}, out, metadata, params);
-
- assertArrayEquals(new byte[] {2, 3, 4}, out.toByteArray());
- assertEquals(Collections.singletonMap("int", "1"), metadata);
- assertEquals(Collections.singletonMap("int", "2"), params);
- }
-
- @Test
- public void testLastTransformError() throws IOException, TransformException {
- TransformPipeline pipeline = new TransformPipeline(Arrays.asList(
- new ErroringTransform(false), new IncrementTransform()));
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
- metadata.put("int", "0");
- Map<String, String> params = new HashMap<String, String>();
- params.put("int", "1");
-
- pipeline.transform(new byte[] {1, 2, 3}, out, metadata, params);
-
- assertArrayEquals(new byte[] {2, 3, 4}, out.toByteArray());
- assertEquals(Collections.singletonMap("int", "1"), metadata);
- assertEquals(Collections.singletonMap("int", "2"), params);
- }
-
- @Test
- public void testTransformErrorFatal() throws IOException, TransformException {
- TransformPipeline pipeline = new TransformPipeline(Arrays.asList(
- new IncrementTransform(), new ErroringTransform(true)));
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
- metadata.put("int", "0");
- Map<String, String> params = new HashMap<String, String>();
- params.put("int", "1");
-
- thrown.expect(TransformException.class);
- try {
- pipeline.transform(new byte[] {1, 2, 3}, out, metadata, params);
- } finally {
- assertArrayEquals(new byte[] {}, out.toByteArray());
- assertEquals(Collections.singletonMap("int", "0"), metadata);
- assertEquals(Collections.singletonMap("int", "1"), params);
- }
- }
-
- @Test
- public void testResetTransform() throws Exception {
- List<DocumentTransform> transforms = new ArrayList<DocumentTransform>();
- transforms.add(new AbstractDocumentTransform() {
- @Override
- public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
- Map<String, String> metadata, Map<String, String> p)
- throws IOException {
- // Modifying contentIn is not allowed.
- contentIn.reset();
- }
- });
- TransformPipeline pipeline = new TransformPipeline(transforms);
- thrown.expect(UnsupportedOperationException.class);
- pipeline.transform(new byte[] {1, 2, 3}, new ByteArrayOutputStream(),
- new HashMap<String, String>(), new HashMap<String, String>());
- }
-
- @Test
- public void testWriteTransform1() throws Exception {
- List<DocumentTransform> transforms = new ArrayList<DocumentTransform>();
- transforms.add(new AbstractDocumentTransform() {
- @Override
- public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
- Map<String, String> metadata, Map<String, String> p)
- throws IOException {
- // Modifying contentIn is not allowed.
- contentIn.write(new byte[1], 0, 1);
- }
- });
- TransformPipeline pipeline = new TransformPipeline(transforms);
- thrown.expect(UnsupportedOperationException.class);
- pipeline.transform(new byte[] {1, 2, 3}, new ByteArrayOutputStream(),
- new HashMap<String, String>(), new HashMap<String, String>());
- }
-
- @Test
- public void testWriteTransform2() throws Exception {
- List<DocumentTransform> transforms = new ArrayList<DocumentTransform>();
- transforms.add(new AbstractDocumentTransform() {
- @Override
- public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
- Map<String, String> metadata, Map<String, String> p)
- throws IOException {
- // Modifying contentIn is not allowed.
- contentIn.write(0);
- }
- });
- TransformPipeline pipeline = new TransformPipeline(transforms);
- thrown.expect(UnsupportedOperationException.class);
- pipeline.transform(new byte[] {1, 2, 3}, new ByteArrayOutputStream(),
- new HashMap<String, String>(), new HashMap<String, String>());
- }
-
- @Test
- public void testWriteTransform3() throws Exception {
- List<DocumentTransform> transforms = new ArrayList<DocumentTransform>();
- transforms.add(new AbstractDocumentTransform() {
- @Override
- public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
- Map<String, String> metadata, Map<String, String> p)
- throws IOException {
- // Modifying contentIn is not allowed.
- contentIn.write(new byte[1]);
- }
- });
- TransformPipeline pipeline = new TransformPipeline(transforms);
- thrown.expect(UnsupportedOperationException.class);
- pipeline.transform(new byte[] {1, 2, 3}, new ByteArrayOutputStream(),
- new HashMap<String, String>(), new HashMap<String, String>());
- }
-
private static class IncrementTransform extends AbstractDocumentTransform {
@Override
public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
- Map<String, String> metadata, Map<String, String> p)
+ Metadata metadata, Map<String, String> p)
throws TransformException, IOException {
byte[] content = contentIn.toByteArray();
for (int i = 0; i < content.length; i++) {
content[i]++;
}
contentOut.write(content);
- metadata.put("int", "" + (Integer.parseInt(metadata.get("int")) + 1));
+ metadata.set("int", "" + (Integer.parseInt(metadata.getOneValue("int")) + 1));
p.put("int", "" + (Integer.parseInt(p.get("int")) + 1));
}
}
@@ -271,14 +113,14 @@
@Override
public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
- Map<String, String> metadata, Map<String, String> p)
+ Metadata metadata, Map<String, String> p)
throws TransformException, IOException {
byte[] content = contentIn.toByteArray();
for (int i = 0; i < content.length; i++) {
content[i] *= factor;
}
contentOut.write(content);
- metadata.put("int", "" + (Integer.parseInt(metadata.get("int")) * factor));
+ metadata.set("int", "" + (Integer.parseInt(metadata.getOneValue("int")) * factor));
p.put("int", "" + (Integer.parseInt(p.get("int")) * factor));
}
}
@@ -287,16 +129,185 @@
public ErroringTransform(boolean required) {
super(null, required);
}
-
@Override
public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
- Map<String, String> metadata, Map<String, String> p)
+ Metadata metadata, Map<String, String> p)
throws TransformException, IOException {
// Do some work, but don't complete.
contentOut.write(new byte[] {1});
- metadata.put("trash", "value");
+ metadata.set("trash", "value");
p.put("more trash", "values");
throw new TransformException("test exception");
}
}
+
+ @Test
+ public void testTransform() throws IOException, TransformException {
+ TransformPipeline pipeline = new TransformPipeline(Arrays.asList(new IncrementTransform()));
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Metadata metadata = new Metadata();
+ metadata.add("int", "0");
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("int", "1");
+
+ pipeline.transform(new byte[] {1, 2, 3}, out, metadata, params);
+
+ assertArrayEquals(new byte[] {2, 3, 4}, out.toByteArray());
+ Metadata goldenMetadata = new Metadata();
+ goldenMetadata.add("int", "1");
+ assertEquals(goldenMetadata, metadata);
+ assertEquals(Collections.singletonMap("int", "2"), params);
+ }
+
+ @Test
+ public void testMultipleTransforms() throws IOException, TransformException {
+ TransformPipeline pipeline = new TransformPipeline(Arrays.asList(
+ new IncrementTransform(), new ProductTransform(2)));
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Metadata metadata = new Metadata();
+ metadata.set("int", "0");
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("int", "1");
+
+ pipeline.transform(new byte[] {1, 2, 3}, out, metadata, params);
+
+ assertArrayEquals(new byte[] {4, 6, 8}, out.toByteArray());
+ Metadata goldenMetadata = new Metadata();
+ goldenMetadata.set("int", "2");
+ assertEquals(goldenMetadata, metadata);
+ assertEquals(Collections.singletonMap("int", "4"), params);
+ }
+
+ @Test
+ public void testNotLastTransformError() throws IOException, TransformException {
+ TransformPipeline pipeline = new TransformPipeline(Arrays.asList(
+ new IncrementTransform(), new ErroringTransform(false)));
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Metadata metadata = new Metadata();
+ metadata.set("int", "0");
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("int", "1");
+
+ pipeline.transform(new byte[] {1, 2, 3}, out, metadata, params);
+
+ assertArrayEquals(new byte[] {2, 3, 4}, out.toByteArray());
+ Metadata goldenMetadata = new Metadata();
+ goldenMetadata.add("int", "1");
+ assertEquals(goldenMetadata, metadata);
+ assertEquals(Collections.singletonMap("int", "2"), params);
+ }
+
+ @Test
+ public void testLastTransformError() throws IOException, TransformException {
+ TransformPipeline pipeline = new TransformPipeline(Arrays.asList(
+ new ErroringTransform(false), new IncrementTransform()));
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Metadata metadata = new Metadata();
+ metadata.set("int", "0");
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("int", "1");
+
+ pipeline.transform(new byte[] {1, 2, 3}, out, metadata, params);
+
+ assertArrayEquals(new byte[] {2, 3, 4}, out.toByteArray());
+ Metadata goldenMetadata = new Metadata();
+ goldenMetadata.set("int", "1");
+ assertEquals(goldenMetadata, metadata);
+ assertEquals(Collections.singletonMap("int", "2"), params);
+ }
+
+ @Test
+ public void testTransformErrorFatal() throws IOException, TransformException {
+ TransformPipeline pipeline = new TransformPipeline(Arrays.asList(
+ new IncrementTransform(), new ErroringTransform(true)));
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Metadata metadata = new Metadata();
+ metadata.set("int", "0");
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("int", "1");
+
+ thrown.expect(TransformException.class);
+ try {
+ pipeline.transform(new byte[] {1, 2, 3}, out, metadata, params);
+ } finally {
+ assertArrayEquals(new byte[] {}, out.toByteArray());
+ Metadata goldenMetadata = new Metadata();
+ goldenMetadata.set("int", "0");
+ assertEquals(goldenMetadata, metadata);
+ assertEquals(Collections.singletonMap("int", "1"), params);
+ }
+ }
+
+ @Test
+ public void testResetTransform() throws Exception {
+ List<DocumentTransform> transforms = new ArrayList<DocumentTransform>();
+ transforms.add(new AbstractDocumentTransform() {
+ @Override
+ public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
+ Metadata metadata, Map<String, String> p)
+ throws IOException {
+ // Modifying contentIn is not allowed.
+ contentIn.reset();
+ }
+ });
+ TransformPipeline pipeline = new TransformPipeline(transforms);
+ thrown.expect(UnsupportedOperationException.class);
+ pipeline.transform(new byte[] {1, 2, 3}, new ByteArrayOutputStream(),
+ new Metadata(), new HashMap<String, String>());
+ }
+
+ @Test
+ public void testWriteTransform1() throws Exception {
+ List<DocumentTransform> transforms = new ArrayList<DocumentTransform>();
+ transforms.add(new AbstractDocumentTransform() {
+ @Override
+ public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
+ Metadata metadata, Map<String, String> p)
+ throws IOException {
+ // Modifying contentIn is not allowed.
+ contentIn.write(new byte[1], 0, 1);
+ }
+ });
+ TransformPipeline pipeline = new TransformPipeline(transforms);
+ thrown.expect(UnsupportedOperationException.class);
+ pipeline.transform(new byte[] {1, 2, 3}, new ByteArrayOutputStream(),
+ new Metadata(), new HashMap<String, String>());
+ }
+
+ @Test
+ public void testWriteTransform2() throws Exception {
+ List<DocumentTransform> transforms = new ArrayList<DocumentTransform>();
+ transforms.add(new AbstractDocumentTransform() {
+ @Override
+ public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
+ Metadata metadata, Map<String, String> p)
+ throws IOException {
+ // Modifying contentIn is not allowed.
+ contentIn.write(0);
+ }
+ });
+ TransformPipeline pipeline = new TransformPipeline(transforms);
+ thrown.expect(UnsupportedOperationException.class);
+ pipeline.transform(new byte[] {1, 2, 3}, new ByteArrayOutputStream(),
+ new Metadata(), new HashMap<String, String>());
+ }
+
+ @Test
+ public void testWriteTransform3() throws Exception {
+ List<DocumentTransform> transforms = new ArrayList<DocumentTransform>();
+ transforms.add(new AbstractDocumentTransform() {
+ @Override
+ public void transform(ByteArrayOutputStream contentIn, OutputStream contentOut,
+ Metadata metadata, Map<String, String> p)
+ throws IOException {
+ // Modifying contentIn is not allowed.
+ contentIn.write(new byte[1]);
+ }
+ });
+ TransformPipeline pipeline = new TransformPipeline(transforms);
+ thrown.expect(UnsupportedOperationException.class);
+ pipeline.transform(new byte[] {1, 2, 3}, new ByteArrayOutputStream(),
+ new Metadata(), new HashMap<String, String>());
+ }
}
diff --git a/test/com/google/enterprise/adaptor/examples/CalaisNERTransformTest.java b/test/com/google/enterprise/adaptor/examples/CalaisNERTransformTest.java
index 1079de7..aa76a4e 100644
--- a/test/com/google/enterprise/adaptor/examples/CalaisNERTransformTest.java
+++ b/test/com/google/enterprise/adaptor/examples/CalaisNERTransformTest.java
@@ -16,6 +16,7 @@
import static org.junit.Assert.*;
+import com.google.enterprise.adaptor.Metadata;
import com.google.enterprise.adaptor.TransformException;
import mx.bigdata.jcalais.CalaisClient;
@@ -134,7 +135,7 @@
CalaisNERTransform transform = new CalaisNERTransform(new Factory());
ByteArrayOutputStream contentIn = new ByteArrayOutputStream();
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
+ Metadata metadata = new Metadata();
Map<String, String> params = new HashMap<String, String>();
params.put("OpenCalaisApiKey", "4ydv87zawg7tf29jzex22d9u");
params.put("UseCalaisEntity:Person", "True");
@@ -167,7 +168,7 @@
CalaisNERTransform transform = new CalaisNERTransform(new Factory());
ByteArrayOutputStream contentIn = new ByteArrayOutputStream();
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
+ Metadata metadata = new Metadata();
Map<String, String> params = new HashMap<String, String>();
params.put("OpenCalaisApiKey", "4ydv87zawg7tf29jzex22d9u");
params.put("UseCalaisEntity:All", "True");
diff --git a/test/com/google/enterprise/adaptor/examples/MetaTaggerTransformTest.java b/test/com/google/enterprise/adaptor/examples/MetaTaggerTransformTest.java
index 267a924..886af4b 100644
--- a/test/com/google/enterprise/adaptor/examples/MetaTaggerTransformTest.java
+++ b/test/com/google/enterprise/adaptor/examples/MetaTaggerTransformTest.java
@@ -16,6 +16,7 @@
import static org.junit.Assert.*;
+import com.google.enterprise.adaptor.Metadata;
import com.google.enterprise.adaptor.TransformException;
import org.junit.Test;
@@ -36,7 +37,7 @@
MetaTaggerTransform transform = new MetaTaggerTransform();
ByteArrayOutputStream contentIn = new ByteArrayOutputStream();
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
+ Metadata metadata = new Metadata();
Map<String, String> params = new HashMap<String, String>();
params.put("key1", "value1");
@@ -46,7 +47,7 @@
assertEquals(testString, contentIn.toString());
assertEquals(testString, contentOut.toString());
- assertEquals(0, metadata.size());
+ assertTrue(metadata.isEmpty());
assertEquals("value1", params.get("key1"));
assertEquals(1, params.keySet().size());
}
@@ -56,7 +57,7 @@
MetaTaggerTransform transform = new MetaTaggerTransform();
ByteArrayOutputStream contentIn = new ByteArrayOutputStream();
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
+ Metadata metadata = new Metadata();
Map<String, String> params = new HashMap<String, String>();
params.put("key1", "value1");
@@ -66,7 +67,7 @@
assertEquals(testString, contentIn.toString());
assertEquals(testString, contentOut.toString());
- assertEquals(0, metadata.size());
+ assertTrue(metadata.isEmpty());
assertEquals("value1", params.get("key1"));
assertEquals(1, params.keySet().size());
}
@@ -76,7 +77,7 @@
MetaTaggerTransform transform = new MetaTaggerTransform(TEST_DIR + "testPattern1.txt");
ByteArrayOutputStream contentIn = new ByteArrayOutputStream();
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
+ Metadata metadata = new Metadata();
Map<String, String> params = new HashMap<String, String>();
params.put("key1", "value1");
String content =
@@ -100,7 +101,7 @@
transform.transform(contentIn, contentOut, metadata, params);
assertEquals(goldenContent, contentOut.toString());
- assertEquals(0, metadata.size());
+ assertTrue(metadata.isEmpty());
assertEquals("value1", params.get("key1"));
assertEquals(1, params.keySet().size());
}
@@ -110,7 +111,7 @@
MetaTaggerTransform transform = new MetaTaggerTransform(TEST_DIR + "testPattern1.txt");
ByteArrayOutputStream contentIn = new ByteArrayOutputStream();
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
+ Metadata metadata = new Metadata();
Map<String, String> params = new HashMap<String, String>();
params.put("key1", "value1");
String content =
@@ -122,7 +123,7 @@
transform.transform(contentIn, contentOut, metadata, params);
assertEquals(content, contentOut.toString());
- assertEquals(0, metadata.size());
+ assertTrue(metadata.isEmpty());
assertEquals("value1", params.get("key1"));
assertEquals(1, params.keySet().size());
}
@@ -132,7 +133,7 @@
MetaTaggerTransform transform = new MetaTaggerTransform(TEST_DIR + "testPatternDup.txt");
ByteArrayOutputStream contentIn = new ByteArrayOutputStream();
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
+ Metadata metadata = new Metadata();
Map<String, String> params = new HashMap<String, String>();
params.put("key1", "value1");
@@ -157,7 +158,7 @@
transform.transform(contentIn, contentOut, metadata, params);
assertEquals(goldenContent, contentOut.toString());
- assertEquals(0, metadata.size());
+ assertTrue(metadata.isEmpty());
assertEquals("value1", params.get("key1"));
assertEquals(1, params.keySet().size());
}
diff --git a/test/com/google/enterprise/adaptor/examples/TableGeneratorTransformTest.java b/test/com/google/enterprise/adaptor/examples/TableGeneratorTransformTest.java
index 5ea1b4b..47d5077 100644
--- a/test/com/google/enterprise/adaptor/examples/TableGeneratorTransformTest.java
+++ b/test/com/google/enterprise/adaptor/examples/TableGeneratorTransformTest.java
@@ -16,6 +16,7 @@
import static org.junit.Assert.*;
+import com.google.enterprise.adaptor.Metadata;
import com.google.enterprise.adaptor.TransformException;
import org.junit.Test;
@@ -34,14 +35,14 @@
TableGeneratorTransform transform = new TableGeneratorTransform();
ByteArrayOutputStream contentIn = new ByteArrayOutputStream();
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
+ Metadata metadata = new Metadata();
Map<String, String> params = new HashMap<String, String>();
params.put("key1", "value1");
transform.transform(contentIn, contentOut, metadata, params);
String actualOutput = contentOut.toString();
assertEquals("<HTML><HEAD></HEAD><BODY></BODY></HTML>", actualOutput);
- assertEquals(0, metadata.size());
+ assertTrue(metadata.isEmpty());
assertEquals("value1", params.get("key1"));
assertEquals(1, params.keySet().size());
}
@@ -51,7 +52,7 @@
TableGeneratorTransform transform = new TableGeneratorTransform();
ByteArrayOutputStream contentIn = new ByteArrayOutputStream();
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
- Map<String, String> metadata = new HashMap<String, String>();
+ Metadata metadata = new Metadata();
Map<String, String> params = new HashMap<String, String>();
params.put("key1", "value1");
@@ -80,7 +81,7 @@
transform.transform(contentIn, contentOut, metadata, params);
assertEquals(goldenOutput, contentOut.toString());
- assertEquals(0, metadata.size());
+ assertTrue(metadata.isEmpty());
assertEquals("value1", params.get("key1"));
assertEquals(1, params.keySet().size());
}
diff --git a/test/com/google/enterprise/adaptor/prebuilt/CommandLineAdaptorTest.java b/test/com/google/enterprise/adaptor/prebuilt/CommandLineAdaptorTest.java
index 676cc50..66afb2b 100644
--- a/test/com/google/enterprise/adaptor/prebuilt/CommandLineAdaptorTest.java
+++ b/test/com/google/enterprise/adaptor/prebuilt/CommandLineAdaptorTest.java
@@ -14,17 +14,21 @@
package com.google.enterprise.adaptor.prebuilt;
+import static com.google.enterprise.adaptor.TestHelper.getDocIds;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import static java.util.Map.Entry;
+
import com.google.enterprise.adaptor.Acl;
import com.google.enterprise.adaptor.Adaptor;
import com.google.enterprise.adaptor.AuthnIdentity;
import com.google.enterprise.adaptor.AuthzStatus;
import com.google.enterprise.adaptor.DocId;
+import com.google.enterprise.adaptor.Metadata;
import com.google.enterprise.adaptor.Request;
import com.google.enterprise.adaptor.Response;
-import static com.google.enterprise.adaptor.TestHelper.getDocIds;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
import org.junit.Test;
@@ -83,7 +87,7 @@
private static final Map<String, String> ID_TO_MIME_TYPE;
private static final Map<String, Date> ID_TO_LAST_MODIFIED;
private static final Map<String, Date> ID_TO_LAST_CRAWLED;
- private static final Map<String, Map<String, String>> ID_TO_METADATA;
+ private static final Map<String, Metadata> ID_TO_METADATA;
static {
Map<String, String> idToContent = new HashMap<String, String>();
@@ -109,21 +113,22 @@
idToLastCrawled.put("1003", new Date(5000));
ID_TO_LAST_CRAWLED = Collections.unmodifiableMap(idToLastCrawled);
- Map<String, String> id1002Metadata = new HashMap<String, String>();
- id1002Metadata.put("metaname-1002a", "metavalue-1002a");
- id1002Metadata.put("metaname-1002b", "metavalue-1002b");
+ Metadata id1002Metadata = new Metadata();
+ id1002Metadata.add("metaname-1002a", "metavalue-1002a");
+ id1002Metadata.add("metaname-1002b", "metavalue-1002b");
+ Metadata id1003Metadata = new Metadata();
+ id1003Metadata.add("metaname-1003", "metavalue-1003");
- Map<String, Map<String, String>> idToMetadata
- = new HashMap<String, Map<String, String>>();
- idToMetadata.put("1002", id1002Metadata);
- idToMetadata.put("1003",
- Collections.singletonMap("metaname-1003", "metavalue-1003"));
+ Map<String, Metadata> idToMetadata = new HashMap<String, Metadata>();
+ idToMetadata.put("1002", id1002Metadata.unmodifiableView());
+ idToMetadata.put("1003", id1003Metadata.unmodifiableView());
+
ID_TO_METADATA = Collections.unmodifiableMap(idToMetadata);
}
private String docId;
private String content;
- private Map<String, String> metadata;
+ private Metadata metadata;
private Date lastModified;
private Date lastCrawled;
private String mimeType;
@@ -155,7 +160,7 @@
result.append("mime-type=").append(mimeType).append("\n");
}
if (metadata != null) {
- for (Map.Entry<String, String> item : metadata.entrySet()) {
+ for (Map.Entry<String, String> item : metadata) {
result.append("meta-name=").append(item.getKey()).append("\n");
result.append("meta-value=").append(item.getValue()).append("\n");
}
@@ -259,7 +264,7 @@
private static class ContentsResponseTestMock implements Response {
private OutputStream os;
private String contentType;
- private Map<String, String> metadata;
+ private Metadata metadata = new Metadata();
private Acl acl;
private List<URI> anchorUris = new ArrayList<URI>();
private List<String> anchorTexts = new ArrayList<String>();
@@ -295,9 +300,8 @@
}
@Override
- public void setMetadata(Map<String, String> m) {
- this.metadata
- = Collections.unmodifiableMap(new HashMap<String, String>(m));
+ public void addMetadata(String key, String value) {
+ this.metadata.add(key, value);
}
@Override
@@ -330,8 +334,9 @@
return contentType;
}
- public Map<String, String> getMetadata() {
- return metadata;
+ /** Returns unmodifibale view of metadata. */
+ Metadata getMetadata() {
+ return metadata.unmodifiableView();
}
public Acl getAcl() {
diff --git a/test/com/google/enterprise/adaptor/prebuilt/CommandLineTransformTest.java b/test/com/google/enterprise/adaptor/prebuilt/CommandLineTransformTest.java
index b5f0370..443e3bb 100644
--- a/test/com/google/enterprise/adaptor/prebuilt/CommandLineTransformTest.java
+++ b/test/com/google/enterprise/adaptor/prebuilt/CommandLineTransformTest.java
@@ -16,6 +16,7 @@
import static org.junit.Assert.*;
+import com.google.enterprise.adaptor.Metadata;
import com.google.enterprise.adaptor.TestHelper;
import com.google.enterprise.adaptor.TransformException;
import com.google.enterprise.adaptor.TransformPipeline;
@@ -37,8 +38,8 @@
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
// The newline causes the test to work with both BSD and GNU sed.
String testStr = "testing\n";
- Map<String, String> metadata = new HashMap<String, String>();
- metadata.put("metaKey1", "metaValue1");
+ Metadata metadata = new Metadata();
+ metadata.add("metaKey1", "metaValue1");
Map<String, String> params = new HashMap<String, String>();
params.put("key1", "value1");
@@ -46,11 +47,11 @@
cmd.setTransformCommand(Arrays.asList(new String[] {"sed", "s/i/1/"}));
cmd.setCommandAcceptsParameters(false);
TransformPipeline pipeline = new TransformPipeline(Arrays.asList(cmd));
- pipeline.transform(testStr.getBytes(), contentOut, new HashMap<String, String>(), params);
+ pipeline.transform(testStr.getBytes(), contentOut, metadata, params);
assertEquals(testStr.replace("i", "1"), contentOut.toString());
- assertEquals("metaValue1", metadata.get("metaKey1"));
- assertEquals(1, metadata.size());
+ assertEquals("metaValue1", metadata.getOneValue("metaKey1"));
+ assertEquals(1, metadata.getKeys().size());
assertEquals("value1", params.get("key1"));
assertEquals(1, params.keySet().size());
}
@@ -62,8 +63,8 @@
ByteArrayOutputStream contentOut = new ByteArrayOutputStream();
// The newline causes the test to work with both BSD and GNU sed.
String testStr = "testing\n";
- Map<String, String> metadata = new HashMap<String, String>();
- metadata.put("metaKey1", "metaValue1");
+ Metadata metadata = new Metadata();
+ metadata.add("metaKey1", "metaValue1");
Map<String, String> params = new HashMap<String, String>();
params.put("key1", "value1");
@@ -83,8 +84,8 @@
pipeline.transform(testStr.getBytes(), contentOut, metadata, params);
assertEquals(testStr.replace("i", "1"), contentOut.toString());
- assertEquals("metaValue2", metadata.get("metaKey2"));
- assertEquals(1, metadata.size());
+ assertEquals(1, metadata.getKeys().size());
+ assertEquals("metaValue2", metadata.getOneValue("metaKey2"));
assertEquals("value3", params.get("key3"));
assertEquals(1, params.size());
}