ElasticsearchDocument.java

/*
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 *
 * The Apereo Foundation licenses this file to you under the Educational
 * Community 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://opensource.org/licenses/ecl2.txt
 *
 * 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.opencastproject.elasticsearch.impl;

import org.opencastproject.elasticsearch.api.Language;
import org.opencastproject.elasticsearch.api.SearchMetadata;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

/**
 * Document that encapsulates business objects and offers support for adding those objects to a search index.
 */
public final class ElasticsearchDocument extends HashMap<String, Object> {

  /** Serial version uid */
  private static final long serialVersionUID = 2687550418831284487L;

  /** The document identifier */
  private String id = null;

  /** The document type */
  private String type = null;

  /**
   * Creates a new elastic search document based on the id, the document type and the metadata.
   * <p>
   * Note that the type needs to map to an Elasticsearch document type mapping.
   *
   * @param id
   *          the resource identifier.
   * @param type
   *          the document type
   * @param resource
   *          the resource metadata
   */
  public ElasticsearchDocument(String id, String type, List<SearchMetadata<?>> resource) {
    this.id = id;
    this.type = type;
    for (SearchMetadata<?> entry : resource) {
      String metadataKey = entry.getName();
      put(metadataKey, entry.getValues());

      // TODO Not sure what to use for localizedFulltextFieldName
      if (entry.addToText()) {
        addToFulltext(entry, IndexSchema.TEXT, IndexSchema.TEXT);
      }
    }
  }

  /**
   * Returns the document type.
   *
   * @return the type
   */
  public String getType() {
    return type;
  }

  /**
   * Adds the resource metadata to the designated fulltext fields.
   *
   * @param item
   *          the metadata item
   * @param fulltextFieldName
   *          the fulltext field name
   * @param localizedFulltextFieldName
   *          the localized fulltext field name
   */
  @SuppressWarnings("unchecked")
  private void addToFulltext(SearchMetadata<?> item, String fulltextFieldName, String localizedFulltextFieldName) {

    // Get existing fulltext entries
    Collection<String> fulltext = (Collection<String>) get(fulltextFieldName);
    if (fulltext == null) {
      fulltext = new ArrayList<String>();
      put(fulltextFieldName, fulltext);
    }

    // Language neutral elements
    for (Object value : item.getValues()) {
      if (value.getClass().isArray()) {
        Object[] fieldValues = (Object[]) value;
        for (Object v : fieldValues) {
          fulltext.add(v.toString());
        }
      } else {
        fulltext.add(value.toString());
      }
    }

    // Add localized metadata values
    for (Language language : item.getLocalizedValues().keySet()) {
      // Get existing fulltext entries
      String localizedFieldName = MessageFormat.format(localizedFulltextFieldName, language.getIdentifier());
      Collection<String> localizedFulltext = (Collection<String>) get(localizedFieldName);
      if (fulltext == null) {
        fulltext = new ArrayList<String>();
        put(localizedFieldName, fulltext);
      }
      Collection<?> values = item.getLocalizedValues().get(language);
      for (Object value : values) {
        if (value.getClass().isArray()) {
          Object[] fieldValues = (Object[]) value;
          for (Object v : fieldValues) {
            localizedFulltext.add(v.toString());
          }
        } else {
          localizedFulltext.add(value.toString());
        }
      }
    }

  }

  /**
   * Returns the identifier.
   *
   * @return the identifier
   */
  public String getUID() {
    return id;
  }

}