net.conquiris.lucene.document.BaseDocumentBuilder.java Source code

Java tutorial

Introduction

Here is the source code for net.conquiris.lucene.document.BaseDocumentBuilder.java

Source

/*
 * Copyright (C) the original author or authors.
 *
 * 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 net.conquiris.lucene.document;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import java.io.Reader;
import java.util.UUID;

import net.conquiris.schema.BinarySchemaItem;
import net.conquiris.schema.BooleanSchemaItem;
import net.conquiris.schema.DoubleSchemaItem;
import net.conquiris.schema.FloatSchemaItem;
import net.conquiris.schema.InstantSchemaItem;
import net.conquiris.schema.IntegerSchemaItem;
import net.conquiris.schema.LongSchemaItem;
import net.conquiris.schema.NumericSchemaItem;
import net.conquiris.schema.SchemaItem;
import net.conquiris.schema.StreamSchemaItem;
import net.conquiris.schema.TextSchemaItem;
import net.conquiris.schema.UUIDSchemaItem;
import net.derquinse.common.base.Builder;
import net.derquinse.common.base.ByteString;
import net.derquinse.common.reflect.This;

import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Fieldable;
import org.joda.time.ReadableInstant;

import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import com.google.common.collect.Multisets;

/**
 * Base class for document builders. Document builders can only be used once and are NOT THREAD
 * SAFE.
 * @author Andres Rodriguez
 */
public abstract class BaseDocumentBuilder<B extends BaseDocumentBuilder<B>> extends This<B>
        implements Builder<Document> {
    /** Document. */
    private Document document = new Document();
    /** Added fields. */
    private final Multiset<String> fields = HashMultiset.create();

    /**
     * Constructor.
     */
    protected BaseDocumentBuilder() {
    }

    /** Checks the document has not been built yet. */
    private void checkAvailable() {
        checkState(document != null, "Document already built");
    }

    /**
     * Completes the document before building.
     * @param fields A live but unmodifiable view of the fields added to the document.
     * @throws IllegalStateException if the document must not be built.
     */
    protected void complete(Multiset<String> fields) {
    }

    /**
     * Builds the document.
     * @throws IllegalStateException if the document can't be built or was already built.
     */
    @Override
    public final Document build() {
        checkAvailable();
        complete(Multisets.unmodifiableMultiset(fields));
        Document d = document;
        document = null;
        return d;
    }

    /**
     * Adds a fieldable to the document.
     * @param fieldable Fieldable to add.
     * @return This builder.
     * @throws IllegalStateException if the document was already built.
     */
    public final B add(Fieldable fieldable) {
        checkAvailable();
        checkNotNull(fieldable, "The fieldable to add must be provided");
        fields.add(fieldable.name());
        document.add(fieldable);
        return thisValue();
    }

    /**
     * Adds several fieldables to the document.
     * @param fieldables Fieldables to add.
     * @return This builder.
     * @throws IllegalStateException if the document was already built.
     */
    public final B add(Iterable<? extends Fieldable> fieldables) {
        checkAvailable();
        checkNotNull(fieldables, "The fieldables to add must be provided");
        for (Fieldable f : fieldables) {
            add(f);
        }
        return thisValue();
    }

    /**
     * Creates a new numeric field builder that adds to the current document.
     * @param name Field name.
     */
    public final DocNumericFieldBuilder numeric(String name) {
        return new DocNumericFieldBuilder(name);
    }

    /**
     * Creates a new text field builder that adds to the current document.
     * @param name Field name.
     */
    public final DocTextFieldBuilder text(String name) {
        return new DocTextFieldBuilder(name);
    }

    /**
     * Creates a new binary field builder that adds to the current document.
     * @param name Field name.
     */
    public final DocBinaryFieldBuilder binary(String name) {
        return new DocBinaryFieldBuilder(name);
    }

    /**
     * Checks whether a value for a schema item can be added.
     * @throws IllegalStateException if the maximum number of occurrences has been reached.
     */
    private void checkItem(SchemaItem item) {
        checkNotNull(item, "The schema item must be provided");
        String name = item.getName();
        checkState(fields.count(name) < item.getMaxOccurs(), "Maximum number of occurrences for field [%s] reached",
                name);
    }

    /**
     * Returns a numeric field builder based on a schema item.
     * @param item Schema item to base the builder on.
     * @throws IllegalStateException if the maximum number of occurrences has been reached.
     */
    private DocNumericFieldBuilder numeric(NumericSchemaItem<?> item) {
        checkItem(item);
        return new DocNumericFieldBuilder(item);
    }

    /**
     * Returns a text builder based on a schema item.
     * @param item Schema item to base the builder on.
     * @throws IllegalStateException if the maximum number of occurrences has been reached.
     */
    private DocTextFieldBuilder text(TextSchemaItem item) {
        checkItem(item);
        return new DocTextFieldBuilder(item);
    }

    /**
     * Returns a binary builder based on a schema item.
     * @param item Schema item to base the builder on.
     * @throws IllegalStateException if the maximum number of occurrences has been reached.
     */
    private DocBinaryFieldBuilder binary(BinarySchemaItem item) {
        checkItem(item);
        return new DocBinaryFieldBuilder(item);
    }

    /**
     * Adds an integer field based on a schema item.
     * @param item Schema item.
     * @param value Field value.
     * @return This builder.
     * @throws IllegalStateException if the maximum number of occurrences for this field has been
     *           reached.
     */
    public final B add(IntegerSchemaItem item, int value) {
        return numeric(item).add(value);
    }

    /**
     * Adds a long field based on a schema item.
     * @param item Schema item.
     * @param value Field value.
     * @return This builder.
     * @throws IllegalStateException if the maximum number of occurrences for this field has been
     *           reached.
     */
    public final B add(LongSchemaItem item, long value) {
        return numeric(item).add(value);
    }

    /**
     * Adds a float field based on a schema item.
     * @param item Schema item.
     * @param value Field value.
     * @return This builder.
     * @throws IllegalStateException if the maximum number of occurrences for this field has been
     *           reached.
     */
    public final B add(FloatSchemaItem item, float value) {
        return numeric(item).add(value);
    }

    /**
     * Adds a double field based on a schema item.
     * @param item Schema item.
     * @param value Field value.
     * @return This builder.
     * @throws IllegalStateException if the maximum number of occurrences for this field has been
     *           reached.
     */
    public final B add(DoubleSchemaItem item, double value) {
        return numeric(item).add(value);
    }

    /**
     * Adds a textual field based on a schema item.
     * @param item Schema item.
     * @param value Field value.
     * @return This builder.
     * @throws IllegalStateException if the maximum number of occurrences for this field has been
     *           reached.
     */
    public final B add(TextSchemaItem item, String value) {
        return text(item).add(value);
    }

    /**
     * Adds a streamed textual field based on a schema item.
     * @param item Schema item.
     * @param reader Field value reader.
     * @return This builder.
     * @throws IllegalStateException if the maximum number of occurrences for this field has been
     *           reached.
     */
    public final B add(StreamSchemaItem item, Reader reader) {
        return text(item).add(reader);
    }

    /**
     * Adds a streamed textual field based on a schema item.
     * @param item Schema item.
     * @param tokenStream Field value token stream.
     * @return This builder.
     * @throws IllegalStateException if the maximum number of occurrences for this field has been
     *           reached.
     */
    public final B add(StreamSchemaItem item, TokenStream tokenStream) {
        return text(item).add(tokenStream);
    }

    /**
     * Adds an UUID field based on a schema item.
     * @param item Schema item.
     * @param value Field value.
     * @return This builder.
     * @throws IllegalStateException if the maximum number of occurrences for this field has been
     *           reached.
     */
    public final B add(UUIDSchemaItem item, UUID value) {
        return text(item).add(value.toString());
    }

    /**
     * Adds a binary field based on a schema item.
     * @param item Schema item.
     * @param value Field value.
     * @return This builder.
     * @throws IllegalStateException if the maximum number of occurrences for this field has been
     *           reached.
     */
    public final B add(BinarySchemaItem item, byte[] value) {
        return binary(item).add(value);
    }

    /**
     * Adds a binary field based on a schema item.
     * @param item Schema item.
     * @param value Field value.
     * @return This builder.
     * @throws IllegalStateException if the maximum number of occurrences for this field has been
     *           reached.
     */
    public final B add(BinarySchemaItem item, ByteString value) {
        return binary(item).add(value);
    }

    /**
     * Adds an instant field based on a schema item.
     * @param item Schema item.
     * @param value Field value.
     * @return This builder.
     * @throws IllegalStateException if the maximum number of occurrences for this field has been
     *           reached.
     */
    public final B add(InstantSchemaItem item, ReadableInstant value) {
        return numeric(item).add(value.getMillis());
    }

    /**
     * Adds a boolean field based on a schema item.
     * @param item Schema item.
     * @param value Field value.
     * @return This builder.
     * @throws IllegalStateException if the maximum number of occurrences for this field has been
     *           reached.
     */
    public final B add(BooleanSchemaItem item, boolean value) {
        return new DocNumericFieldBuilder(item).add(value);
    }

    /** Numeric field builder that adds to the current document builder. */
    public final class DocNumericFieldBuilder extends BaseNumericFieldBuilder<DocNumericFieldBuilder>
            implements NumericFieldAdder<B> {
        /**
         * Constructor.
         * @param name Field name.
         */
        private DocNumericFieldBuilder(String name) {
            super(name);
        }

        /**
         * Constructor based on a schema item.
         * @param item Schema item to base this builder on.
         */
        private DocNumericFieldBuilder(NumericSchemaItem<?> item) {
            super(item);
        }

        /**
         * Constructor based on a boolean schema item.
         * @param item Schema item to base this builder on.
         */
        private DocNumericFieldBuilder(BooleanSchemaItem item) {
            super(item);
        }

        @Override
        public B add(int value) {
            return BaseDocumentBuilder.this.add(build(value));
        }

        @Override
        public B add(long value) {
            return BaseDocumentBuilder.this.add(build(value));
        }

        @Override
        public B add(float value) {
            return BaseDocumentBuilder.this.add(build(value));
        }

        @Override
        public B add(double value) {
            return BaseDocumentBuilder.this.add(build(value));
        }

        @Override
        public B add(boolean value) {
            return BaseDocumentBuilder.this.add(build(value));
        }
    }

    /** Text field builder that adds to the current document builder. */
    public final class DocTextFieldBuilder extends BaseTextFieldBuilder<DocTextFieldBuilder>
            implements TextFieldAdder<B> {
        /**
         * Constructor.
         * @param name Field name.
         */
        private DocTextFieldBuilder(String name) {
            super(name);
        }

        /**
         * Constructor based on a schema item.
         * @param item Schema item to base this builder on.
         */
        private DocTextFieldBuilder(TextSchemaItem item) {
            super(item);
        }

        @Override
        public B add(String value) {
            return BaseDocumentBuilder.this.add(build(value));
        }

        @Override
        public B add(Reader reader) {
            return BaseDocumentBuilder.this.add(build(reader));
        }

        @Override
        public B add(TokenStream tokenStream) {
            return BaseDocumentBuilder.this.add(build(tokenStream));
        }
    }

    /** Binary field builder that adds to the current document builder. */
    public final class DocBinaryFieldBuilder extends BaseBinaryFieldBuilder<DocBinaryFieldBuilder>
            implements BinaryFieldAdder<B> {
        /**
         * Constructor.
         * @param name Field name.
         */
        private DocBinaryFieldBuilder(String name) {
            super(name);
        }

        /**
         * Constructor based on a schema item.
         * @param item Schema item to base this builder on.
         */
        private DocBinaryFieldBuilder(BinarySchemaItem item) {
            super(item);
        }

        @Override
        public B add(byte[] value) {
            return BaseDocumentBuilder.this.add(build(value));
        }

        @Override
        public B add(ByteString value) {
            return BaseDocumentBuilder.this.add(build(value));
        }
    }

}