/*
 * Copyright (C) 2005-2010 Alfresco Software Limited.
 *
 * This file is part of Alfresco
 *
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see .
 */
package org.alfresco.repo.props;
import java.io.Serializable;
import org.springframework.dao.DataIntegrityViolationException;
/**
 * A component that gives high-level access to manipulate standalone properties.
 * 
 * There are two types of properties: shared and unshared.
 * 
 * Simple, Shared Properties:
 * These properties are globally unique (apart from values that don't have a meaningful key).
 * If two different applications attempt to create the same value, then the same ID will
 * be returned (after conflict resolution), assuming that the value is not treated as binary
 * data.  It is not possible to modify or delete these values.  You should store types that
 * can be converted to and from a well-known type.  Complex collections should not be stored
 * using this value.
 * Unshared Properties:
 * These properties may be duplicated, modifed and deleted.  It is not possible to look
 * values up and therefore new IDs are generated for each creation.  Complex values can
 * be stored in these properties and will be exploded recursively.
 * 
 * @author Derek Hulley
 * @since 3.2
 */
public interface PropertyValueComponent
{
    /**
     * @param id                the ID (may not be null)
     * @throws DataIntegrityViolationException if the ID is invalid
     */
    Serializable getSharedValueById(Long id);
    /**
     * @param value             the value to find the ID for (may be null)
     * @return                  Returns the ID of the shared value or null if it doesn't exist
     */
    Long getSharedValueId(Serializable value);
    /**
     * @param value             the value to find the ID for (may be null)
     * @return                  Returns the ID of the shared value (created or not)
     */
    Long getOrCreateSharedValue(Serializable value);
    
    /**
     * @param id                the ID (may not be null)
     * @return                  Returns the value of the property (never null)
     * @throws DataIntegrityViolationException if the ID is invalid
     */
    Serializable getUnsharedPropertyById(Long id);
    /**
     * @param value             the value to create (may be null)
     * @return                  Returns the new property's ID
     */
    Long createUnsharedProperty(Serializable value);
    /**
     * @param id                the ID of the root property to change (may not be null)
     * @param value             the new property value
     * @throws DataIntegrityViolationException if the ID is invalid
     */
    void updateUnsharedProperty(Long id, Serializable value);
    /**
     * @param id                the ID of the root property to delete (may be null)
     * @throws DataIntegrityViolationException if the ID is invalid
     */
    void deleteUnsharedProperty(Long id);
    
    /**
     * Create a new combination of three unique properties.
     * 
     * @param value1                the first property, which should denote application name or use-case ID
     *                              (null allowed)
     * @param value2                the second property, which should denote the context or container value
     *                              (null allowed)
     * @param value3                the third property, which should denote the unique value within the context
     *                              of the previous two properties (null allowed)
     * @return                      Returns the ID of the unique property combination for later updates
     * @throws PropertyUniqueConstraintViolation        if the combination is not unique
     */
    Long createPropertyUniqueContext(Serializable value1, Serializable value2, Serializable value3);
    /**
     * Get the ID of a unique property context.
     * 
     * @see #createPropertyUniqueContext(Serializable, Serializable, Serializable)
     */
    Long getPropertyUniqueContext(Serializable value1, Serializable value2, Serializable value3);
    /**
     * Update a unique property context.
     * 
     * @see #createPropertyUniqueContext(Serializable, Serializable, Serializable)
     */
    void updatePropertyUniqueContext(Long id, Serializable value1, Serializable value2, Serializable value3);
    /**
     * Update a combination of three unique properties.  If the before values exist, then they
     * are updated to the new values.  If the before values don't exist, then the new values
     * are created assuming no pre-existence -
     * using {@link #createPropertyUniqueContext(Serializable, Serializable, Serializable) create} is better
     * if there is no pre-existing set of values. 
     * 
     * @param value1Before          the first property before (null allowed)
     * @param value2Before          the second property before (null allowed)
     * @param value3Before          the third property before (null allowed)
     * @param value1                the first property (null allowed)
     * @param value2                the second property (null allowed)
     * @param value3                the third property (null allowed)
     * @return                      Returns the ID of the unique property combination for later updates
     * @throws PropertyUniqueConstraintViolation        if the new combination is not unique
     */
    Long updatePropertyUniqueContext(
            Serializable value1Before, Serializable value2Before, Serializable value3Before,
            Serializable value1, Serializable value2, Serializable value3);
    /**
     * Delete a unique property context.
     * 
     * @see #createPropertyUniqueContext(Serializable, Serializable, Serializable)
     */
    void deletePropertyUniqueContext(Long id);
    /**
     * Delete a combination of three unique properties.  It doesn't matter if the unique combination
     * already existed or not.
     * 
     * @param values                an array of one, two or three values, any of which may be null
     * @return                      Returns the number of unique combinations deleted
     */
    int deletePropertyUniqueContexts(Serializable ... values);
}