All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.basistech.rosette.dm.BaseAttribute Maven / Gradle / Ivy

There is a newer version: 3.0.3
Show newest version
/*
* Copyright 2014 Basis Technology Corp.
*
* 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 com.basistech.rosette.dm;

import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Base class for attributes that annotate text.  Each attribute contains
 * an extended properties map of String to Object to hold optional
 * "user-defined" elements.
 *
 * @adm.ignore
 */
public abstract class BaseAttribute implements Serializable {
    private static final long serialVersionUID = 222L;

    protected Map extendedProperties;

    protected BaseAttribute() {
        this.extendedProperties = ImmutableMap.of();
    }

    protected BaseAttribute(Map extendedProperties) {
        if (extendedProperties != null) {
            if (extendedProperties instanceof ImmutableMap) {
                this.extendedProperties = extendedProperties;
            } else {
                this.extendedProperties = ImmutableMap.copyOf(extendedProperties);
            }
        } else {
            this.extendedProperties = ImmutableMap.of();
        }
    }

    /**
     * Returns the extended properties.  All attributes store a map of extended
     * properties. This mechanism is available to add additional data to
     * attributes.
     *
     * @return the map of extended properties
     */
    public Map getExtendedProperties() {
        return extendedProperties;
    }

    /**
     * Called only from Jackson to implement deserialization via JsonAnySetter.
     * @param name property name
     * @param value property value
     */
    protected void setExtendedProperty(String name, Object value) {
        /* This is only called in deserialization. So we do something
        * to work around the read-only collection. */
        if (extendedProperties.size() > 0) {
            extendedProperties = ImmutableMap.builder().putAll(extendedProperties).put(name, value).build();
        } else {
            extendedProperties = ImmutableMap.of(name, value);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        BaseAttribute that = (BaseAttribute) o;

        return extendedProperties.equals(that.extendedProperties);

    }

    protected Objects.ToStringHelper toStringHelper() {
        return Objects.toStringHelper(this).omitNullValues()
                .add("extendedProperties", extendedProperties);
    }

    @Override
    public String toString() {
        return toStringHelper().toString();
    }

    @Override
    public int hashCode() {
        return extendedProperties.hashCode();
    }

    /**
     * Utility method for the 'no empty lists' convention. Takes a list,
     * if empty returns null, else returns a copy of the list.  Use this
     * in constructors of the the immutable objects, not in their builders.
     * @param listToBuild the list
     * @param  the type of the list
     * @return a list, or null.
     */
    protected static  List listOrNull(List listToBuild) {
        // note: Guava's nullable business is an option here, but it's a lot to drag in at the moment.
        if (listToBuild == null || listToBuild.size() == 0) {
            return null;
        } else {
            return ImmutableList.copyOf(listToBuild);
        }
    }

    /**
     * Utility method for the 'no empty sets' convention. Takes a set,
     * if empty returns null, else returns a copy of the set.  Use this
     * in constructors of the the immutable objects, not in their builders.
     * @param setToBuild the list
     * @param  the type of the list
     * @return a list, or null.
     */
    static  Set setOrNull(Set setToBuild) {
        // note: Guava's nullable business is an option here, but it's a lot to drag in at the moment.
        if (setToBuild == null || setToBuild.size() == 0) {
            return null;
        } else {
            return ImmutableSet.copyOf(setToBuild);
        }
    }

    static Map mapOrNull(Map mapToCopy) {
        if (mapToCopy == null || mapToCopy.size() == 0) {
            return null;
        } else {
            return ImmutableMap.copyOf(mapToCopy);
        }
    }

    /**
     * Base class for builders for the subclasses of {@link com.basistech.rosette.dm.BaseAttribute}.
     */
    public abstract static class Builder> {
        private ImmutableMap.Builder extendedPropertiesBuilder;
        private ImmutableMap extendedPropertiesToCopy;

        /**
         * Constructs a builder with no data.
         */
        protected Builder() {
            /* Usually we don't have any. So start with an empty map, which the constructor above will 'copy'
             * cheaply due to optimization inside ImmutableMap.
             */
            this.extendedPropertiesToCopy = ImmutableMap.of();
        }

        /**
         * Constructs a builder with values derived from an existing object.
         *
         * @param toCopy the object to copy
         */
        protected Builder(BaseAttribute toCopy) {
            /* Just treat the copy as an immutable item until the caller asks us to change it. */
            this.extendedPropertiesToCopy = (ImmutableMap) toCopy.extendedProperties;
        }

        protected abstract B getThis();

        /**
         * Cook up a map to pass to the constructor.
         * If we have an unmodified map to 'copy', we just use it. Otherwise, we build from the builder.
         * @return the map.
         */
        protected Map buildExtendedProperties() {
            if (extendedPropertiesToCopy != null) {
                return extendedPropertiesToCopy;
            } else if (extendedPropertiesBuilder != null) {
                return extendedPropertiesBuilder.build();
            } else {
                return null;
            }
        }

        /**
         * Adds an extended value key-value pair.
         *
         * @param key the key
         * @param value the value
         * @return this
         */
        public B extendedProperty(String key, Object value) {
            if (extendedPropertiesBuilder == null) {
                /* if we don't have a builder yet, forget 'toCopy' in favor of a builder. */
                extendedPropertiesBuilder = ImmutableMap.builder();
                if (extendedPropertiesToCopy != null) {
                    extendedPropertiesBuilder.putAll(extendedPropertiesToCopy);
                    extendedPropertiesToCopy = null;
                }
            }
            this.extendedPropertiesBuilder.put(key, value);
            return getThis();
        }

        /**
         * Replace the entire extended property map.
         * @param properties a map of extended properties.
         * @return this.
         */
        public B extendedProperties(Map properties) {
            /* Turn this into the version we copy. */
            if (properties instanceof ImmutableMap) {
                this.extendedPropertiesToCopy = (ImmutableMap) properties;
            } else {
                this.extendedPropertiesToCopy = ImmutableMap.copyOf(properties);
            }
            /* No builder. */
            this.extendedPropertiesBuilder = null;
            return getThis();
        }

        /**
         * Add all the entries of a list to another list, but don't NPE if the 'to be added' list is null.
         * @param list list to add to.
         * @param toAdd list to add.
         * @param  type of elements.
         */
        protected static  void addAllToList(List list, List toAdd) {
            if (toAdd != null) {
                list.addAll(toAdd);
            }
        }

        /**
         * Add all the entries of a set to another set, but don't NPE if the 'to be added' collection is null.
         * @param set set to add to.
         * @param toAdd set to add.
         * @param  type of elements.
         */
        protected static  void addAllToSet(Set set, Set toAdd) {
            if (toAdd != null) {
                set.addAll(toAdd);
            }
        }

        protected static  List nullOrList(List newListValue) {
            if (newListValue == null) {
                return Lists.newArrayList();
            } else {
                return newListValue;
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy