All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tangosol.util.processor.VersionedPutAll Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

package com.tangosol.util.processor;


import com.tangosol.io.ExternalizableLite;

import com.tangosol.io.pof.PofReader;
import com.tangosol.io.pof.PofWriter;
import com.tangosol.io.pof.PortableObject;

import com.tangosol.util.ClassHelper;
import com.tangosol.util.ExternalizableHelper;
import com.tangosol.util.InvocableMap;
import com.tangosol.util.LiteMap;
import com.tangosol.util.Versionable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.json.bind.annotation.JsonbProperty;


/**
* VersionedPutAll is an EntryProcessor that assumes that entry values
* implement {@link com.tangosol.util.Versionable} interface and performs an
* {@link com.tangosol.util.InvocableMap.Entry#setValue(Object)
* Entry.setValue} operation only for entries whose versions match to versions
* of the corresponding current values. In case of the match, the
* VersionedPutAll will increment the version indicator before each value is
* updated.
*
* @see VersionedPut
* @author gg 2006.05.07
* @since Coherence 3.2
*/
public class VersionedPutAll
        extends    AbstractProcessor
        implements ExternalizableLite, PortableObject
    {
    // ----- constructors ---------------------------------------------------

    /**
    * Default constructor (necessary for the ExternalizableLite interface).
    */
    public VersionedPutAll()
        {
        }

    /**
    * Construct a VersionedPutAll processor that updates an entry with a new
    * value if and only if the version of the new value matches to the
    * version of the current entry's value (which must exist).
    * The result of the {@link #process} invocation does not return any
    * result.
    *
    * @param map a map of values to update entries with
    */
    public VersionedPutAll(Map map)
        {
        this(map, false, false);
        }

    /**
    * Construct a VersionedPutAll processor that updates an entry with a new
    * value if and only if the version of the new value matches to the
    * version of the current entry's value (which must exist). This processor
    * optionally returns a map of entries that have not been updated (the
    * versions did not match).
    *
    * @param map           a map of values to update entries with
    * @param fAllowInsert  specifies whether or not an insert should be
    *                      allowed (no currently existing value)
    * @param fReturn       specifies whether or not the processor should
    *                      return the entries that have not been updated
    */
    public VersionedPutAll(Map map, boolean fAllowInsert, boolean fReturn)
        {
        azzert(map != null, "Map is null");

        m_map     = new HashMap(map);
        m_fInsert = fAllowInsert;
        m_fReturn = fReturn;
        }


    // ----- EntryProcessor interface ---------------------------------------

    /**
    * {@inheritDoc}
    */
    public V process(InvocableMap.Entry entry)
        {
        Object oResult = processEntry(entry, m_map, m_fInsert, m_fReturn);
        return oResult == NO_RESULT ? null : (V) oResult;
        }

    /**
    * {@inheritDoc}
    */
    public Map processAll(Set> setEntries)
        {
        Map     mapResult = new LiteMap();
        Map     mapAll    = m_map;
        boolean fInsert   = m_fInsert;
        boolean fReturn   = m_fReturn;

        for (Iterator iter = setEntries.iterator(); iter.hasNext();)
            {
            InvocableMap.Entry entry = (InvocableMap.Entry) iter.next();

            Object oResult = processEntry(entry, mapAll, fInsert, fReturn);

            if (oResult != NO_RESULT)
                {
                mapResult.put(entry.getKey(), oResult);
                }
            }

        return mapResult;
        }


// ----- Object methods -------------------------------------------------

    /**
    * Compare the VersionedPutAll with another object to determine equality.
    *
    * @return true iff this VersionedPutAll and the passed object are
    *         equivalent VersionedPutAll
    */
    public boolean equals(Object o)
        {
        if (o instanceof VersionedPutAll)
            {
            VersionedPutAll that = (VersionedPutAll) o;
            return equals(this.m_map,       that.m_map)
                &&        this.m_fInsert == that.m_fInsert
                &&        this.m_fReturn == that.m_fReturn;
            }

        return false;
        }

    /**
    * Determine a hash value for the VersionedPutAll object according to the
    * general {@link Object#hashCode()} contract.
    *
    * @return an integer hash value for this VersionedPutAll object
    */
    public int hashCode()
        {
        return m_map.hashCode() + (m_fInsert ? 1 : 2) + (m_fReturn ? 3 : 4);
        }

    /**
    * Return a human-readable description for this VersionedPutAll.
    *
    * @return a String description of the VersionedPutAll
    */
    public String toString()
        {
        return ClassHelper.getSimpleName(getClass()) +
            "{InsertAllowed="   + m_fInsert +
            ", ReturnRequired=" + m_fReturn +
            ", Map=" + m_map + '}';
        }


    // ----- ExternalizableLite interface -----------------------------------

    /**
    * {@inheritDoc}
    */
    public void readExternal(DataInput in)
            throws IOException
        {
        Map map = m_map = new HashMap();
        ExternalizableHelper.readMap(in, map, null);
        m_fInsert = in.readBoolean();
        m_fReturn = in.readBoolean();
        }

    /**
    * {@inheritDoc}
    */
    public void writeExternal(DataOutput out)
            throws IOException
        {
        ExternalizableHelper.writeMap(out, m_map);
        out.writeBoolean(m_fInsert);
        out.writeBoolean(m_fReturn);
        }


    // ----- PortableObject interface ---------------------------------------

    /**
    * {@inheritDoc}
    */
    public void readExternal(PofReader in)
            throws IOException
        {
        m_map     = in.readMap(0, new HashMap());
        m_fInsert = in.readBoolean(1);
        m_fReturn = in.readBoolean(2);
        }

    /**
    * {@inheritDoc}
    */
    public void writeExternal(PofWriter out)
            throws IOException
        {
        out.writeMap(0, m_map);
        out.writeBoolean(1, m_fInsert);
        out.writeBoolean(2, m_fReturn);
        }


    // ----- helper methods -------------------------------------------------

    /**
    * Process the given entry.
    *
    * @param entry   entry the entry to be processed
    * @param mapAll  the map of new values
    * @param fInsert specifies whether or not an insert is allowed
    * @param fReturn specifies whether or not a return value is required
    *
    * @return the result of processing the entry; can be NO_RESULT
    */
    protected Object processEntry(InvocableMap.Entry entry, Map mapAll,
                                  boolean fInsert,  boolean fReturn)
        {
        K oKey = entry.getKey();

        if (mapAll.containsKey(oKey))
            {
            V oValueCur = entry.getValue();
            V oValueNew = mapAll.get(oKey);
            boolean     fMatch;

            if (oValueCur == null)
                {
                fMatch = fInsert;
                }
            else
                {
                Comparable verCur = oValueCur.getVersionIndicator();
                Comparable verNew = oValueNew.getVersionIndicator();

                fMatch = verCur.compareTo(verNew) == 0;
                }

            if (fMatch)
                {
                oValueNew.incrementVersion();
                entry.setValue(oValueNew, false);
                return NO_RESULT;
                }
            return fReturn ? oValueCur : NO_RESULT;
            }

        return NO_RESULT;
        }


    // ----- constants ------------------------------------------------------

    /**
    * Used internally to differentiate between "no result" and a null result.
    * NO_RESULT should never be returned through the public APIs.
    * A value of NO_RESULT may be returned from processEntry() and will
    * never be included in the result map returned from processAll().
    */
    private static final Object NO_RESULT = new Object();


    // ----- data members ---------------------------------------------------

    /**
    * Specifies the map of new values.
    */
    @JsonbProperty("entries")
    protected Map m_map;

    /**
    * Specifies whether or not an insert is allowed.
    */
    @JsonbProperty("insert")
    protected boolean m_fInsert;

    /**
    * Specifies whether or not a return value is required.
    */
    @JsonbProperty("return")
    protected boolean m_fReturn;
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy