/* * Copyright 2007 T-Rank AS * * 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 no.trank.openpipe.api.document; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @version $Revision$ */ public class Document { private static final Logger log = LoggerFactory.getLogger(Document.class); private final Map<String, ArrayList<AnnotatedField>> fieldMap = new LinkedHashMap<String, ArrayList<AnnotatedField>>(); private RawData rawData; private String operation; /** * Constructs a document without raw-data. Equivalent of <tt>new Document(null)</tt>. * * @see #Document(RawData) */ public Document() { this(null); } /** * Constructs a document with the given raw-data. * * @param rawData the raw-data of this document, can be <tt>null</tt>. * * @see #Document() */ public Document(RawData rawData) { this.rawData = rawData; } /** * Gets a set of all field-names of this document. * * @return an unmodifiable set of field-names. This method <i>never</i> returns <tt>null</tt>. */ public Set<String> getFieldNames() { return Collections.unmodifiableSet(fieldMap.keySet()); } /** * Gets the field-value, as a string, of a given field. <b>Note</b>: if wanted field has more than one value, only * the first value is returned, and a warning is logged. * * @param fieldName the name of the wanted field. * * @return the value of the field or <tt>null</tt>. */ public String getFieldValue(String fieldName) { final AnnotatedField field = getField(fieldName); return field == null ? null : field.getValue(); } /** * Gets the field-value, of a given field. <b>Note</b>: if wanted field has more than one value, only the first value * is returned, and a warning is logged. * * @param fieldName the name of the wanted field. * * @return the value of the field or <tt>null</tt>. */ public AnnotatedField getField(String fieldName) { final ArrayList<AnnotatedField> fieldList = fieldMap.get(fieldName); if (fieldList != null && !fieldList.isEmpty()) { if (fieldList.size() > 1) { log.warn("getField({}) called on multivalued field.", fieldName); } return fieldList.get(0); } return null; } /** * Gets the field-values, as strings, of a given field. * * @param fieldName the name of the wanted field. * * @return an unmodifiable list of strings. This method <i>never</i> returns <tt>null</tt>. */ public List<String> getFieldValues(String fieldName) { final List<AnnotatedField> fieldList = fieldMap.get(fieldName); if (fieldList != null) { final List<String> fieldValueList = new ArrayList<String>(fieldList.size()); for (AnnotatedField annotatedField : fieldList) { fieldValueList.add(annotatedField.getValue()); } return Collections.unmodifiableList(fieldValueList); } return Collections.emptyList(); } /** * Gets the field-values of a given field. * * @param fieldName the name of the wanted field. * * @return an unmodifiable list of field-values. This method <i>never</i> returns <tt>null</tt>. */ public List<AnnotatedField> getFields(String fieldName) { final List<AnnotatedField> fieldList = fieldMap.get(fieldName); if (fieldList != null) { return Collections.unmodifiableList(fieldList); } return Collections.emptyList(); } /** * Sets field-values to a given field. If either <tt>name</tt> or <tt>fields</tt> is <tt>null</tt> no change will * occur. * * @param name the name of the field. * @param fieldList the new values of the field. */ public void setField(String name, List<? extends AnnotatedField> fieldList) { if (notNull(name, fieldList)) { if (fieldList instanceof ArrayList) { @SuppressWarnings("unchecked") final ArrayList<AnnotatedField> list = (ArrayList<AnnotatedField>) fieldList; fieldMap.put(name, list); } else { fieldMap.put(name, new ArrayList<AnnotatedField>(fieldList)); } } } /** * Sets field-value to a given field. If either <tt>name</tt> or <tt>field</tt> is <tt>null</tt> no change will * occur. * * @param name the name of the field. * @param field the new value of the field. */ public void setField(String name, AnnotatedField field) { if (notNull(name, field)) { final ArrayList<AnnotatedField> list = new ArrayList<AnnotatedField>(); list.add(field); fieldMap.put(name, list); } } /** * Sets field-value to a given field. If either <tt>name</tt> or <tt>value</tt> is <tt>null</tt> no change will * occur. * * @param name the name of the field. * @param value the new value of the field. */ public void setFieldValue(String name, String value) { if (notNull(name, value)) { setField(name, new BaseAnnotatedField(value)); } } /** * Sets field-values to a given field. If either <tt>name</tt> or <tt>values</tt> is <tt>null</tt> no change will * occur. * * @param name the name of the field. * @param values the new values of the field. */ public void setFieldValues(String name, List<String> values) { if (notNull(name, values)) { final ArrayList<AnnotatedField> fieldList = new ArrayList<AnnotatedField>(); for (String value : values) { fieldList.add(new BaseAnnotatedField(value)); } fieldMap.put(name, fieldList); } } /** * Adds field-value to a given field. If either <tt>name</tt> or <tt>field</tt> is <tt>null</tt> no change will * occur. * * @param name the name of the field. * @param field the value to be added to the field. */ public void addField(String name, AnnotatedField field) { if (notNull(name, field)) { ArrayList<AnnotatedField> fieldList = fieldMap.get(name); if (fieldList == null) { fieldList = new ArrayList<AnnotatedField>(); fieldMap.put(name, fieldList); } fieldList.add(field); } } /** * Adds field-values to a given field. If either <tt>name</tt> or <tt>fields</tt> is <tt>null</tt> no change will * occur. * * @param name the name of the field. * @param fields the values to be added to the field. */ public void addField(String name, List<? extends AnnotatedField> fields) { if (notNull(name, fields)) { final List<AnnotatedField> fieldList = fieldMap.get(name); if (fieldList == null) { setField(name, fields); } else { fieldList.addAll(fields); } } } /** * Adds field-value to a given field. If either <tt>name</tt> or <tt>value</tt> is <tt>null</tt> no change will * occur. * * @param name the name of the field. * @param value the value to be added to the field. */ public void addFieldValue(String name, String value) { if (notNull(name, value)) { addField(name, new BaseAnnotatedField(value)); } } /** * Adds field-values to a given field. If either <tt>name</tt> or <tt>values</tt> is <tt>null</tt> no change will * occur. * * @param name the name of the field. * @param values the values to be added the field. */ public void addFieldValues(String name, List<String> values) { if (notNull(name, values)) { ArrayList<AnnotatedField> fieldList = fieldMap.get(name); if (fieldList == null) { fieldList = new ArrayList<AnnotatedField>(values.size()); } for (String value : values) { fieldList.add(new BaseAnnotatedField(value)); } } } /** * Removes a field from the document. * * @param name the field to remove. * * @return <tt>true</tt> if field with name <tt>name</tt> was removed. */ public boolean removeField(String name) { return fieldMap.remove(name) != null; } /** * Returns <tt>true</tt> if this document contains a field with name <tt>name</tt>. * * @param name the name of the field. * * @return <tt>true</tt> if this document contains a field with name <tt>name</tt>. */ public boolean containsField(String name) { return fieldMap.containsKey(name); } /** * Gets the raw-data of this document if any. * * @return the raw-data or <tt>null</tt>. */ public RawData getRawData() { return rawData; } /** * Sets the raw-data of this document. * * @param rawData the raw-data. */ public void setRawData(RawData rawData) { this.rawData = rawData; } /** * Gets the operation of this document if any. * * @return the operation or <tt>null</tt>. */ public String getOperation() { return operation; } /** * Sets the operation of this document. * * @param operation the new operation of this document. */ public void setOperation(String operation) { this.operation = operation; } /** * A sane (but somwhat heavy-weight) string representation of this object. * * @return a string representation of this object. */ @Override public String toString() { return "Document{" + "fieldMap=" + fieldMap + ", operation=" + operation + '}'; } private static boolean notNull(String name, Object value) { return name != null && value != null; } }