com.fitbur.jackson.databind.PropertyName Maven / Gradle / Ivy
package com.fitbur.jackson.databind;
import com.fitbur.jackson.core.SerializableString;
import com.fitbur.jackson.core.io.SerializedString;
import com.fitbur.jackson.core.util.InternCache;
import com.fitbur.jackson.databind.cfg.MapperConfig;
/**
* Simple value class used for containing names of properties as defined
* by annotations (and possibly other configuration sources).
*
* @since 2.1
*/
public class PropertyName
implements java.io.Serializable
{
private static final long serialVersionUID = 1L; // 2.5
private final static String _USE_DEFAULT = "";
private final static String _NO_NAME = "";
/**
* Special placeholder value that indicates that name to use should be
* based on the standard heuristics. This can be different from returning
* null, as null means "no information available, whereas this value
* indicates explicit defaulting.
*/
public final static PropertyName USE_DEFAULT = new PropertyName(_USE_DEFAULT, null);
/**
* Special placeholder value that indicates that there is no name associated.
* Exact semantics to use (if any) depend on actual annotation in use, but
* commonly this value disables behavior for which name would be needed.
*/
public final static PropertyName NO_NAME = new PropertyName(new String(_NO_NAME), null);
/**
* Basic name of the property.
*/
protected final String _simpleName;
/**
* Additional namespace, for formats that have such concept (JSON
* does not, XML does, for example).
*/
protected final String _namespace;
/**
* Lazily-constructed efficient representation of the simple name.
*
* NOTE: not defined as volatile to avoid performance problem with
* concurrent access in multi-core environments; due to statelessness
* of {@link SerializedString} at most leads to multiple instantiations.
*
* @since 2.4
*/
protected SerializableString _encodedSimple;
public PropertyName(String simpleName) {
this(simpleName, null);
}
public PropertyName(String simpleName, String namespace)
{
_simpleName = (simpleName == null) ? "" : simpleName;
_namespace = namespace;
}
// To support JDK serialization, recovery of Singleton instance
protected Object readResolve() {
if (_simpleName == null || _USE_DEFAULT.equals(_simpleName)) {
return USE_DEFAULT;
}
if (_simpleName.equals(_NO_NAME) && _namespace == null) {
return NO_NAME;
}
return this;
}
/**
* @since 2.6
*/
public static PropertyName construct(String simpleName)
{
if (simpleName == null || simpleName.length() == 0) {
return USE_DEFAULT;
}
return new PropertyName(InternCache.instance.intern(simpleName), null);
}
public static PropertyName construct(String simpleName, String ns)
{
if (simpleName == null) {
simpleName = "";
}
if (ns == null && simpleName.length() == 0) {
return USE_DEFAULT;
}
return new PropertyName(InternCache.instance.intern(simpleName), ns);
}
public PropertyName internSimpleName()
{
if (_simpleName.length() == 0) { // empty String is canonical already
return this;
}
String interned = InternCache.instance.intern(_simpleName);
if (interned == _simpleName) { // was already interned
return this;
}
return new PropertyName(interned, _namespace);
}
/**
* Fluent factory method for constructing an instance with different
* simple name.
*/
public PropertyName withSimpleName(String simpleName)
{
if (simpleName == null) {
simpleName = "";
}
if (simpleName.equals(_simpleName)) {
return this;
}
return new PropertyName(simpleName, _namespace);
}
/**
* Fluent factory method for constructing an instance with different
* namespace.
*/
public PropertyName withNamespace(String ns) {
if (ns == null) {
if (_namespace == null) {
return this;
}
} else if (ns.equals(_namespace)) {
return this;
}
return new PropertyName(_simpleName, ns);
}
/*
/**********************************************************
/* Accessors
/**********************************************************
*/
public String getSimpleName() {
return _simpleName;
}
/**
* Accessor that may be used to get lazily-constructed efficient
* representation of the simple name.
*
* @since 2.4
*/
public SerializableString simpleAsEncoded(MapperConfig> config) {
SerializableString sstr = _encodedSimple;
if (sstr == null) {
if (config == null) {
sstr = new SerializedString(_simpleName);
} else {
sstr = config.compileString(_simpleName);
}
_encodedSimple = sstr;
}
return sstr;
}
public String getNamespace() {
return _namespace;
}
public boolean hasSimpleName() {
return _simpleName.length() > 0;
}
/**
* @since 2.3
*/
public boolean hasSimpleName(String str) {
if (str == null) {
return _simpleName == null;
}
return str.equals(_simpleName);
}
public boolean hasNamespace() {
return _namespace != null;
}
/**
* Method that is basically equivalent of:
*
* !hasSimpleName() << !hasNamespace();
*
*
* @since 2.4
*/
public boolean isEmpty() {
return (_namespace == null) && (_simpleName.isEmpty());
}
/*
/**********************************************************
/* Std method overrides
/**********************************************************
*/
@Override
public boolean equals(Object o)
{
if (o == this) return true;
if (o == null) return false;
/* 13-Nov-2012, tatu: by default, require strict type equality.
* Re-evaluate if this becomes an issue.
*/
if (o.getClass() != getClass()) return false;
// 13-Nov-2012, tatu: Should we have specific rules on matching USE_DEFAULT?
// (like, it only ever matching exact instance)
// If we did, would need to check symmetrically; that is, if either 'this'
// or 'o' was USE_DEFAULT, both would have to be.
PropertyName other = (PropertyName) o;
if (_simpleName == null) {
if (other._simpleName != null) return false;
} else if (!_simpleName.equals(other._simpleName)) {
return false;
}
if (_namespace == null) {
return (null == other._namespace);
}
return _namespace.equals(other._namespace);
}
@Override
public int hashCode() {
if (_namespace == null) {
return _simpleName.hashCode();
}
return _namespace.hashCode() ^ _simpleName.hashCode();
}
@Override
public String toString() {
if (_namespace == null) {
return _simpleName;
}
return "{"+_namespace + "}" + _simpleName;
}
}