org.eclipse.skalli.services.extension.PropertyLookup.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.skalli.services.extension.PropertyLookup.java

Source

/*******************************************************************************
 * Copyright (c) 2010-2014 SAP AG and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     SAP AG - initial API and implementation
 *******************************************************************************/
package org.eclipse.skalli.services.extension;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrLookup;
import org.eclipse.skalli.commons.CollectionUtils;
import org.eclipse.skalli.model.EntityBase;
import org.eclipse.skalli.model.ExtensibleEntityBase;
import org.eclipse.skalli.model.ExtensionEntityBase;
import org.eclipse.skalli.model.Project;
import org.eclipse.skalli.model.PropertyName;

/**
 * A {@link StrLookup} implementation that reflectively scans a given
 * {@link EntityBase entity}, e.g. a project, for properties.
 * <p>
 * Maps property values to the respective property names declared with
 * {@link PropertyName} annotations in the entity.
 * For {@link ExtensibleEntityBase extensible entities}, properties of
 * extensions are mapped to keys of the form <tt>extensionName.propertyName</tt>,
 * where <tt>extensionName</tt> is the {@link ExtensionService#getShortName() short name}
 * of the extension. Properties of the extensible entity itself are mapped to
 * simple <tt>propertyName</tt>.
 */
public class PropertyLookup extends StrLookup {

    private final HashMap<String, Object> properties = new HashMap<String, Object>();

    /**
     * Creates a property lookup instance from a given property map.
     * The given properties are mapped to placeholders by their respective keys.
     *
     * @param @param customProperties  optional custom properties, or <code>null</code>.
     */
    public PropertyLookup(Map<String, ?> customProperties) {
        this(null, customProperties);
    }

    /**
     * Creates a property lookup instance for a given entity, e.g. a {@link Project}.
     * Properties of the entity are scanned and provided as placeholders for the lookup.
     *
     * @param entity  the entity, for which to create a property lookup.
     */
    public PropertyLookup(EntityBase entity) {
        this(entity, null);
    }

    /**
     * Creates a property lookup instance for a given entity, e.g. a {@link Project}.
     * Properties of the entity are scanned and provided as placeholders for the lookup.
     * If the entity is {@link ExtensibleEntityBase extensible}, extensions are scanned,
     * too, and added as placeholders of the form <tt>${extensionName.propertyName}</tt>.
     * The given custom properties are mapped to placeholders by their respective keys
     * and provided for the lookup as well.
     *
     * @param entity  the entity, for which to create a property lookup.
     * @param customProperties  optional custom properties, or <code>null</code>.
     */
    public PropertyLookup(EntityBase entity, Map<String, ?> customProperties) {
        if (entity != null) {
            putAllProperties(entity, ""); //$NON-NLS-1$
        }
        if (customProperties != null) {
            properties.putAll(customProperties);
        }
    }

    /**
     * Adds all properties of the given entity to this property lookup.
     * Property names of the entity are scanned and provided as placeholders of the form
     * <tt>${prefix.propertyName}</tt> for the lookup. If the prefix is blank, placeholders
     * of the form <tt>${propertyName}</tt> are used.
     * Extensions of the entity are scanned, too, and added as placeholders of the form
     * <tt>${prefix.extensionName.propertyName}</tt>. If the prefix is blank, placeholders are
     * named <tt>${extensionName.propertyName}</tt>, respectively.
     *
     * @param entity  the entity to add to this property lookup.
     * @param prefix  the prefix for building placeholders.
     */
    public void putAllProperties(EntityBase entity, String prefix) {
        prefix = StringUtils.removeEnd(prefix, "."); //$NON-NLS-1$
        if (entity instanceof ExtensibleEntityBase) {
            putAllProperties((ExtensibleEntityBase) entity, prefix);
        }
        for (String propertyName : entity.getPropertyNames()) {
            properties.put(concat(prefix, propertyName), entity.getProperty(propertyName));
        }
    }

    private void putAllProperties(ExtensibleEntityBase extensible, String prefix) {
        for (ExtensionEntityBase extension : extensible.getAllExtensions()) {
            ExtensionService<?> extensionService = ExtensionServices.getByExtensionClass(extension.getClass());
            if (extensionService != null) {
                putAllProperties(extension, concat(prefix, extensionService.getShortName()));
            }
        }
    }

    private String concat(String prefix, String s) {
        StringBuilder sb = new StringBuilder(prefix);
        if (sb.length() > 0) {
            sb.append('.');
        }
        sb.append(s);
        return sb.toString();
    }

    /**
     * Returns the properties available for lookup as map.
     */
    public Map<String, Object> asMap() {
        return properties;
    }

    /**
     * Returns the number of properties available for the lookup.
     */
    public int size() {
        return properties.size();
    }

    /**
     * Returns <tt>true</tt> if this lookup contains no properties at all.
     */
    public boolean isEmpty() {
        return properties.isEmpty();
    }

    /**
     * Returns <tt>true</tt> if this lookup contains a property with the given key.
     *
     * @param key  the key of the property (without the surrounding
     * <tt>${...}</tt> of the placeholder).
     */
    public boolean containsKey(String key) {
        return properties.containsKey(key);
    }

    /**
     * Returns <tt>true</tt> if this lookup contains a given property value.
     *
     * @param value  the property value to search for.
     */
    public boolean containsValue(Object value) {
        return properties.containsValue(value);
    }

    /**
     * Returns all known property keys
     *
     * @return a set of keys (equivalent to the placeholders, but without the surrounding
     * <tt>${...}</tt>), or an empty set.
     */
    public Set<String> keySet() {
        return properties.keySet();
    }

    /**
     * Returns the property for the given key.
     *
     * @param key the key of the property to return (equivalent to the placeholder,
     * but without the surrounding <tt>${...}</tt>).
     *
     * @return  the value of the property, or <code>nully</code> if there is no property
     * with the given key.
     */
    public Object get(String key) {
        return properties.get(key);
    }

    /**
     * Returns a collection of all property values.
     * @return the collection of property values, or an empty collection.
     */
    public Collection<Object> values() {
        return properties.values();
    }

    /**
     * Returns an entry set of all properties.
     * @return an entry set of properties, or an empty set.
     */
    public Set<Map.Entry<String, Object>> entrySet() {
        return properties.entrySet();
    }

    @Override
    public String lookup(String key) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        Object o = properties.get(key);
        if (o == null) {
            return null;
        }
        if (o instanceof Collection) {
            return CollectionUtils.toString((Collection<?>) o, ',');
        }
        return o.toString();
    }
}