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

Java tutorial

Introduction

Here is the source code for grails.plugin.searchable.internal.compass.mapping.CompassMappingUtils.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.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.groovy.grails.commons.GrailsDomainClass;
import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.compass.core.Compass;
import org.compass.core.config.CompassConfiguration;
import org.compass.core.config.CompassMappingBinding;
import org.compass.core.mapping.AliasMapping;
import org.compass.core.mapping.CompassMapping;
import org.compass.core.mapping.ResourceMapping;
import org.compass.core.mapping.SpellCheck;
import org.compass.core.mapping.osem.ClassMapping;
import org.compass.core.mapping.osem.ClassPropertyMapping;
import org.compass.core.mapping.osem.ClassPropertyMetaDataMapping;
import org.compass.core.spi.InternalCompass;
import org.compass.core.util.ClassUtils;
import org.compass.core.util.FieldInvoker;
import org.springframework.util.Assert;

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

    /**
     * Provide a default alias for the given Class. This is the Class's short-name
     *
     * @param clazz the class
     * @return the Compass alias
     */
    public static String getDefaultAlias(Class clazz) {
        Assert.notNull(clazz, "clazz cannot be null");
        return ClassUtils.getShortName(clazz);
    }

    /**
     * Get the alias used to map the class in Compass
     * @param compass Compass
     * @param clazz the class whose alias to look up
     * @return the alias
     */
    public static String getMappingAlias(Compass compass, Class clazz) {
        return ((InternalCompass) compass).getMapping().findRootMappingByClass(clazz).getAlias();
    }

    /**
     * Get the mapping aliases for the given user-defined domain classes any
     * @param compass Compass instance
     * @param clazzes the user-defined domain classes
     * @return the Compass aliases for the hierarchy
     */
    public static String[] getMappingAliases(Compass compass, Collection clazzes) {
        Set aliases = new HashSet();
        for (Iterator iter = clazzes.iterator(); iter.hasNext();) {
            Class clazz = (Class) iter.next();
            aliases.add(getMappingAlias(compass, clazz));
        }
        return (String[]) aliases.toArray(new String[aliases.size()]);
    }

    /**
     * Resolve aliases between mappings
     * Note this method is destructive in the sense that it modifies the passed in mappings
     */
    public static void resolveAliases(List classMappings, Collection grailsDomainClasses,
            CompassConfiguration compassConfiguration) {
        // resolve aliases, faking plugin class mappings for those classes already mapped by annotations/xml
        List tempClassMappings = new ArrayList(classMappings);
        try {
            CompassMapping mapping = (CompassMapping) new FieldInvoker(CompassConfiguration.class, "mapping")
                    .prepare().get(compassConfiguration);
            AliasMapping[] mappings = mapping.getMappings();
            for (int i = 0; i < mappings.length; i++) {
                AliasMapping am = mappings[i];
                if (am instanceof ClassMapping) {
                    ClassMapping cm = (ClassMapping) am;
                    CompassClassMapping dummyMapping = new CompassClassMapping();
                    dummyMapping.setAlias(cm.getAlias());
                    dummyMapping.setMappedClass(cm.getClazz());
                    tempClassMappings.add(dummyMapping);
                }
            }
        } catch (Exception e) {
            throw new IllegalStateException("Failed to get Compass mapping: " + e);
        }

        resolveAliases(tempClassMappings, grailsDomainClasses);
    }

    /**
     * Resolve aliases between mappings
     * Note this method is destructive in the sense that it modifies the passed in mappings
     */
    public static void resolveAliases(List classMappings, Collection grailsDomainClasses) {
        // set defaults for those classes without explicit aliases and collect aliases
        Map mappingByClass = new HashMap();
        Map mappingsByAlias = new HashMap();
        for (Iterator iter = classMappings.iterator(); iter.hasNext();) {
            CompassClassMapping classMapping = (CompassClassMapping) iter.next();
            if (classMapping.getAlias() == null) {
                classMapping.setAlias(getDefaultAlias(classMapping.getMappedClass()));
            }
            mappingByClass.put(classMapping.getMappedClass(), classMapping);
            List mappings = (List) mappingsByAlias.get(classMapping.getAlias());
            if (mappings == null) {
                mappings = new ArrayList();
                mappingsByAlias.put(classMapping.getAlias(), mappings);
            }
            mappings.add(classMapping);
        }

        // override duplicate inherited aliases
        for (Iterator iter = mappingsByAlias.keySet().iterator(); iter.hasNext();) {
            List mappings = (List) mappingsByAlias.get(iter.next());
            if (mappings.size() == 1) {
                continue;
            }
            CompassClassMapping parentMapping = null;
            for (Iterator miter = mappings.iterator(); miter.hasNext();) {
                CompassClassMapping classMapping = (CompassClassMapping) miter.next();
                if (classMapping.getMappedClassSuperClass() == null) {
                    parentMapping = classMapping;
                    break;
                }
            }
            mappings.remove(parentMapping);
            for (Iterator miter = mappings.iterator(); miter.hasNext();) {
                CompassClassMapping classMapping = (CompassClassMapping) miter.next();
                LOG.debug("Overriding duplicated alias [" + classMapping.getAlias() + "] for class ["
                        + classMapping.getMappedClass().getName()
                        + "] with default alias. (Aliases must be unique - maybe this was inherited from a superclass?)");
                classMapping.setAlias(getDefaultAlias(classMapping.getMappedClass()));
            }
        }

        // resolve property ref aliases
        for (Iterator iter = classMappings.iterator(); iter.hasNext();) {
            CompassClassMapping classMapping = (CompassClassMapping) iter.next();
            Class mappedClass = classMapping.getMappedClass();
            for (Iterator piter = classMapping.getPropertyMappings().iterator(); piter.hasNext();) {
                CompassClassPropertyMapping propertyMapping = (CompassClassPropertyMapping) piter.next();
                if ((propertyMapping.isComponent() || propertyMapping.isReference())
                        && !propertyMapping.hasAttribute("refAlias")) {
                    Set aliases = new HashSet();
                    Class clazz = propertyMapping.getPropertyType();
                    aliases.add(((CompassClassMapping) mappingByClass.get(clazz)).getAlias());
                    GrailsDomainClassProperty domainClassProperty = GrailsDomainClassUtils
                            .getGrailsDomainClassProperty(grailsDomainClasses, mappedClass,
                                    propertyMapping.getPropertyName());

                    GrailsDomainClass dc = domainClassProperty.getReferencedDomainClass();
                    if (dc == null) {
                        Class elementClass = SearchableUtils.getElementClass(domainClassProperty);
                        dc = GrailsDomainClassUtils.getGrailsDomainClass(elementClass, grailsDomainClasses);

                        if (dc == null) {
                            LOG.warn("Cannot find domain class for property '" + domainClassProperty.getName()
                                    + "' of class '" + domainClassProperty.getDomainClass().getFullName());
                            continue;
                        }
                    }
                    Collection clazzes = GrailsDomainClassUtils.getClazzes(dc.getSubClasses());
                    for (Iterator citer = clazzes.iterator(); citer.hasNext();) {
                        CompassClassMapping mapping = (CompassClassMapping) mappingByClass.get(citer.next());
                        if (mapping != null) {
                            aliases.add(mapping.getAlias());
                        }
                    }
                    propertyMapping.setAttribute("refAlias", DefaultGroovyMethods.join(aliases, ", "));
                }
            }
        }

        // resolve extend aliases
        for (Iterator iter = classMappings.iterator(); iter.hasNext();) {
            CompassClassMapping classMapping = (CompassClassMapping) iter.next();
            Class mappedClassSuperClass = classMapping.getMappedClassSuperClass();
            if (mappedClassSuperClass != null && classMapping.getExtend() == null) {
                CompassClassMapping mapping = (CompassClassMapping) mappingByClass.get(mappedClassSuperClass);
                classMapping.setExtend(mapping.getAlias());
            }
        }
    }

    public static boolean hasSpellCheckMapping(Compass compass) {
        return hasSpellCheckMapping(compass.getConfig());
    }

    public static boolean hasSpellCheckMapping(CompassConfiguration compassConfiguration) {
        try {
            FieldInvoker invoker = new FieldInvoker(CompassConfiguration.class, "mappingBinding").prepare();
            CompassMappingBinding mappingBinding = (CompassMappingBinding) invoker.get(compassConfiguration);
            if (mappingBinding == null) {
                return false;
            }

            invoker = new FieldInvoker(CompassMappingBinding.class, "mapping").prepare();
            CompassMapping mapping = (CompassMapping) invoker.get(mappingBinding);

            ResourceMapping[] mappings = mapping.getRootMappings();
            for (int i = 0; i < mappings.length; i++) {
                ResourceMapping resourceMapping = mappings[i];
                if (resourceMapping.getSpellCheck().equals(SpellCheck.INCLUDE)) {
                    return true;
                }
                for (Iterator iter = resourceMapping.mappingsIt(); iter.hasNext();) {
                    Object o = iter.next();
                    if (o instanceof ClassPropertyMapping) {
                        for (Iterator iter2 = ((ClassPropertyMapping) o).mappingsIt(); iter2.hasNext();) {
                            Object o2 = iter2.next();
                            if (o2 instanceof ClassPropertyMetaDataMapping) {
                                if (((ClassPropertyMetaDataMapping) o2).getSpellCheck()
                                        .equals(SpellCheck.INCLUDE)) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
            return false;
        } catch (IllegalAccessException ex) {
            throw new RuntimeException("Failed to get CompassConfiguration#mappingBinding", ex);
        } catch (NoSuchFieldException ex) {
            throw new RuntimeException("Failed to get CompassConfiguration#mappingBinding", ex);
        }
    }
}