grails.plugin.searchable.internal.compass.mapping.SearchableGrailsDomainClassCompassMappingUtils.java Source code

Java tutorial

Introduction

Here is the source code for grails.plugin.searchable.internal.compass.mapping.SearchableGrailsDomainClassCompassMappingUtils.java

Source

/*
 * Copyright 2007 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 grails.plugin.searchable.internal.compass.mapping;

import grails.plugin.searchable.internal.SearchableUtils;
import grails.plugin.searchable.internal.util.GrailsDomainClassUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler;
import org.codehaus.groovy.grails.commons.GrailsApplication;
import org.codehaus.groovy.grails.commons.GrailsDomainClass;
import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty;
import org.compass.core.Compass;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

/**
 * @author Maurice Nicholson
 */
public class SearchableGrailsDomainClassCompassMappingUtils {
    private static final Log LOG = LogFactory.getLog(SearchableGrailsDomainClassCompassMappingUtils.class);

    /**
     * Is the given GrailsDomainClass a root class in the Compass mapping?
     * @param grailsDomainClass the domain class to check for
     * @param searchableGrailsDomainClasses a collection of searchable GrailsDomainClass instances
     * @return true unless it's an embedded class in another domain class without explicit searchable declaration
     */
    public static boolean isRoot(GrailsDomainClass grailsDomainClass, Collection searchableGrailsDomainClasses) {
        // TODO log warning when used as both component and non-component
        Object value = SearchableUtils.getSearchablePropertyValue(grailsDomainClass);
        if (value instanceof Boolean) {
            return (Boolean) value;
        }
        if (value == null) {
            return !SearchableUtils.isEmbeddedPropertyOfOtherDomainClass(grailsDomainClass,
                    searchableGrailsDomainClasses);
        }
        return true;
    }

    /**
     * Get the mappable domain class properties
     * @param grailsDomainClass
     * @param searchableValue
     * @param searchableGrailsDomainClasses
     * @param excludedProperties
     * @param domainClassPropertyMappingFactory
     * @return
     */
    public static GrailsDomainClassProperty[] getMappableProperties(GrailsDomainClass grailsDomainClass,
            Object searchableValue, Collection searchableGrailsDomainClasses, final List excludedProperties,
            SearchableGrailsDomainClassPropertyMappingFactory domainClassPropertyMappingFactory) {
        boolean defaultExcludes = false;
        if (searchableValue instanceof Boolean) {
            if (!(Boolean) searchableValue) {
                return null;
            }
            searchableValue = new HashMap();
            ((Map) searchableValue).put("except", excludedProperties);
            defaultExcludes = true;
        }

        Class mappedClass = grailsDomainClass.getClazz();
        List properties = new ArrayList();
        GrailsDomainClassProperty[] domainClassProperties = grailsDomainClass.getProperties();
        for (int i = 0, max = domainClassProperties.length; i < max; i++) {
            GrailsDomainClassProperty property = domainClassProperties[i];
            String propertyName = property.getName();
            if (!GrailsDomainClassUtils.isIndentityProperty(property)
                    && !SearchableUtils.isIncludedProperty(propertyName, searchableValue)) {
                LOG.debug("Not mapping [" + ClassUtils.getShortName(mappedClass) + "." + propertyName
                        + "] because of "
                        + (defaultExcludes ? "default property exclusions" : "specified only/except rule"));
                continue;
            }

            if (domainClassPropertyMappingFactory.getGrailsDomainClassPropertyMapping(property,
                    searchableGrailsDomainClasses) == null) {
                LOG.debug("Can't map [" + ClassUtils.getShortName(mappedClass) + "." + propertyName + "]");
                continue;
            }
            LOG.debug("Mapping [" + ClassUtils.getShortName(mappedClass) + "." + propertyName + "]");
            properties.add(property);
        }
        return (GrailsDomainClassProperty[]) properties.toArray(new GrailsDomainClassProperty[properties.size()]);
    }

    /**
     * Builds a CompassClassMapping for the GrailsDomainClass and property mappings
     * @param grailsDomainClass
     * @param searchableGrailsDomainClasses
     * @param propertyMappings
     * @return
     */
    public static CompassClassMapping buildCompassClassMapping(GrailsDomainClass grailsDomainClass,
            Collection searchableGrailsDomainClasses, List propertyMappings) {
        CompassClassMapping classMapping = new CompassClassMapping();
        classMapping.setMappedClass(grailsDomainClass.getClazz());
        classMapping.setPropertyMappings(propertyMappings);
        if (classMapping.getRoot() == null) {
            classMapping.setRoot(Boolean.valueOf(SearchableGrailsDomainClassCompassMappingUtils
                    .isRoot(grailsDomainClass, searchableGrailsDomainClasses)));
        }
        Collection superClasses = GrailsDomainClassUtils.getSuperClasses(grailsDomainClass,
                searchableGrailsDomainClasses);
        if (!superClasses.isEmpty()) {
            GrailsDomainClass parent = GrailsDomainClassUtils.getSuperClass(grailsDomainClass, superClasses);
            classMapping.setMappedClassSuperClass(parent.getClazz());
        }
        if (GrailsDomainClassUtils.isWithinInhertitanceHierarchy(grailsDomainClass,
                searchableGrailsDomainClasses)) {
            Map data = new HashMap();
            data.put("index", "not_analyzed");
            data.put("excludeFromAll", true);
            classMapping.addConstantMetaData("$/poly/class", data,
                    Arrays.asList(grailsDomainClass.getClazz().getName()));
        }
        classMapping.setPoly(
                !grailsDomainClass.getSubClasses().isEmpty() || classMapping.getMappedClassSuperClass() != null);
        return classMapping;
    }

    /**
     * Merges the given property mappings, overriding parent mappings with child mappings
     * @param mappedProperties
     * @param parentClassPropertyMappings
     */
    public static void mergePropertyMappings(List mappedProperties, List parentClassPropertyMappings) {
        if (parentClassPropertyMappings == null) {
            return;
        }
        Assert.notNull(mappedProperties, "mappedProperties cannot be null");
        List temp = new ArrayList(parentClassPropertyMappings);
        temp.addAll(mappedProperties);
        for (Iterator citer = mappedProperties.iterator(); citer.hasNext();) {
            CompassClassPropertyMapping cmapping = (CompassClassPropertyMapping) citer.next();
            for (Iterator piter = parentClassPropertyMappings.iterator(); piter.hasNext();) {
                CompassClassPropertyMapping pmapping = (CompassClassPropertyMapping) piter.next();
                if (cmapping.getPropertyName().equals(pmapping.getPropertyName())) {
                    temp.remove(pmapping);
                }
            }
        }
        mappedProperties.clear();
        mappedProperties.addAll(temp);
    }

    /**
     * Get the mapping aliases for the given user-defined domain class and its subclasses if any
     * @param compass Compass instance
     * @param clazz the user-defined domain class
     * @param application the GrailsApplication
     * @return the Compass aliases for the hierarchy
     */
    public static String[] getPolyMappingAliases(Compass compass, Class clazz, GrailsApplication application) {
        List grailsDomainClasses = Arrays.asList(application.getArtefacts(DomainClassArtefactHandler.TYPE));
        GrailsDomainClass grailsDomainClass = GrailsDomainClassUtils.getGrailsDomainClass(clazz,
                grailsDomainClasses);
        Collection clazzes = new HashSet(GrailsDomainClassUtils.getClazzes(grailsDomainClass.getSubClasses()));
        clazzes.add(clazz);
        return CompassMappingUtils.getMappingAliases(compass, clazzes);
    }
}