com.gemstone.gemfire.pdx.PdxInstance Maven / Gradle / Ivy
/*
* Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
*
* 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. See accompanying
* LICENSE file.
*/
package com.gemstone.gemfire.pdx;
import java.util.List;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
/**
* PdxInstance provides run time access to the fields of a PDX without
* deserializing the PDX. Preventing deserialization saves time
* and memory and does not require the domain class.
* This interface is implemented by GemFire. The PdxInstance implementation
* is a light weight wrapper that simply refers to the raw bytes of the PDX
* that are kept in the cache.
* Applications can choose to access PdxInstances instead of Java objects by
* configuring the Cache to prefer PDX instances during deserialization.
* This can be done in cache.xml
by setting the attribute read-serialized
* to true on the pdx
element. Or it can be done programmatically using
* either the {@link CacheFactory#setPdxReadSerialized(boolean) setPdxReadSerialized}
* or {@link ClientCacheFactory#setPdxReadSerialized(boolean) client setPdxReadSerialized}
* method. Once this preference is configured, then any time deserialization of a
* PDX is done it will deserialize into a PdxInstance.
* PdxInstances are immutable. If you want to change one call
* {@link #createWriter}.
*
* A PdxInstance's fields will always be those of the version it represents.
* So if you add a field to your domain class you can end up with a PdxInstance
* for version 1 (that does not have the field) and a PdxInstance for version 2.
* The PdxInstance for version 1 will not have the added field and the PdxInstance
* for version 2 will have the field. This differs from deserialization of a pdx
* back to a domain class. In that case if version 2 is deserializing version 1
* PdxReader will return a default value for the added field even though version 1
* has no knowledge of it.
*
* @author darrel
* @since 6.6
*/
public interface PdxInstance extends java.io.Serializable {
/**
* Return the full name of the class that this pdx instance represents.
* @return the name of the class that this pdx instance represents.
* @since 6.6.2
*/
public String getClassName();
/**
* Returns true if this instance represents an enum.
* Enum's have a String field named "name" and an int field named "ordinal".
* It is ok to cast a PdxInstance that represents an enum to {@link java.lang.Comparable}.
* PdxInstances representing enums are not writable.
* @return true if this instance represents an enum.
*/
public boolean isEnum();
/**
* Deserializes and returns the domain object that this instance represents.
*
* @return the deserialized domain object.
* @throws PdxSerializationException if the instance could not be deserialized
*/
public Object getObject();
/**
* Checks if the named field exists and returns the result.
*
This can be useful when writing code that handles more than one version of
* a PDX class.
* @param fieldName the name of the field to check
* @return true
if the named field exists; otherwise false
*/
public boolean hasField(String fieldName);
/**
* Return an unmodifiable list of the field names on this PdxInstance.
* @return an unmodifiable list of the field names on this PdxInstance
*/
public List getFieldNames();
/**
* Checks if the named field was {@link PdxWriter#markIdentityField(String) marked} as an identity field.
* Note that if no fields have been marked then all the fields are used as identity fields even though
* this method will return false
since none of them have been marked.
* @param fieldName the name of the field to check
* @return true
if the named field exists and was marked as an identify field; otherwise false
*/
public boolean isIdentityField(String fieldName);
/**
* Reads the named field and returns its value. If the field does
* not exist null
is returned.
*
A null
result indicates that the field does not exist
* or that it exists and its value is currently null
.
* The {@link #hasField(String) hasField} method can be used to figure out
* which if these two cases is true.
*
If an Object[] is deserialized by this call then that array's component
* type will be Object.class
instead of the original class that
* the array had when it was serialized. This is done so that PdxInstance objects
* can be added to the array.
*
* @param fieldName
* name of the field to read
*
* @return If this instance has the named field then the field's value is returned,
* otherwise null
is returned.
* @throws PdxSerializationException if the field could not be deserialized
*/
public Object getField(String fieldName);
/**
* Returns true if the given object is equals to this instance.
*
If other
is not a PdxInstance then it is not equal to this instance.
* NOTE: Even if other
is the result of calling {@link #getObject()} it will not
* be equal to this instance.
*
Otherwise equality of two PdxInstances is determined as follows:
*
* - The domain class name must be equal for both PdxInstances
*
- Each identity field must be equal.
*
* If one of the instances does not have a field that the other one does then equals will assume it
* has the field with a default value.
* If a PdxInstance has marked identity fields using {@link PdxWriter#markIdentityField(String) markIdentityField}
* then only the marked identity fields are its identity fields.
* Otherwise all its fields are identity fields.
* An identity field is equal if all the following are true:
*
* - The field name is equal.
*
- The field type is equal.
*
- The field value is equal.
*
* If a field's type is OBJECT
then its value must be deserialized to determine if it is equals. If the deserialized object is an array then {@link java.util.Arrays#deepEquals(Object[], Object[]) deepEquals} is used to determine equality. Otherwise {@link Object#equals(Object) equals} is used.
*
If a field's type is OBJECT[]
then its value must be deserialized and {@link java.util.Arrays#deepEquals(Object[], Object[]) deepEquals} is used to determine equality.
*
For all other field types then the value does not need to be deserialized. Instead the serialized raw bytes are compared and used to determine equality.
*
Note that any fields that have objects that do not override {@link Object#equals(Object) equals} will cause equals to return false when you might have expected it to return true.
* The only exceptions to this are those that call {@link java.util.Arrays#deepEquals(Object[], Object[]) deepEquals} as noted above. You should either override equals and hashCode in these cases
* or mark other fields as your identity fields.
* @param other the other instance to compare to this.
* @return true
if this instance is equal to other
.
*/
public boolean equals(Object other);
/**
* Generates a hashCode based on the identity fields of
* this PdxInstance.
*
If a PdxInstance has marked identity fields using {@link PdxWriter#markIdentityField(String) markIdentityField}
* then only the marked identity fields are its identity fields.
* Otherwise all its fields are identity fields.
*
* If an identity field is of type OBJECT
then it is deserialized. If the deserialized object is an array then {@link java.util.Arrays#deepHashCode(Object[]) deepHashCode} is used. Otherwise {@link Object#hashCode() hashCode} is used.
*
If an identity field is of type OBJECT[]
this it is deserialized and {@link java.util.Arrays#deepHashCode(Object[]) deepHashCode} is used.
*
Otherwise the field is not deserialized and the raw bytes of its value are used to compute the hash code.
*
* The algorithm used to compute the hashCode is:
* hashCode = 1;
* foreach (field: sortedIdentityFields()) {
* if (field.isDefaultValue())
* continue;
* if (field.isArray()) {
* hashCode = hashCode*31 + Arrays.deepHashCode(field);
* } else {
* hashCode = hashCode*31 + field.hashCode();
* }
* }
* if (hashCode == 0) {
* hashCode = 1;
* }
*/
public int hashCode();
/**
* Prints out all of the identity fields of this PdxInstance.
*
If a PdxInstance has marked identity fields using {@link PdxWriter#markIdentityField(String) markIdentityField}
* then only the marked identity fields are its identity fields.
* Otherwise all its fields are identity fields.
*/
public String toString();
/**
* Creates and returns a {@link WritablePdxInstance} whose initial
* values are those of this PdxInstance.
* This call returns a copy of the current field values so modifications
* made to the returned value will not modify this PdxInstance.
*
* @return a {@link WritablePdxInstance}
* @throws IllegaStateException if the PdxInstance is an enum.
*/
public WritablePdxInstance createWriter();
}