diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/documentBuilding/DocumentModifier.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/documentBuilding/DocumentModifier.java index 6806cff64..c6323b17d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/documentBuilding/DocumentModifier.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/documentBuilding/DocumentModifier.java @@ -6,7 +6,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchInputDocument; /** - * This interface represents an object that can add to a SearchInputDocument. + * An object that can add to a SearchInputDocument. */ public interface DocumentModifier { /** @@ -20,7 +20,9 @@ public interface DocumentModifier { */ public void modifyDocument(Individual individual, SearchInputDocument doc); - // called to inform the DocumentModifier that the system is shutting down + /** + * Called to inform the DocumentModifier that the system is shutting down. + */ public void shutdown(); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/documentBuilding/NameFields.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/documentBuilding/NameFields.java index 8728a86e2..964a16e4a 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/documentBuilding/NameFields.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/documentBuilding/NameFields.java @@ -18,7 +18,7 @@ import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory; import edu.cornell.mannlib.vitro.webapp.search.VitroSearchTermNames; /** - * Adds all labels to name fields, not just the one returned by Indivdiual.getName(). + * Adds all labels to name fields, not just the one returned by Individual.getName(). */ public class NameFields implements DocumentModifier { RDFServiceFactory rsf; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchengine/base/BaseSearchInputDocument.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchengine/base/BaseSearchInputDocument.java index a41054ff3..51bfb596d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchengine/base/BaseSearchInputDocument.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchengine/base/BaseSearchInputDocument.java @@ -14,8 +14,28 @@ import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchInputField; * A foundation class for implementing SearchInputDocument. */ public class BaseSearchInputDocument implements SearchInputDocument { - private final Map fieldMap = new HashMap<>(); - private float documentBoost = 1.0F; + private final Map fieldMap; + private float documentBoost; + + /** + * Default constructor. + */ + public BaseSearchInputDocument() { + this.fieldMap = new HashMap<>(); + this.documentBoost = 1.0F; + } + + /** + * Create a deep copy, down to the value objects. + */ + public BaseSearchInputDocument(BaseSearchInputDocument doc) { + this.documentBoost = doc.documentBoost; + this.fieldMap = new HashMap<>(); + for (String fieldName : doc.getFieldMap().keySet()) { + this.fieldMap.put(fieldName, + new BaseSearchInputField(doc.getField(fieldName))); + } + } @Override public void addField(SearchInputField field) { @@ -77,10 +97,33 @@ public class BaseSearchInputDocument implements SearchInputDocument { return new BaseSearchInputField(name); } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Float.floatToIntBits(documentBoost); + result = prime * result + fieldMap.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BaseSearchInputDocument other = (BaseSearchInputDocument) obj; + return (Float.floatToIntBits(documentBoost) == Float + .floatToIntBits(other.documentBoost)) + && fieldMap.equals(other.fieldMap); + } + @Override public String toString() { return "BaseSearchInputDocument[fieldMap=" + fieldMap + ", documentBoost=" + documentBoost + "]"; } - + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchengine/base/BaseSearchInputField.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchengine/base/BaseSearchInputField.java index b0ce82393..c83fa757c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchengine/base/BaseSearchInputField.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchengine/base/BaseSearchInputField.java @@ -14,12 +14,22 @@ import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchInputField; */ public class BaseSearchInputField implements SearchInputField { private final String name; - private final List valueList = new ArrayList<>(); - - private float boost = 1.0F; + private final List valueList; + private float boost; public BaseSearchInputField(String name) { this.name = name; + this.valueList = new ArrayList<>(); + this.boost = 1.0F; + } + + /** + * Create a copy of the field. + */ + public BaseSearchInputField(SearchInputField field) { + this.name = field.getName(); + this.valueList = new ArrayList<>(field.getValues()); + this.boost = field.getBoost(); } @Override @@ -61,10 +71,58 @@ public class BaseSearchInputField implements SearchInputField { } } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Float.floatToIntBits(boost); + result = prime * result + name.hashCode(); + result = prime * result + valueList.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BaseSearchInputField other = (BaseSearchInputField) obj; + return (Float.floatToIntBits(boost) == Float + .floatToIntBits(other.boost)) + && name.equals(other.name) + && equalsIgnoreOrder(valueList, other.valueList); + } + + /** + * Can't just compare the value lists, because they are considered to be + * equivalent even if the order is differemt. + * + * Can't just convert them to Sets, because either list may contain the same + * object multiple times. + * + * Remove the members of list1 from list2, one at a time. If any member is + * not found, the lists are not equivalent. + */ + private boolean equalsIgnoreOrder(List list1, List list2) { + if (list1.size() != list2.size()) { + return false; + } + List remaining = new ArrayList<>(list2); + for (Object value : list1) { + if (!remaining.remove(value)) { + return false; + } + } + return true; + } + @Override public String toString() { - return "BaseSearchInputField[name=" + name + ", valueList=" - + valueList + ", boost=" + boost + "]"; + return "BaseSearchInputField[name=" + name + ", valueList=" + valueList + + ", boost=" + boost + "]"; } } diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/searchengine/base/BaseSearchInputDocumentTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/searchengine/base/BaseSearchInputDocumentTest.java new file mode 100644 index 000000000..9ff844e9c --- /dev/null +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/searchengine/base/BaseSearchInputDocumentTest.java @@ -0,0 +1,56 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.searchengine.base; + +import static org.junit.Assert.*; + +import java.util.Collection; +import java.util.Map; + +import org.junit.Test; + +import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchInputField; + +/** + * TODO + */ +public class BaseSearchInputDocumentTest { + /** + * The copy constructor should make a deep copy, down to (but not including) + * the field values. The component parts should be equal, but not the same. + */ + @Test + public void copyConstructor() { + BaseSearchInputDocument doc = new BaseSearchInputDocument(); + doc.setDocumentBoost(42.6F); + + SearchInputField field1 = new BaseSearchInputField("testField"); + field1.addValues("value1", "value2"); + field1.setBoost(1.1F); + doc.addField(field1); + + SearchInputField field2 = new BaseSearchInputField("anotherField"); + field2.setBoost(-16F); + doc.addField(field2); + + BaseSearchInputDocument other = new BaseSearchInputDocument(doc); + assertEquals(doc, other); + assertEquals(doc.getDocumentBoost(), other.getDocumentBoost(), 0.01F); + + Map docMap = doc.getFieldMap(); + Map otherMap = other.getFieldMap(); + assertEquals(docMap, otherMap); + assertNotSame(docMap, otherMap); + + for (String fieldName : docMap.keySet()) { + SearchInputField docField = doc.getField(fieldName); + SearchInputField otherField = other.getField(fieldName); + assertEquals(docField, otherField); + assertNotSame(docField, otherField); + + Collection docFieldValues = docField.getValues(); + Collection otherFieldValues = otherField.getValues(); + assertEquals(docFieldValues, otherFieldValues); + } + } +}