Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.solr.common; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.solr.common.util.NamedList; /** * A concrete representation of a document within a Solr index. Unlike a lucene * Document, a SolrDocument may have an Object value matching the type defined in * schema.xml * * For indexing documents, use the SolrInputDocument that contains extra information * for document and field boosting. * * * @since solr 1.3 */ public class SolrDocument extends SolrDocumentBase<Object, SolrDocument> implements Iterable<Map.Entry<String, Object>> { protected final Map<String, Object> _fields; private List<SolrDocument> _childDocuments; public SolrDocument() { _fields = new LinkedHashMap<>(); } @Override public void writeMap(EntryWriter ew) throws IOException { _fields.forEach(ew.getBiConsumer()); } public SolrDocument(Map<String, Object> fields) { this._fields = fields; } /** * @return a list of field names defined in this document - this Collection is directly backed by this SolrDocument. * @see #keySet */ @Override public Collection<String> getFieldNames() { return this.keySet(); } /////////////////////////////////////////////////////////////////// // Add / Set / Remove Fields /////////////////////////////////////////////////////////////////// /** * Remove all fields from the document */ @Override public void clear() { _fields.clear(); if (_childDocuments != null) { _childDocuments.clear(); } } /** * Remove all fields with the name */ public boolean removeFields(String name) { return this.remove(name) != null; } /** * Set a field with the given object. If the object is an Array, it will * set multiple fields with the included contents. This will replace any existing * field with the given name */ @SuppressWarnings("unchecked") public void setField(String name, Object value) { if (value instanceof Object[]) { value = new ArrayList(Arrays.asList((Object[]) value)); } else if (value instanceof Collection) { // nothing } else if (value instanceof NamedList) { // nothing } else if (value instanceof Iterable && !(value instanceof SolrDocumentBase)) { ArrayList<Object> lst = new ArrayList<>(); for (Object o : (Iterable) value) { lst.add(o); } value = lst; } _fields.put(name, value); } /** * This will add a field to the document. If fields already exist with this * name it will append value to the collection. If the value is Collection, * each value will be added independently. * * The class type of value and the name parameter should match schema.xml. * schema.xml can be found in conf directory under the solr home by default. * * @param name Name of the field, should match one of the field names defined under "fields" tag in schema.xml. * @param value Value of the field, should be of same class type as defined by "type" attribute of the corresponding field in schema.xml. */ @SuppressWarnings("unchecked") @Override public void addField(String name, Object value) { Object existing = _fields.get(name); if (existing == null) { if (value instanceof Collection) { Collection<Object> c = new ArrayList<>(3); for (Object o : (Collection<Object>) value) { c.add(o); } this.setField(name, c); } else { this.setField(name, value); } return; } Collection<Object> vals = null; if (existing instanceof Collection) { vals = (Collection<Object>) existing; } else { vals = new ArrayList<>(3); vals.add(existing); } // Add the values to the collection if (value instanceof Iterable && !(value instanceof SolrDocumentBase)) { for (Object o : (Iterable<Object>) value) { vals.add(o); } } else if (value instanceof Object[]) { for (Object o : (Object[]) value) { vals.add(o); } } else { vals.add(value); } _fields.put(name, vals); } /////////////////////////////////////////////////////////////////// // Get the field values /////////////////////////////////////////////////////////////////// /** * returns the first value for a field */ public Object getFirstValue(String name) { Object v = _fields.get(name); if (v == null || !(v instanceof Collection)) return v; Collection c = (Collection) v; if (c.size() > 0) { return c.iterator().next(); } return null; } /** * Get the value or collection of values for a given field. */ @Override public Object getFieldValue(String name) { return _fields.get(name); } /** * Get a collection of values for a given field name */ @SuppressWarnings("unchecked") @Override public Collection<Object> getFieldValues(String name) { Object v = _fields.get(name); if (v instanceof Collection) { return (Collection<Object>) v; } if (v != null) { ArrayList<Object> arr = new ArrayList<>(1); arr.add(v); return arr; } return null; } @Override public String toString() { return "SolrDocument" + _fields; } /** * Iterate of String->Object keys */ @Override public Iterator<Entry<String, Object>> iterator() { return _fields.entrySet().iterator(); } //----------------------------------------------------------------------------------------- // JSTL Helpers //----------------------------------------------------------------------------------------- /** * Expose a Map interface to the solr field value collection. */ public Map<String, Collection<Object>> getFieldValuesMap() { return new Map<String, Collection<Object>>() { /** Get the field Value */ @Override public Collection<Object> get(Object key) { return getFieldValues((String) key); } // Easily Supported methods @Override public boolean containsKey(Object key) { return _fields.containsKey(key); } @Override public Set<String> keySet() { return _fields.keySet(); } @Override public int size() { return _fields.size(); } @Override public boolean isEmpty() { return _fields.isEmpty(); } // Unsupported operations. These are not necessary for JSTL @Override public void clear() { throw new UnsupportedOperationException(); } @Override public boolean containsValue(Object value) { throw new UnsupportedOperationException(); } @Override public Set<java.util.Map.Entry<String, Collection<Object>>> entrySet() { throw new UnsupportedOperationException(); } @Override public void putAll(Map<? extends String, ? extends Collection<Object>> t) { throw new UnsupportedOperationException(); } @Override public Collection<Collection<Object>> values() { throw new UnsupportedOperationException(); } @Override public Collection<Object> put(String key, Collection<Object> value) { throw new UnsupportedOperationException(); } @Override public Collection<Object> remove(Object key) { throw new UnsupportedOperationException(); } @Override public String toString() { return _fields.toString(); } }; } /** * Expose a Map interface to the solr fields. This function is useful for JSTL */ public Map<String, Object> getFieldValueMap() { return new Map<String, Object>() { /** Get the field Value */ @Override public Object get(Object key) { return getFirstValue((String) key); } // Easily Supported methods @Override public boolean containsKey(Object key) { return _fields.containsKey(key); } @Override public Set<String> keySet() { return _fields.keySet(); } @Override public int size() { return _fields.size(); } @Override public boolean isEmpty() { return _fields.isEmpty(); } // Unsupported operations. These are not necessary for JSTL @Override public void clear() { throw new UnsupportedOperationException(); } @Override public boolean containsValue(Object value) { throw new UnsupportedOperationException(); } @Override public Set<java.util.Map.Entry<String, Object>> entrySet() { throw new UnsupportedOperationException(); } @Override public void putAll(Map<? extends String, ? extends Object> t) { throw new UnsupportedOperationException(); } @Override public Collection<Object> values() { throw new UnsupportedOperationException(); } @Override public Collection<Object> put(String key, Object value) { throw new UnsupportedOperationException(); } @Override public Collection<Object> remove(Object key) { throw new UnsupportedOperationException(); } @Override public String toString() { return _fields.toString(); } }; } //--------------------------------------------------- // MAP interface //--------------------------------------------------- @Override public boolean containsKey(Object key) { return _fields.containsKey(key); } @Override public boolean containsValue(Object value) { return _fields.containsValue(value); } @Override public Set<Entry<String, Object>> entrySet() { return _fields.entrySet(); } //TODO: Shouldn't the input parameter here be a String? The _fields map requires a String. @Override public Object get(Object key) { return _fields.get(key); } @Override public boolean isEmpty() { return _fields.isEmpty(); } @Override public Set<String> keySet() { return _fields.keySet(); } @Override public Object put(String key, Object value) { return _fields.put(key, value); } @Override public void putAll(Map<? extends String, ? extends Object> t) { _fields.putAll(t); } @Override public Object remove(Object key) { return _fields.remove(key); } @Override public int size() { return _fields.size(); } @Override public Collection<Object> values() { return _fields.values(); } @Override public void addChildDocument(SolrDocument child) { if (_childDocuments == null) { _childDocuments = new ArrayList<>(); } _childDocuments.add(child); } @Override public void addChildDocuments(Collection<SolrDocument> children) { for (SolrDocument child : children) { addChildDocument(child); } } @Override public List<SolrDocument> getChildDocuments() { return _childDocuments; } @Override public boolean hasChildDocuments() { boolean isEmpty = (_childDocuments == null || _childDocuments.isEmpty()); return !isEmpty; } @Override public int getChildDocumentCount() { if (_childDocuments == null) return 0; return _childDocuments.size(); } }