View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  
22  
23  package org.opencastproject.elasticsearch.impl;
24  
25  import static org.opencastproject.elasticsearch.impl.IndexSchema.FUZZY_FIELDNAME_EXTENSION;
26  
27  import org.opencastproject.elasticsearch.api.Language;
28  import org.opencastproject.elasticsearch.api.SearchMetadata;
29  
30  import java.text.MessageFormat;
31  import java.util.ArrayList;
32  import java.util.Collection;
33  import java.util.HashMap;
34  import java.util.List;
35  
36  /**
37   * Document that encapsulates business objects and offers support for adding those objects to a search index.
38   */
39  public final class ElasticsearchDocument extends HashMap<String, Object> {
40  
41    /** Serial version uid */
42    private static final long serialVersionUID = 2687550418831284487L;
43  
44    /** The document identifier */
45    private String id = null;
46  
47    /** The document type */
48    private String type = null;
49  
50    /**
51     * Creates a new elastic search document based on the id, the document type and the metadata.
52     * <p>
53     * Note that the type needs to map to an Elasticsearch document type mapping.
54     *
55     * @param id
56     *          the resource identifier.
57     * @param type
58     *          the document type
59     * @param resource
60     *          the resource metadata
61     */
62    public ElasticsearchDocument(String id, String type, List<SearchMetadata<?>> resource) {
63      this.id = id;
64      this.type = type;
65      for (SearchMetadata<?> entry : resource) {
66        String metadataKey = entry.getName();
67        put(metadataKey, entry.getValues());
68  
69        // TODO Not sure what to use for localizedFulltextFieldName
70        if (entry.addToText()) {
71          addToFulltext(entry, IndexSchema.TEXT, IndexSchema.TEXT);
72        }
73      }
74    }
75  
76    /**
77     * Returns the document type.
78     *
79     * @return the type
80     */
81    public String getType() {
82      return type;
83    }
84  
85    /**
86     * Adds the resource metadata to the designated fulltext fields.
87     *
88     * @param item
89     *          the metadata item
90     * @param fulltextFieldName
91     *          the fulltext field name
92     * @param localizedFulltextFieldName
93     *          the localized fulltext field name
94     */
95    @SuppressWarnings("unchecked")
96    private void addToFulltext(SearchMetadata<?> item, String fulltextFieldName, String localizedFulltextFieldName) {
97  
98      // Get existing fulltext entries
99      Collection<String> fulltext = (Collection<String>) get(fulltextFieldName);
100     if (fulltext == null) {
101       fulltext = new ArrayList<String>();
102       put(fulltextFieldName, fulltext);
103       put(fulltextFieldName + FUZZY_FIELDNAME_EXTENSION, fulltext);
104     }
105 
106     // Language neutral elements
107     for (Object value : item.getValues()) {
108       if (value.getClass().isArray()) {
109         Object[] fieldValues = (Object[]) value;
110         for (Object v : fieldValues) {
111           fulltext.add(v.toString());
112         }
113       } else {
114         fulltext.add(value.toString());
115       }
116     }
117 
118     // Add localized metadata values
119     for (Language language : item.getLocalizedValues().keySet()) {
120       // Get existing fulltext entries
121       String localizedFieldName = MessageFormat.format(localizedFulltextFieldName, language.getIdentifier());
122       Collection<String> localizedFulltext = (Collection<String>) get(localizedFieldName);
123       if (fulltext == null) {
124         fulltext = new ArrayList<String>();
125         put(localizedFieldName, fulltext);
126       }
127       Collection<?> values = item.getLocalizedValues().get(language);
128       for (Object value : values) {
129         if (value.getClass().isArray()) {
130           Object[] fieldValues = (Object[]) value;
131           for (Object v : fieldValues) {
132             localizedFulltext.add(v.toString());
133           }
134         } else {
135           localizedFulltext.add(value.toString());
136         }
137       }
138     }
139 
140   }
141 
142   /**
143    * Returns the identifier.
144    *
145    * @return the identifier
146    */
147   public String getUID() {
148     return id;
149   }
150 
151 }