org.efaps.admin.index.Indexer.java Source code

Java tutorial

Introduction

Here is the source code for org.efaps.admin.index.Indexer.java

Source

/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * 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 org.efaps.admin.index;

import java.io.IOException;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.facet.FacetField;
import org.apache.lucene.facet.taxonomy.TaxonomyWriter;
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.efaps.admin.datamodel.Attribute;
import org.efaps.admin.datamodel.attributetype.CreatedType;
import org.efaps.admin.dbproperty.DBProperties;
import org.efaps.admin.index.IndexDefinition.IndexField;
import org.efaps.admin.program.esjp.EFapsClassLoader;
import org.efaps.admin.user.Company;
import org.efaps.db.Context;
import org.efaps.db.Instance;
import org.efaps.db.InstanceQuery;
import org.efaps.db.MultiPrintQuery;
import org.efaps.db.QueryBuilder;
import org.efaps.util.EFapsException;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The Class Indexer.
 *
 * @author The eFaps Team
 */
public final class Indexer {

    /**
     * The Enum Key.
     */
    public enum Key {

        /** The oid. */
        OID,

        /** The all. */
        ALL,

        /** The msgphrase. */
        MSGPHRASE,

        /** The created numeric field used for sorting. */
        CREATED,

        /** The created string field used for searching. */
        CREATEDSTR;
    }

    /**
     * The Enum Dim.
     */
    public enum Dimension {

        /** The type. */
        DIMTYPE,

        /** The created. */
        DIMCREATED;
    }

    /**
     * Logging instance used in this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(Indexer.class);

    /**
     * Instantiates a new indexer.
     */
    private Indexer() {
    }

    /**
     * Index or reindex using the Indexdefinitions.
     *
     * @throws EFapsException the e faps exception
     */
    public static void index() throws EFapsException {
        final List<IndexDefinition> defs = IndexDefinition.get();
        for (final IndexDefinition def : defs) {
            final QueryBuilder queryBldr = new QueryBuilder(def.getUUID());
            final InstanceQuery query = queryBldr.getQuery();
            index(query.execute());
        }
    }

    /**
     * Index or reindex a given list of instances. The given instances m,ust be
     * all of the same type!
     *
     * @param _instances the _instances
     * @throws EFapsException the e faps exception
     */
    public static void index(final List<Instance> _instances) throws EFapsException {
        Indexer.index(new IndexContext().setAnalyzer(Index.getAnalyzer()).setDirectory(Index.getDirectory())
                .setLanguage(Context.getThreadContext().getLanguage())
                .setCompanyId(Context.getThreadContext().getCompany().getId()), _instances);
    }

    /**
     * Index or reindex a given list of instances. The given instances m,ust be
     * all of the same type!
     *
     * @param _context the _context
     * @param _instances the instances
     * @throws EFapsException the e faps exception
     */
    public static void index(final IndexContext _context, final List<Instance> _instances) throws EFapsException {
        if (CollectionUtils.isNotEmpty(_instances)) {
            final Company currentCompany = Context.getThreadContext().getCompany();
            final String currentLanguage = Context.getThreadContext().getLanguage();

            Context.getThreadContext().setCompany(Company.get(_context.getCompanyId()));
            Context.getThreadContext().setLanguage(_context.getLanguage());
            final IndexWriterConfig config = new IndexWriterConfig(_context.getAnalyzer());
            try (IndexWriter writer = new IndexWriter(_context.getDirectory(), config);
                    TaxonomyWriter taxonomyWriter = new DirectoryTaxonomyWriter(_context.getTaxonomyDirectory());) {

                final IndexDefinition def = IndexDefinition.get(_instances.get(0).getType().getUUID());
                final MultiPrintQuery multi = new MultiPrintQuery(_instances);
                for (final IndexField field : def.getFields()) {
                    multi.addSelect(field.getSelect());
                }
                Attribute createdAttr = null;
                if (!_instances.get(0).getType().getAttributes(CreatedType.class).isEmpty()) {
                    createdAttr = _instances.get(0).getType().getAttributes(CreatedType.class).iterator().next();
                    multi.addAttribute(createdAttr);
                }
                multi.addMsgPhrase(def.getMsgPhrase());
                multi.executeWithoutAccessCheck();
                while (multi.next()) {
                    final String oid = multi.getCurrentInstance().getOid();
                    final String type = multi.getCurrentInstance().getType().getLabel();
                    final DateTime created;
                    if (createdAttr == null) {
                        created = new DateTime();
                    } else {
                        created = multi.getAttribute(createdAttr);
                    }

                    final Document doc = new Document();
                    doc.add(new FacetField(Dimension.DIMTYPE.name(), type));
                    doc.add(new FacetField(Dimension.DIMCREATED.name(), String.valueOf(created.getYear()),
                            String.format("%02d", created.getMonthOfYear())));
                    doc.add(new StringField(Key.OID.name(), oid, Store.YES));
                    doc.add(new TextField(DBProperties.getProperty("index.Type"), type, Store.YES));
                    doc.add(new NumericDocValuesField(Key.CREATED.name(), created.getMillis()));
                    doc.add(new StringField(Key.CREATEDSTR.name(),
                            DateTools.dateToString(created.toDate(), DateTools.Resolution.DAY), Store.NO));

                    final StringBuilder allBldr = new StringBuilder().append(type).append(" ");

                    for (final IndexField field : def.getFields()) {
                        final String name = DBProperties.getProperty(field.getKey());
                        Object value = multi.getSelect(field.getSelect());
                        if (value != null) {
                            if (StringUtils.isNoneEmpty(field.getTransform())) {
                                final Class<?> clazz = Class.forName(field.getTransform(), false,
                                        EFapsClassLoader.getInstance());
                                final ITransformer transformer = (ITransformer) clazz.newInstance();
                                value = transformer.transform(value);
                            }
                            switch (field.getFieldType()) {
                            case LONG:
                                long val = 0;
                                if (value instanceof String) {
                                    val = NumberUtils.toLong((String) value);
                                } else if (value instanceof Number) {
                                    val = ((Number) value).longValue();
                                }
                                doc.add(new LongField(name, val, Store.YES));
                                allBldr.append(value).append(" ");
                                break;
                            case SEARCHLONG:
                                long val2 = 0;
                                if (value instanceof String) {
                                    val2 = NumberUtils.toLong((String) value);
                                } else if (value instanceof Number) {
                                    val2 = ((Number) value).longValue();
                                }
                                doc.add(new LongField(name, val2, Store.NO));
                                allBldr.append(value).append(" ");
                                break;
                            case STRING:
                                doc.add(new StringField(name, String.valueOf(value), Store.YES));
                                allBldr.append(value).append(" ");
                                break;
                            case SEARCHSTRING:
                                doc.add(new StringField(name, String.valueOf(value), Store.NO));
                                allBldr.append(value).append(" ");
                                break;
                            case TEXT:
                                doc.add(new TextField(name, String.valueOf(value), Store.YES));
                                allBldr.append(value).append(" ");
                                break;
                            case SEARCHTEXT:
                                doc.add(new TextField(name, String.valueOf(value), Store.NO));
                                allBldr.append(value).append(" ");
                                break;
                            case STORED:
                                doc.add(new StoredField(name, String.valueOf(value)));
                                allBldr.append(value).append(" ");
                                break;
                            default:
                                break;
                            }
                        }
                    }
                    doc.add(new StoredField(Key.MSGPHRASE.name(), multi.getMsgPhrase(def.getMsgPhrase())));
                    doc.add(new TextField(Key.ALL.name(), allBldr.toString(), Store.NO));
                    writer.updateDocument(new Term(Key.OID.name(), oid),
                            Index.getFacetsConfig().build(taxonomyWriter, doc));
                    LOG.debug("Add Document: {}", doc);
                }
                writer.close();
                taxonomyWriter.close();
            } catch (final IOException | ClassNotFoundException | InstantiationException
                    | IllegalAccessException e) {
                throw new EFapsException(Indexer.class, "IOException", e);
            } finally {
                Context.getThreadContext().setCompany(currentCompany);
                Context.getThreadContext().setLanguage(currentLanguage);
            }
        }
    }
}