org.compass.core.lucene.LuceneResource.java Source code

Java tutorial

Introduction

Here is the source code for org.compass.core.lucene.LuceneResource.java

Source

/*
 * Copyright 2004-2009 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 org.compass.core.lucene;

import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.compass.core.Property;
import org.compass.core.Resource;
import org.compass.core.converter.mapping.ResourcePropertyConverter;
import org.compass.core.engine.SearchEngineException;
import org.compass.core.engine.SearchEngineFactory;
import org.compass.core.lucene.engine.LuceneSearchEngineFactory;
import org.compass.core.lucene.support.FieldHelper;
import org.compass.core.mapping.ResourceMapping;
import org.compass.core.mapping.ResourcePropertyMapping;
import org.compass.core.spi.AliasedObject;
import org.compass.core.spi.InternalResource;
import org.compass.core.spi.ResourceKey;
import org.compass.core.util.StringUtils;

/**
 * @author kimchy
 */
public class LuceneResource implements AliasedObject, InternalResource, Map<String, Property[]> {

    private static final long serialVersionUID = 3904681565727306034L;

    private ArrayList<Property> properties = new ArrayList<Property>();

    private int docNum;

    private float boost = 1.0f;

    private transient LuceneSearchEngineFactory searchEngineFactory;

    private transient ResourceMapping resourceMapping;

    private transient ResourceKey resourceKey;

    private String alias;

    public LuceneResource(String alias, LuceneSearchEngineFactory searchEngineFactory) {
        this(alias, new Document(), -1, searchEngineFactory);
    }

    public LuceneResource(Document document, int docNum, LuceneSearchEngineFactory searchEngineFactory) {
        this(null, document, docNum, searchEngineFactory);
    }

    public LuceneResource(String alias, Document document, int docNum,
            LuceneSearchEngineFactory searchEngineFactory) {
        this.searchEngineFactory = searchEngineFactory;
        String aliasProperty = searchEngineFactory.getAliasProperty();
        this.docNum = docNum;
        if (alias != null) {
            this.alias = alias;
            Field aliasField = new Field(aliasProperty, alias, Field.Store.YES, Field.Index.NOT_ANALYZED);
            aliasField.setOmitNorms(true);
            properties.add(new LuceneProperty(aliasField));
        } else {
            Fieldable aliasField = document.getField(aliasProperty);
            if (aliasField != null) {
                properties.add(new LuceneProperty(aliasField));
                this.alias = aliasField.stringValue();
            }
        }

        verifyResourceMapping();

        List fields = document.getFields();
        for (Iterator fieldsIt = fields.iterator(); fieldsIt.hasNext();) {
            Fieldable field = (Fieldable) fieldsIt.next();
            if (field.name().equals(aliasProperty)) {
                continue;
            }
            LuceneProperty lProperty = new LuceneProperty(field);
            lProperty.setPropertyMapping(resourceMapping.getResourcePropertyMapping(field.name()));
            properties.add(lProperty);
        }
    }

    public LuceneSearchEngineFactory getSearchEngineFactory() {
        return this.searchEngineFactory;
    }

    public void attach(SearchEngineFactory searchEngineFactory) {
        this.searchEngineFactory = (LuceneSearchEngineFactory) searchEngineFactory;
        this.resourceMapping = searchEngineFactory.getMapping().getRootMappingByAlias(getAlias());
    }

    public void copy(Resource resource) {
        LuceneResource luceneResource = (LuceneResource) resource;
        this.docNum = luceneResource.docNum;
        this.properties = luceneResource.properties;
        this.alias = luceneResource.alias;
        if (luceneResource.searchEngineFactory != null) {
            this.searchEngineFactory = luceneResource.searchEngineFactory;
        }
        if (luceneResource.resourceMapping != null) {
            this.resourceMapping = luceneResource.resourceMapping;
        }
    }

    public Document getDocument() {
        Document document = new Document();
        document.setBoost(boost);
        for (Property property : properties) {
            document.add(((LuceneProperty) property).getField());
        }
        return document;
    }

    public ResourceKey getResourceKey() {
        if (resourceKey == null) {
            resourceKey = new ResourceKey(resourceMapping, this);
        }
        return resourceKey;
    }

    public ResourceMapping getResourceMapping() {
        return this.resourceMapping;
    }

    public String getSubIndex() {
        return getResourceKey().getSubIndex();
    }

    public String getValue(String name) {
        for (Property property : properties) {
            if (property.getName().equals(name) && (!property.isBinary()))
                return property.getStringValue();
        }
        return null;
    }

    public Object getObject(String name) {
        Property prop = getProperty(name);
        if (prop == null) {
            return null;
        }
        return prop.getObjectValue();
    }

    public Object[] getObjects(String name) {
        Property[] props = getProperties(name);
        Object[] ret = new Object[props.length];
        for (int i = 0; i < props.length; i++) {
            ret[i] = props[i].getObjectValue();
        }
        return ret;
    }

    private final static String[] NO_STRINGS = new String[0];

    public String[] getValues(String name) {
        List<String> result = new ArrayList<String>();
        for (Property property : properties) {
            if (property.getName().equals(name) && (!property.isBinary()))
                result.add(property.getStringValue());
        }

        if (result.size() == 0)
            return NO_STRINGS;

        return result.toArray(new String[result.size()]);
    }

    public String getAlias() {
        return alias;
    }

    public String getUID() {
        return getResourceKey().buildUID();
    }

    public String getId() {
        String[] ids = getIds();
        return ids[0];
    }

    public String[] getIds() {
        Property[] idProperties = getIdProperties();
        String[] ids = new String[idProperties.length];
        for (int i = 0; i < idProperties.length; i++) {
            if (idProperties[i] != null) {
                ids[i] = idProperties[i].getStringValue();
            }
        }
        return ids;
    }

    public Property getIdProperty() {
        Property[] idProperties = getIdProperties();
        return idProperties[0];
    }

    public Property[] getIdProperties() {
        return getResourceKey().getIds();
    }

    public Resource addProperty(String name, Object value) throws SearchEngineException {
        String alias = getAlias();

        ResourcePropertyMapping propertyMapping = resourceMapping.getResourcePropertyMapping(name);
        if (propertyMapping == null) {
            throw new SearchEngineException("No resource property mapping is defined for alias [" + alias
                    + "] and resource property [" + name + "]");
        }
        ResourcePropertyConverter converter = propertyMapping.getResourcePropertyConverter();
        if (converter == null) {
            converter = (ResourcePropertyConverter) searchEngineFactory.getMapping().getConverterLookup()
                    .lookupConverter(value.getClass());
        }
        String strValue = converter.toString(value, propertyMapping);

        Property property = searchEngineFactory.getResourceFactory().createProperty(strValue, propertyMapping);
        property.setBoost(propertyMapping.getBoost());
        return addProperty(property);
    }

    public Resource addProperty(String name, Reader value) throws SearchEngineException {
        String alias = getAlias();

        ResourcePropertyMapping propertyMapping = resourceMapping.getResourcePropertyMapping(name);
        if (propertyMapping == null) {
            throw new SearchEngineException("No resource property mapping is defined for alias [" + alias
                    + "] and resource property [" + name + "]");
        }

        Field.TermVector fieldTermVector = FieldHelper.getFieldTermVector(propertyMapping.getTermVector());
        Field field = new Field(name, value, fieldTermVector);
        LuceneProperty property = new LuceneProperty(field);
        property.setBoost(propertyMapping.getBoost());
        property.setPropertyMapping(propertyMapping);
        return addProperty(property);
    }

    public Resource addProperty(Property property) {
        LuceneProperty lProperty = (LuceneProperty) property;
        lProperty.setPropertyMapping(resourceMapping.getResourcePropertyMapping(property.getName()));
        properties.add(property);
        return this;
    }

    public Resource setProperty(String name, Object value) throws SearchEngineException {
        removeProperties(name);
        return addProperty(name, value);
    }

    public Resource setProperty(String name, Reader value) throws SearchEngineException {
        removeProperties(name);
        return addProperty(name, value);
    }

    public Resource setProperty(Property property) {
        removeProperties(property.getName());
        return addProperty(property);
    }

    public Resource removeProperty(String name) {
        Iterator<Property> it = properties.iterator();
        while (it.hasNext()) {
            Property property = it.next();
            if (property.getName().equals(name)) {
                it.remove();
                return this;
            }
        }
        return this;
    }

    public Resource removeProperties(String name) {
        Iterator<Property> it = properties.iterator();
        while (it.hasNext()) {
            Property property = it.next();
            if (property.getName().equals(name)) {
                it.remove();
            }
        }
        return this;
    }

    public Property getProperty(String name) {
        for (Property property : properties) {
            if (property.getName().equals(name)) {
                return property;
            }
        }
        return null;
    }

    public Property[] getProperties(String name) {
        List<Property> result = new ArrayList<Property>();
        for (int i = 0; i < properties.size(); i++) {
            Property property = properties.get(i);
            if (property.getName().equals(name)) {
                result.add(property);
            }
        }

        if (result.size() == 0)
            return new Property[0];

        return result.toArray(new Property[result.size()]);
    }

    public Property[] getProperties() {
        return properties.toArray(new Property[properties.size()]);
    }

    public float getBoost() {
        return boost;
    }

    public Resource setBoost(float boost) {
        this.boost = boost;
        return this;
    }

    public void setDocNum(int docNum) {
        this.docNum = docNum;
    }

    /**
     * Returns the Lucene document number. If not set (can be in case the
     * resource is newly created), than returns -1.
     */
    public int getDocNum() {
        return this.docNum;
    }

    public void addUID() {
        removeProperties(resourceMapping.getUIDPath());
        Property uidProp = searchEngineFactory.getResourceFactory().createProperty(resourceMapping.getUIDPath(),
                getResourceKey().buildUID(), Property.Store.YES, Property.Index.NOT_ANALYZED);
        uidProp.setOmitNorms(true);
        uidProp.setOmitTf(true);
        addProperty(uidProp);
    }

    private void verifyResourceMapping() throws SearchEngineException {
        String alias = getAlias();
        if (resourceMapping == null) {
            if (alias == null) {
                throw new SearchEngineException(
                        "Can't add a resource property based on resource mapping without an alias associated with the resource first");
            }
            if (!searchEngineFactory.getMapping().hasRootMappingByAlias(alias)) {
                throw new SearchEngineException("No mapping is defined for alias [" + alias + "]");
            }
            resourceMapping = searchEngineFactory.getMapping().getRootMappingByAlias(alias);
        }
    }

    public String toString() {
        return "{" + getAlias() + "} " + StringUtils.arrayToCommaDelimitedString(getProperties());
    }

    // methods from the Map interface
    // ------------------------------

    public void clear() {
        throw new UnsupportedOperationException("Map operations are supported for read operations only");
    }

    public boolean containsValue(Object value) {
        throw new UnsupportedOperationException("Map operations are supported for read operations only");
    }

    public void putAll(Map<? extends String, ? extends Property[]> t) {
        for (Iterator it = t.entrySet().iterator(); it.hasNext();) {
            Map.Entry entry = (Entry) it.next();
            put((String) entry.getKey(), (Property[]) entry.getValue());
        }
    }

    public Property[] remove(Object key) {
        removeProperties(key.toString());
        // TODO should return the old value
        return null;
    }

    public Property[] put(String key, Property[] value) {
        removeProperties(key);
        for (Property aValue : value) {
            addProperty(aValue);
        }
        // TODO should return the old value
        return null;
    }

    public Set<Map.Entry<String, Property[]>> entrySet() {
        Set<String> keySey = keySet();
        Set<Entry<String, Property[]>> entrySet = new HashSet<Entry<String, Property[]>>();
        for (Iterator it = keySey.iterator(); it.hasNext();) {
            final String name = it.next().toString();
            final Property[] props = getProperties(name);
            entrySet.add(new Map.Entry<String, Property[]>() {
                public String getKey() {
                    return name;
                }

                public Property[] getValue() {
                    return props;
                }

                public Property[] setValue(Property[] value) {
                    put(name, value);
                    // TODO should return the old value
                    return null;
                }
            });
        }
        return Collections.unmodifiableSet(entrySet);
    }

    public Set<String> keySet() {
        Set<String> keySet = new HashSet<String>();
        for (Property property : properties) {
            keySet.add((property).getName());
        }
        return Collections.unmodifiableSet(keySet);
    }

    public boolean containsKey(Object key) {
        return getProperty(key.toString()) != null;
    }

    public int size() {
        return this.properties.size();
    }

    public boolean isEmpty() {
        return this.properties.isEmpty();
    }

    public Collection<Property[]> values() {
        Set<String> keySet = keySet();
        List<Property[]> values = new ArrayList<Property[]>();
        for (String name : keySet) {
            values.add(getProperties(name));
        }
        return Collections.unmodifiableList(values);
    }

    public Property[] get(Object key) {
        return getProperties(key.toString());
    }
}