| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more contributor license |
| * agreements. See the NOTICE file distributed with this work for additional information regarding |
| * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.pdx; |
| |
| import java.util.List; |
| |
| import org.apache.geode.cache.CacheFactory; |
| import org.apache.geode.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 <code>cache.xml</code> by setting the |
| * attribute <code>read-serialized</code> to true on the <code>pdx</code> 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. |
| * <P> |
| * PdxInstances are immutable. If you want to change one call {@link #createWriter}. |
| * <p> |
| * 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. |
| * |
| * @since GemFire 6.6 |
| */ |
| public interface PdxInstance extends java.io.Serializable { |
| |
| /** |
| * Return the full name of the class that this pdx instance represents. |
| * An empty string will be returned if no class is associated with this instance. |
| * |
| * @return the name of the class that this pdx instance represents. |
| * @since GemFire 6.6.2 |
| */ |
| 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. |
| */ |
| boolean isEnum(); |
| |
| /** |
| * Deserializes and returns the domain object that this instance represents. |
| * If this instance is one that never deserializes then getObject returns "this". |
| * |
| * @return the deserialized domain object or "this" if this instance never deserializes |
| * @throws PdxSerializationException if the instance could not be deserialized |
| */ |
| Object getObject(); |
| |
| /** |
| * Checks if the named field exists and returns the result. |
| * <p> |
| * 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 <code>true</code> if the named field exists; otherwise <code>false</code> |
| */ |
| 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 |
| */ |
| List<String> getFieldNames(); |
| |
| /** |
| * Checks if the named field was {@link PdxWriter#markIdentityField(String) marked} as an identity |
| * field. |
| * <p> |
| * Note that if no fields have been marked then all the fields are used as identity fields even |
| * though this method will return <code>false</code> since none of them have been <em>marked</em>. |
| * |
| * @param fieldName the name of the field to check |
| * @return <code>true</code> if the named field exists and was marked as an identify field; |
| * otherwise <code>false</code> |
| */ |
| boolean isIdentityField(String fieldName); |
| |
| /** |
| * Reads the named field and returns its value. If the field does not exist <code>null</code> is |
| * returned. |
| * <p> |
| * A <code>null</code> result indicates that the field does not exist or that it exists and its |
| * value is currently <code>null</code>. The {@link #hasField(String) hasField} method can be used |
| * to figure out which if these two cases is true. |
| * <p> |
| * If an Object[] is deserialized by this call then that array's component type will be |
| * <code>Object.class</code> 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 |
| * <code>null</code> is returned. |
| * @throws PdxSerializationException if the field could not be deserialized |
| */ |
| Object getField(String fieldName); |
| |
| /** |
| * Returns true if the given object is equals to this instance. |
| * <p> |
| * If <code>other</code> is not a PdxInstance then it is not equal to this instance. NOTE: Even if |
| * <code>other</code> is the result of calling {@link #getObject()} it will not be equal to this |
| * instance. |
| * <p> |
| * Otherwise equality of two PdxInstances is determined as follows: |
| * <ol> |
| * <li>The domain class name must be equal for both PdxInstances |
| * <li>Each identity field must be equal. |
| * </ol> |
| * If the domain class is not the empty string then |
| * 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. |
| * <P> |
| * An identity field is equal if all the following are true: |
| * <ol> |
| * <li>The field name is equal. |
| * <li>The field type is equal. |
| * <li>The field value is equal. |
| * </ol> |
| * <P> |
| * If a field's type is <code>OBJECT</code> 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. |
| * <P> |
| * If a field's type is <code>OBJECT[]</code> then its value must be deserialized and |
| * {@link java.util.Arrays#deepEquals(Object[], Object[]) deepEquals} is used to determine |
| * equality. |
| * <P> |
| * 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. |
| * <P> |
| * 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 <code>true</code> if this instance is equal to <code>other</code>. |
| */ |
| boolean equals(Object other); |
| |
| /** |
| * Generates a hashCode based on the identity fields of this PdxInstance. |
| * <p> |
| * 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. |
| * <p> |
| * If an identity field is of type <code>OBJECT</code> 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. |
| * <p> |
| * If an identity field is of type <code>OBJECT[]</code> this it is deserialized and |
| * {@link java.util.Arrays#deepHashCode(Object[]) deepHashCode} is used. |
| * <p> |
| * Otherwise the field is not deserialized and the raw bytes of its value are used to compute the |
| * hash code. |
| * <p> |
| * 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; } |
| */ |
| int hashCode(); |
| |
| /** |
| * Prints out all of the identity fields of this PdxInstance. |
| * <p> |
| * 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. |
| */ |
| 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 IllegalStateException if the PdxInstance is an enum. |
| */ |
| WritablePdxInstance createWriter(); |
| |
| |
| /** |
| * Returns false if this instance will never be deserialized to a domain class. |
| * Instances that never deserialize can be created using |
| * {@link PdxInstanceFactory#neverDeserialize} or by creating a factory with |
| * an empty string as the class name. |
| * |
| * @return false if this instance will never be deserialized to a domain class. |
| * |
| * @since Geode 1.9 |
| */ |
| default boolean isDeserializable() { |
| return false; |
| } |
| |
| } |