Interface Property

  • All Superinterfaces:
    Cloneable, Iterable<Property>, Serializable
    All Known Subinterfaces:
    DocumentPart
    All Known Implementing Classes:
    AbstractProperty, ArrayProperty, BinaryProperty, BlobProperty, BlobProperty.ScalarMemberProperty, BooleanProperty, ComplexProperty, DateProperty, DocumentPartImpl, DoubleProperty, ExternalBlobProperty, ListProperty, LongProperty, MapProperty, RemovedProperty, ScalarProperty, StringProperty

    public interface Property
    extends Cloneable, Serializable, Iterable<Property>
    Document properties are instances of document schema fields.

    You can say that a Field object is like a Java class and a Property object like a class instance. Thus, schemas defines fields (or elements) which have a name and a type, and each field of a document can be instantiated (if the schema permits) as a Property object.

    Properties are always bound to a schema field that provides the type and constraints on the property values. An exception is the root property the DocumentPart object which is not bound to a field but to a schema.

    So properties are holding the actual values for each defined field.

    The usual way of using properties is to get a document from the storage server then modify document properties and send them back to the storage server to that modifications are be stored.

    Note that the storage server can be on a remote machine so when modifying properties remotely they are serialized and sent through the network between the two machines. This means properties must hold serializable values and also they must store some state flags so that the storage can decide which property was modified and how in order to correctly update the stored versions.

    As we have seen each property may hold a serializable value which we will refer to as the normalized property value. For each schema field type there is only one java serializable object representation that will be used as the normalized value. The property API is giving you the possibility to use different compatible objects when setting or getting property values. Each property implementation will automatically convert the given value into a normalized one; so internally only the normalized value is stored.

    For example, for date properties you may use either Date or Calendar when setting or retrieving a property value, but the normalized value will be the Calendar one.

    As we have seen, properties keep some state flags. Property flags can be divided in two groups:

    • Dirty Flags - that reflect the public status of the document
    • Internal Flags - that reflect some internal state

    Property Types:

    Before going deeper in property flags, we will talk first about property types. There are several types of properties that are very closed on the type of fields they are bound onto.

    • Root Property (or DocumentPart) - this is a special property that is bound to a schema instead of a field And it is the root of the property tree.
    • Complex Properties - container properties that are bound to complex field types that can be represented as java Map objects. These properties contains a set of schema defined properties. You cannot add new child properties. You can only modify existing child properties. Complex property values are expressed as java Map objects.
      • Structured Properties - this is a special case of complex properties. The difference is that structured property values are expressed as scalar java objects instead of java maps. By scalar java objects we mean any well structured object which is not a container like a Map or a Collection. These objects are usually as scalar values - it doesn't make sense for example to set only some parts of that objects without creating the object completely. An example of usage are Blob properties that use Blob values.
    • List Properties - container properties that are bound to list field types.
    • Scalar Properties - atomic properties that are bound to scalar field types and that are using as values scalar or primitive java objects like arrays, primitives, String, Date etc.

    As we've seen there are 2 categories of properties: container properties and scalar properties Complex and list properties are container properties while structured and scalar properties are scalar.

    Dirty Flags:

    Dirty flags are used to keep track of the dirty state of a property. The following flags are supported:

    • IS_PHANTOM - whether the property is existing in the storage (was explicitly set by the user) or it was dynamically generated using the default value by the implementation to fulfill schema definition. This applies to all property types
    • IS_MODIFIED - whether the property value was modified. This applies to all property types.
    • IS_NEW - whether the property is a new property that was added to a parent list property This applies only to properties that are children of a list property.
    • IS_REMOVED - whether a property was removed. A removed property will be removed from the storage and the next time you access the property it will be a phantom one. This applies only to properties that are children of a complex property.
    • IS_MOVED - whether the property was moved on another position inside the container list. This applies only to properties that are children of a list property.

    There are several constraints on how property flags may change. This is a list of all changes that may occur over dirty flags:

    • NONE + MODIFIED => MODFIED
    • NONE + REMOVED => REMOVED
    • NONE + MOVED => MOVED
    • PHANTOM + MODIFIED => MODIFIED
    • NEW + MODIFIED => NEW | MODIFIED
    • NEW + MOVED => NEW | MOVED
    • MODIFIED + REMOVED => REMOVED
    • MODIFIED + MOVED => MODIFIED | MOVED
    • MODIFIED + MODIFIED => MODIFIED

    The combinations not listed above are not permitted.

    In case of list items, the REMOVED flag is not used since the property will be physically removed from the property tree.

    Also when the dirty flag of a children property changes, its parent is informed to update its MODIFIED flag if needed. This way a modification on a children property is propagated to parents in the form of a MODIFIED flag.

    Internal Flags:

    Internal flags are used by the implementation to keep some internal state. For these flags you should look into the implementation

    Author:
    Bogdan Stefanescu
    See Also:
    "TestPropertyModel for usage of property API"
    • Method Detail

      • isNew

        boolean isNew()
        Tests if this property is new (just created but not yet stored).

        A property is new when added to a collection. This is the typical state for a new property added to a list

        Returns:
        true if this property is new, false otherwise
      • isRemoved

        boolean isRemoved()
        Tests if a property is flagged as removed. Removed properties are child property that were removed from their container.
        Returns:
        if the property was removed, false otherwise
      • isModified

        boolean isModified()
        Tests if a property value was modified.
        Returns:
        if the property was removed, false otherwise
      • isMoved

        boolean isMoved()
        Tests if a property value was moved to another index in the parent list if any.
        Returns:
        if the property was removed, false otherwise
      • isPhantom

        boolean isPhantom()
        Tests if the property is a phantom. This means it doesn't exists yet in the storage and it is not a new property. This is a placeholder for a property that is defined by the schema but was not yet set.
        Returns:
        true if a phantom false otherwise
      • isDirty

        boolean isDirty()
        Tests whether a property is dirty.

        This tests whether or not a dirty flag is set on the property.

        Returns:
        true if the property changed or is new
      • isForceDirty

        boolean isForceDirty()
        only for SimpleDocumentModel
      • setForceDirty

        void setForceDirty​(boolean forceDirty)
        only for SimpleDocumentModel
      • getDirtyFlags

        int getDirtyFlags()
        Get the dirty flags that are set on this property.
        Returns:
        the dirty flags mask
      • clearDirtyFlags

        void clearDirtyFlags()
        Notify the property that its changes was stored so it can safely remove dirty flags.

        Dirty flags are removed according to the type of the modifications. This way if the property was REMOVED it becomes a PHANTOM otherwise all dirty flags are cleared.

        This method should be used by storage implementors to notify the property it should reset its dirty flags. Note that clearing dirty flags is not propagated to the parent property or to children. You need to clear dirty flags explicitly for each property.

      • isReadOnly

        boolean isReadOnly()
        Whether the property is read only.
        Returns:
        true if read only false otherwise
      • setReadOnly

        void setReadOnly​(boolean value)
        Sets the read only flag.
        Parameters:
        value - true to set this property read only false otherwise
      • isSecured

        boolean isSecured()
        Returns true if this property is flagged as secured in system.
        Since:
        11.1
      • isComplex

        boolean isComplex()
        Tests whether this property is of a map (complex) type.
        Returns:
        true if the property is of map type, false otherwise
      • isList

        boolean isList()
        Tests whether this property is of a list type.
        Returns:
        true if the property is of list type, false otherwise
      • isScalar

        boolean isScalar()
        Tests whether this property is of a scalar type.
        Returns:
        true if the property is of a scalar type, false otherwise
      • isContainer

        boolean isContainer()
        Whether this property is a container - this means the property value is a map or a list.

        Container properties don't have a scalar values. Container values are computed each time they are requested - by calling on of the getValue methods - by collecting the values of the child properties.

        Returns:
        true if scalar false otherwise
      • hasDefaultValue

        boolean hasDefaultValue()
        Whether or not this property has a default value. For complex property, this method will lookup in its children.
        Returns:
        true if property has a default value
        Since:
        11.1
      • getName

        String getName()
        Gets the property name.
        Returns:
        the property name
      • getXPath

        String getXPath()
        Gets the xpath of this property.

        The xpath is of the form pref:foo/mylist/123/elem, of note:

        • there is no initial /
        • the schema prefix is only present if a prefix is configured for the base property's schema
        • list elements indexes start at 0
        • list elements aren't using the old syntax foo/bar[123]/baz but the new syntax foo/123/baz
        Returns:
        the xpath
        Since:
        9.1
      • getPath

        @Deprecated
        String getPath()
        Deprecated.
        since 9.1 as it's cumbersome to use; use getXPath() instead
        Gets the path of this property relative to the owner document.

        The path for top level properties is the same to the property name.

        NOTE the path returned contains an initial / and expresses list indexes using an old syntax

        Returns:
        the path
      • getType

        Type getType()
        Get the type of the field corresponding to this property.
        Returns:
        the property type
      • getField

        Field getField()
        Gets the field corresponding to this property.

        The field is the object defining the property. You can see the field as a java class and the property as a class instance

      • getParent

        Property getParent()
        Gets the property parent.
        Returns:
        the property parent for sub properties or null for top level properties
      • getSchema

        Schema getSchema()
        Gets the document schema defining the property tree from which the property belongs.
        Returns:
        the document schema owning the field corresponding to the property
      • init

        void init​(Serializable value)
           throws PropertyException
        Initializes the property with the given normalized value.

        The given value must be normalized - note that no check is done on that.

        The phantom flag is unset by this operation.

        This method should be used to initialize properties.

        Parameters:
        value - the normalized value to set
        Throws:
        PropertyException
      • setValue

        void setValue​(Object value)
               throws PropertyException
        Sets this property value. The value will be first normalized and then set.

        For complex or list properties the value will be set recursively (as a map or list value).

        Parameters:
        value - the value to set
        Throws:
        InvalidPropertyValueException - if the given value type is not compatible with the expected value type
        PropertyException
      • getValue

        <T> T getValue​(Class<T> type)
                throws PropertyException
        Gets the property value as the given type.

        The value is converted using the registered converter to the given type.

        If conversion is not supported a runtime exception will be triggered.

        Returns:
        the property value, which may be null
        Throws:
        PropertyException
      • get

        Property get​(String name)
              throws PropertyNotFoundException
        Gets the child property having the given name.

        If the property is a scalar, this will return always null.

        The given name should be the full name (i.e. prefixed name if any prefix exists).

        If a non prefixed name is given, the first child property having the given local name will be returned.

        Relative paths are not resolved. THis method is intended to lookup direct children. For path lookups use resolvePath(String) instead.

        Parameters:
        name - the child property name (the full name including the prefix if any)
        Returns:
        the child property if any null if no child property with that name is found or if the property is a scalar
        Throws:
        UnsupportedOperationException - if the property is a scalar property (doesn't have children)
        PropertyNotFoundException - if the child property is not found in the type definition
      • set

        void set​(String name,
                 Property property)
          throws PropertyException
        Sets the child property having the given name.

        The given name should be the full name (i.e. prefixed name if any prefix exists).

        If a non prefixed name is given, the first child property having the given local name will be returned.

        Relative paths are not resolved. This method is intended to lookup direct children. For path lookups use resolvePath(String) instead.

        Parameters:
        name - the child property name (the full name including the prefix if any)
        property - the child property to set
        Throws:
        UnsupportedOperationException - if the current property is a scalar property (doesn't have children)
        PropertyNotFoundException - if the child property is not found in the type definition
        PropertyException
        Since:
        11.1
      • getChildren

        Collection<PropertygetChildren()
        Get a collection over the children properties. This includes all children including phantom ones (those who are not yet set by the user).

        The returned collection is ordered for list properties, and unordered for complex properties

        Be aware that this method is creating phantom child properties for all schema fields that are not yet set.

        Returns:
        the children properties
      • size

        int size()
        Get the count of the children properties. This includes phantom properties. So the returned size will be equal to the one returned by the property ComplexType.getFieldsCount().
        Returns:
        the children properties count
      • addValue

        Property addValue​(int index,
                          Object value)
                   throws PropertyException
        Inserts at the given position a new value to the list. A new property will be created to store the given value and appended to the children list.

        The created property will be marked as isNew().

        Parameters:
        index - the position to insert the value
        Returns:
        the added property
        Throws:
        PropertyException
      • moveTo

        void moveTo​(int index)
        Moves a property position into the parent container list.

        This method applies only for list item properties. The given index includes removed properties.

        Parameters:
        index - the position in the parent container to move this property
        Throws:
        UnsupportedOperationException - if the operation is not supported by the target property
      • resolvePath

        Property resolvePath​(Path path)
                      throws PropertyNotFoundException
        Resolves the given path relative to the current property and return the property if any is found otherwise throws an exception.

        The path format is a subset of XPath. Thus, / is used as path element separator, [n] for list element indexes. Attribute separator '@' are not supported since all properties are assumed to be elements. Also you .. and . can be used as element names.

        Example of paths:

        • dc:title
        • attachments/item[2]/mimeType
        • ../dc:title
        Parameters:
        path - the path to resolve.
        Returns:
        the resolved property
        Throws:
        PropertyNotFoundException - if the path cannot be resolved
      • getValue

        <T> T getValue​(Class<T> type,
                       String path)
                throws PropertyException
        Gets the value of the property resolved using the given path.

        The value will be converted to the given type if possible, otherwise an exception will be thrown.

        This method is a shortcut for: resolvePath(path).getValue(type).

        Type Parameters:
        T - The type of the value to return
        Parameters:
        type - the class of the value
        path - the java path of the property value
        Returns:
        the value
        Throws:
        PropertyException
      • setValue

        void setValue​(String path,
                      Object value)
               throws PropertyException
        Sets the value of the property resolved using the given path.

        This method is a shortcut for: resolvePath(path).setValue(value).

        Parameters:
        path - the property path
        value - the value
        Throws:
        PropertyException
      • normalize

        Serializable normalize​(Object value)
                        throws PropertyConversionException
        Normalizes the given value as dictated by the property type.

        Normalized values are the ones that are used for transportation over the net and that are given to the storage implementation to be stored in the repository

        Normalized values must be Serializable

        If the given value is already normalized it will be returned back.

        Parameters:
        value - the value to normalize according to the property type
        Returns:
        the normalized value
        Throws:
        PropertyConversionException
      • isNormalized

        boolean isNormalized​(Object value)
        Checks if the given value is a normalized one. This means the value has a type that is normalized.

        Null values are considered as normalized.

        Parameters:
        value - the value to check
        Returns:
        true if the value is normalized false otherwise
      • convertTo

        <T> T convertTo​(Serializable value,
                        Class<T> toType)
                 throws PropertyConversionException
        Converts the given normalized value to the given type.

        If the value has already the given type it will be returned back.

        Parameters:
        value - the normalized value to convert
        toType - the conversion type
        Returns:
        the converted value, which may be null
        Throws:
        PropertyConversionException - if the conversion cannot be made because of type incompatibilities
      • validateType

        boolean validateType​(Class<?> type)
        Validates the given value type.

        Tests if the given value type can be converted to a normalized type and thus a value of this type can be set to that property.

        Parameters:
        type - the type to validate
        Returns:
        true if the type is valid, false otherwise
      • newInstance

        Object newInstance()
        Creates a new and empty instance of a normalized value.

        Empty is used in the sense of a value that has not been initialized or can be considered as an empty value. For example for the String type the empty value will be the empty string ""

        Returns:
        the empty instance the empty instance, or null for some implementations
      • accept

        void accept​(PropertyVisitor visitor,
                    Object arg)
             throws PropertyException
        Method that implement the visitor pattern.

        The visitor must return null to stop visiting children otherwise a context object that will be passed as the arg argument to children

        Parameters:
        visitor - the visitor to accept
        arg - an argument passed to the visitor. This should be used by the visitor to carry on the visiting context.
        Throws:
        PropertyException