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

com.crankuptheamps.client.fields.BookmarkField Maven / Gradle / Ivy

////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010-2024 60East Technologies Inc., All Rights Reserved.
//
// This computer software is owned by 60East Technologies Inc. and is
// protected by U.S. copyright laws and other laws and by international
// treaties.  This computer software is furnished by 60East Technologies
// Inc. pursuant to a written license agreement and may be used, copied,
// transmitted, and stored only in accordance with the terms of such
// license agreement and with the inclusion of the above copyright notice.
// This computer software or any other copies thereof may not be provided
// or otherwise made available to any other person.
//
// U.S. Government Restricted Rights.  This computer software: (a) was
// developed at private expense and is in all respects the proprietary
// information of 60East Technologies Inc.; (b) was not developed with
// government funds; (c) is a trade secret of 60East Technologies Inc.
// for all purposes of the Freedom of Information Act; and (d) is a
// commercial item and thus, pursuant to Section 12.212 of the Federal
// Acquisition Regulations (FAR) and DFAR Supplement Section 227.7202,
// Government's use, duplication or disclosure of the computer software
// is subject to the restrictions set forth by 60East Technologies Inc..
//
////////////////////////////////////////////////////////////////////////////

package com.crankuptheamps.client.fields;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.zip.CRC32;

/**
 * Field data for a {@link com.crankuptheamps.client.Message} consisting of the bookmark.
 * This is the AMPS Bookmark for the Message.
 */

public class BookmarkField extends StringField implements Cloneable
{
    /**
     * The character used to separate components of a bookmark, and to
     * separate bookmarks from each other in a list.
     */
    public static final char SEPARATOR_CHAR = '|';

    public static final int MAX_BOOKMARK_LENGTH = 42;
    public static final int MAX_TIMESTAMP_LENGTH = 24;
    public static final int MIN_TIMESTAMP_LENGTH = 10;

    /**
     * Overrides the base classes' initial default size for the byte and
     * char conversion buffers used by this instance. Defaults to 42 for
     * this class since bookmark fields are usually no larger than 40 bytes.
     * 
     * @return Returns a default size of 42.
     */
    @Override
    protected int getConversionBufInitialSize() { return 42; }

    /**
     * Constructor with specified buffer, position, and length.
     * @param buffer   The byte array containing the bookmark field.
     * @param position The starting position of the bookmark field
     *                 in the buffer.
     * @param length   The length of the bookmark field.
     */
    protected BookmarkField(byte[] buffer, int position, int length)
    {
        super(buffer, position, length);
    }

    /**
     * Default constructor.
     */
    public BookmarkField()
    {
    }
    
    /**
     * Indicates whether this bookmark value appears to be a timestamp.
     * 
     * @return True if the value looks like an AMPS ISO-8601 timestamp.
     */
    public boolean isTimestamp()
    {
        return length >= MIN_TIMESTAMP_LENGTH
               && buffer[position + 8] == (int)'T';
    }

    /**
     * Indicates whether this bookmark value appears to be a range,
     * using only a simple check for brackets or parentheses.
     *
     * @return True if the value looks like a range.
     */
    public boolean isRange()
    {
        if (length >= 5) {
            int pos = position;
            while (buffer[pos] == ' ') {
                if (++pos >= position + length) return false;
            }
            if (buffer[pos] == '(' || buffer[pos] == '[') {
                pos = position + length - 1;
            }
            while (buffer[pos] == ' ') {
                if (--pos <= position) return false;
            }
            if (buffer[pos] == ')' || buffer[pos] == ']') {
                return true;
            }
        }
        return false;
    }

    /**
     * Gets the publisher id for this bookmark.
     * @return Returns the publisher id for this bookmark.
     */
    public long getPublisherId()
    {
        if (isTimestamp() || isRange()) return 0;
        long result = 0;
        for(int i = this.position; i < this.position + this.length; i++)
        {
            if( this.buffer[i] == (int)SEPARATOR_CHAR )
            {
                break;
            }

            result *= 10;
            result += this.buffer[i] - 48;
        }
        return result;
    }

    /**
     * Gets the sequence number for this bookmark.
     * @return Returns the sequence number for this bookmark.
     */
    public long getSequenceNumber()
    {
        if (isTimestamp() || isRange()) return 0;
        long result = 0;
        int i = this.position;
        for(; i < this.position + this.length; i++)
        {
            if( this.buffer[i] == (int)SEPARATOR_CHAR )
            {
                break;
            }
        }

        for(i = i+1; i < this.position + this.length; i++)
        {
            if( this.buffer[i] == (int)SEPARATOR_CHAR )
            {
                break;
            }
            result *= 10;
            result += this.buffer[i] - 48;
        }

        return result;
    }

    /**
     * Compare two signed long values as unsigned long values;
     * the publisherId_ and sequence are signed in java, but the actual values
     * are unsigned, so we have to do some work to compare them.
     * @param seqLeft_ The value being compared.
     * @param seqRight_ The value to compare to.
     * @return true if seqLeft_ is less than seqRight_ as unsigned long values.
     */
    public static boolean unsignedLongLess(long seqLeft_, long seqRight_)
    {
        final BigInteger offset = BigInteger.valueOf(Long.MAX_VALUE)
                .shiftLeft(1).add(BigInteger.valueOf(2));
        if(seqLeft_<0 || seqRight_<0)
        {
            BigInteger left = offset.add(BigInteger.valueOf(seqLeft_));
            BigInteger right = offset.add(BigInteger.valueOf(seqRight_));
            return left.compareTo(right) < 0;
        }
        else
        {
            return seqLeft_ < seqRight_;
        }
    }

    /**
     * Compare two signed long values as unsigned long values;
     * the publisherId_ and sequence are signed in java, but the actual values
     * are unsigned, so we have to do some work to compare them.
     * @param seqLeft_ The value being compared.
     * @param seqRight_ The value to compare to.
     * @return true if seqLeft_ is less than or equal to seqRight_ as unsigned long values.
     */
    public static boolean unsignedLongLessEqual(long seqLeft_, long seqRight_)
    {
        final BigInteger offset = BigInteger.valueOf(Long.MAX_VALUE)
                .shiftLeft(1).add(BigInteger.valueOf(2));
        if(seqLeft_<0 || seqRight_<0)
        {
            BigInteger left = offset.add(BigInteger.valueOf(seqLeft_));
            BigInteger right = offset.add(BigInteger.valueOf(seqRight_));
            return left.compareTo(right) <= 0;
        }
        else
        {
            return seqLeft_ <= seqRight_;
        }
    }

    public boolean isBookmarkList()
    {
        for (int comma=position; comma parseBookmarkList()
    {
        ArrayList bookmarks = new ArrayList();
        int start = position;
        int comma = position;
        for ( ; comma start) {
            bookmarks.add(new BookmarkField(buffer, start, comma-start));
        }
        return bookmarks;
    }

    protected final CRC32 c = new CRC32();

    /**
     * Calculates the hash code for the bookmark field.
     *
     * @return The hash code of the bookmark field.
     */
    public int hashCode()
    {
        c.reset();
        c.update(buffer, position, length);
        return (int)c.getValue();
    }


    /**
     * Provides a way to duplicate this object and retain its specific type (and hashcode() implementation).
     */
    public BookmarkField clone()
    {
        byte[] copy = null;

        if (buffer != null) {
            copy = new byte[length];
            System.arraycopy(buffer, position, copy, 0, length);
        }
        return new BookmarkField(copy, 0, length);
    }

    /**
     * Override base class's copy() method appropriately, so we don't inadvertently mix
     * BookmarkFields and Fields up -- they have different hashCode implementations.
     */
    public BookmarkField copy()
    {
        return clone();
    }

    /**
     * Checks if the bookmark field is equal to another object.
     *
     * @param object_ The object to compare.
     * @return {@code true} if the bookmark field is equal to the specified object, {@code false} otherwise.
     */
    @Override
    public boolean equals(Object object_)
    {
        return super.equals(object_);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy