com.basistech.rosette.dm.BaseAttribute Maven / Gradle / Ivy
/*
* 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