Initial commit from SVN.
This commit is contained in:
706
Common/src/com/common/util/AdvancedTextParser.java
Normal file
706
Common/src/com/common/util/AdvancedTextParser.java
Normal file
@@ -0,0 +1,706 @@
|
||||
/*
|
||||
* Copyright (c) 2003,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* This string parser uses delimiter strings to parse a source character data into segements.
|
||||
* While the string parser is not thread safe, the set of delimiters is since it cannot be modified once used. Therefore you may create multiple string parsers using the same delimiter set at the same time.<p>
|
||||
* <p><b>WARNING: This class is NOT thread safe.</b></p>
|
||||
* <p><b>WARNING: This class is NOT serializable.</b></p>
|
||||
*/
|
||||
public class AdvancedTextParser {
|
||||
private String source = null; //The source string to parse.//
|
||||
private int currentPosition = 0; //The current position in the parsed string. This index is of the next character in the string that has NOT been looked at.//
|
||||
private int firstPosition = 0; //The first position in the parsed string.//
|
||||
private int lastPosition = 0; //The last position in the parsed string.//
|
||||
private boolean isLastDelimiter = false; //Whether the last element returned was a delimiter.//
|
||||
private DelimiterSet delimiterSet = null; //The set of delimiters used by the parser.//
|
||||
private final CharacterHolder characterHolder = new CharacterHolder(); //A simple holder for characters used when querying the delimiter tree. This saves on GC time and is allowed because this class is NOT thread safe.//
|
||||
private DelimiterEndNode nextDelimiter = null; //The next known delimiter in the source. If there are no more delimiters this will be null and the nextDelimiterPosition will be -1; otherwise this will be null if the next delimiter has not yet be located.//
|
||||
private int nextDelimiterPosition = 0; //The position of the next delimiter. This will only be -1 if there are no more delimiters. This is not valid if nextDelimiter is null.//
|
||||
private int lastDelimiterIdentifier = 0; //The user assigned number associated with the last delimiter returned by this parser. Delimiters not returned by the parser are ignored. A value of zero indicates an unknown identifier.//
|
||||
private int[] previousPositions = null; //The beginning position of the last parsed segment.//
|
||||
|
||||
public static class DelimiterSet {
|
||||
private LiteHashMap rootMap = null; //The root map of character holders to delimiter nodes for the set.//
|
||||
private boolean isImmutable = false; //Whether the set cannot be modified. This will be automatically set to true when the set is first used.//
|
||||
|
||||
private DelimiterSet() {
|
||||
rootMap = new LiteHashMap(9);
|
||||
}//DelimiterSet()//
|
||||
}//DelimiterSet//
|
||||
private static class CharacterHolder {
|
||||
private char character;
|
||||
|
||||
private CharacterHolder() {
|
||||
}//CharacterHolder()//
|
||||
private CharacterHolder(char character) {
|
||||
this.character = character;
|
||||
}//CharacterHolder()//
|
||||
public int hashCode() {
|
||||
return (int) character;
|
||||
}//hashCode()//
|
||||
public boolean equals(Object object) {
|
||||
return (object instanceof CharacterHolder) && (((CharacterHolder) object).character == character);
|
||||
}//equals()//
|
||||
public String toString() {
|
||||
return "" + character;
|
||||
}//toString()//
|
||||
}//CharacterHolder//
|
||||
private static class DelimiterNode {
|
||||
private LiteHashMap characterMap = null;
|
||||
private DelimiterEndNode endNode = null;
|
||||
private DelimiterNode parent = null;
|
||||
|
||||
protected DelimiterNode() {
|
||||
}//DelimiterNode()//
|
||||
protected DelimiterNode(DelimiterNode parent) {
|
||||
this.parent = parent;
|
||||
}//DelimiterNode()//
|
||||
protected DelimiterNode(DelimiterEndNode endNode) {
|
||||
this.endNode = endNode;
|
||||
}//DelimiterNode()//
|
||||
private DelimiterNode(DelimiterNode parent, DelimiterEndNode endNode) {
|
||||
this.parent = parent;
|
||||
this.endNode = endNode;
|
||||
}//DelimiterNode()//
|
||||
}//DelimiterNode//
|
||||
private static class DelimiterEndNode {
|
||||
private String delimiter = null;
|
||||
private int identifier = 0;
|
||||
private boolean returnDelimiter = false;
|
||||
private boolean ignoreCase = false;
|
||||
private boolean requiresTerminationValidation = false; //Whether terminating characters must be verified.//
|
||||
private boolean canOccurAtSourceEnd = false;
|
||||
private LiteHashSet terminatingCharacters = null; //A map of characters that are allowed to terminate the delimiter (not included in the delimiter). This is null if it does not apply to this delimiter.//
|
||||
private IList terminatingStrings = null; //A list of terminating strings that are allowed to terminate the delimiter. All strings will be longer than one character. This may be null if it does not apply.//
|
||||
|
||||
private DelimiterEndNode() {
|
||||
}//DelimiterEndNode()//
|
||||
private DelimiterEndNode(String delimiter, boolean returnDelimiter, boolean ignoreCase, IList terminators, int identifier) {
|
||||
this.delimiter = delimiter;
|
||||
this.returnDelimiter = returnDelimiter;
|
||||
this.ignoreCase = ignoreCase;
|
||||
this.identifier = identifier;
|
||||
|
||||
if((terminators != null) && (terminators.getSize() > 0)) {
|
||||
IIterator iterator = terminators.iterator();
|
||||
|
||||
requiresTerminationValidation = true;
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
String next = (String) iterator.next();
|
||||
|
||||
if((next == null) || (next.length() == 0)) {
|
||||
canOccurAtSourceEnd = true;
|
||||
}//if//
|
||||
else if(next.length() == 1) {
|
||||
if(terminatingCharacters == null) {
|
||||
terminatingCharacters = new LiteHashSet(7);
|
||||
}//if//
|
||||
|
||||
terminatingCharacters.add(new CharacterHolder(next.charAt(0)));
|
||||
}//if//
|
||||
else {
|
||||
if(terminatingStrings == null) {
|
||||
terminatingStrings = new LiteList(5, 10);
|
||||
}//if//
|
||||
|
||||
terminatingStrings.add(next);
|
||||
}//else//
|
||||
}//while//
|
||||
}//if//
|
||||
}//DelimiterEndNode()//
|
||||
}//DelimiterEndNode//
|
||||
/**
|
||||
* Constructs a parser for the specified source.
|
||||
* @param source The source to parse.
|
||||
*/
|
||||
public AdvancedTextParser(String source) {
|
||||
this(source, 1);
|
||||
}//AdvancedTextParser()//
|
||||
/**
|
||||
* Constructs a parser for the specified source.
|
||||
* @param source The source to parse.
|
||||
* @param previousPositionCount The number of previous positions to track. If this is 2 for example, then the last two positions in the source will be saved and will be retrievable.
|
||||
*/
|
||||
public AdvancedTextParser(String source, int previousPositionCount) {
|
||||
setSource(source);
|
||||
previousPositions = new int[previousPositionCount < 1 ? 1 : previousPositionCount];
|
||||
}//AdvancedTextParser()//
|
||||
/**
|
||||
* Constructs a parser for the specified source.
|
||||
* <p><b>WARNING: Once used, the delimiter set cannot be changed. All additions to the set must occur before using the set.</b>
|
||||
* @param source The source to parse.
|
||||
* @param previousPositionCount The number of previous positions to track. If this is 2 for example, then the last two positions in the source will be saved and will be retrievable.
|
||||
* @param delimiterSet The set of all delimiters used to parse the source. This set may be changed at any time while parsing.
|
||||
*/
|
||||
public AdvancedTextParser(String source, int previousPositionCount, DelimiterSet delimiterSet) {
|
||||
setSource(source);
|
||||
setDelimiterSet(delimiterSet);
|
||||
previousPositions = new int[previousPositionCount < 1 ? 1 : previousPositionCount];
|
||||
}//AdvancedTextParser()//
|
||||
/**
|
||||
* Constructs a parser for the specified source.
|
||||
* <p><b>WARNING: Once used, the delimiter set cannot be changed. All additions to the set must occur before using the set.</b>
|
||||
* @param source The source to parse.
|
||||
* @param delimiterSet The set of all delimiters used to parse the source. This set may be changed at any time while parsing.
|
||||
*/
|
||||
public AdvancedTextParser(String source, DelimiterSet delimiterSet) {
|
||||
this(source, 1, delimiterSet);
|
||||
}//AdvancedTextParser()//
|
||||
/**
|
||||
* Adds a delimiter to the collection.
|
||||
* @param delimiterSet The set of delimiters to add the delimiter to. This may be null in which case a new set will be created.
|
||||
* @param delimiter The delimiter string to add to the collection of delimiters.
|
||||
* @param returnable Whether the delimiter should be returned by the parser when it is found. If this is false then this delimiter will be ignored and will mearly separate other content.
|
||||
* @param terminators The collection of strings that can terminate the delimiter. This may be null if any character may terminate the delimiter. A null of empty terminator indicates that the delimiter can occur as the last characters in the source.
|
||||
* @return The updated delimiter set. This should be used in place of the set passed to this method for future calls since it may or may not be the same object as the passed set.
|
||||
*/
|
||||
public static DelimiterSet addDelimiter(DelimiterSet delimiterSet, String delimiter, boolean returnable, boolean ignoreCase, IList terminators) {
|
||||
if(delimiterSet == null) {
|
||||
delimiterSet = new DelimiterSet();
|
||||
}//if//
|
||||
|
||||
if(delimiterSet.isImmutable) {
|
||||
throw new RuntimeException("Cannot modify an immutable delimiter set.");
|
||||
}//if//
|
||||
|
||||
internalAddDelimiter(delimiterSet, delimiter, returnable, ignoreCase, terminators, 0);
|
||||
|
||||
return delimiterSet;
|
||||
}//addDelimiter()//
|
||||
/**
|
||||
* Adds a delimiter to the collection.
|
||||
* @param delimiterSet The set of delimiters to add the delimiter to. This may be null in which case a new set will be created.
|
||||
* @param delimiter The delimiter string to add to the collection of delimiters.
|
||||
* @param returnable Whether the delimiter should be returned by the parser when it is found. If this is false then this delimiter will be ignored and will mearly separate other content.
|
||||
* @param terminators The collection of strings that can terminate the delimiter. This may be null if any character may terminate the delimiter. A null of empty terminator indicates that the delimiter can occur as the last characters in the source.
|
||||
* @param identifier The identifier associated with the delimiter. This must be a value greater than zero (zero is used for unknown).
|
||||
* @return The updated delimiter set. This should be used in place of the set passed to this method for future calls since it may or may not be the same object as the passed set.
|
||||
*/
|
||||
public static DelimiterSet addDelimiter(DelimiterSet delimiterSet, String delimiter, boolean returnable, boolean ignoreCase, IList terminators, int identifier) {
|
||||
if(delimiterSet == null) {
|
||||
delimiterSet = new DelimiterSet();
|
||||
}//if//
|
||||
|
||||
if(delimiterSet.isImmutable) {
|
||||
throw new RuntimeException("Cannot modify an immutable delimiter set.");
|
||||
}//if//
|
||||
|
||||
internalAddDelimiter(delimiterSet, delimiter, returnable, ignoreCase, terminators, identifier);
|
||||
|
||||
return delimiterSet;
|
||||
}//addDelimiter()//
|
||||
/**
|
||||
* Adds delimiters to the collection.
|
||||
* @param delimiterSet The set of delimiters to add the delimiter to. This may be null in which case a new set will be created.
|
||||
* @param delimiters The delimiter strings to add to the collection of delimiters.
|
||||
* @param returnable Whether the delimiter should be returned by the parser when it is found. If this is false then this delimiter will be ignored and will mearly separate other content.
|
||||
* @param terminators The collection of strings that can terminate the delimiter. This may be null if any character may terminate the delimiter. A null of empty terminator indicates that the delimiter can occur as the last characters in the source.
|
||||
* @return The updated delimiter set. This should be used in place of the set passed to this method for future calls since it may or may not be the same object as the passed set.
|
||||
*/
|
||||
public static DelimiterSet addDelimiters(DelimiterSet delimiterSet, String[] delimiters, boolean returnable, boolean ignoreCase, IList terminators) {
|
||||
if(delimiterSet == null) {
|
||||
delimiterSet = new DelimiterSet();
|
||||
}//if//
|
||||
|
||||
if(delimiterSet.isImmutable) {
|
||||
throw new RuntimeException("Cannot modify an immutable delimiter set.");
|
||||
}//if//
|
||||
|
||||
for(int index = 0; index < delimiters.length; index++) {
|
||||
internalAddDelimiter(delimiterSet, delimiters[index], returnable, ignoreCase, terminators, 0);
|
||||
}//for//
|
||||
|
||||
return delimiterSet;
|
||||
}//addDelimiters()//
|
||||
/**
|
||||
* Adds delimiters to the collection.
|
||||
* @param delimiterSet The set of delimiters to add the delimiter to. This may be null in which case a new set will be created.
|
||||
* @param delimiters The delimiter strings to add to the collection of delimiters.
|
||||
* @param returnable Whether the delimiter should be returned by the parser when it is found. If this is false then this delimiter will be ignored and will mearly separate other content.
|
||||
* @param terminators The collection of strings that can terminate the delimiter. This may be null if any character may terminate the delimiter. A null of empty terminator indicates that the delimiter can occur as the last characters in the source.
|
||||
* @return The updated delimiter set. This should be used in place of the set passed to this method for future calls since it may or may not be the same object as the passed set.
|
||||
*/
|
||||
public static DelimiterSet addDelimiters(DelimiterSet delimiterSet, IList delimiters, boolean returnable, boolean ignoreCase, IList terminators) {
|
||||
IIterator iterator = delimiters.iterator();
|
||||
|
||||
if(delimiterSet == null) {
|
||||
delimiterSet = new DelimiterSet();
|
||||
}//if//
|
||||
|
||||
if(delimiterSet.isImmutable) {
|
||||
throw new RuntimeException("Cannot modify an immutable delimiter set.");
|
||||
}//if//
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
internalAddDelimiter(delimiterSet, (String) iterator.next(), returnable, ignoreCase, terminators, 0);
|
||||
}//while//
|
||||
|
||||
return delimiterSet;
|
||||
}//addDelimiters()//
|
||||
/**
|
||||
* Gets the parser's current position in the string.
|
||||
* @return The current index in the string (points to the next character to be looked at).
|
||||
*/
|
||||
public int getCurrentPosition() {
|
||||
return currentPosition;
|
||||
}//getCurrentPosition()//
|
||||
/**
|
||||
* Gets the set of delimiters that is being used to parse the source from the current position.
|
||||
* @return The immutable set of all delimiters used in parsing the source from the current source location (previous parsing may have already occured).
|
||||
*/
|
||||
public DelimiterSet getDelimiterSet() {
|
||||
return delimiterSet;
|
||||
}//getDelimiterSet()//
|
||||
/**
|
||||
* Gets the parser's first character position in the source string.
|
||||
* @return The first read index in the source string.
|
||||
*/
|
||||
public int getFirstPosition() {
|
||||
return firstPosition;
|
||||
}//getFirstPosition()//
|
||||
/**
|
||||
* Gets the last delimiter's identifier.
|
||||
* @return The user assigned identifier of the last returned delimiter. The value is zero if no delimiters have been retrieved yet or if the last delimiter was not assigned an identifier.
|
||||
* @see #isLastDelimiter()
|
||||
*/
|
||||
public int getLastDelimiterIdentifier() {
|
||||
return lastDelimiterIdentifier;
|
||||
}//getLastDelimiterIdentifier()//
|
||||
/**
|
||||
* Gets the parser's last character position in the source string.
|
||||
* @return The last read index in the source string.
|
||||
*/
|
||||
public int getLastPosition() {
|
||||
return lastPosition;
|
||||
}//getLastPosition()//
|
||||
/**
|
||||
* Gets the location of a previously returned source segment.
|
||||
* The index will be of the first character in the segment.
|
||||
* How many steps backward the user can go is dependant on the <code>previousPositionCount</code> parameter passed in the constructor (defaults to 1).
|
||||
* @param stepCount The number of steps backward in the parser where a value of zero indicates the most recently parsed segement.
|
||||
* @return The index of the first character in the most recently returned source segment. This will be zero if there is no previous segment.
|
||||
*/
|
||||
public int getPreviousPosition(int stepCount) {
|
||||
return previousPositions[stepCount];
|
||||
}//getPreviousPosition()//
|
||||
/**
|
||||
* Gets the source string being parsed.
|
||||
* @return The string being parsed into segments.
|
||||
*/
|
||||
public String getSource() {
|
||||
return source;
|
||||
}//getSource()//
|
||||
/**
|
||||
* Determines whether there is a next segment.
|
||||
* @return Whether there is another string segment to be returned by the next() method.
|
||||
* @see #next()
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
//If the next delimiter is unkown then locate it.//
|
||||
if((nextDelimiter == null) && (nextDelimiterPosition != -1)) {
|
||||
locateNextDelimiter();
|
||||
}//if//
|
||||
|
||||
//Ignore hidden delimiters.//
|
||||
while((nextDelimiterPosition == currentPosition) && (!nextDelimiter.returnDelimiter)) {
|
||||
currentPosition += nextDelimiter.delimiter.length();
|
||||
locateNextDelimiter();
|
||||
}//while//
|
||||
|
||||
//Determine whether there are more source characters left (that are not hidden).//
|
||||
return currentPosition <= lastPosition;
|
||||
}//hasNext()//
|
||||
/**
|
||||
* Recusivly builds the delimiter tree for the give end node.
|
||||
* @param character The next character in the delimiter. This character should not be modified.
|
||||
* @param characterMap The hashmap to place the delimiter within.
|
||||
* @param previousNode The last node in the tree that was checked for the given end node.
|
||||
* @param endNode The end node that requires placement.
|
||||
* @param index The index of the next character in the end node's delimiter. This also is the depth within the tree.
|
||||
* @param ignoreCase Whether the delimiter character case should be ignored. This should only be true if necessary since it can dramatically increase the size of the delimiter tree structure.
|
||||
*/
|
||||
private static void internalAddDelimiter(char character, LiteHashMap characterMap, DelimiterNode previousNode, DelimiterEndNode endNode, int index, boolean ignoreCase) {
|
||||
DelimiterNode node = null;
|
||||
CharacterHolder characterHolder = new CharacterHolder(character);
|
||||
|
||||
node = (DelimiterNode) characterMap.get(characterHolder);
|
||||
|
||||
if(node == null) {
|
||||
//It does not matter how long the delimiter since there is currently only one with this starting character.//
|
||||
characterMap.put(characterHolder, new DelimiterNode(previousNode, endNode));
|
||||
}//if//
|
||||
else {
|
||||
//Shift the node's end node if necessary to a lower position in the tree.//
|
||||
if((node.endNode != null) && (node.endNode.delimiter.length() > index)) {
|
||||
internalAddDelimiter(node, node.endNode, index, ignoreCase);
|
||||
node.endNode = null;
|
||||
}//if//
|
||||
|
||||
//If the new end node has a length greater than the index then push it farther down in the tree.//
|
||||
if(endNode.delimiter.length() > index) {
|
||||
internalAddDelimiter(node, endNode, index, ignoreCase);
|
||||
}//if//
|
||||
else {
|
||||
//Since the node has a length equal to index then we will place it here in the tree.//
|
||||
node.endNode = endNode;
|
||||
}//else//
|
||||
}//else//
|
||||
}//internalAddDelimiter()//
|
||||
/**
|
||||
* Recusivly builds the delimiter tree for the give end node.
|
||||
* @param previousNode The last node in the tree that was checked for the given end node.
|
||||
* @param endNode The end node that requires placement.
|
||||
* @param index The index of the next character in the end node's delimiter. This also is the depth within the tree.
|
||||
* @param ignoreCase Whether the delimiter character case should be ignored. This should only be true if necessary since it can dramatically increase the size of the delimiter tree structure.
|
||||
*/
|
||||
private static void internalAddDelimiter(DelimiterNode previousNode, DelimiterEndNode endNode, int index, boolean ignoreCase) {
|
||||
char character;
|
||||
|
||||
if(previousNode.characterMap == null) {
|
||||
previousNode.characterMap = new LiteHashMap(4);
|
||||
}//if//
|
||||
|
||||
//Get the next character in the delimiter and increment the character index.//
|
||||
character = endNode.delimiter.charAt(index++);
|
||||
|
||||
//Determine how to add the delimiter to the root mapping based on whether the case is ignored.//
|
||||
if((ignoreCase) && (Character.isLetter(character))) {
|
||||
internalAddDelimiter(Character.toUpperCase(character), previousNode.characterMap, previousNode, endNode, index, ignoreCase);
|
||||
internalAddDelimiter(Character.toLowerCase(character), previousNode.characterMap, previousNode, endNode, index, ignoreCase);
|
||||
}//if//
|
||||
else {
|
||||
internalAddDelimiter(character, previousNode.characterMap, previousNode, endNode, index, ignoreCase);
|
||||
}//else//
|
||||
}//internalAddDelimiter()//
|
||||
/**
|
||||
* Adds a delimiter to the collection.
|
||||
* @param delimiterSet The set of delimiters to add the delimiter to.
|
||||
* @param delimiter The delimiter string to add to the collection of delimiters.
|
||||
* @param returnable Whether the delimiter should be returned by the parser when it is found. If this is false then this delimiter will be ignored and will mearly separate other content.
|
||||
* @param ignoreCase Whether the delimiter character case should be ignored. This should only be true if necessary since it can dramatically increase the size of the delimiter tree structure.
|
||||
* @param terminators The collection of strings that can terminate the delimiter. This may be null if any character may terminate the delimiter. A null of empty terminator indicates that the delimiter can occur as the last characters in the source.
|
||||
* @param identifier The number assigned to this delimiter. A value of zero indicates an unknown delimiter. The value should be positive and should not overlap with other identifiers. It is up to the application to validate these values.
|
||||
*/
|
||||
private static void internalAddDelimiter(DelimiterSet delimiterSet, String delimiter, boolean returnable, boolean ignoreCase, IList terminators, int identifier) {
|
||||
DelimiterEndNode endNode = new DelimiterEndNode(delimiter, returnable, ignoreCase, terminators, identifier);
|
||||
char character;
|
||||
|
||||
//Check for programmer errors.//
|
||||
if((delimiter == null) || (delimiter == "")) {
|
||||
throw new RuntimeException("Invalid delimiter");
|
||||
}//if//
|
||||
|
||||
character = delimiter.charAt(0);
|
||||
|
||||
//Determine how to add the delimiter to the root mapping based on whether the case is ignored.//
|
||||
if((ignoreCase) && (Character.isLetter(character))) {
|
||||
internalAddDelimiter(Character.toUpperCase(character), delimiterSet.rootMap, null, endNode, 1, ignoreCase);
|
||||
internalAddDelimiter(Character.toLowerCase(character), delimiterSet.rootMap, null, endNode, 1, ignoreCase);
|
||||
}//if//
|
||||
else {
|
||||
internalAddDelimiter(character, delimiterSet.rootMap, null, endNode, 1, ignoreCase);
|
||||
}//else//
|
||||
}//internalAddDelimiter()//
|
||||
/**
|
||||
* Determines whether the last element returned was a delimiter element.
|
||||
* @return Whether the last element was a delimiter element.
|
||||
*/
|
||||
public boolean isLastDelimiter() {
|
||||
return isLastDelimiter;
|
||||
}//isLastDelimiter()//
|
||||
/**
|
||||
* Determines whether the next element returned is going to be a delimiter element.
|
||||
* @return Whether the next element will be a delimiter element. This will always be false if all delimiters are not ever returned. This will also be false if hasNext returns false.
|
||||
*/
|
||||
public boolean isNextDelimiter() {
|
||||
//If the next delimiter is unkown then locate it.//
|
||||
if((nextDelimiter == null) && (nextDelimiterPosition != -1)) {
|
||||
locateNextDelimiter();
|
||||
}//if//
|
||||
|
||||
//Ignore hidden delimiters.//
|
||||
while((nextDelimiterPosition == currentPosition) && (!nextDelimiter.returnDelimiter)) {
|
||||
currentPosition += nextDelimiter.delimiter.length();
|
||||
locateNextDelimiter();
|
||||
}//while//
|
||||
|
||||
//Determine whether the next segment returned will be a delimiter.//
|
||||
return nextDelimiterPosition == currentPosition;
|
||||
}//isNextDelimiter()//
|
||||
/**
|
||||
* Locates the next delimiter in the source.
|
||||
* If there are no more delimiters then <code>nextDelimiter</code> will be <code>null</code> and <code>nextDelimiterPosition</code> will be <code>-1</code>,
|
||||
* otherwise the <code>nextDelimiterPosition</code> will be the absolute source index of the next delimiter and <code>nextDelimiter</code> will reference the DelimiterEndNode of that delimiter.
|
||||
*/
|
||||
private void locateNextDelimiter() {
|
||||
DelimiterNode node = null;
|
||||
DelimiterNode nextNode = null;
|
||||
int positionOffset;
|
||||
DelimiterEndNode nextDelimiter = null;
|
||||
|
||||
//Start at the current position.//
|
||||
int nextPosition = currentPosition;
|
||||
|
||||
//Keep reading characters until a valid delimiter is found or the end of the source string is found.//
|
||||
while((nextDelimiter == null) && (nextPosition <= lastPosition)) {
|
||||
positionOffset = 0;
|
||||
characterHolder.character = source.charAt(nextPosition);
|
||||
nextNode = (DelimiterNode) delimiterSet.rootMap.get(characterHolder);
|
||||
|
||||
//Locate the longest valid delimiter if one or more match the string from the next position.//
|
||||
while(nextNode != null) {
|
||||
node = nextNode;
|
||||
positionOffset++;
|
||||
|
||||
//Make sure there are enough source characters.//
|
||||
if(lastPosition - nextPosition - positionOffset < 0) {
|
||||
nextNode = null;
|
||||
}//if//
|
||||
else {
|
||||
//Check the next source character.//
|
||||
characterHolder.character = source.charAt(nextPosition + positionOffset);
|
||||
nextNode = (DelimiterNode) (node.characterMap != null ? node.characterMap.get(characterHolder) : null);
|
||||
}//else//
|
||||
}//while//
|
||||
|
||||
//Search valid nodes for a valid delimiter.//
|
||||
while(node != null) {
|
||||
if(node.endNode != null) {
|
||||
int difference = node.endNode.delimiter.length() - positionOffset;
|
||||
|
||||
//Start looking at this delimiter and all previous delimiters.//
|
||||
if((difference == 0) || ((lastPosition >= difference + nextPosition + positionOffset) && (node.endNode.delimiter.regionMatches(node.endNode.ignoreCase, positionOffset, source, nextPosition + positionOffset, difference)))) {
|
||||
if(validateDelimiter(node.endNode, nextPosition + node.endNode.delimiter.length())) {
|
||||
nextDelimiter = node.endNode;
|
||||
node = null;
|
||||
continue;
|
||||
}//if//
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
//Move up the node chain.//
|
||||
node = node.parent;
|
||||
}//while//
|
||||
|
||||
//If we did not find a delimiter beginning on the nextPosition index then increment the index.//
|
||||
if(nextDelimiter == null) {
|
||||
nextPosition++;
|
||||
}//if//
|
||||
}//while//
|
||||
|
||||
//We now have the position of the next delimiter: nextPosition; and we have the delimiter: nextDelimiter.//
|
||||
if(nextDelimiter != null) {
|
||||
this.nextDelimiter = nextDelimiter;
|
||||
this.nextDelimiterPosition = nextPosition;
|
||||
}//if//
|
||||
else {
|
||||
this.nextDelimiter = null;
|
||||
this.nextDelimiterPosition = -1;
|
||||
}//else//
|
||||
}//locateNextDelimiter()//
|
||||
/**
|
||||
* Gets the next string segment in the parse operation.
|
||||
* @return The next available string segment.
|
||||
*/
|
||||
public String next() {
|
||||
String retVal = null;
|
||||
|
||||
//If the next delimiter is unkown then locate it.//
|
||||
if((nextDelimiter == null) && (nextDelimiterPosition != -1)) {
|
||||
locateNextDelimiter();
|
||||
}//if//
|
||||
|
||||
//Ignore hidden delimiters.//
|
||||
while((nextDelimiterPosition == currentPosition) && (!nextDelimiter.returnDelimiter)) {
|
||||
currentPosition += nextDelimiter.delimiter.length();
|
||||
locateNextDelimiter();
|
||||
}//while//
|
||||
|
||||
//Get the next segment of the source.//
|
||||
if(nextDelimiterPosition == currentPosition) {
|
||||
retVal = nextDelimiter.delimiter;
|
||||
isLastDelimiter = true;
|
||||
lastDelimiterIdentifier = nextDelimiter.identifier;
|
||||
nextDelimiter = null;
|
||||
}//if//
|
||||
else {
|
||||
retVal = nextDelimiterPosition == -1 ? source.substring(currentPosition, lastPosition + 1) : source.substring(currentPosition, nextDelimiterPosition);
|
||||
isLastDelimiter = false;
|
||||
}//else//
|
||||
|
||||
//Save the previous position in the source.//
|
||||
if(previousPositions != null) {
|
||||
for(int index = previousPositions.length - 1; index > 0; index--) {
|
||||
previousPositions[index] = previousPositions[index - 1];
|
||||
}//for//
|
||||
|
||||
previousPositions[0] = currentPosition;
|
||||
}//if//
|
||||
|
||||
//Increment the current position.//
|
||||
currentPosition += retVal.length();
|
||||
|
||||
return retVal;
|
||||
}//next()//
|
||||
/**
|
||||
* Resets the current position to the first position in the string.
|
||||
*/
|
||||
public void reset() {
|
||||
resetTo(firstPosition);
|
||||
}//reset()//
|
||||
/**
|
||||
* Resets the current position to the given position in the string.
|
||||
* @param index The position to move to. The index will point to the first character to next be parsed.
|
||||
*/
|
||||
public void resetTo(int index) {
|
||||
if((index < firstPosition) || (index > lastPosition + 1)) {
|
||||
throw new IndexOutOfBoundsException("The index " + index + " must be greater than or equal to " + firstPosition + " and less than or equal to " + (lastPosition + 1) + ".");
|
||||
}//if//
|
||||
|
||||
this.currentPosition = index;
|
||||
this.nextDelimiter = null;
|
||||
this.nextDelimiterPosition = 0;
|
||||
|
||||
//Save the previous position in the source.//
|
||||
if(previousPositions != null) {
|
||||
for(int index2 = previousPositions.length - 1; index2 >= 0; index2--) {
|
||||
previousPositions[index2] = firstPosition;
|
||||
}//for//
|
||||
}//if//
|
||||
}//resetTo()//
|
||||
/**
|
||||
* Resets the current position to the first position in the string.
|
||||
*/
|
||||
public void resetToFront() {
|
||||
resetTo(firstPosition);
|
||||
}//resetToFront()//
|
||||
/**
|
||||
* Sets the set of delimiters that will be used to parse the source from the current position.
|
||||
* <p><b>WARNING: Once used, the delimiter set cannot be changed. All additions to the set must occur before using the set.</b>
|
||||
* @param delimiterSet The immutable set of all delimiters used in parsing the source from the current source location (previous parsing may have already occured).
|
||||
*/
|
||||
public void setDelimiterSet(DelimiterSet delimiterSet) {
|
||||
this.delimiterSet = delimiterSet;
|
||||
delimiterSet.isImmutable = true;
|
||||
}//setDelimiterSet()//
|
||||
/**
|
||||
* Sets the string to parse.
|
||||
* @param source The string to parse into segments.
|
||||
*/
|
||||
public void setSource(String source) {
|
||||
setSource(source, 0, source.length() - 1);
|
||||
}//setString()//
|
||||
/**
|
||||
* Sets the string to parse.
|
||||
* @param source The string to parse into segments.
|
||||
* @param startIndex The first (inclusive) character index in the source to include when parsing.
|
||||
* @param endIndex The last (inclusive) character index in the source to include when parsing.
|
||||
*/
|
||||
public void setSource(String source, int startIndex, int endIndex) {
|
||||
this.source = source;
|
||||
this.firstPosition = startIndex;
|
||||
this.lastPosition = endIndex >= source.length() ? source.length() - 1 : endIndex;
|
||||
this.currentPosition = 0;
|
||||
this.nextDelimiter = null;
|
||||
this.nextDelimiterPosition = 0;
|
||||
|
||||
//Save the previous position in the source.//
|
||||
if(previousPositions != null) {
|
||||
for(int index = previousPositions.length - 1; index >= 0; index--) {
|
||||
previousPositions[index] = firstPosition;
|
||||
}//for//
|
||||
}//if//
|
||||
}//setString()//
|
||||
/**
|
||||
* Skips the next <code>skipCount</code> characters in the source.
|
||||
* @param skipCount The number of characters to be skipped.
|
||||
*/
|
||||
public void skipCharacters(char[] characters) {
|
||||
String source = getSource();
|
||||
int index = getCurrentPosition();
|
||||
boolean done = false;
|
||||
|
||||
while(!done) {
|
||||
char ch = source.charAt(index);
|
||||
boolean contained = false;
|
||||
|
||||
for(int charIndex = 0; (!contained) && (charIndex < characters.length); charIndex++) {
|
||||
if(ch == characters[charIndex]) {
|
||||
contained = true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
if(!contained) {
|
||||
done = true;
|
||||
}//if//
|
||||
else if(index == lastPosition) {
|
||||
done = true;
|
||||
index++;
|
||||
}//else if//
|
||||
else {
|
||||
index++;
|
||||
}//else//
|
||||
}//while//
|
||||
|
||||
resetTo(index);
|
||||
}//skipCharacters()//
|
||||
/**
|
||||
* Skips the next <code>skipCount</code> characters in the source.
|
||||
* @param skipCount The number of characters to be skipped.
|
||||
*/
|
||||
public void skipCharacters(int skipCount) {
|
||||
resetTo(getCurrentPosition() + skipCount);
|
||||
}//skipCharacters()//
|
||||
/**
|
||||
*
|
||||
* @param endNode The endNode being validated.
|
||||
* @param sourcePosition The position in the source of the next valid character after the delimiter.
|
||||
*/
|
||||
private boolean validateDelimiter(DelimiterEndNode endNode, int sourcePosition) {
|
||||
boolean isValid = false;
|
||||
|
||||
//Verify end conditions.//
|
||||
if(endNode.requiresTerminationValidation) {
|
||||
int remainingSourceCharacterCount = source.length() - sourcePosition;
|
||||
|
||||
//If this is the end of the source then check to see if the delimiter can end the source.//
|
||||
if(remainingSourceCharacterCount == 0) {
|
||||
isValid = endNode.canOccurAtSourceEnd;
|
||||
}//if//
|
||||
else {
|
||||
//Check terminating characters.//
|
||||
if(endNode.terminatingCharacters != null) {
|
||||
characterHolder.character = source.charAt(sourcePosition);
|
||||
|
||||
if(endNode.terminatingCharacters.containsValue(characterHolder)) {
|
||||
isValid = true;
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
//Check terminating strings.//
|
||||
if((!isValid) && (endNode.terminatingStrings != null)) {
|
||||
IIterator iterator = endNode.terminatingStrings.iterator();
|
||||
|
||||
while((!isValid) && (iterator.hasNext())) {
|
||||
String terminatingString = (String) iterator.next();
|
||||
|
||||
isValid = (remainingSourceCharacterCount >= terminatingString.length()) && (source.regionMatches(false, sourcePosition, terminatingString, 0, terminatingString.length()));
|
||||
}//while//
|
||||
}//if//
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
isValid = true;
|
||||
}//else//
|
||||
|
||||
return isValid;
|
||||
}//validateDelimiter()//
|
||||
}//AdvancedTextParser//
|
||||
151
Common/src/com/common/util/CircularQueue.java
Normal file
151
Common/src/com/common/util/CircularQueue.java
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.debug.QueuedLog;
|
||||
|
||||
/**
|
||||
* Implements a circular queue - FIFO (first in first out) collection where the size is fixed and new entries will overwrite the oldest entries and entries cannot be removed.
|
||||
* <p><b>WARNING: This class is not thread safe.</b>
|
||||
*/
|
||||
public class CircularQueue implements ICircularQueue {
|
||||
private Object[] data = null;
|
||||
private boolean hasLooped = false;
|
||||
private int nextIndex = 0;
|
||||
|
||||
/**
|
||||
* An iterator over the circular queue.
|
||||
* <p><b>WARNING: This class is not thread safe. The iterator is designed to only be used either as a forward or reverse iterator, but not necessarily both at the same time.</b>
|
||||
*/
|
||||
private class Iterator implements IReversableIterator {
|
||||
private int startIndex = -1;
|
||||
private int index = -1;
|
||||
|
||||
private Iterator() {
|
||||
}//Iterator()//
|
||||
public boolean remove() {
|
||||
//Values cannot be removed from a circular queue.//
|
||||
throw new com.common.exception.MethodNotSupportedException();
|
||||
}//remove()//
|
||||
public boolean hasNext() {
|
||||
return getSize() > 0 && (index == -1 || index != startIndex);
|
||||
}//hasNext()//
|
||||
public boolean hasPrevious() {
|
||||
return getSize() > 0 && (index == -1 || index != startIndex);
|
||||
}//hasPrevious()//
|
||||
public Object next() {
|
||||
Object result;
|
||||
|
||||
if(!hasNext()) {
|
||||
throw new IndexOutOfBoundsException("Call iterator.hasNext() before calling iterator.next()");
|
||||
}//if//
|
||||
|
||||
if(index == -1) {
|
||||
if(CircularQueue.this.hasLooped) {
|
||||
startIndex = index = CircularQueue.this.nextIndex == 0 ? CircularQueue.this.data.length - 1 : CircularQueue.this.nextIndex - 1;
|
||||
}//if//
|
||||
else {
|
||||
index = 0;
|
||||
startIndex = CircularQueue.this.nextIndex;
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
//Increment & wrap the index.//
|
||||
if(++index == CircularQueue.this.data.length && CircularQueue.this.hasLooped) {
|
||||
index = 0;
|
||||
}//if//
|
||||
|
||||
result = data[index];
|
||||
|
||||
return result;
|
||||
}//next()//
|
||||
public Object previous() {
|
||||
Object result;
|
||||
|
||||
if(!hasPrevious()) {
|
||||
throw new IndexOutOfBoundsException("Call iterator.hasPrevious() before calling iterator.previous()");
|
||||
}//if//
|
||||
|
||||
if(index == -1) {
|
||||
if(CircularQueue.this.hasLooped) {
|
||||
startIndex = index = CircularQueue.this.nextIndex == 0 ? CircularQueue.this.data.length : CircularQueue.this.nextIndex;
|
||||
}//if//
|
||||
else {
|
||||
index = CircularQueue.this.nextIndex;
|
||||
startIndex = 0;
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
if(--index == -1 && CircularQueue.this.hasLooped) {
|
||||
index = CircularQueue.this.data.length - 1;
|
||||
}//if//
|
||||
|
||||
result = data[index];
|
||||
|
||||
return result;
|
||||
}//previous()//
|
||||
public void resetToFront() {
|
||||
startIndex = index = -1;
|
||||
}//resetToFront()//
|
||||
public void resetToBack() {
|
||||
startIndex = index = -1;
|
||||
}//resetToBack()//
|
||||
}//Iterator//
|
||||
/**
|
||||
* CircularQueue constructor.
|
||||
*/
|
||||
public CircularQueue(int size) {
|
||||
super();
|
||||
|
||||
data = new Object[size];
|
||||
}//CircularQueue()//
|
||||
/**
|
||||
* ICircularQueue#enqueue(Object)
|
||||
*/
|
||||
public boolean enqueue(Object value) {
|
||||
data[nextIndex++] = value;
|
||||
|
||||
if(nextIndex == data.length) {
|
||||
nextIndex = 0;
|
||||
hasLooped = true;
|
||||
}//if//
|
||||
|
||||
return true;
|
||||
}//enqueue()//
|
||||
/**
|
||||
* ICircularQueue#getSize()
|
||||
*/
|
||||
public int getSize() {
|
||||
return hasLooped ? data.length : nextIndex;
|
||||
}//getSize()//
|
||||
/**
|
||||
* ICircularQueue#iterator()
|
||||
*/
|
||||
public IReversableIterator iterator() {
|
||||
return new Iterator();
|
||||
}//iterator()//
|
||||
/**
|
||||
* Reads the collection from the stream.
|
||||
* @param in java.io.ObjectInput The stream that the object data can be read from.
|
||||
*/
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
data = (Object[]) in.readObject();
|
||||
hasLooped = in.readBoolean();
|
||||
nextIndex = in.readInt();
|
||||
}//readExternal()//
|
||||
/**
|
||||
* Writes the collection to the stream.
|
||||
* @param out java.io.ObjectOutput The stream that the object data can be written to.
|
||||
*/
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
out.writeObject(data);
|
||||
out.writeBoolean(hasLooped);
|
||||
out.writeInt(nextIndex);
|
||||
}//writeExternal()//
|
||||
}//CircularQueue//
|
||||
51
Common/src/com/common/util/EmptyIterator.java
Normal file
51
Common/src/com/common/util/EmptyIterator.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2005,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/*
|
||||
* A simple empty iterator singleton.
|
||||
*/
|
||||
public final class EmptyIterator implements IIterator {
|
||||
/** The one and only empty iterator object. */
|
||||
private static EmptyIterator singleton = new EmptyIterator();
|
||||
/**
|
||||
* Gets the single instance of this iterator.
|
||||
* @return The one and only empty iterator object.
|
||||
*/
|
||||
public static IIterator getSingleton() {
|
||||
return singleton;
|
||||
}//getSingleton()//
|
||||
/**
|
||||
* EmptyIterator constructor.
|
||||
*/
|
||||
private EmptyIterator() {
|
||||
}//EmptyIterator()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIterator#hasNext()
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}//hasNext()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIterator#next()
|
||||
*/
|
||||
public Object next() {
|
||||
throw new IndexOutOfBoundsException("Empty iterator.");
|
||||
}//next()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIterator#remove()
|
||||
*/
|
||||
public boolean remove() {
|
||||
return false;
|
||||
}//remove()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIterator#resetToFront()
|
||||
*/
|
||||
public void resetToFront() {
|
||||
}//resetToFront()//
|
||||
}//EmptyIterator//
|
||||
100
Common/src/com/common/util/FileContentStream.java
Normal file
100
Common/src/com/common/util/FileContentStream.java
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.io.StreamSupport;
|
||||
|
||||
/**
|
||||
* A simple implemenation of IContentStream that gets its content from a file.
|
||||
* <p>TODO: Really not happy with this setup. I would like to better report when the stream is closed, and it would be nice if the stream could be turned on remotely, but the flow would be controlled by the client (would require a second proxy).
|
||||
* Also this interface won't work well for other types of streams I imagine.</p>
|
||||
*/
|
||||
public class FileContentStream implements IContentStream {
|
||||
private File file;
|
||||
private FileInputStream fin;
|
||||
private long fileSize;
|
||||
private long readCount = 0;
|
||||
/**
|
||||
* FileContentStream constructor.
|
||||
* @param file The file to stream.
|
||||
*/
|
||||
public FileContentStream(File file) throws IOException {
|
||||
this.file = file;
|
||||
this.fileSize = file.length();
|
||||
this.fin = new FileInputStream(file);
|
||||
}//FileContentStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IContentStream#getNextChunk(int)
|
||||
*/
|
||||
public byte[] getNextChunk(int maximumSize) {
|
||||
byte[] result = null;
|
||||
|
||||
try {
|
||||
if(fin != null || readCount == 0) {
|
||||
int count;
|
||||
long size = maximumSize > 0 ? maximumSize : 1000000;
|
||||
|
||||
if(size > fileSize - readCount) {
|
||||
size = fileSize - readCount;
|
||||
}//if//
|
||||
|
||||
result = new byte[(int) size];
|
||||
|
||||
if(readCount == 0 && fin == null) {
|
||||
fin = new FileInputStream(file);
|
||||
}//if//
|
||||
|
||||
count = StreamSupport.readBytes(fin, result);
|
||||
|
||||
if(count <= 0) {
|
||||
result = null;
|
||||
}//if//
|
||||
else if(count != result.length) {
|
||||
byte[] temp = new byte[count];
|
||||
|
||||
System.arraycopy(result, 0, temp, 0, temp.length);
|
||||
result = temp;
|
||||
}//if//
|
||||
|
||||
readCount += count;
|
||||
|
||||
//Close the file stream if we have read all the bytes.//
|
||||
if(readCount == fileSize) {
|
||||
close();
|
||||
}//if//
|
||||
}//else//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
//TODO: Display error? Couldn't find or open the file?
|
||||
}//catch//
|
||||
|
||||
return result;
|
||||
}//getNextChunk()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IContentStream#close()
|
||||
*/
|
||||
public void close() {
|
||||
if(fin != null) {
|
||||
try {fin.close();}catch(Throwable e) {}
|
||||
fin = null;
|
||||
}//if//
|
||||
}//close()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#finalize()
|
||||
*/
|
||||
public void finalize() {
|
||||
//Make sure we close the file input stream so it releases any locks. This is last resort.//
|
||||
close();
|
||||
}//finalize()//
|
||||
}//FileContentStream//
|
||||
29
Common/src/com/common/util/ICircularQueue.java
Normal file
29
Common/src/com/common/util/ICircularQueue.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* Defines the interface for a standard queueing mechanism.
|
||||
*/
|
||||
public interface ICircularQueue {
|
||||
/**
|
||||
* Queues the given value.
|
||||
* @param value The value to place in the queue.
|
||||
*/
|
||||
public boolean enqueue(Object value);
|
||||
/**
|
||||
* Gets the number of values in the queue.
|
||||
* @return The queued element count.
|
||||
*/
|
||||
public int getSize();
|
||||
/**
|
||||
* Gets an iterator over the values in the queue.
|
||||
* @return A reversable iterator over the queued values.
|
||||
*/
|
||||
public IReversableIterator iterator();
|
||||
}//ICircularQueue//
|
||||
183
Common/src/com/common/util/ICollection.java
Normal file
183
Common/src/com/common/util/ICollection.java
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import com.common.event.*;
|
||||
|
||||
/**
|
||||
* Defines the methods of a standard collection of values that provides thread synchronization and event management services.
|
||||
* @see com.common.util.ILiteCollection
|
||||
*/
|
||||
public interface ICollection extends java.io.Externalizable {
|
||||
/**
|
||||
* Adds the given item to the collection.
|
||||
* @param value A value to add to this collection.
|
||||
* @return The index of the addition if the collection is indexed, 0 if the collection is not indexed, or -1 if the operation failed.
|
||||
*/
|
||||
public int add(Object value);
|
||||
/**
|
||||
* Adds the given items to the collection.
|
||||
* @param values An array of values to add to this collection.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean addAll(Object[] values);
|
||||
/**
|
||||
* Adds the given items to the collection.
|
||||
* @param values An array of values to add to this collection.
|
||||
* @param offset The offset of the first value to add.
|
||||
* @param length The count of values to add.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean addAll(Object[] values, int offset, int length);
|
||||
/**
|
||||
* Adds the given items to the collection.
|
||||
* @param values An iterator over a collection of values to add to this collection.
|
||||
* @return Returns true if the operation was a success (all items were found and added).
|
||||
*/
|
||||
public boolean addAll(IIterator values);
|
||||
/**
|
||||
* Adds the given items to the collection.
|
||||
* @param values A collection of values to add to this collection.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean addAll(ICollection values);
|
||||
/**
|
||||
* Adds the given items to the collection.
|
||||
* @param values A collection of values to add to this collection.
|
||||
* @param offset The offset of the first value to add.
|
||||
* @param length The count of values to add.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean addAll(IIndexedCollection values, int offset, int length);
|
||||
/**
|
||||
* Collects values in the collection which are returned by the passed handler.
|
||||
* @param handler The handler will be passed each value in the collection (one at a time) and should return what ever value is desired.
|
||||
* @param results The collection to add selected values to. If this is not specified then a new IList will be created and returned.
|
||||
* @return The collection of collected values.
|
||||
*/
|
||||
public IList collect(ObjectHandler1 handler, IList results);
|
||||
/**
|
||||
* Will check to see if a value is contained in this collection.
|
||||
* @param value The value to check for.
|
||||
* @return Returns true if the value is a member of the collection.
|
||||
*/
|
||||
public boolean containsValue(Object value);
|
||||
/**
|
||||
* Returns a the number of values contained in the Collection.
|
||||
* @return The number of values stored in this collection.
|
||||
*/
|
||||
public int getSize();
|
||||
/**
|
||||
* Determines whether the collection may be changed or not.
|
||||
* <p>NOTE: Something that is immutable is never changing.
|
||||
* @return Whether the collection may be changed. This is false if the collection may no longer be modified.
|
||||
*/
|
||||
public boolean isChangeable();
|
||||
/**
|
||||
* Determines whether the collection may be changed or not.
|
||||
* @param isChangeable Whether the collection may be changed. This is false if the collection may no longer be modified.
|
||||
*/
|
||||
public void isChangeable(boolean isChangeable);
|
||||
/**
|
||||
* Returns an iterator which can be used to cycle over each item in the Collection.
|
||||
* @return An iterator over this collection.
|
||||
*/
|
||||
public IIterator iterator();
|
||||
/**
|
||||
* Performs some action (sepecified by the handler) on each value in this collection.
|
||||
* @param handler The handler will be passed each value in the collection (one at a time) to allow it to perform some action on the value.
|
||||
*/
|
||||
public void perform(VoidHandler1 handler);
|
||||
/**
|
||||
* Collects values in the collection which are rejected by the passed handler.
|
||||
* @param handler The handler will be passed each value in the collection (one at a time) and return <code>Boolean.FALSE</code> if the item is to be rejected (or added to the output list).
|
||||
* @param results The collection to add rejected values to. If this is not specified then a new IList will be created and returned.
|
||||
* @return The collection of values rejected.
|
||||
*/
|
||||
public IList reject(BooleanHandler1 handler, IList results);
|
||||
/**
|
||||
* Removes the given item from the collection.
|
||||
* @param value A value to remove from this collection.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean remove(Object value);
|
||||
/**
|
||||
* Removes all of the items from the collection.
|
||||
*/
|
||||
public void removeAll();
|
||||
/**
|
||||
* Removes all of the given items from the collection.
|
||||
* @param values An array of values to remove from this collection.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean removeAll(Object[] values);
|
||||
/**
|
||||
* Removes all of the given items from the collection.
|
||||
* @param values An array of values to remove from this collection.
|
||||
* @param offset The offset of the first value to remove.
|
||||
* @param length The count of values to remove.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean removeAll(Object[] values, int offset, int length);
|
||||
/**
|
||||
* Removes all of the given items from the collection.
|
||||
* @param values An iterator over a collection of values to remove from this collection.
|
||||
* @return Returns true if the operation was a success (all items were found and removed).
|
||||
*/
|
||||
public boolean removeAll(IIterator values);
|
||||
/**
|
||||
* Removes all of the given items from the collection.
|
||||
* @param values A collection of values to remove from this collection.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean removeAll(ICollection values);
|
||||
/**
|
||||
* Replaces one value with another in the collection.
|
||||
* <p>NOTE: Whether the new value is in the exact same location in the collection is up to the collection.
|
||||
* @param oldValue The value to remove from this collection.
|
||||
* @param newValue The value to add to this collection.
|
||||
* @return Will be true if the operation was a success.
|
||||
*/
|
||||
public boolean replace(Object oldValue, Object newValue);
|
||||
/**
|
||||
* Replaces all the values in the current collection with those of the given collection.
|
||||
* @param values The values to replace those values currently in the collection.
|
||||
* @return Whether the operation completed successfully. The operation may only partially complete if this is false.
|
||||
*/
|
||||
public boolean replaceAll(ICollection values);
|
||||
/**
|
||||
* Replaces the removed values in the current collection with those in the added values collection.
|
||||
* @param removedValues The values to be replaced.
|
||||
* @param addedValues The values to replace the removed values. Note that the collections need not be of the same size.
|
||||
* @return Whether the operation completed successfully. The operation may only partially complete if this is false.
|
||||
*/
|
||||
public boolean replaceAll(ICollection removedValues, ICollection addedValues);
|
||||
/**
|
||||
* Selects values in the collection which are selected by the passed handler.
|
||||
* @param handler The handler will be passed each value in the collection (one at a time) and return <code>Boolean.TRUE</code> if the item is to be selected (or added to the output list).
|
||||
* @param results The collection to add selected values to. If this is not specified then a new IList will be created and returned.
|
||||
* @return The collection of values selected.
|
||||
*/
|
||||
public IList select(BooleanHandler1 handler, IList results);
|
||||
/**
|
||||
* Gets the first accessable value from the collection. Collections that are not indexed may return any value that is easily accessable.
|
||||
* @return The first available value in the collection. Indexed collections must return the value with the lowest index.
|
||||
*/
|
||||
public Object getFirst();
|
||||
/**
|
||||
* Creates an array of the values in the collection.
|
||||
* @return An array of collection values.
|
||||
*/
|
||||
public Object[] toArray();
|
||||
/**
|
||||
* Fills in an array with the collection values. If the array is not large enough to hold all of the values then as many as possible will be inserted.
|
||||
* @param array An array object capable of contain collection values.
|
||||
* @return The number of elements copied into the array.
|
||||
*/
|
||||
public int toArray(Object array);
|
||||
}//ICollection//
|
||||
22
Common/src/com/common/util/IContentStream.java
Normal file
22
Common/src/com/common/util/IContentStream.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
public interface IContentStream {
|
||||
/**
|
||||
* Requests the next chunk of the content from the stream.
|
||||
* @param maximumSize The maximum number of bytes in the chunk.
|
||||
* @return The next content chunk or null if there isn't any more content.
|
||||
*/
|
||||
public byte[] getNextChunk(int maximumSize);
|
||||
/**
|
||||
* Closes the stream.
|
||||
* The application should call this method if the stream is not completely read, otherwise it is not necessary.
|
||||
*/
|
||||
public void close();
|
||||
}//IContentStream//
|
||||
78
Common/src/com/common/util/IHashMap.java
Normal file
78
Common/src/com/common/util/IHashMap.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* Defines the standard methods for a map which stores data using a hash of the key in the key value pair being stored.
|
||||
*/
|
||||
public interface IHashMap extends IMap {
|
||||
/**
|
||||
* Determines whether the key exists in the map.
|
||||
* @param key The key to look for.
|
||||
* @return Will be <code>true</code> if the key is already in the map.
|
||||
*/
|
||||
public boolean containsKey(Object key);
|
||||
/**
|
||||
* Will get an object in the Hash by its' key.
|
||||
*/
|
||||
public Object get(Object key);
|
||||
/**
|
||||
* For use by the iterators.
|
||||
* This method is only public because the iterator might be remote.
|
||||
* deprecated Should not be called by anything other than the HashMap iterators.
|
||||
*/
|
||||
public Object getKey(int index);
|
||||
/**
|
||||
* Gets the collection of all keys in the map.
|
||||
* @param keys A collection that will contain the keys.
|
||||
* @return The collection with the keys in it. This will be the same collection as the one passed if it is non-null.
|
||||
*/
|
||||
public IList getKeys(IList keys);
|
||||
/**
|
||||
* Gets the collection of all keys in the map.
|
||||
* @param array An array where key values will be placed.
|
||||
* @return The count of keys placed in the array.
|
||||
*/
|
||||
public int getKeys(Object array);
|
||||
/**
|
||||
* Gets the collection of all keys in the map.
|
||||
* @param array An array where key values will be placed.
|
||||
* @param outputOffset The offset in the array where the first key value will be placed.
|
||||
* @return The count of keys placed in the array.
|
||||
*/
|
||||
public int getKeys(Object array, int outputOffset);
|
||||
/**
|
||||
* Will return a keyIterator.
|
||||
*/
|
||||
public IIterator keyIterator();
|
||||
/**
|
||||
* Will place an object in the Hash by its' key.
|
||||
* Returns the old value if there was one.
|
||||
*/
|
||||
public Object put(Object key, Object value);
|
||||
/**
|
||||
* Removes a key value pair from the HashMap.
|
||||
* @param key The key identifying which key/value pair to remove.
|
||||
* @return If the key value pair doesn't exist, <code>null</code> will be returned, otherwise the removed value will be returned.
|
||||
*/
|
||||
public Object remove(Object key);
|
||||
/**
|
||||
* Removes all key value pairs from the HashMap.
|
||||
*/
|
||||
public void removeAll();
|
||||
/**
|
||||
* Fills the passed array with key values.
|
||||
* @param keyArray An array to be filled with key values.
|
||||
* @return The number of key values placed in the array.
|
||||
*/
|
||||
public int toKeyArray(Object keyArray);
|
||||
/**
|
||||
* Will return a valueIterator.
|
||||
*/
|
||||
public IIterator valueIterator();
|
||||
}//IHashMap//
|
||||
50
Common/src/com/common/util/IHashSet.java
Normal file
50
Common/src/com/common/util/IHashSet.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import com.common.comparison.IComparator;
|
||||
|
||||
/**
|
||||
* Defines the methods of a standard set using a hash value to store and locate values.
|
||||
*/
|
||||
public interface IHashSet extends ISet {
|
||||
/** Duplicate values added to the collection will be rejected completely. It will not be possible to have the same (or equal) value more than once. */
|
||||
public static final int STYLE_NO_DUPLICATES = 0;
|
||||
/** Duplicate values added to the collection will be counted more than once but only internally (ie: the iterator will return the value only once, but remove must be called the same number of times as the add to remove the value). */
|
||||
public static final int STYLE_COUNT_DUPLICATES = 1;
|
||||
/** Duplicate values added to the collection will be counted more than once both internally and externally (ie: the iterator will return the value more than once). */
|
||||
public static final int STYLE_ADD_DUPLICATES = 2;
|
||||
/** The default style settings. */
|
||||
public static final int DEFAULT_STYLE = STYLE_NO_DUPLICATES;
|
||||
/**
|
||||
* Gets the value given the value - this is useful only if logical equality is used, such that the passed value is not exactly the same as the result value.
|
||||
* @param value The value to be found.
|
||||
* @return The value found.
|
||||
*/
|
||||
public Object get(Object value);
|
||||
/**
|
||||
* Gets the ratio of collection size divided by array size.
|
||||
* @return The ratio indicating how loaded the set can get before it requires resizing.
|
||||
*/
|
||||
public float getLoadFactor();
|
||||
/**
|
||||
* Gets the next set size at which the set must be resized.
|
||||
* @return The next resize point.
|
||||
*/
|
||||
public int getThreshold();
|
||||
/**
|
||||
* Gets the comparator used to locate values in the collection.
|
||||
* @return The comparator used by this collection for locating values.
|
||||
*/
|
||||
public IComparator getLocateComparator();
|
||||
/**
|
||||
* Gets the style used for the hash set.
|
||||
* @return The style which indicates how duplicate entries are handled.
|
||||
*/
|
||||
public int getStyle();
|
||||
}//IHashSet//
|
||||
183
Common/src/com/common/util/IIndexedCollection.java
Normal file
183
Common/src/com/common/util/IIndexedCollection.java
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* Defines the methods of a standard collection where items can be identified by an index.
|
||||
*/
|
||||
public interface IIndexedCollection extends ICollection {
|
||||
public static final int VALUE_NOT_FOUND = -1;
|
||||
/** Used to move an item in the collection up one or more indices forward or backward in the collection. If used with a positive number then the item will be moved toward the back of the list (higher indices), if used with a negative number then the item will be moved toward the front of the list (lower indices). */
|
||||
public static final int MOVE = 0;
|
||||
/** A shortcut to move an item in the collection to the front of the collection (so it would be at index zero). */
|
||||
public static final int MOVE_FRONT = 1;
|
||||
/** A shortcut to move an item in the collection to the back of the collection (so it would be at index N). */
|
||||
public static final int MOVE_BACK = 2;
|
||||
/**
|
||||
* Adds the given value to the indexed collection at the given index.
|
||||
* <p><b>NOTE: If the collection is sorted then the index will be ignored.</b>
|
||||
* @param index The index to add the item atin the collection.
|
||||
* @param value A value to add to this collection.
|
||||
* @return The index of the addition, or -1 if the operation failed.
|
||||
* @throws IndexOutOfBoundsException When the index is not within the indexed collection's valid range.
|
||||
*/
|
||||
public int add(int index, Object value);
|
||||
/**
|
||||
* Adds the given items to the indexed collection starting at the given index.
|
||||
* <p><b>NOTE: If the collection is sorted then the index will be ignored.</b>
|
||||
* @param index The index to add the items at in the collection.
|
||||
* @param values An array of values to add to this collection.
|
||||
* @return Returns true if the operation was a success.
|
||||
* @throws IndexOutOfBoundsException When the index is not within the indexed collection's valid range.
|
||||
*/
|
||||
public boolean addAll(int index, Object[] values);
|
||||
/**
|
||||
* Adds the given items to the indexed collection starting at the given index.
|
||||
* <p><b>NOTE: If the collection is sorted then the index will be ignored.</b>
|
||||
* @param index The index to add the items at in the collection.
|
||||
* @param values An array of values to add to this collection.
|
||||
* @param offset The offset of the first value to add.
|
||||
* @param length The count of values to add.
|
||||
* @return Returns true if the operation was a success.
|
||||
* @throws IndexOutOfBoundsException When the index is not within the indexed collection's valid range.
|
||||
*/
|
||||
public boolean addAll(int index, Object[] values, int offset, int length);
|
||||
/**
|
||||
* Adds the given items to the indexed collection starting at the given index.
|
||||
* <p><b>NOTE: If the collection is sorted then the index will be ignored.</b>
|
||||
* @param index The index to add the item atin the collection.
|
||||
* @param values A collection of values to add to this collection.
|
||||
* @return Returns true if the operation was a success.
|
||||
* @throws IndexOutOfBoundsException When the index is not within the indexed collection's valid range.
|
||||
*/
|
||||
public boolean addAll(int index, ICollection values);
|
||||
/**
|
||||
* Adds the given items to the indexed collection starting at the given index.
|
||||
* <p><b>NOTE: If the collection is sorted then the index will be ignored.</b>
|
||||
* @param index The index to add the item atin the collection.
|
||||
* @param values A collection of values to add to this collection.
|
||||
* @param offset The offset of the first value to add.
|
||||
* @param length The count of values to add.
|
||||
* @return Returns true if the operation was a success.
|
||||
* @throws IndexOutOfBoundsException When the index is not within the indexed collection's valid range.
|
||||
*/
|
||||
public boolean addAll(int index, IIndexedCollection values, int offset, int length);
|
||||
/**
|
||||
* Gets the value at the given index in the collection.
|
||||
* @param index The index of the requested value in the collection.
|
||||
* @return The value in the collection at the given index.
|
||||
* @throws IndexOutOfBoundsException When the index is not within the indexed collection's valid range.
|
||||
*/
|
||||
public Object get(int index);
|
||||
/**
|
||||
* Gets the first value in the collection.
|
||||
* @return The first value in the collection.
|
||||
* @throws IndexOutOfBoundsException When there are no values in the collection.
|
||||
*/
|
||||
public Object getFirst();
|
||||
/**
|
||||
* Gets the index of the first instance of value in the collection.
|
||||
* @param value The value that may or may not be in this indexed collection.
|
||||
* @return The location index of the value in the indexed collection. Returns <code>VALUE_NOT_FOUND</code> if the value was not in the collection.
|
||||
* @see #VALUE_NOT_FOUND
|
||||
*/
|
||||
public int getIndexOf(Object value);
|
||||
/**
|
||||
* Gets the index of the last instance of value in the collection.
|
||||
* @param value The value that may or may not be in this indexed collection.
|
||||
* @return The location index of the value in the indexed collection. Returns <code>VALUE_NOT_FOUND</code> if the value was not in the collection.
|
||||
* @see #VALUE_NOT_FOUND
|
||||
*/
|
||||
public int getLastIndexOf(Object value);
|
||||
/**
|
||||
* Gets the last value in the collection.
|
||||
* @return The last value in the collection.
|
||||
* @throws IndexOutOfBoundsException When there are no values in the collection.
|
||||
*/
|
||||
public Object getLast();
|
||||
/**
|
||||
* Retrieves the collection specific iterator for this object.
|
||||
* The iterator may be used to iterate over the items in the collection starting with the first item and ending with the last item.
|
||||
* <p><bold>NOTE: The iterator is only guaranteed to iterate over all of the items in the collection if the collection does not change except through the iterator.</bold>
|
||||
* @return An indexed iterator object starting at the beginning of the collection.
|
||||
*/
|
||||
public IReversableIterator indexedIterator();
|
||||
/**
|
||||
* Removes the value at the given index.
|
||||
* @param index The index of the value to be removed.
|
||||
* @return The value removed from this collection.
|
||||
* @throws IndexOutOfBoundsException When the index is not within the indexed collection's valid range.
|
||||
*/
|
||||
public Object remove(int index);
|
||||
/**
|
||||
* Replaces the value at the given index with the passed value.
|
||||
* @param index The index of the value to be replaced.
|
||||
* @param value The value to be put in place of the removed value.
|
||||
* @return The value previously at the index.
|
||||
* @throws IndexOutOfBoundsException When the index is not within the indexed collection's valid range.
|
||||
*/
|
||||
public Object replace(int index, Object value);
|
||||
/**
|
||||
* Sets the value at the given index and returns the value previously at that index.
|
||||
* @param index The index of the value to be replaced.
|
||||
* @param value The value to be put in place of the removed value.
|
||||
* @return The value previously at the index.
|
||||
* @throws IndexOutOfBoundsException When the index is not within the indexed collection's valid range.
|
||||
*/
|
||||
public Object set(int index, Object value);
|
||||
/**
|
||||
* Used to move an item in the collection up one or more indices forward or backward in the collection.
|
||||
* If used with a positive number then the item will be moved toward the back of the list (higher indices).
|
||||
* If used with a negative number then the item will be moved toward the front of the list (lower indices).
|
||||
* <p>Warning: This method will adjust the offset to stay within the bounds of the collection.</p>
|
||||
* @param value The collection item to be moved.
|
||||
* @param offset The offset used to move the item. This will be added to the current index to produce the new index.
|
||||
* @throws IndexOutOfBoundsException If the value doesn't exist in the collection.
|
||||
* @throws IllegalStateException Thrown if an order comparator is assigned to the collection. Automatically ordered collections cannot be manually ordered.
|
||||
*/
|
||||
public void move(Object value, int offset);
|
||||
/**
|
||||
* Used to move an item in the collection up one or more indices forward or backward in the collection.
|
||||
* If used with a positive number then the item will be moved toward the back of the list (higher indices).
|
||||
* If used with a negative number then the item will be moved toward the front of the list (lower indices).
|
||||
* <p>Warning: This method will adjust the offset to stay within the bounds of the collection.</p>
|
||||
* @param index The collection item to be moved.
|
||||
* @param offset The offset used to move the item. This will be added to the current index to produce the new index.
|
||||
* @throws IndexOutOfBoundsException If the index is not valid for the collection.
|
||||
* @throws IllegalStateException Thrown if an order comparator is assigned to the collection. Automatically ordered collections cannot be manually ordered.
|
||||
*/
|
||||
public void move(int index, int offset);
|
||||
/**
|
||||
* A shortcut to move an item in the collection to the front of the collection (so it would be at index zero).
|
||||
* @param value The collection item to be moved.
|
||||
* @throws IndexOutOfBoundsException If the value doesn't exist in the collection.
|
||||
* @throws IllegalStateException Thrown if an order comparator is assigned to the collection. Automatically ordered collections cannot be manually ordered.
|
||||
*/
|
||||
public void moveToFirst(Object value);
|
||||
/**
|
||||
* A shortcut to move an item in the collection to the front of the collection (so it would be at index zero).
|
||||
* @param index The collection item to be moved.
|
||||
* @throws IndexOutOfBoundsException If the index is not valid for the collection.
|
||||
* @throws IllegalStateException Thrown if an order comparator is assigned to the collection. Automatically ordered collections cannot be manually ordered.
|
||||
*/
|
||||
public void moveToFirst(int index);
|
||||
/**
|
||||
* A shortcut to move an item in the collection to the back of the collection (so it would be at index N).
|
||||
* @param value The collection item to be moved.
|
||||
* @throws IndexOutOfBoundsException if the value doesn't exist in the collection.
|
||||
* @throws IllegalStateException if an order comparator is assigned to the collection. Automatically ordered collections cannot be manually ordered.
|
||||
*/
|
||||
public void moveToLast(Object value);
|
||||
/**
|
||||
* A shortcut to move an item in the collection to the back of the collection (so it would be at index N).
|
||||
* @param index The collection item to be moved.
|
||||
* @throws IndexOutOfBoundsException If the index is not valid for the collection.
|
||||
* @throws IllegalStateException Thrown if an order comparator is assigned to the collection. Automatically ordered collections cannot be manually ordered.
|
||||
*/
|
||||
public void moveToLast(int index);
|
||||
}//IIndexedCollection//
|
||||
42
Common/src/com/common/util/IIterator.java
Normal file
42
Common/src/com/common/util/IIterator.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* Defines simple iteration methods so that all collection providing an iterator have a common set of basic functionality.
|
||||
* There are more advanced iterator interfaces that will allow such features as reverse iterating and value removal.
|
||||
*/
|
||||
public interface IIterator {
|
||||
//public void insert(Object object);
|
||||
/**
|
||||
* Makes sure there is a next value in the collection.
|
||||
* This method does not ensure that the collection will not be changed by another thread.
|
||||
* @return Whether there is a next value in the collection.
|
||||
* @see #next()
|
||||
*/
|
||||
public boolean hasNext();
|
||||
/**
|
||||
* Gets the next value in the collection.
|
||||
* This method does not ensure that the collection will have a next value, even if the hasNext method has been called and returned a positive result.
|
||||
* @return The next value in the collection.
|
||||
* @see #hasNext()
|
||||
*/
|
||||
public Object next();
|
||||
/**
|
||||
* Removes the last returned value.
|
||||
* @return Whether the value was successfully removed.
|
||||
*/
|
||||
public boolean remove();
|
||||
/**
|
||||
* Resets the iterator to iterate over the collection starting with the first value.
|
||||
* The first item to be returned will be the first item in the collection.
|
||||
* @see #next()
|
||||
* @see #hasNext()
|
||||
*/
|
||||
public void resetToFront();
|
||||
}//IIterator//
|
||||
33
Common/src/com/common/util/IList.java
Normal file
33
Common/src/com/common/util/IList.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import com.common.comparison.*;
|
||||
|
||||
public interface IList extends IIndexedCollection {
|
||||
/**
|
||||
* Gets the comparator used to locate values in the collection.
|
||||
* @return The comparator the collection uses to compare two values when trying to get an index for a value.
|
||||
*/
|
||||
public IComparator getLocateComparator();
|
||||
/**
|
||||
* Sets the comparator used to locate values in the collection.
|
||||
* @param locateComparator The comparator the collection uses to compare two values when trying to get an index for a value.
|
||||
*/
|
||||
public void setLocateComparator(IComparator locateComparator);
|
||||
/**
|
||||
* Gets the optional comparator used to order values in the collection.
|
||||
* @return The comparator the collection uses to determine the value ordering. This may be null if the collection is not automatically ordered.
|
||||
*/
|
||||
public IComparator getOrderComparator();
|
||||
/**
|
||||
* Sets the optional comparator used to order values in the collection.
|
||||
* @param orderComparator The comparator the collection uses to determine the value ordering. This may be null if the collection is not automatically ordered.
|
||||
*/
|
||||
public void setOrderComparator(IComparator orderComparator);
|
||||
}//IList//
|
||||
30
Common/src/com/common/util/IMap.java
Normal file
30
Common/src/com/common/util/IMap.java
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2007 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import com.common.comparison.*;
|
||||
import com.common.io.IExternalizable;
|
||||
|
||||
public interface IMap extends java.io.Externalizable, IExternalizable {
|
||||
/**
|
||||
* Gets the comparator used to compare key values.
|
||||
* @return The comparator used to compare keys.
|
||||
*/
|
||||
public IComparator getKeyComparator();
|
||||
public float getLoadFactor();
|
||||
/**
|
||||
* Will retrieve the number of entries in the map.
|
||||
* @return int The number of key value pairs mapped.
|
||||
*/
|
||||
public int getSize();
|
||||
/**
|
||||
* Gets the comparator used to compare values.
|
||||
* @return The comparator used to compare values.
|
||||
*/
|
||||
public IComparator getValueComparator();
|
||||
}//IMap//
|
||||
16
Common/src/com/common/util/IQueue.java
Normal file
16
Common/src/com/common/util/IQueue.java
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* Defines the interface for a standard queueing mechanism.
|
||||
*/
|
||||
public interface IQueue {
|
||||
public Object dequeue();
|
||||
public boolean enqueue(Object object);
|
||||
}//IQueue//
|
||||
35
Common/src/com/common/util/IReversableIterator.java
Normal file
35
Common/src/com/common/util/IReversableIterator.java
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* Adds the ability to reverse iterate over a collection.
|
||||
*/
|
||||
public interface IReversableIterator extends IIterator{
|
||||
/**
|
||||
* Makes sure there is a previous value in the collection.
|
||||
* This method does not ensure that the collection will not be changed by another thread.
|
||||
* @return Whether there is a previous value in the collection.
|
||||
* @see #previous()
|
||||
*/
|
||||
public boolean hasPrevious();
|
||||
/**
|
||||
* Gets the previous value in the collection.
|
||||
* This method does not ensure that the collection will have a previous value, even if the hasPrevious method has been called and returned a positive result.
|
||||
* @return The previous value in the collection.
|
||||
* @see #hasPrevious()
|
||||
*/
|
||||
public Object previous();
|
||||
/**
|
||||
* Resets the iterator to reverse iterate over the collection.
|
||||
* The first item to be returned will be the last item in the collection.
|
||||
* @see #previous()
|
||||
* @see #hasPrevious()
|
||||
*/
|
||||
public void resetToBack();
|
||||
}//IReversableIterator//
|
||||
14
Common/src/com/common/util/ISet.java
Normal file
14
Common/src/com/common/util/ISet.java
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* Defines the interface for a standard unordered set of values.
|
||||
*/
|
||||
public interface ISet extends ICollection {
|
||||
}//ISet//
|
||||
47
Common/src/com/common/util/ISortedMap.java
Normal file
47
Common/src/com/common/util/ISortedMap.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2003,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import com.common.comparison.*;
|
||||
|
||||
public interface ISortedMap extends IMap {
|
||||
/**
|
||||
* Gets the comparator used to sort the map keys.
|
||||
* @return The comparator that determines which keys are greater or less than other keys.
|
||||
*/
|
||||
public IComparator getComparator();
|
||||
/**
|
||||
* Gets the first (lowest) key currently in this sorted map.
|
||||
* @return The first (lowest) key currently in this sorted map.
|
||||
*/
|
||||
public Object getFirstKey();
|
||||
/**
|
||||
* Gets the sorted map containing all keys that occur before the given key (exclusive).
|
||||
* @param key The key to use to split the map.
|
||||
* @return The new sorted map containing the desired values.
|
||||
*/
|
||||
public ISortedMap getHeadMap(Object key);
|
||||
/**
|
||||
* Gets the last (highest) key currently in this sorted map.
|
||||
* @return The last (highest) key currently in this sorted map.
|
||||
*/
|
||||
public Object getLastKey();
|
||||
/**
|
||||
* Gets a new sorted map containing the keys between the fromKey (inclusive) and toKey (exclusive).
|
||||
* @param fromKey The key that begins the range desired, and is included in the range.
|
||||
* @param toKey The key that ends the range of keys desired and is not included.
|
||||
* @return The new sorted mapping of the selected keys.
|
||||
*/
|
||||
public ISortedMap getSubMap(Object fromKey, Object toKey);
|
||||
/**
|
||||
* Gets the sorted map containing all keys that occur after the given key (inclusive).
|
||||
* @param key The key to use to split the map (is included in the range).
|
||||
* @return The new sorted map containing the desired values.
|
||||
*/
|
||||
public ISortedMap getTailMap(Object fromKey);
|
||||
}//ISortedMap//
|
||||
16
Common/src/com/common/util/IStack.java
Normal file
16
Common/src/com/common/util/IStack.java
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* Defines the interface for a standard stack collection.
|
||||
*/
|
||||
public interface IStack {
|
||||
public Object pop();
|
||||
public boolean push(Object object);
|
||||
}//IStack//
|
||||
118
Common/src/com/common/util/ITree.java
Normal file
118
Common/src/com/common/util/ITree.java
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2003,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* Defines a tree consisting of a set of nodes each referencing a value. Values are placed into the tree and the tree manages the associations between the values.
|
||||
*/
|
||||
public interface ITree extends ICollection {
|
||||
/**
|
||||
* Adds the given value to the tree under the parent value.
|
||||
* @param parent The value's parent value, or null if this is a root level tree value.
|
||||
* @param value A value to add to the tree.
|
||||
* @return Will be true if the operation was a success.
|
||||
*/
|
||||
public boolean add(Object parent, Object value);
|
||||
/**
|
||||
* Adds the given value to the tree under the parent value.
|
||||
* @param parent The value's parent value, or null if this is a root level tree value.
|
||||
* @param value A value to add to the tree.
|
||||
* @param context The context under which the change is being made.
|
||||
* @return Will be true if the operation was a success.
|
||||
*/
|
||||
public boolean add(Object parent, Object value, byte context);
|
||||
/**
|
||||
* Adds the given values to the tree under the parent value.
|
||||
* @param parent The parent for the new values.
|
||||
* @param values The values to add to the tree.
|
||||
* @return Will be true if the operation was a success.
|
||||
*/
|
||||
public boolean addAll(Object parent, Object[] values);
|
||||
/**
|
||||
* Adds the given values to the tree under the parent value.
|
||||
* @param parent The parent for the new values.
|
||||
* @param values The values to add to the tree.
|
||||
* @param context The context under which the change is being made.
|
||||
* @return Will be true if the operation was a success.
|
||||
*/
|
||||
public boolean addAll(Object parent, Object[] values, byte context);
|
||||
/**
|
||||
* Adds the given values to the tree under the parent value.
|
||||
* @param parent The parent for the new values.
|
||||
* @param values The values to add to the tree.
|
||||
* @return Will be true if the operation was a success.
|
||||
*/
|
||||
public boolean addAll(Object parent, ICollection values);
|
||||
/**
|
||||
* Adds the given values to the tree under the parent value.
|
||||
* @param parent The parent for the new values.
|
||||
* @param values The values to add to the tree.
|
||||
* @param context The context under which the change is being made.
|
||||
* @return Will be true if the operation was a success.
|
||||
*/
|
||||
public boolean addAll(Object parent, ICollection values, byte context);
|
||||
/**
|
||||
* Adds the given tree of values to the tree under the parent value.
|
||||
* @param parent The parent for the new values.
|
||||
* @param values The tree of values to add to the tree.
|
||||
* @return Will be true if the operation was a success.
|
||||
*/
|
||||
public boolean addAll(Object parent, ITree values);
|
||||
/**
|
||||
* Adds the given tree of values to the tree under the parent value.
|
||||
* @param parent The parent for the new values.
|
||||
* @param values The tree of values to add to the tree.
|
||||
* @param context The context under which the change is being made.
|
||||
* @return Will be true if the operation was a success.
|
||||
*/
|
||||
public boolean addAll(Object parent, ITree values, byte context);
|
||||
/**
|
||||
* Gets the value's child count.
|
||||
* @param value The value whose children are to be counted, or null for root level values.
|
||||
* @return The number of children under the given tree value.
|
||||
*/
|
||||
public int getChildCount(Object value);
|
||||
/**
|
||||
* Gets the value's children.
|
||||
* @param value The value whose children are to be found, or null for root level values.
|
||||
* @return The tree of children for the given value.
|
||||
*/
|
||||
public ITree getChildren(Object value);
|
||||
/**
|
||||
* Gets the value's children.
|
||||
* @param value The value whose children are to be found, or null for root level values.
|
||||
* @param children The collection that the children will be added to.
|
||||
* @return Whether the operation was successful.
|
||||
*/
|
||||
public boolean getChildren(Object value, IList children);
|
||||
/**
|
||||
* Gets the value's parent value.
|
||||
* @param value The value whose parent value is to be found.
|
||||
* @return The parent value for the given value, or null if there isn't one (the value is a root level value).
|
||||
*/
|
||||
public Object getParent(Object value);
|
||||
/**
|
||||
* Gets a depth first iterator over all of the tree values.
|
||||
* @param rootValue The root of the iterator.
|
||||
* @return An iterator that will iterate over all the tree values using a depth first algorithm.
|
||||
*/
|
||||
public IIterator iterator(Object rootValue);
|
||||
/**
|
||||
* Gets a depth first iterator over all of the tree values.
|
||||
* @param depthFirst Whether the iterator should start at the bottom and traverse from left to right. A standard iterator starts at the top and works from left to right (first to last).
|
||||
* @return An iterator that will iterate over all the tree values using a depth first algorithm.
|
||||
*/
|
||||
public IIterator iteratorDepthFirst();
|
||||
/**
|
||||
* Gets a depth first iterator over all of the tree values.
|
||||
* @param rootValue The root of the iterator.
|
||||
* @param depthFirst Whether the iterator should start at the bottom and traverse from left to right. A standard iterator starts at the top and works from left to right (first to last).
|
||||
* @return An iterator that will iterate over all the tree values using a depth first algorithm.
|
||||
*/
|
||||
public IIterator iteratorDepthFirst(Object rootValue);
|
||||
}//ITree//
|
||||
128
Common/src/com/common/util/IndexedIterator.java
Normal file
128
Common/src/com/common/util/IndexedIterator.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import com.common.orb.*;
|
||||
import com.common.debug.*;
|
||||
|
||||
/**
|
||||
* The iterator class used by classes that implement IIndexedCollection.
|
||||
*/
|
||||
public class IndexedIterator implements IReversableIterator, java.io.Externalizable {
|
||||
private IIndexedCollection indexedCollection = null;
|
||||
private int index = -1; //Always start at the beginning.//
|
||||
private int previousIndex = -1; //Tracks the previously returned value's index so we can go back one value in iteration (after removing).//
|
||||
private boolean hasRemoved = false; //Ensures we only remove once per call to next or previous.//
|
||||
/**
|
||||
* IndexedIterator constructor.
|
||||
* @param indexedCollection IIndexedCollection The list to iterate over.
|
||||
*/
|
||||
public IndexedIterator(IIndexedCollection indexedCollection) {
|
||||
super();
|
||||
|
||||
this.indexedCollection = indexedCollection;
|
||||
}//IndexedIterator()//
|
||||
/**
|
||||
* Gets the current item in the collection.
|
||||
* This method does not ensure that the collection has a current item.
|
||||
*/
|
||||
public Object current() {
|
||||
return indexedCollection.get(index);
|
||||
}//current()//
|
||||
/**
|
||||
* Makes sure there is a next item in the collection.
|
||||
* This method does not ensure that the collection will not be changed by another thread.
|
||||
* To be used in conjunction with the next() method.
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
return index < indexedCollection.getSize() - 1;
|
||||
}//hasNext()//
|
||||
/**
|
||||
* Makes sure there is a previous item in the collection.
|
||||
* This method does not ensure that the collection will not be changed by another thread.
|
||||
* To be used in conjunction with the previous() method.
|
||||
*/
|
||||
public boolean hasPrevious() {
|
||||
return index > 0;
|
||||
}//hasPrevious()//
|
||||
/**
|
||||
* Gets the next item in the collection.
|
||||
* This method does not ensure that the collection will have a next item, even if the hasNext method has been called and returned a positive result.
|
||||
*/
|
||||
public Object next() {
|
||||
previousIndex = index;
|
||||
hasRemoved = false;
|
||||
|
||||
return indexedCollection.get(++index);
|
||||
}//next()//
|
||||
/**
|
||||
* Gets the previous item in the collection.
|
||||
* This method does not ensure that the collection will have a previous item, even if the hasPrevious method has been called and returned a positive result.
|
||||
*/
|
||||
public Object previous() {
|
||||
previousIndex = index;
|
||||
hasRemoved = false;
|
||||
|
||||
return indexedCollection.get(--index);
|
||||
}//previous()//
|
||||
/**
|
||||
* Will read the collection from the stream.
|
||||
* @param in java.io.ObjectInput The stream that the object data can be read from.
|
||||
*/
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
/*byte version = */in.readByte();
|
||||
|
||||
this.indexedCollection = (IIndexedCollection) in.readObject();
|
||||
this.index = in.readInt();
|
||||
}//readExternal()//
|
||||
/* (non-Javadoc)
|
||||
* @see IIterator#remove()
|
||||
*/
|
||||
public boolean remove() {
|
||||
boolean retVal = false;
|
||||
|
||||
//Make sure we have something to remove, and we only remove once per next or previous call.//
|
||||
if((index != -1) && (!hasRemoved)) {
|
||||
indexedCollection.remove(index);
|
||||
index = previousIndex;
|
||||
hasRemoved = true;
|
||||
retVal = true;
|
||||
}//if//
|
||||
|
||||
return retVal;
|
||||
}//remove()//
|
||||
/**
|
||||
* Resets the iterator to the front of the indexed collection.
|
||||
*/
|
||||
public void resetToBack() {
|
||||
index = indexedCollection.getSize();
|
||||
}//resetToFront()//
|
||||
/**
|
||||
* Resets the iterator to the front of the indexed collection.
|
||||
*/
|
||||
public void resetToFront() {
|
||||
index = -1;
|
||||
}//resetToFront()//
|
||||
/**
|
||||
* Will write the collection to the stream.
|
||||
* @param out java.io.ObjectOutput The stream that the object data can be written to.
|
||||
*/
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
out.writeByte(0);
|
||||
|
||||
try {
|
||||
out.writeObject(Orb.getProxy(indexedCollection, IIndexedCollection.class));
|
||||
}//try//
|
||||
catch(IllegalArgumentException e) {
|
||||
out.writeObject(null);
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
|
||||
out.writeInt(index);
|
||||
}//writeExternal()//
|
||||
}//IndexedIterator//
|
||||
24
Common/src/com/common/util/IntegerHolder.java
Normal file
24
Common/src/com/common/util/IntegerHolder.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2006,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
public class IntegerHolder {
|
||||
public int value = 0;
|
||||
/**
|
||||
* IntegerHolder constructor.
|
||||
*/
|
||||
public IntegerHolder() {
|
||||
}//IntegerHolder()//
|
||||
/**
|
||||
* IntegerHolder constructor.
|
||||
* @param value The initial value for the holder.
|
||||
*/
|
||||
public IntegerHolder(int value) {
|
||||
this.value = value;
|
||||
}//IntegerHolder()//
|
||||
}//IntegerHolder//
|
||||
146
Common/src/com/common/util/JobQueue.java
Normal file
146
Common/src/com/common/util/JobQueue.java
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import com.common.debug.*;
|
||||
import com.common.event.*;
|
||||
import com.common.thread.*;
|
||||
|
||||
public class JobQueue {
|
||||
private Queue queue = new Queue(10);
|
||||
private Object monitor = new Object();
|
||||
private boolean isClosed = false;
|
||||
|
||||
private static class JobHolder {
|
||||
private boolean isComplete = false;
|
||||
private VoidHandler1 handler = null;
|
||||
|
||||
public JobHolder(VoidHandler1 handler) {
|
||||
this.handler = handler;
|
||||
}//JobHolder()//
|
||||
}//JobHolder//
|
||||
|
||||
private class JobRunnable implements Runnable {
|
||||
private Object resource = null;
|
||||
|
||||
private JobRunnable() {
|
||||
}//JobRunnable()//
|
||||
private JobRunnable(Object resource) {
|
||||
this.resource = resource;
|
||||
}//JobRunnable()//
|
||||
public void run() {
|
||||
while(true) {
|
||||
JobHolder jobHolder = waitForJob();
|
||||
|
||||
if(jobHolder != null) {
|
||||
processJob(jobHolder, resource);
|
||||
}//if//
|
||||
else {
|
||||
//Assume we are done with the queue.//
|
||||
break;
|
||||
}//else//
|
||||
}//while//
|
||||
}//run()//
|
||||
}//JobRunnable//
|
||||
/**
|
||||
* JobQueue constructor.
|
||||
*/
|
||||
public JobQueue(Object[] runnableResources) {
|
||||
super();
|
||||
|
||||
for(int index = 0; index < runnableResources.length; index++) {
|
||||
ThreadService.run(new JobRunnable(runnableResources[index]));
|
||||
}//for//
|
||||
}//JobQueue()//
|
||||
/**
|
||||
* JobQueue constructor.
|
||||
*/
|
||||
public JobQueue(int threadCount) {
|
||||
super();
|
||||
|
||||
for(int index = 0; index < threadCount; index++) {
|
||||
ThreadService.run(new JobRunnable());
|
||||
}//for//
|
||||
}//JobQueue()//
|
||||
/**
|
||||
* Adds a job to the ras queue so that the worker threads will process the job as resources are available.
|
||||
* @param handler The handler will process the job when the worker thread determines the resources are available. The parameter will be any RAS resource (maybe connection reference?) that is necessary for the job.
|
||||
* @param timeout The amount of time to wait for the job to finish. If this is zero then the thread will not wait. If this is less than zero than the thread will wait for ever.
|
||||
*/
|
||||
public void addJob(VoidHandler1 handler, long timeout) {
|
||||
JobHolder jobHolder = new JobHolder(handler);
|
||||
|
||||
//Add the job to the queue.//
|
||||
synchronized(monitor) {
|
||||
if(!isClosed) {
|
||||
queue.enqueue(jobHolder);
|
||||
monitor.notify();
|
||||
}//if//
|
||||
else {
|
||||
throw new RuntimeException("Cannot add a job to a closed job queue.");
|
||||
}//else//
|
||||
}//synchronized//
|
||||
|
||||
//Wait for the job to finish.//
|
||||
synchronized(jobHolder) {
|
||||
if((timeout != 0) && (jobHolder.isComplete == false)) {
|
||||
try {
|
||||
jobHolder.wait(timeout < 0 ? 0 : timeout);
|
||||
}//try//
|
||||
catch(InterruptedException e) {
|
||||
Debug.handle(e);
|
||||
}//catch//
|
||||
}//if//
|
||||
}//synchronized//
|
||||
}//addJob()//
|
||||
/**
|
||||
* Closes the JobQueue so that no other jobs will be added and all threads will be released after all jobs have been processed.
|
||||
*/
|
||||
public void close() {
|
||||
synchronized(monitor) {
|
||||
isClosed = true;
|
||||
monitor.notifyAll();
|
||||
}//synchronized//
|
||||
}//close()//
|
||||
/**
|
||||
* Processes the next job in the queue.
|
||||
* @param jobHolder The holder for the job.
|
||||
*/
|
||||
private void processJob(JobHolder jobHolder, Object resource) {
|
||||
//Perform the job.//
|
||||
jobHolder.handler.evaluate(resource); //TODO: Pass any necessary resources to the job.//
|
||||
|
||||
synchronized(jobHolder) {
|
||||
jobHolder.isComplete = true;
|
||||
jobHolder.notifyAll();
|
||||
}//synchronized//
|
||||
}//processJob()//
|
||||
/**
|
||||
* Waits for a job to become available. If one is already queued then the wait does not occur.
|
||||
*/
|
||||
private JobHolder waitForJob() {
|
||||
JobHolder retVal = null;
|
||||
|
||||
synchronized(monitor) {
|
||||
while((!isClosed) && (queue.getSize() == 0)) {
|
||||
try {
|
||||
monitor.wait();
|
||||
}//try//
|
||||
catch(InterruptedException e) {
|
||||
Debug.handle(e);
|
||||
}//catch//
|
||||
}//while//
|
||||
|
||||
if(queue.getSize() > 0) {
|
||||
retVal = (JobHolder) queue.dequeue();
|
||||
}//if//
|
||||
}//synchronized//
|
||||
|
||||
return retVal;
|
||||
}//waitForJob()//
|
||||
}//JobQueue//
|
||||
532
Common/src/com/common/util/LiteCollection.java
Normal file
532
Common/src/com/common/util/LiteCollection.java
Normal file
@@ -0,0 +1,532 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.common.comparison.Comparator;
|
||||
import com.common.comparison.IComparator;
|
||||
import com.common.event.*;
|
||||
import com.common.exception.*;
|
||||
|
||||
/**
|
||||
* The LiteCollection base class provides collection functionality without any event handling or synchronization.
|
||||
* If you need event handling or synchronization you should use a collection class that extends Collection.
|
||||
*/
|
||||
public abstract class LiteCollection implements ICollection {
|
||||
private boolean isChangeable = true;
|
||||
/**
|
||||
* LiteCollection constructor.
|
||||
*/
|
||||
protected LiteCollection() {
|
||||
super();
|
||||
}//LiteCollection()//
|
||||
/**
|
||||
* LiteCollection constructor.
|
||||
* @param isChangeable Whether the collection may be changed. This should be false if the collection may no longer be modified.
|
||||
*/
|
||||
protected LiteCollection(boolean isChangeable) {
|
||||
super();
|
||||
|
||||
this.isChangeable = isChangeable;
|
||||
}//LiteCollection()//
|
||||
/**
|
||||
* Ensures that the collection can hold at least the number of components specified by the minimum capacity argument.
|
||||
* @param minimumCapacity The desired minimum capacity of this collection (above what it currently holds).
|
||||
*/
|
||||
public abstract void ensureCapacity(int minimumCapacity);
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#add(java.lang.Object)
|
||||
*/
|
||||
public int add(Object value) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
return internalAdd(value);
|
||||
}//add()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#addAll(java.lang.Object[])
|
||||
*/
|
||||
public boolean addAll(Object[] values) {
|
||||
return addAll(values, 0, values.length);
|
||||
}//addAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#addAll(java.lang.Object[], int, int)
|
||||
*/
|
||||
public boolean addAll(Object[] values, int offset, int length) {
|
||||
boolean result = true;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
//Resize the collection only once if it requires it at all.//
|
||||
ensureCapacity(length);
|
||||
|
||||
//Make sure that the collection has values.//
|
||||
if((values != null) && (values.length > 0) && (length + offset <= values.length) && (offset >= 0)) {
|
||||
Object next = null;
|
||||
|
||||
//Iterate over the items to be added and add them one at a time.//
|
||||
for(int index = offset; index < length; index++) {
|
||||
next = values[index];
|
||||
|
||||
if(internalAdd(next) == -1) {
|
||||
result = false;
|
||||
}//if//
|
||||
}//while//
|
||||
}//if//
|
||||
else {
|
||||
result = false;
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//addAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#addAll(com.common.util.ICollection)
|
||||
*/
|
||||
public boolean addAll(ICollection values) {
|
||||
boolean result = true;
|
||||
|
||||
if(values instanceof IIndexedCollection) {
|
||||
result = addAll((IIndexedCollection) values, 0, values.getSize());
|
||||
}//if//
|
||||
else {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
//Resize the collection only once if it requires it at all.//
|
||||
ensureCapacity(values.getSize());
|
||||
|
||||
//Make sure that the collection has values.//
|
||||
if((values != null) && (values.getSize() > 0)) {
|
||||
Object next = null;
|
||||
|
||||
//Iterate over the items to be added and add them one at a time.//
|
||||
for(IIterator iterator = values.iterator(); iterator.hasNext(); ) {
|
||||
next = iterator.next();
|
||||
|
||||
if(internalAdd(next) == -1) {
|
||||
result = false;
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
else {
|
||||
result = false;
|
||||
}//else//
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//addAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#addAll(com.common.util.IIndexedCollection, int, int)
|
||||
*/
|
||||
public boolean addAll(IIndexedCollection values, int offset, int length) {
|
||||
boolean result = true;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
//Resize the collection only once if it requires it at all.//
|
||||
ensureCapacity(length);
|
||||
|
||||
//Make sure that the collection has values.//
|
||||
if((values != null) && (length > 0)) {
|
||||
Object next = null;
|
||||
|
||||
//Iterate over the items to be added and add them one at a time.//
|
||||
for(int valuesIndex = offset, count = offset + length; valuesIndex < count; valuesIndex++) {
|
||||
next = values.get(valuesIndex);
|
||||
|
||||
if(internalAdd(next) == -1) {
|
||||
result = false;
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
else {
|
||||
result = false;
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//addAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#addAll(com.common.util.IIterator)
|
||||
*/
|
||||
public boolean addAll(IIterator values) {
|
||||
boolean result = true;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Make sure that the collection has values.//
|
||||
if(values != null) {
|
||||
Object next = null;
|
||||
|
||||
//Iterate over the items to be added and add them one at a time.//
|
||||
while(values.hasNext()) {
|
||||
next = values.next();
|
||||
|
||||
if(internalAdd(next) == -1) {
|
||||
result = false;
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
else {
|
||||
result = false;
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//addAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#collect(com.common.event.ObjectHandler1, com.common.util.IList)
|
||||
*/
|
||||
public IList collect(ObjectHandler1 handler, IList results) {
|
||||
IIterator iterator = iterator();
|
||||
|
||||
if(results == null) {
|
||||
results = new LiteList(getSize());
|
||||
}//if//
|
||||
|
||||
//Iterate over the items in this collection passing them to the handler, and collect the resulting values.//
|
||||
while(iterator.hasNext()) {
|
||||
results.add(handler.evaluate(iterator.next()));
|
||||
}//while//
|
||||
|
||||
return results;
|
||||
}//collect()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#containsValue(java.lang.Object)
|
||||
*/
|
||||
public abstract boolean containsValue(Object value);
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#getSize()
|
||||
*/
|
||||
public abstract int getSize();
|
||||
/**
|
||||
* Will add a value to the collection.
|
||||
* @param value Object The value to add.
|
||||
* @return The index of the addition if the collection is indexed, 0 if the collection is not indexed, or -1 if the operation failed.
|
||||
*/
|
||||
protected abstract int internalAdd(Object value);
|
||||
/**
|
||||
* Will remove a value from the collection.
|
||||
* @param value Object The value to remove.
|
||||
* @return boolean Will return true if the operation was successful.
|
||||
*/
|
||||
protected abstract boolean internalRemove(Object value);
|
||||
/**
|
||||
* Will remove all of the values in the collection.
|
||||
* @return boolean Will return true if the operation was successful.
|
||||
*/
|
||||
protected abstract void internalRemoveAll();
|
||||
/**
|
||||
* Replaces one value with another in the collection.
|
||||
* @param oldValue Object The value to replace.
|
||||
* @param newValue Object The value to insert.
|
||||
* @return boolean Will return true if the operation was successful.
|
||||
*/
|
||||
protected abstract boolean internalReplace(Object oldValue, Object newValue);
|
||||
/**
|
||||
* Replaces the values currently in the collection with the given collection of values.
|
||||
* @param values The values to replace the ones currently in the collection.
|
||||
* @return Returns true if the operation was successful.
|
||||
*/
|
||||
protected abstract boolean internalReplaceAll(ICollection values);
|
||||
/**
|
||||
* Replaces the removed values in the current collection with those in the added values collection.
|
||||
* @param removedValues The values to be replaced.
|
||||
* @param addedValues The values to replace the removed values. Note that the collections need not be of the same size.
|
||||
* @return Whether the operation completed successfully. The operation may only partially complete if this is false.
|
||||
*/
|
||||
protected abstract boolean internalReplaceAll(ICollection removedValues, ICollection addedValues);
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#isChangeable()
|
||||
*/
|
||||
public boolean isChangeable() {
|
||||
return isChangeable;
|
||||
}//isChangeable()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#isChangeable(boolean)
|
||||
*/
|
||||
public void isChangeable(boolean isChangeable) {
|
||||
if(!isChangeable) {
|
||||
this.isChangeable = isChangeable;
|
||||
}//if//
|
||||
else if(this.isChangeable == isChangeable) {
|
||||
//Do nothing as nothing has changed.//
|
||||
}//else if//
|
||||
else {
|
||||
throw new RuntimeException("You may not change the collection to be changeable after it has been locked.");
|
||||
}//else//
|
||||
}//isChangeable()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#iterator()
|
||||
*/
|
||||
public abstract IIterator iterator();
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#perform(com.common.event.VoidHandler1)
|
||||
*/
|
||||
public void perform(VoidHandler1 handler) {
|
||||
IIterator iterator = iterator();
|
||||
|
||||
//Iterate over the items in this collection passing them to the handler to perform some function.//
|
||||
while(iterator.hasNext()) {
|
||||
handler.evaluate(iterator.next());
|
||||
}//while//
|
||||
}//perform()//
|
||||
/**
|
||||
* Will read the collection from the stream.
|
||||
* @param in java.io.ObjectInput The stream that the object data can be read from.
|
||||
*/
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
}//readExternal()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#reject(com.common.event.BooleanHandler1, com.common.util.IList)
|
||||
*/
|
||||
public IList reject(BooleanHandler1 handler, IList results) {
|
||||
IIterator iterator = iterator();
|
||||
|
||||
if(results == null) {
|
||||
results = new LiteList(10, 50);
|
||||
}//if//
|
||||
|
||||
//Iterate over the items in this collection passing them to the handler, and collect the resulting values.//
|
||||
while(iterator.hasNext()) {
|
||||
Object value = iterator.next();
|
||||
|
||||
if(!handler.evaluate(value).booleanValue()) {
|
||||
results.add(value);
|
||||
}//if//
|
||||
}//while//
|
||||
|
||||
return results;
|
||||
}//reject()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#remove(java.lang.Object)
|
||||
*/
|
||||
public boolean remove(Object value) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
return internalRemove(value);
|
||||
}//remove()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#removeAll()
|
||||
*/
|
||||
public void removeAll() {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
internalRemoveAll();
|
||||
}//removeAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#removeAll(java.lang.Object[])
|
||||
*/
|
||||
public boolean removeAll(Object[] values) {
|
||||
return removeAll(values, 0, values.length);
|
||||
}//removeAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#removeAll(java.lang.Object[], int, int)
|
||||
*/
|
||||
public boolean removeAll(Object[] values, int offset, int length) {
|
||||
boolean result = true;
|
||||
|
||||
//Verify that this collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Make sure that there are values to remove.//
|
||||
if((values != null) && (values.length > 0) && (offset >= 0) && (offset + length <= values.length)) {
|
||||
Object next = null;
|
||||
|
||||
//Remove the values one at a time.//
|
||||
for(int index = offset; index < length; index++) {
|
||||
next = values[index];
|
||||
|
||||
if(!internalRemove(next)) {
|
||||
result = false;
|
||||
}//if//
|
||||
}//while//
|
||||
}//if//
|
||||
else {
|
||||
result = false;
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//removeAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#removeAll(com.common.util.ICollection)
|
||||
*/
|
||||
public boolean removeAll(ICollection values) {
|
||||
boolean result = true;
|
||||
|
||||
//Verify that this collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Make sure that there are values to remove.//
|
||||
if((values != null) && (values.getSize() > 0)) {
|
||||
Object next = null;
|
||||
|
||||
//Remove the values one at a time.//
|
||||
for(IIterator iterator = values.iterator(); iterator.hasNext(); ) {
|
||||
next = iterator.next();
|
||||
|
||||
if(!internalRemove(next)) {
|
||||
result = false;
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
else {
|
||||
result = false;
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//removeAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#removeAll(com.common.util.ICollection)
|
||||
*/
|
||||
public boolean removeAll(IIterator values) {
|
||||
boolean result = true;
|
||||
|
||||
//Verify that this collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Make sure that there are values to remove.//
|
||||
if(values != null) {
|
||||
Object next = null;
|
||||
|
||||
//Remove the values one at a time.//
|
||||
while(values.hasNext()) {
|
||||
next = values.next();
|
||||
|
||||
if(!internalRemove(next)) {
|
||||
result = false;
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
else {
|
||||
result = false;
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//removeAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#replace(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
public boolean replace(Object oldValue, Object newValue) {
|
||||
//Verify that this collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
return internalReplace(oldValue, newValue);
|
||||
} //replace()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#replaceAll(com.common.util.ICollection)
|
||||
*/
|
||||
public boolean replaceAll(ICollection values) {
|
||||
return internalReplaceAll(values);
|
||||
}//replaceAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#replaceAll(com.common.util.ICollection, com.common.util.ICollection)
|
||||
*/
|
||||
public boolean replaceAll(ICollection removedValues, ICollection addedValues) {
|
||||
return internalReplaceAll(removedValues, addedValues);
|
||||
}//replaceAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#select(com.common.event.BooleanHandler1, com.common.util.IList)
|
||||
*/
|
||||
public IList select(BooleanHandler1 handler, IList results) {
|
||||
IIterator iterator = iterator();
|
||||
|
||||
if(results == null) {
|
||||
results = new LiteList(10, 50);
|
||||
}//if//
|
||||
|
||||
//Iterate over the items in this collection passing them to the handler, and collect the resulting values.//
|
||||
while(iterator.hasNext()) {
|
||||
Object value = iterator.next();
|
||||
|
||||
if(handler.evaluate(value).booleanValue()) {
|
||||
results.add(value);
|
||||
}//if//
|
||||
}//while//
|
||||
|
||||
return results;
|
||||
}//select()//
|
||||
/**
|
||||
* Converts the list to an object array.
|
||||
* @return Object[] An array of the values in the collection.
|
||||
*/
|
||||
public Object[] toArray() {
|
||||
Object[] result = new Object[getSize()];
|
||||
|
||||
toArray(result);
|
||||
|
||||
return result;
|
||||
}//toArray()//
|
||||
/* (Non-Javadoc)
|
||||
* @see ICollection.toArray(Object)
|
||||
*/
|
||||
public abstract int toArray(Object array);
|
||||
/**
|
||||
* Verifies that the collection may be modified.
|
||||
* @throws IllegalOperationException If the isImmutable flag is set.
|
||||
*/
|
||||
protected void verifyIsChangeable() {
|
||||
if(!isChangeable) {
|
||||
throw new IllegalOperationException("The collection is immutable which prevents the collection from being modified.");
|
||||
}//if//
|
||||
}//verifyIsChangeable()//
|
||||
/**
|
||||
* Writes the collection to the stream.
|
||||
* @param out java.io.ObjectOutput The stream that the object data can be written to.
|
||||
*/
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
}//writeExternal()//
|
||||
/**
|
||||
* Calculates the diffences between the old array and new array.
|
||||
* @param oldArray The old array.
|
||||
* @param newArray The new array.
|
||||
* @param comparator The optional comparator used to determine equality. If null then exact equality will be used (==).
|
||||
* @param added The optional set of items that are new in the new array (that don't exist in the old array).
|
||||
* @param removed The optional set of items that are old in the old array (that don't exist in the new array).
|
||||
* @param unchanged The optional set of items that have not changed and are in both arrays.
|
||||
*/
|
||||
public static void calculateDifferences(Object[] oldArray, Object[] newArray, IComparator comparator, ICollection added, ICollection removed, ICollection unchanged) {
|
||||
boolean[] newMatched = new boolean[newArray.length];
|
||||
|
||||
Arrays.fill(newMatched, false);
|
||||
|
||||
if(comparator == null) {
|
||||
comparator = Comparator.getIdentityComparator();
|
||||
}//if//
|
||||
|
||||
//For each old item, see if it exists in the new items and add to the appropriate collections. Mark matched items so we can easily see which items are new.//
|
||||
for(int oldIndex = 0; oldIndex < oldArray.length; oldIndex++) {
|
||||
boolean found = false;
|
||||
|
||||
//Search for a match in the new collection.//
|
||||
for(int newIndex = 0; (!found) && (newIndex < newArray.length); newIndex++) {
|
||||
if((!newMatched[newIndex]) && (Comparator.isEqual(comparator.compare(oldArray[oldIndex], newArray[newIndex])))) {
|
||||
found = true;
|
||||
newMatched[newIndex] = true;
|
||||
|
||||
if(unchanged != null) {
|
||||
unchanged.add(oldArray[oldIndex]);
|
||||
}//if//
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
if((!found) && (removed != null)) {
|
||||
removed.add(oldArray[oldIndex]);
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//If we need to collect added items then iterate over the new items and add those that are not marked as matched.//
|
||||
if(added != null) {
|
||||
for(int newIndex = 0; newIndex < newArray.length; newIndex++) {
|
||||
if(!newMatched[newIndex]) {
|
||||
added.add(newArray[newIndex]);
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
}//calculateDifferences()//
|
||||
}//LiteCollection//
|
||||
580
Common/src/com/common/util/LiteHashMap.java
Normal file
580
Common/src/com/common/util/LiteHashMap.java
Normal file
@@ -0,0 +1,580 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import com.common.comparison.*;
|
||||
|
||||
/**
|
||||
* A map collection that maps values by a key so that they may be looked up by that key.
|
||||
* <p><b>Warning:</b> This class is NOT thread safe. To use it in a multi threaded environment all access to the map should by in a synchronization block.
|
||||
*/
|
||||
public class LiteHashMap extends Map implements IHashMap {
|
||||
/** A reusable always empty map. */
|
||||
public static final LiteHashMap EMPTY_MAP = new LiteHashMap(1);
|
||||
|
||||
static {
|
||||
EMPTY_MAP.isChangeable(false);
|
||||
}//static//
|
||||
|
||||
private LiteList keys = null;
|
||||
/** Whether the map should maintain the counter for each map entry. If this is true then items added more than once to the map (same key/value pair) will increment the count, and removes will decrement the count. */
|
||||
private boolean maintainCount = false;
|
||||
|
||||
/**
|
||||
* The Entry wrappers the key/value pair.
|
||||
*/
|
||||
protected static class Entry extends BasicEntry {
|
||||
protected Object key = null;
|
||||
protected Object value = null;
|
||||
protected int count = 1;
|
||||
|
||||
public Entry() {
|
||||
super();
|
||||
}//Entry()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
super.readExternal(in);
|
||||
key = in.readObject();
|
||||
value = in.readObject();
|
||||
count = in.readInt();
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
}//readExternal()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
super.writeExternal(out);
|
||||
out.writeObject(key == NULL_KEY ? null : key);
|
||||
out.writeObject(value);
|
||||
out.writeInt(count);
|
||||
}//writeExternal()//
|
||||
public int createKeyHash() {
|
||||
return key.hashCode();
|
||||
}//createKeyHash()//
|
||||
public String toString() {
|
||||
return super.toString() + "\r\n\tKey: " + (key == NULL_KEY ? "null" : key.toString()) + "\r\n\tValue: " + value + (next != null ? "\r\n\t" + next.toString() : "");
|
||||
}//toString()//
|
||||
}//Entry//
|
||||
|
||||
public static class KeyIterator extends Iterator implements IReversableIterator {
|
||||
public KeyIterator(LiteHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//KeyIterator()//
|
||||
public Object next() {
|
||||
Object result = ((Entry) nextEntry()).key;
|
||||
|
||||
if(result == NULL_KEY) {
|
||||
result = null;
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//next()//
|
||||
public Object previous() {
|
||||
Object result = ((Entry) previousEntry()).key;
|
||||
|
||||
if(result == NULL_KEY) {
|
||||
result = null;
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//previous()//
|
||||
}//KeyIterator//
|
||||
|
||||
public static class ValueIterator extends Iterator implements IIterator {
|
||||
public ValueIterator(LiteHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//ValueIterator()//
|
||||
public Object next() {
|
||||
return ((Entry) nextEntry()).value;
|
||||
}//next()//
|
||||
public Object previous() {
|
||||
return ((Entry) previousEntry()).value;
|
||||
}//previous()//
|
||||
}//ValueIterator//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* <p>This constructor is private because is not advisable to use the default initial size because it will not be optimal for most applications.
|
||||
*/
|
||||
public LiteHashMap() {
|
||||
super();
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public LiteHashMap(int initialCapacity) {
|
||||
super(initialCapacity);
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param maintainCount Whether the map should maintain the counter for each map entry. If this is true then items added more than once to the map (same key/value pair) will increment the count, and removes will decrement the count.
|
||||
*/
|
||||
public LiteHashMap(int initialCapacity, boolean maintainCount) {
|
||||
super(initialCapacity);
|
||||
this.maintainCount = maintainCount;
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public LiteHashMap(int initialCapacity, float loadFactor) {
|
||||
super(initialCapacity, loadFactor);
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
* @param maintainCount Whether the map should maintain the counter for each map entry. If this is true then items added more than once to the map (same key/value pair) will increment the count, and removes will decrement the count.
|
||||
*/
|
||||
public LiteHashMap(int initialCapacity, float loadFactor, boolean maintainCount) {
|
||||
super(initialCapacity, loadFactor);
|
||||
this.maintainCount = maintainCount;
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public LiteHashMap(int initialCapacity, float loadFactor, IComparator keyComparator, IComparator valueComparator) {
|
||||
super(initialCapacity, loadFactor, keyComparator, valueComparator);
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
* @param maintainCount Whether the map should maintain the counter for each map entry. If this is true then items added more than once to the map (same key/value pair) will increment the count, and removes will decrement the count.
|
||||
*/
|
||||
public LiteHashMap(int initialCapacity, float loadFactor, IComparator keyComparator, IComparator valueComparator, boolean maintainCount) {
|
||||
super(initialCapacity, loadFactor, keyComparator, valueComparator);
|
||||
this.maintainCount = maintainCount;
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public LiteHashMap(int initialCapacity, IComparator keyComparator, IComparator valueComparator) {
|
||||
super(initialCapacity, keyComparator, valueComparator);
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public LiteHashMap(IComparator keyComparator, IComparator valueComparator) {
|
||||
super(keyComparator, valueComparator);
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* This constructor will copy an existing IHashMap.
|
||||
* @param map A map to copy.
|
||||
*/
|
||||
public LiteHashMap(IHashMap map) {
|
||||
super(map.getSize() > 10 ? map.getSize() : 10, map.getLoadFactor());
|
||||
IIterator iterator = map.keyIterator();
|
||||
|
||||
//Iterate over the existing map's keys and put the key value pairs in this map.//
|
||||
while(iterator.hasNext()) {
|
||||
Object key = iterator.next();
|
||||
Object value = map.get(key);
|
||||
|
||||
put(key, value);
|
||||
}//while//
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* This constructor will copy an existing IHashMap.
|
||||
* @param map A map to copy.
|
||||
*/
|
||||
public LiteHashMap(LiteHashMap map) {
|
||||
super(map.getSize() > 10 ? map.getSize() : 10, map.getLoadFactor(), map.getKeyComparator(), map.getValueComparator());
|
||||
IIterator iterator = map.keyIterator();
|
||||
|
||||
//Iterate over the existing map's keys and put the key value pairs in this map.//
|
||||
while(iterator.hasNext()) {
|
||||
Object key = iterator.next();
|
||||
Object value = map.get(key);
|
||||
|
||||
put(key, value);
|
||||
}//while//
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* @param initialSize The initial size of the map.
|
||||
* @param initialKeyValuePairs The initial key/value pairs to be placed in the map. This should be an array of arrays where the inner array consists of a key object and a value object, no more, no less.
|
||||
*/
|
||||
public LiteHashMap(int initialSize, Object[][] initialKeyValuePairs) {
|
||||
this(initialSize);
|
||||
|
||||
for(int index = 0; index < initialKeyValuePairs.length; index++) {
|
||||
if(initialKeyValuePairs[index].length == 2) {
|
||||
Object key = initialKeyValuePairs[index][0];
|
||||
Object value = initialKeyValuePairs[index][1];
|
||||
|
||||
put(key, value);
|
||||
}//if//
|
||||
}//for//
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* LiteHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
* @param keys The keys, or null if the value index is used.
|
||||
* @param values The values, or null if the key index is used. If both values and keys are null then nothing is added to the map.
|
||||
* @param isChangeable Whether the map is changeable after initialization.
|
||||
*/
|
||||
public LiteHashMap(int initialSize, float loadFactor, IComparator keyComparator, IComparator valueComparator, Object[] keys, Object[] values, boolean isChangeable) {
|
||||
this(initialSize, loadFactor, keyComparator, valueComparator);
|
||||
|
||||
if(keys != null && values != null) {
|
||||
for(int index = 0, max = Math.min(keys.length, values.length); index < max; index++) {
|
||||
put(keys[index], values[index]);
|
||||
}//for//
|
||||
}//if//
|
||||
else if(keys != null) {
|
||||
for(int index = 0; index < keys.length; index++) {
|
||||
put(keys[index], new Integer(index));
|
||||
}//for//
|
||||
}//else if//
|
||||
else if(values != null) {
|
||||
for(int index = 0; index < values.length; index++) {
|
||||
put(new Integer(index), values[index]);
|
||||
}//for//
|
||||
}//else if//
|
||||
}//LiteHashMap()//
|
||||
/**
|
||||
* Determines whether the key exists in the map.
|
||||
* @param key The key to look for.
|
||||
* @return Will be <code>true</code> if the key is already in the map.
|
||||
*/
|
||||
public boolean containsKey(Object key) {
|
||||
return get(key) != null;
|
||||
}//containsKey()//
|
||||
/**
|
||||
* Creates an entry object of the specific type used by this map.
|
||||
* @return An entry object that can be filled and passed to the addEntry method.
|
||||
*/
|
||||
protected IBasicEntry createEntry() {
|
||||
return new Entry();
|
||||
}//createEntry()//
|
||||
/**
|
||||
* Gets the first key in the map.
|
||||
* @return The first accessable key in the mapping.
|
||||
*/
|
||||
public Object getFirstKey() {
|
||||
if(getSize() > 0) {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
Object result = null;
|
||||
|
||||
for(int index = 0; (result == null) && (index < entries.length); index++) {
|
||||
if(entries[index] != null) {
|
||||
result = ((Entry) entries[index]).key;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return result;
|
||||
}//if//
|
||||
else {
|
||||
throw new RuntimeException("No keys in the mapping.");
|
||||
}//else//
|
||||
}//getFirstKey()//
|
||||
/**
|
||||
* Gets an object in the map by its' key.
|
||||
* @param key The key whose value should be retieved.
|
||||
* @return The value associated with the key. A <code>null</code> value will be returned only if the key was not found.
|
||||
*/
|
||||
public Object get(Object key) {
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(Entry entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key, key)))) {
|
||||
return entry.value;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return null;
|
||||
}//get()//
|
||||
/**
|
||||
* Gets the reference count for the map entry identified by the given key.
|
||||
* @param key The map entry's key.
|
||||
* @return The number of times the map entry (same exact key/value pair) has been added to the mapping.
|
||||
*/
|
||||
public int getCount(Object key) {
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(Entry entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key, key)))) {
|
||||
return entry.count;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return 0;
|
||||
}//getCount()//
|
||||
/**
|
||||
* Gets the key at the given index.
|
||||
* <p>NOTE: This method is intended for use by the iterators and it is not advisable to use this method else where.
|
||||
* @param index The index in the list of keys.
|
||||
* @return The key at the given index.
|
||||
*/
|
||||
public Object getKey(int index) {
|
||||
if(keys == null) {
|
||||
refreshKeys();
|
||||
}//if//
|
||||
|
||||
return keys.get(index);
|
||||
}//getKey()//
|
||||
/**
|
||||
* Gets the collection of all keys in the map.
|
||||
* @param keys A collection that will contain the keys.
|
||||
* @return The collection with the keys in it. This will be the same collection as the one passed if it is non-null.
|
||||
*/
|
||||
public IList getKeys(IList keys) {
|
||||
if(this.keys == null) {
|
||||
refreshKeys();
|
||||
}//if//
|
||||
|
||||
if(keys == null) {
|
||||
keys = new LiteList(this.keys.getSize(), 10);
|
||||
}//if//
|
||||
|
||||
keys.addAll(this.keys);
|
||||
|
||||
return keys;
|
||||
}//getKeys()//
|
||||
/**
|
||||
* Gets the collection of all keys in the map.
|
||||
* @param array An array where key values will be placed.
|
||||
* @return The count of keys placed in the array.
|
||||
*/
|
||||
public int getKeys(Object array) {
|
||||
return getKeys(array, 0);
|
||||
}//getKeys()//
|
||||
/**
|
||||
* Gets the collection of all keys in the map.
|
||||
* @param array An array where key values will be placed.
|
||||
* @param outputOffset The offset in the array where the first key value will be placed.
|
||||
* @return The count of keys placed in the array.
|
||||
*/
|
||||
public int getKeys(Object array, int outputOffset) {
|
||||
if(keys == null) {
|
||||
refreshKeys();
|
||||
}//if//
|
||||
|
||||
return keys.toArray(array, outputOffset);
|
||||
}//getKeys()//
|
||||
/**
|
||||
* Invalidates the collection of keys.
|
||||
* This should occur when a value is added/removed/changed in a way that invalidates the collection of keys.
|
||||
*/
|
||||
protected void invalidateKeys() {
|
||||
keys = null;
|
||||
}//invalidateKeys()//
|
||||
/**
|
||||
* Gets an iterator over the keys contained in this collection.
|
||||
* @return An iterator over the map keys.
|
||||
*/
|
||||
public IIterator keyIterator() {
|
||||
return new KeyIterator(this);
|
||||
}//keyIterator()//
|
||||
/**
|
||||
* Places a key/value pair in the map.
|
||||
* The value can be retrieved later with the given key.
|
||||
* @param key The key that will be used to map the value.
|
||||
* @param value The value stored in map. A <code>null</code> value will remove the key from the mapping.
|
||||
* @return The value previously associated with the key.
|
||||
*/
|
||||
public Object put(Object key, Object value) {
|
||||
Object result = null;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
if(value == null) {
|
||||
//Remove the key if it exists because you cannot associate a key with a null value.//
|
||||
result = remove(key);
|
||||
}//if//
|
||||
else {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry entry = null;
|
||||
|
||||
//Try to locate an existing value.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key, key)))) {
|
||||
if(maintainCount) {
|
||||
if(getValueComparator().compare(entry.value, value) == Comparator.EQUAL) {
|
||||
entry.count++;
|
||||
}//if//
|
||||
else {
|
||||
throw new RuntimeException("Cannot replace one value with another in a map when maintaining a count.");
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
Object oldValue = entry.value;
|
||||
|
||||
entry.value = value;
|
||||
|
||||
return oldValue;
|
||||
}//else//
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Determine if we need to re-hash.//
|
||||
if(resize(getSize() + 1)) {
|
||||
entries = getEntries();
|
||||
//Recalculate the insertion index if the map resized.//
|
||||
index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
}//if//
|
||||
|
||||
//Create and add the new entry.//
|
||||
entry = (Entry) createEntry();
|
||||
entry.hash = hash;
|
||||
entry.key = key;
|
||||
entry.value = value;
|
||||
addEntry(index, entry);
|
||||
|
||||
if(keys != null) {
|
||||
keys.add(key); //Just add the key instead of invalidating the keys collection.//
|
||||
}//if//
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//put()//
|
||||
/**
|
||||
* Recreates the collection of keys.
|
||||
*/
|
||||
protected void refreshKeys() {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int index;
|
||||
Entry entry;
|
||||
|
||||
keys = new LiteList(getSize(), 20);
|
||||
|
||||
for(index = 0; index < entries.length; index++) {
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
Object key = entry.key;
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == NULL_KEY) {
|
||||
key = null;
|
||||
}//if//
|
||||
|
||||
keys.add(key);
|
||||
}//for//
|
||||
}//for//
|
||||
}//refreshKeys()//
|
||||
/**
|
||||
* Optimizes the collection of Entry objects to improve access time.
|
||||
* @param arrayLength The new length of the entry array.
|
||||
*/
|
||||
protected void rehash(int arrayLength) {
|
||||
super.rehash(arrayLength);
|
||||
//Invalidate the list of keys.//
|
||||
invalidateKeys();
|
||||
}//rehash()//
|
||||
/**
|
||||
* Removes a key/value pair from the map.
|
||||
* @param key The key that should be removed (with its' value) from the map.
|
||||
* @return Will be the value removed from map. A <code>null</code> value is returned if the key was not found.
|
||||
*/
|
||||
public Object remove(Object key) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry previousEntry = null;
|
||||
Entry entry = null;
|
||||
Object result = null;
|
||||
|
||||
//Iterate through the entries stored at the key's hash location and remove the given key.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key, key)))) {
|
||||
//Save the removed value.//
|
||||
result = entry.value;
|
||||
|
||||
if(--entry.count == 0) {
|
||||
//Remove the entry from the map.//
|
||||
removeEntry(index, previousEntry);
|
||||
//Could find the key in the collection and remove it, but that may take to long.//
|
||||
invalidateKeys();
|
||||
}//if//
|
||||
|
||||
//Break from the loop so we can exit.//
|
||||
break;
|
||||
}//if//
|
||||
|
||||
previousEntry = entry;
|
||||
}//for//
|
||||
|
||||
return result;
|
||||
}//remove()//
|
||||
/**
|
||||
* Removes all key/value pairs from the map.
|
||||
*/
|
||||
public void removeAll() {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
invalidateKeys();
|
||||
removeAllEntries();
|
||||
}//removeAll()//
|
||||
/**
|
||||
* Gets the collection of all keys in the map.
|
||||
* @param keys An array of the necessary type to old the key values.
|
||||
* @return The collection with the keys in it. This will be the same collection as the one passed if it is non-null.
|
||||
*/
|
||||
public int toKeyArray(Object keyArray) {
|
||||
if(keys == null) {
|
||||
refreshKeys();
|
||||
}//if//
|
||||
|
||||
return keys.toArray(keyArray);
|
||||
}//toKeyArray()//
|
||||
/**
|
||||
* Gets an iterator over the values contained in this collection.
|
||||
* @return An iterator over the map values.
|
||||
*/
|
||||
public IIterator valueIterator() {
|
||||
return new ValueIterator(this);
|
||||
}//valueIterator()//
|
||||
}//HashMap//
|
||||
693
Common/src/com/common/util/LiteHashSet.java
Normal file
693
Common/src/com/common/util/LiteHashSet.java
Normal file
@@ -0,0 +1,693 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import com.common.debug.*;
|
||||
import com.common.exception.*;
|
||||
import com.common.comparison.*;
|
||||
|
||||
/**
|
||||
* <p>TODO: Make this class serializeable by implementing the read and writeExternal methods. Don't forget to convert NULL_VALUE references to null's and back when reading.</p>
|
||||
* An collection that stores values so that they can be easily found and the collection can be manipulated rapidly.
|
||||
* Collection modification is very fast, and determining whether a value is in the collection is very fast.
|
||||
* Collection iteration is a bit slower than in a standard list, and indexing is not available.
|
||||
*/
|
||||
public class LiteHashSet extends LiteSet implements IHashSet {
|
||||
public static final int DEFAULT_INITIAL_CAPACITY = 51;
|
||||
public static final float DEFAULT_LOAD_FACTOR = 0.75f;
|
||||
public static final IComparator DEFAULT_COMPARATOR = Comparator.getLogicalComparator();
|
||||
public static final LiteHashSet EMPTY_SET = new LiteHashSet(1);
|
||||
|
||||
/** The array of hash entries. */
|
||||
private HashSetEntry[] entries;
|
||||
/** The number of hash entries in the set. Note that this only counts duplicates if using STYLE_ADD_DUPLICATES. */
|
||||
private int size;
|
||||
/** ? */
|
||||
private int threshold;
|
||||
/** The ratio of size to the entries array size (size / entries.length). If this ratio is smaller than the actual ratio then the entries array will be resized. */
|
||||
private float loadFactor;
|
||||
private boolean reuseEntryObjects = false;
|
||||
private LiteList reusableEntries = null;
|
||||
private IComparator locateComparator = DEFAULT_COMPARATOR;
|
||||
/** Whether multiple references to the same object instance can be stored in this collection. This is normally set to reject duplicates. */
|
||||
private int style = DEFAULT_STYLE;
|
||||
|
||||
/**
|
||||
* The entry class used to store HashSet values.
|
||||
*/
|
||||
protected static class HashSetEntry {
|
||||
public int hash;
|
||||
public Object value;
|
||||
public HashSetEntry next;
|
||||
public int count;
|
||||
|
||||
protected HashSetEntry() {
|
||||
}//HashSetEntry()//
|
||||
}//HashSetEntry//
|
||||
|
||||
/**
|
||||
* An iterator that can be used to iterate over the HashSet values.
|
||||
* <p>WARNING: While this class can be serialized, it will reset its' position to the start of the HashSet.
|
||||
* Also, the HashSet will be serialized with the iterator.
|
||||
* <p>This class is NOT thread safe.
|
||||
*/
|
||||
public static class HashSetIterator implements IIterator {
|
||||
private LiteHashSet hashSet = null;
|
||||
protected int currentIndex = -1;
|
||||
protected HashSetEntry currentEntry = null;
|
||||
protected int nextIndex = -1;
|
||||
protected HashSetEntry nextEntry = null;
|
||||
protected boolean hasNextEntry = false;
|
||||
|
||||
protected HashSetIterator(LiteHashSet hashSet) {
|
||||
this.hashSet = hashSet;
|
||||
}//HashSetIterator()//
|
||||
public void resetToFront() {
|
||||
currentIndex = -1;
|
||||
currentEntry = null;
|
||||
nextIndex = -1;
|
||||
nextEntry = null;
|
||||
hasNextEntry = false;
|
||||
}//resetToFront()//
|
||||
public boolean remove() {
|
||||
boolean result = false;
|
||||
|
||||
if(currentEntry != null) {
|
||||
result = hashSet.remove(currentEntry.value);
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//remove()//
|
||||
public Object next() {
|
||||
loadNextEntry();
|
||||
currentEntry = nextEntry;
|
||||
currentIndex = nextIndex;
|
||||
hasNextEntry = false;
|
||||
nextEntry = null;
|
||||
|
||||
return currentEntry.value == NULL_VALUE ? null : currentEntry.value;
|
||||
}//next()//
|
||||
public boolean hasNext() {
|
||||
loadNextEntry();
|
||||
|
||||
return nextEntry != null;
|
||||
}//hasNext()//
|
||||
/**
|
||||
* Preloads the next entry. This makes querying to see if the next entry exists and then getting the next entry much easier.
|
||||
*/
|
||||
protected void loadNextEntry() {
|
||||
if(!hasNextEntry) {
|
||||
nextEntry = null;
|
||||
nextIndex = currentIndex;
|
||||
|
||||
if((currentEntry != null) && (currentEntry.next != null)) {
|
||||
nextEntry = currentEntry.next;
|
||||
}//if//
|
||||
else {
|
||||
HashSetEntry[] entries = hashSet.entries;
|
||||
|
||||
while((nextEntry == null) && (entries.length > ++nextIndex)) {
|
||||
if(entries[nextIndex] != null) {
|
||||
nextEntry = entries[nextIndex];
|
||||
}//if//
|
||||
}//while//
|
||||
}//else//
|
||||
|
||||
if(nextEntry != null) {
|
||||
hasNextEntry = true;
|
||||
}//if//
|
||||
}//if//
|
||||
}//loadNextEntry()//
|
||||
/**
|
||||
* Allows the iterator to peek at the next value after calling loadNextEntry.
|
||||
* <p>This is for use only by subclasses an is not intended for public consumption. The value is only valid after calling loadNextEntry().</p>
|
||||
* @return The value that will be returned by the next call to next().
|
||||
* @see #next()
|
||||
* @see #loadNextEntry()
|
||||
*/
|
||||
protected Object peekNext() {
|
||||
return nextEntry.value == NULL_VALUE ? null : nextEntry.value;
|
||||
}//peekNext()//
|
||||
/**
|
||||
* Allows the iterator to peek at whether there is a next value after calling loadNextEntry.
|
||||
* <p>This is for use only by subclasses an is not intended for public consumption. The value is only valid after calling loadNextEntry().</p>
|
||||
* @return Whether there is a next value, otherwise the iterator is finished.
|
||||
* @see #hasNext()
|
||||
* @see #loadNextEntry()
|
||||
*/
|
||||
protected boolean peekHasNext() {
|
||||
return nextEntry != null;
|
||||
}//peekHasNext()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
out.writeObject(hashSet);
|
||||
}//writeExternal()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
hashSet = (LiteHashSet) in.readObject();
|
||||
resetToFront();
|
||||
}//readExternal()//
|
||||
}//HashSetIterator//
|
||||
/**
|
||||
* LiteHashSet constructor.
|
||||
*/
|
||||
public LiteHashSet() {
|
||||
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_COMPARATOR, DEFAULT_STYLE);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* LiteHashSet copy constructor.
|
||||
* @param original The hash set to be copied.
|
||||
*/
|
||||
public LiteHashSet(LiteHashSet original) {
|
||||
this(original.getEntries().length, original.getLoadFactor(), original.getLocateComparator(), original.getStyle());
|
||||
HashSetEntry[] entries = original.getEntries();
|
||||
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
for(HashSetEntry entry = entries[index]; entry != null; entry = entry.next) {
|
||||
for(int count = 0; count < entry.count; count++) {
|
||||
add(entry.value);
|
||||
}//for//
|
||||
}//for//
|
||||
}//for//
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* LiteHashSet constructor.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
*/
|
||||
public LiteHashSet(int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_COMPARATOR, DEFAULT_STYLE);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* LiteHashSet constructor.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
* @throws IllegalArgumentException If the initial capacity or load factor are not within their valid ranges.
|
||||
*/
|
||||
public LiteHashSet(int initialCapacity, IComparator locateComparator, int style) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, locateComparator, style);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* LiteHashSet constructor.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
* @throws IllegalArgumentException If the initial capacity or load factor are not within their valid ranges.
|
||||
*/
|
||||
public LiteHashSet(int initialCapacity, float loadFactor, IComparator locateComparator, int style) {
|
||||
super();
|
||||
|
||||
initialize(initialCapacity, loadFactor, locateComparator, style);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* Initializes the hash set.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
protected void initialize(int initialCapacity, float loadFactor, IComparator locateComparator, int style) {
|
||||
this.style = style;
|
||||
|
||||
if(locateComparator == null) {
|
||||
locateComparator = DEFAULT_COMPARATOR;
|
||||
}//if//
|
||||
|
||||
if(loadFactor <= 0.0) {
|
||||
throw new IllegalArgumentException("Invalid load factor supplied to the HashSet.");
|
||||
}//if//
|
||||
|
||||
if(initialCapacity <= 0) {
|
||||
initialCapacity = 10;
|
||||
}//if//
|
||||
|
||||
this.locateComparator = locateComparator;
|
||||
this.loadFactor = loadFactor;
|
||||
this.entries = new HashSetEntry[initialCapacity];
|
||||
this.threshold = (int)(initialCapacity * loadFactor);
|
||||
}//initialize()//
|
||||
/**
|
||||
* LiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
*/
|
||||
public LiteHashSet(ICollection values) {
|
||||
this(values.getSize(), DEFAULT_LOAD_FACTOR, DEFAULT_COMPARATOR, DEFAULT_STYLE);
|
||||
addAll(values);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* LiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public LiteHashSet(ICollection values, int initialCapacity, float loadFactor, IComparator locateComparator, int style) {
|
||||
this(initialCapacity, loadFactor, locateComparator, style);
|
||||
addAll(values);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* LiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public LiteHashSet(ICollection values, IComparator locateComparator, int style) {
|
||||
this(values.getSize(), DEFAULT_LOAD_FACTOR, locateComparator, style);
|
||||
addAll(values);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* LiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @deprecated Shouldn't be called because the caller shouldn't be relying on defaults for comparison and style.
|
||||
*/
|
||||
public LiteHashSet(Object[] values) {
|
||||
this(values, 0, values.length, values.length, DEFAULT_LOAD_FACTOR, DEFAULT_COMPARATOR, DEFAULT_STYLE);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* LiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public LiteHashSet(Object[] values, IComparator locateComparator, int style) {
|
||||
this(values, 0, values.length, values.length, DEFAULT_LOAD_FACTOR, locateComparator, style);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* LiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public LiteHashSet(Object[] values, int initialCapacity, float loadFactor, IComparator locateComparator, int style) {
|
||||
this(values, 0, values.length, initialCapacity, loadFactor, locateComparator, style);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* LiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param offset The offset of the first value in the values array (this will not be checked for validity).
|
||||
* @param length The count of values in the values array (this will not be checked for validity).
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public LiteHashSet(Object[] values, int offset, int length, IComparator locateComparator, int style) {
|
||||
this(values, offset, length, values.length, DEFAULT_LOAD_FACTOR, locateComparator, style);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* LiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param offset The offset of the first value in the values array (this will not be checked for validity).
|
||||
* @param length The count of values in the values array (this will not be checked for validity).
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public LiteHashSet(Object[] values, int offset, int length, int initialCapacity, float loadFactor, IComparator locateComparator, int style) {
|
||||
this(initialCapacity, loadFactor, locateComparator, style);
|
||||
addAll(values, offset, length);
|
||||
}//LiteHashSet()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.LiteCollection#ensureCapacity(int)
|
||||
*/
|
||||
public void ensureCapacity(int minimumCapacity) {
|
||||
}//ensureCapacity()//
|
||||
/**
|
||||
* Tests to see if the specified value is contained in the collection.
|
||||
* @param value The value to test for.
|
||||
* @return Will be true if the value is contained in the collection.
|
||||
*/
|
||||
public boolean containsValue(Object value) {
|
||||
//Ensure that null values are valid.//
|
||||
if(value == null) {
|
||||
value = NULL_VALUE;
|
||||
}//if//
|
||||
|
||||
int hash = getLocateComparator().hash(value);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(HashSetEntry e = entries[index]; e != null; e = e.next) {
|
||||
if((e.hash == hash) && (Comparator.isEqual(getLocateComparator().compare(e.value, value)))) {
|
||||
return true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return false;
|
||||
}//containsValue()//
|
||||
/**
|
||||
* Gets the number of times the value has been added to the set.
|
||||
* @param value The value to look for.
|
||||
* @return The number of times the value exists in the set. Note that the comparator will be used to compare the value with other values and it determines which objects are considered equivalent.
|
||||
*/
|
||||
public int getCount(Object value) {
|
||||
//Ensure that null values are valid.//
|
||||
if(value == null) {
|
||||
value = NULL_VALUE;
|
||||
}//if//
|
||||
|
||||
int hash = getLocateComparator().hash(value);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(HashSetEntry e = entries[index]; e != null; e = e.next) {
|
||||
if((e.hash == hash) && (Comparator.isEqual(getLocateComparator().compare(e.value, value)))) {
|
||||
return e.count;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return 0;
|
||||
}//getCount()//
|
||||
/**
|
||||
* Creates or reuses an entry.
|
||||
*/
|
||||
protected HashSetEntry createEntry() {
|
||||
if(reuseEntryObjects) {
|
||||
int index = reusableEntries.getSize();
|
||||
|
||||
if(index > 0) {
|
||||
return (HashSetEntry) reusableEntries.remove(index - 1);
|
||||
}//if//
|
||||
else {
|
||||
return new HashSetEntry();
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
return new HashSetEntry();
|
||||
}//else//
|
||||
}//createEntry()//
|
||||
/**
|
||||
* Creates or reuses an entry.
|
||||
*/
|
||||
protected void destroyEntry(HashSetEntry entry) {
|
||||
entry.next = null;
|
||||
entry.value = null;
|
||||
|
||||
if(reuseEntryObjects) {
|
||||
reusableEntries.add(entry);
|
||||
}//if//
|
||||
}//destroyEntry()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#getFirst()
|
||||
*/
|
||||
public Object getFirst() {
|
||||
Object result = null;
|
||||
|
||||
if(getSize() > 0) {
|
||||
for(int index = 0; (index < entries.length) && (result == null); index++) {
|
||||
if(entries[index] != null) {
|
||||
result = entries[index].value;
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//getFirst()//
|
||||
/**
|
||||
* Gets the value in the hash set when given another logically equal value.
|
||||
* @param value The logically equivalent value.
|
||||
* @return The matching value in the collection, or <code>null</code> if none was found.
|
||||
*/
|
||||
public Object get(Object value) {
|
||||
//Ensure that null values are valid.//
|
||||
if(value == null) {
|
||||
value = NULL_VALUE;
|
||||
}//if//
|
||||
|
||||
int hash = getLocateComparator().hash(value);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(HashSetEntry e = entries[index]; e != null; e = e.next) {
|
||||
if((e.hash == hash) && (Comparator.isEqual(getLocateComparator().compare(e.value, value)))) {
|
||||
return e.value;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return null;
|
||||
}//get()//
|
||||
/**
|
||||
* Gets the hash set entries array.
|
||||
* @return The array referencing the indexed hash set entries.
|
||||
*/
|
||||
protected HashSetEntry[] getEntries() {
|
||||
return entries;
|
||||
}//getEntries()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.LiteCollection#getSize()
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}//getSize()//
|
||||
/**
|
||||
* Sets the number of values in the set.
|
||||
* @param size The set's size.
|
||||
*/
|
||||
protected void setSize(int size) {
|
||||
this.size = size;
|
||||
}//setSize()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IHashSet#getLocateComparator()
|
||||
*/
|
||||
public IComparator getLocateComparator() {
|
||||
return locateComparator;
|
||||
}//getLocateComparator()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IHashSet#getThreshold()
|
||||
*/
|
||||
public int getThreshold() {
|
||||
return threshold;
|
||||
}//getThreshold()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IHashSet#getLoadFactor()
|
||||
*/
|
||||
public float getLoadFactor() {
|
||||
return loadFactor;
|
||||
}//getLoadFactor()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IHashSet#getStyle()
|
||||
*/
|
||||
public int getStyle() {
|
||||
return style;
|
||||
}//getStyle()//
|
||||
/**
|
||||
* Performs an actual add of the value to the set.
|
||||
* @param value The value to be added to this set.
|
||||
* @return 0 if successful, or -1 if the operation failed.
|
||||
*/
|
||||
protected int internalAdd(Object value) {
|
||||
//Ensure that null values are valid.//
|
||||
if(value == null) {
|
||||
value = NULL_VALUE;
|
||||
}//if//
|
||||
|
||||
int hash = getLocateComparator().hash(value);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
HashSetEntry entry = null;
|
||||
|
||||
if(style != STYLE_ADD_DUPLICATES) {
|
||||
for(entry = entries[index]; entry != null; entry = entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getLocateComparator().compare(entry.value, value)))) {
|
||||
if(style == STYLE_NO_DUPLICATES) {
|
||||
return -1;
|
||||
}//if//
|
||||
else {
|
||||
entry.count++;
|
||||
return 0;
|
||||
}//else//
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
|
||||
if(size >= threshold) {
|
||||
rehash();
|
||||
|
||||
return internalAdd(value);
|
||||
}//if//
|
||||
|
||||
entry = createEntry();
|
||||
entry.hash = hash;
|
||||
entry.value = value;
|
||||
entry.next = entries[index];
|
||||
entry.count = 1;
|
||||
entries[index] = entry;
|
||||
size++;
|
||||
|
||||
return 0;
|
||||
}//internalAdd()//
|
||||
/**
|
||||
* Handles removing a value from the collection.
|
||||
* @param value The value to remove.
|
||||
* @return Will be <code>true</code> upon success.
|
||||
*/
|
||||
protected boolean internalRemove(Object value) {
|
||||
//Ensure that null values are valid.//
|
||||
if(value == null) {
|
||||
value = NULL_VALUE;
|
||||
}//if//
|
||||
|
||||
int hash = getLocateComparator().hash(value);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
HashSetEntry entry = null;
|
||||
HashSetEntry previous = null;
|
||||
|
||||
for(entry = entries[index], previous = null; entry != null; previous = entry, entry = entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getLocateComparator().compare(entry.value, value)))) {
|
||||
entry.count--;
|
||||
|
||||
if(entry.count == 0) {
|
||||
if(previous != null) {
|
||||
previous.next = entry.next;
|
||||
}//if//
|
||||
else {
|
||||
entries[index] = entry.next;
|
||||
}//else//
|
||||
|
||||
size--;
|
||||
destroyEntry(entry);
|
||||
}//if//
|
||||
|
||||
return true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return false;
|
||||
}//internalRemove()//
|
||||
/**
|
||||
* Handles removing all values from the collection.
|
||||
* @return Will be <code>true</code> upon success.
|
||||
*/
|
||||
protected void internalRemoveAll() {
|
||||
if(reuseEntryObjects) {
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
HashSetEntry entry = entries[index];
|
||||
|
||||
if(entry != null) {
|
||||
HashSetEntry next = null;
|
||||
|
||||
do {
|
||||
next = entry.next;
|
||||
destroyEntry(entry);
|
||||
entry = next;
|
||||
} while(next != null);
|
||||
}//if//
|
||||
|
||||
entries[index] = null;
|
||||
}//for//
|
||||
}//if//
|
||||
else {
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
entries[index] = null;
|
||||
}//for//
|
||||
}//else//
|
||||
|
||||
size = 0;
|
||||
}//internalRemoveAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.LiteCollection#internalReplace(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
protected boolean internalReplace(Object oldValue, Object newValue) {
|
||||
//Note: If this is ever supported, don't forget to replace null's with NULL_VALUE.//
|
||||
throw new MethodNotSupportedException();
|
||||
}//internalReplace()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.LiteCollection#internalReplaceAll(com.common.util.ICollection)
|
||||
*/
|
||||
protected boolean internalReplaceAll(ICollection values) {
|
||||
//Note: If this is ever supported, don't forget to replace null's with NULL_VALUE.//
|
||||
throw new MethodNotSupportedException();
|
||||
}//internalReplaceAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.LiteCollection#internalReplaceAll(com.common.util.ICollection, com.common.util.ICollection)
|
||||
*/
|
||||
protected boolean internalReplaceAll(ICollection removedValues, ICollection addedValues) {
|
||||
//Note: If this is ever supported, don't forget to replace null's with NULL_VALUE.//
|
||||
throw new MethodNotSupportedException();
|
||||
}//internalReplaceAll()//
|
||||
/**
|
||||
* Gets a new iterator over the values in this collection.
|
||||
* @return IIterator The iterator that may be used to iterate over the collection values.
|
||||
*/
|
||||
public IIterator iterator() {
|
||||
return new HashSetIterator(this);
|
||||
}//iterator()//
|
||||
/**
|
||||
* Will rehash the collection so that new items may be added without going over the recommended ratio of values to list entries.
|
||||
*/
|
||||
protected void rehash() {
|
||||
int oldCapacity = entries.length;
|
||||
HashSetEntry[] oldEntries = entries;
|
||||
int newCapacity = (oldCapacity << 1) + 1;
|
||||
HashSetEntry[] newEntries = new HashSetEntry[newCapacity];
|
||||
|
||||
threshold = (int)(newCapacity * loadFactor);
|
||||
entries = newEntries;
|
||||
|
||||
for(int oldIndex = oldCapacity; oldIndex-- > 0; ) {
|
||||
for(HashSetEntry oldEntry = oldEntries[oldIndex]; oldEntry != null; ) {
|
||||
HashSetEntry newEntry = oldEntry;
|
||||
int newIndex;
|
||||
|
||||
oldEntry = oldEntry.next;
|
||||
newIndex = (newEntry.hash & 0x7FFFFFFF) % newCapacity;
|
||||
newEntry.next = newEntries[newIndex];
|
||||
newEntries[newIndex] = newEntry;
|
||||
}//for//
|
||||
}//for//
|
||||
}//rehash()//
|
||||
/**
|
||||
* Fills an array with collection values.
|
||||
* @param array An array capable of containing collection values.
|
||||
* @return The number of values placed in the array.
|
||||
*/
|
||||
public int toArray(Object array) {
|
||||
HashSetEntry entry = null;
|
||||
int position = 0;
|
||||
HashSetEntry[] entries = this.entries;
|
||||
|
||||
//Iterate over the entry table.//
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
entry = entries[index];
|
||||
|
||||
//Iterate through the entries at this table position.//
|
||||
while(entry != null) {
|
||||
java.lang.reflect.Array.set(array, position, entry.value == NULL_VALUE ? null : entry.value);
|
||||
entry = entry.next;
|
||||
position++;
|
||||
}//while//
|
||||
}//for//
|
||||
|
||||
return position;
|
||||
}//toArray()//
|
||||
/**
|
||||
* Generates a string representing the hashset.
|
||||
* @return A debug string that represents this object.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer(100);
|
||||
|
||||
buffer.append("LiteHashSet {\r\n");
|
||||
|
||||
try {
|
||||
IIterator iterator = iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
Object next = iterator.next();
|
||||
|
||||
buffer.append("\t");
|
||||
buffer.append(next == NULL_VALUE ? null : next);
|
||||
buffer.append("\r\n");
|
||||
}//while//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
|
||||
buffer.append("}");
|
||||
|
||||
return buffer.toString();
|
||||
}//toArray()//
|
||||
}//HashSet//
|
||||
257
Common/src/com/common/util/LiteIndexedCollection.java
Normal file
257
Common/src/com/common/util/LiteIndexedCollection.java
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2007 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
public abstract class LiteIndexedCollection extends LiteCollection implements IIndexedCollection {
|
||||
public static final EmptyIterator EMPTY_ITERATOR = new EmptyIterator();
|
||||
|
||||
private static class EmptyIterator implements IReversableIterator {
|
||||
private EmptyIterator() {
|
||||
}//EmptyIterator()//
|
||||
public boolean hasPrevious() {
|
||||
return false;
|
||||
}//hasPrevious()//
|
||||
public Object previous() {
|
||||
return null;
|
||||
}//previous()//
|
||||
public void resetToBack() {
|
||||
}//resetToBack()//
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}//hasNext()//
|
||||
public Object next() {
|
||||
return null;
|
||||
}//next()//
|
||||
public boolean remove() {
|
||||
return false;
|
||||
}//remove()//
|
||||
public void resetToFront() {
|
||||
}//resetToFront()//
|
||||
}//EmptyIterator//
|
||||
/**
|
||||
* LiteIndexedCollection constructor.
|
||||
*/
|
||||
protected LiteIndexedCollection() {
|
||||
super();
|
||||
}//LiteIndexedCollection()//
|
||||
/**
|
||||
* LiteIndexedCollection constructor.
|
||||
* @param isImmutable boolean Will set whether the collection may be changed. This should be true if the collection may no longer be modified.
|
||||
*/
|
||||
protected LiteIndexedCollection(boolean isImmutable) {
|
||||
super(isImmutable);
|
||||
}//LiteIndexedCollection()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIndexedCollection#add(int, java.lang.Object)
|
||||
*/
|
||||
public int add(int index, Object value) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
return internalAdd(index, value);
|
||||
}//add()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIndexedCollection#addAll(int, java.lang.Object[])
|
||||
*/
|
||||
public boolean addAll(int index, Object[] values) {
|
||||
return addAll(index, values, 0, values.length);
|
||||
}//addAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIndexedCollection#addAll(int, java.lang.Object[], int, int)
|
||||
*/
|
||||
public boolean addAll(int index, Object[] values, int offset, int length) {
|
||||
boolean result = true;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
//Resize the collection only once if it requires it at all.//
|
||||
ensureCapacity(values.length);
|
||||
|
||||
//Make sure that the collection has values.//
|
||||
if((values != null) && (values.length > 0)) {
|
||||
Object next = null;
|
||||
|
||||
//Iterate over the items to be added and add them one at a time.//
|
||||
for(int i = offset, count = offset + length; i < count; i++) {
|
||||
next = values[i];
|
||||
|
||||
if(internalAdd(index++, next) == -1) {
|
||||
result = false;
|
||||
index--;
|
||||
}//if//
|
||||
}//while//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//addAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIndexedCollection#addAll(int, com.common.util.ICollection)
|
||||
*/
|
||||
public boolean addAll(int index, ICollection values) {
|
||||
boolean result = true;
|
||||
|
||||
if(values instanceof IIndexedCollection) {
|
||||
result = addAll(index, (IIndexedCollection) values, 0, values.getSize());
|
||||
}//if//
|
||||
else {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
//Resize the collection only once if it requires it at all.//
|
||||
ensureCapacity(values.getSize());
|
||||
|
||||
//Make sure that the collection has values.//
|
||||
if((values != null) && (values.getSize() > 0)) {
|
||||
Object next = null;
|
||||
|
||||
//Iterate over the items to be added and add them one at a time.//
|
||||
for(IIterator iterator = values.iterator(); iterator.hasNext(); ) {
|
||||
next = iterator.next();
|
||||
|
||||
if(internalAdd(index++, next) == -1) {
|
||||
result = false;
|
||||
index--;
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//addAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIndexedCollection#addAll(int, com.common.util.IIndexedCollection, int, int)
|
||||
*/
|
||||
public boolean addAll(int index, IIndexedCollection values, int offset, int length) {
|
||||
boolean result = true;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
//Resize the collection only once if it requires it at all.//
|
||||
ensureCapacity(values.getSize());
|
||||
|
||||
//Make sure that the collection has values.//
|
||||
if((values != null) && (values.getSize() > 0)) {
|
||||
Object next = null;
|
||||
|
||||
//Iterate over the items to be added and add them one at a time.//
|
||||
for(int valuesIndex = offset, count = offset + length; valuesIndex < count; valuesIndex++) {
|
||||
next = values.get(valuesIndex);
|
||||
|
||||
if(internalAdd(index++, next) == -1) {
|
||||
result = false;
|
||||
index--;
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//addAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#containsValue(java.lang.Object)
|
||||
*/
|
||||
public boolean containsValue(Object value) {
|
||||
return getIndexOf(value) != VALUE_NOT_FOUND;
|
||||
}//containsValue()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIndexedCollection#get(int)
|
||||
*/
|
||||
public abstract Object get(int index);
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#getFirst()
|
||||
*/
|
||||
public Object getFirst() {
|
||||
return get(0);
|
||||
}//getFirst()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIndexedCollection#getIndexOf(java.lang.Object)
|
||||
*/
|
||||
public abstract int getIndexOf(Object value);
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIndexedCollection#getLast()
|
||||
*/
|
||||
public Object getLast() {
|
||||
return get(getSize() - 1);
|
||||
}//getLast()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#getSize()
|
||||
*/
|
||||
public abstract int getSize();
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIndexedCollection#indexedIterator()
|
||||
*/
|
||||
public IReversableIterator indexedIterator() {
|
||||
return getSize() == 0 && !isChangeable() ? (IReversableIterator) EMPTY_ITERATOR : new IndexedIterator(this);
|
||||
}//indexedIterator()//
|
||||
/**
|
||||
* Adds a value at a given index.
|
||||
* @param index Where to add the new value.
|
||||
* @param value The value to add to the collection.
|
||||
* @return The index of the addition, or -1 if the operation failed.
|
||||
*/
|
||||
protected abstract int internalAdd(int index, Object object);
|
||||
/**
|
||||
* Removes a value specified by the given index.
|
||||
* @param index Which value to remove.
|
||||
* @return The value removed from the collection.
|
||||
*/
|
||||
protected abstract Object internalRemove(int index);
|
||||
/**
|
||||
* Replaces the value at the given index with the supplied new value.
|
||||
* @param index The index of the value being replaced.
|
||||
* @param newValue The new value to replace the old value with.
|
||||
* @return The value that was replaced.
|
||||
*/
|
||||
protected abstract Object internalReplace(int index, Object newValue);
|
||||
/**
|
||||
* Sets a given value at a given index, replacing what was previously at that index, or expanding the list if necessary.
|
||||
* @param index The index where the value will be stored.
|
||||
* @param value The value to place in the collection.
|
||||
* @return The value that was replaced, or null if no value was replaced.
|
||||
*/
|
||||
protected abstract Object internalSet(int index, Object value);
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#iterator()
|
||||
*/
|
||||
public abstract IIterator iterator();
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIndexedCollection#remove(int)
|
||||
*/
|
||||
public Object remove(int index) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
return internalRemove(index);
|
||||
}//remove()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIndexedCollection#replace(int, java.lang.Object)
|
||||
*/
|
||||
public Object replace(int index, Object value) {
|
||||
//Verify that the collection can be changed.//
|
||||
verifyIsChangeable();
|
||||
|
||||
return internalReplace(index, value);
|
||||
}//replace()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IIndexedCollection#set(int, java.lang.Object)
|
||||
*/
|
||||
public Object set(int index, Object value) {
|
||||
//Verify that the collection can be changed.//
|
||||
verifyIsChangeable();
|
||||
|
||||
return internalSet(index, value);
|
||||
}//set()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
|
||||
*/
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
}//readExternal()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
|
||||
*/
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
}//writeExternal()//
|
||||
}//LiteIndexedCollection//
|
||||
1074
Common/src/com/common/util/LiteList.java
Normal file
1074
Common/src/com/common/util/LiteList.java
Normal file
File diff suppressed because it is too large
Load Diff
26
Common/src/com/common/util/LiteSet.java
Normal file
26
Common/src/com/common/util/LiteSet.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2003,2007 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
public abstract class LiteSet extends LiteCollection {
|
||||
/** A null value marker used to mark a null value in the collection's related added and removed sets. */
|
||||
public static final Object NULL_VALUE = new Object();
|
||||
/**
|
||||
* LiteSet constructor.
|
||||
*/
|
||||
protected LiteSet() {
|
||||
super();
|
||||
}//LiteSet()//
|
||||
/**
|
||||
* LiteSet constructor.
|
||||
* @param isChangeable Whether the collection can be modified. Once set to false it cannot be changed.
|
||||
*/
|
||||
protected LiteSet(boolean isChangeable) {
|
||||
super(isChangeable);
|
||||
}//LiteSet()//
|
||||
}//LiteSet//
|
||||
622
Common/src/com/common/util/Map.java
Normal file
622
Common/src/com/common/util/Map.java
Normal file
@@ -0,0 +1,622 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import com.common.comparison.*;
|
||||
import com.common.exception.IllegalOperationException;
|
||||
import com.common.io.IObjectInputStream;
|
||||
import com.common.io.IObjectOutputStream;
|
||||
|
||||
/**
|
||||
* <p>TODO: Simplify and extensivly test the iterator.</p>
|
||||
* <p>WARNING: This class (and any subclasses) is not thread safe!</p>
|
||||
*/
|
||||
public abstract class Map implements IMap {
|
||||
/** A null key marker used to mark a null key in the collection's related added and removed sets. */
|
||||
public static final Object NULL_KEY = new Object();
|
||||
/** The default initial size of the map if the user does not specify a size. */
|
||||
public static final int DEFAULT_INITIAL_SIZE = 100;
|
||||
/** The default load factor of the map if the user does not specify a load factor. */
|
||||
public static final float DEFAULT_LOAD_FACTOR = 0.75f;
|
||||
/** The default comparator used to compare map keys if the user does not specify a comparator for keys. */
|
||||
public static final IComparator DEFAULT_KEY_COMPARATOR = Comparator.getLogicalComparator();
|
||||
/** The default comparator used to compare map values if the user does not specify a comparator for values. */
|
||||
public static final IComparator DEFAULT_VALUE_COMPARATOR = Comparator.getLogicalComparator();
|
||||
|
||||
private IBasicEntry[] entries = null;
|
||||
private int size = 0;
|
||||
private int threshold = 10;
|
||||
private float loadFactor;
|
||||
//private LiteList reusedEntries = null; //WARNING: Reusing entries can cause problems with iteration over a map since an iterator may reference the to be reused entry and may need that next reference.//
|
||||
private IComparator keyComparator = null;
|
||||
private IComparator valueComparator = null;
|
||||
/** Whether the map can be modified. Once set to false this flag cannot be reset to true. */
|
||||
private boolean isChangeable = true;
|
||||
|
||||
public interface IBasicEntry extends java.io.Externalizable {
|
||||
public int getHash();
|
||||
public void setHash(int hash);
|
||||
public IBasicEntry getNext();
|
||||
public void setNext(IBasicEntry next);
|
||||
public void rehash();
|
||||
public int createKeyHash();
|
||||
}//IBasicEntry//
|
||||
|
||||
/**
|
||||
* The Entry wrappers the key/value pair.
|
||||
*/
|
||||
public static abstract class BasicEntry implements IBasicEntry {
|
||||
public int hash = 0;
|
||||
public BasicEntry next = null;
|
||||
|
||||
public BasicEntry() {
|
||||
super();
|
||||
}//BasicEntry()//
|
||||
public int getHash() {
|
||||
return hash;
|
||||
}//getHash()//
|
||||
public void setHash(int hash) {
|
||||
this.hash = hash;
|
||||
}//setHash()//
|
||||
public IBasicEntry getNext() {
|
||||
return next;
|
||||
}//getNext()//
|
||||
public void setNext(IBasicEntry next) {
|
||||
this.next = (BasicEntry) next;
|
||||
}//setNext()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
hash = in.readInt();
|
||||
next = (BasicEntry) in.readObject();
|
||||
}//readExternal()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
out.writeInt(hash);
|
||||
out.writeObject(next);
|
||||
}//writeExternal()//
|
||||
public void rehash() {
|
||||
hash = createKeyHash();
|
||||
}//rehash()//
|
||||
}//BasicEntry//
|
||||
|
||||
public static abstract class Iterator implements java.io.Externalizable {
|
||||
private Map map = null;
|
||||
private int lastIndex = -1; //The index of the last entry.//
|
||||
private int previousIndex = -1; //The index of the previous entry.//
|
||||
private int currentIndex = -1; //The index of the current entry.//
|
||||
private int nextIndex = -1; //The index of the next entry.//
|
||||
private boolean hasRemoved = false; //Whether the current entry has been removed already.//
|
||||
private IBasicEntry lastEntry = null; //The entry returned prior to the current entry.//
|
||||
private IBasicEntry previousEntry = null; //The entry prior to the current entry. This is only set if hasPrevious is called.//
|
||||
private IBasicEntry currentEntry = null; //The last entry returned to the user through the next or previous methods.//
|
||||
private IBasicEntry nextEntry = null; //The entry after the current entry. This is only set if hasNext is called.//
|
||||
|
||||
protected Iterator() {
|
||||
}//Iterator()//
|
||||
public Iterator(Map map) {
|
||||
this.map = map;
|
||||
}//Iterator()//
|
||||
public void resetToBack() {
|
||||
resetToFront();
|
||||
}//resetToBack()//
|
||||
public void resetToFront() {
|
||||
lastIndex = -1;
|
||||
previousIndex = -1;
|
||||
currentIndex = -1;
|
||||
nextIndex = -1;
|
||||
lastEntry = null;
|
||||
previousEntry = null;
|
||||
currentEntry = null;
|
||||
nextEntry = null;
|
||||
hasRemoved = false;
|
||||
}//resetToFront()//
|
||||
/**
|
||||
* Removes the current entry from the map and moves the iterator back to the last current entry.
|
||||
* @return Whether the removal was successful.
|
||||
*/
|
||||
public boolean remove() {
|
||||
boolean retVal = false;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
map.verifyIsChangeable();
|
||||
|
||||
//Note: Non-synchronous access to this collection while running this method could cause null pointer exceptions.//
|
||||
if((currentEntry != null) && (!hasRemoved)) {
|
||||
IBasicEntry[] entries = map.getEntries();
|
||||
|
||||
if(entries[currentIndex] == currentEntry) {
|
||||
map.removeEntry(currentIndex, null);
|
||||
}//if//
|
||||
else {
|
||||
loadPreviousEntry();
|
||||
map.removeEntry(currentIndex, previousEntry);
|
||||
}//else//
|
||||
|
||||
currentEntry = lastEntry;
|
||||
currentIndex = lastIndex;
|
||||
previousEntry = null;
|
||||
previousIndex = -1;
|
||||
nextEntry = null;
|
||||
nextIndex = -1;
|
||||
lastEntry = null;
|
||||
lastIndex = -1;
|
||||
retVal = true;
|
||||
hasRemoved = true;
|
||||
}//if//
|
||||
|
||||
return retVal;
|
||||
}//remove()//
|
||||
/**
|
||||
* Gets the next entry in the map, making it the current entry.
|
||||
* @return The current entry which occured after the last current entry.
|
||||
*/
|
||||
protected IBasicEntry nextEntry() {
|
||||
loadNextEntry();
|
||||
|
||||
if(nextEntry != null) {
|
||||
lastEntry = currentEntry;
|
||||
lastIndex = currentIndex;
|
||||
currentEntry = nextEntry;
|
||||
currentIndex = nextIndex;
|
||||
nextEntry = null;
|
||||
nextIndex = -1;
|
||||
previousEntry = null;
|
||||
previousIndex = -1;
|
||||
hasRemoved = false;
|
||||
}//if//
|
||||
else {
|
||||
throw new RuntimeException("Error: Cannot get the next map element when there is not a next. Call hasNext to avoid this exception.");
|
||||
}//else//
|
||||
|
||||
return currentEntry;
|
||||
}//nextEntry()//
|
||||
/**
|
||||
* Gets the next entry in the map, making it the current entry.
|
||||
* @return The current entry which occured after the last current entry.
|
||||
*/
|
||||
protected IBasicEntry previousEntry() {
|
||||
loadPreviousEntry();
|
||||
|
||||
if(previousEntry != null) {
|
||||
lastEntry = currentEntry;
|
||||
lastIndex = currentIndex;
|
||||
currentEntry = previousEntry;
|
||||
currentIndex = previousIndex;
|
||||
nextEntry = null;
|
||||
nextIndex = -1;
|
||||
previousEntry = null;
|
||||
previousIndex = -1;
|
||||
hasRemoved = false;
|
||||
}//if//
|
||||
else {
|
||||
throw new RuntimeException("Error: Cannot get the previous map element when there is not a previous. Call hasPrevious to avoid this exception.");
|
||||
}//else//
|
||||
|
||||
return currentEntry;
|
||||
}//previousEntry()//
|
||||
protected IBasicEntry loadNextEntry() {
|
||||
if(nextEntry == null) {
|
||||
if((currentEntry != null) && (currentEntry.getNext() != null)) {
|
||||
nextEntry = currentEntry.getNext();
|
||||
nextIndex = currentIndex;
|
||||
}//if//
|
||||
else {
|
||||
IBasicEntry[] entries = map.getEntries();
|
||||
|
||||
nextIndex = currentIndex + 1;
|
||||
|
||||
while((nextIndex < entries.length) && ((nextEntry = (IBasicEntry) entries[nextIndex]) == null)) {
|
||||
nextIndex++;
|
||||
}//while//
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
return nextEntry;
|
||||
}//loadNextEntry//
|
||||
protected IBasicEntry loadPreviousEntry() {
|
||||
IBasicEntry[] entries = map.getEntries();
|
||||
|
||||
if(previousEntry == null) {
|
||||
if((currentEntry != null) && (entries[currentIndex] != currentEntry)) {
|
||||
previousEntry = entries[currentIndex];
|
||||
|
||||
while(previousEntry.getNext() != currentEntry) {
|
||||
previousEntry = previousEntry.getNext();
|
||||
}//while//
|
||||
|
||||
previousIndex = currentIndex;
|
||||
}//if//
|
||||
else {
|
||||
//If we have reset the map or the iterator has not yet been used, then we should search from the end.//
|
||||
previousIndex = (currentEntry == null) ? entries.length : currentIndex;
|
||||
|
||||
while((--previousIndex >= 0) && (entries[previousIndex] == null)) {
|
||||
//Do nothing.//
|
||||
}//while//
|
||||
|
||||
if(previousIndex != -1) {
|
||||
previousEntry = entries[previousIndex];
|
||||
|
||||
while(previousEntry.getNext() != null) {
|
||||
previousEntry = previousEntry.getNext();
|
||||
}//while//
|
||||
}//if//
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
return nextEntry;
|
||||
}//loadPreviousEntry//
|
||||
public boolean hasNext() {
|
||||
return nextEntry == null ? loadNextEntry() != null : true;
|
||||
}//hasNext()//
|
||||
public boolean hasPrevious() {
|
||||
return previousEntry == null ? loadPreviousEntry() != null : true;
|
||||
}//hasNext()//
|
||||
/**
|
||||
* Reads the object from the input stream.
|
||||
* @param in The input stream.
|
||||
*/
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
/*byte version = */in.readByte();
|
||||
|
||||
map = (Map) in.readObject();
|
||||
resetToFront();
|
||||
}//readExternal()//
|
||||
/**
|
||||
* Writes the object to the output stream.
|
||||
* @param out The output stream.
|
||||
*/
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
out.writeByte(0);
|
||||
|
||||
out.writeObject(map);
|
||||
}//writeExternal()//
|
||||
}//Iterator//
|
||||
/**
|
||||
* Map constructor.
|
||||
*/
|
||||
public Map() {
|
||||
this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, DEFAULT_KEY_COMPARATOR, DEFAULT_VALUE_COMPARATOR);
|
||||
}//HashMap()//
|
||||
/**
|
||||
* Map constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public Map(int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_KEY_COMPARATOR, DEFAULT_VALUE_COMPARATOR);
|
||||
}//HashMap()//
|
||||
/**
|
||||
* Map constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public Map(int initialCapacity, float loadFactor) {
|
||||
this(initialCapacity, loadFactor, DEFAULT_KEY_COMPARATOR, DEFAULT_VALUE_COMPARATOR);
|
||||
}//HashMap()//
|
||||
/**
|
||||
* Map constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public Map(int initialCapacity, float loadFactor, IComparator keyComparator, IComparator valueComparator) {
|
||||
super();
|
||||
|
||||
if((initialCapacity < 0) || (loadFactor <= 0.0)) {
|
||||
throw new IllegalArgumentException("The initial capacity must be greater than or equal to zero and the load factor must be between 0.0 and 1.0.");
|
||||
}//if//
|
||||
|
||||
if(initialCapacity == 0) {
|
||||
initialCapacity = 1;
|
||||
}//if//
|
||||
|
||||
if(keyComparator == null) {
|
||||
keyComparator = DEFAULT_KEY_COMPARATOR;
|
||||
}//if//
|
||||
|
||||
if(valueComparator == null) {
|
||||
valueComparator = DEFAULT_VALUE_COMPARATOR;
|
||||
}//if//
|
||||
|
||||
this.loadFactor = loadFactor;
|
||||
this.entries = new IBasicEntry[initialCapacity];
|
||||
this.threshold = (int)(initialCapacity * loadFactor);
|
||||
this.keyComparator = keyComparator;
|
||||
this.valueComparator = valueComparator;
|
||||
}//HashMap()//
|
||||
/**
|
||||
* Map constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public Map(int initialCapacity, IComparator keyComparator, IComparator valueComparator) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, keyComparator, valueComparator);
|
||||
}//HashMap()//
|
||||
/**
|
||||
* Map constructor.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public Map(IComparator keyComparator, IComparator valueComparator) {
|
||||
this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, keyComparator, valueComparator);
|
||||
}//HashMap()//
|
||||
/**
|
||||
* Determines whether the collection may be changed or not.
|
||||
* <p>NOTE: Something that is immutable is never changing.
|
||||
* @return Whether the collection may be changed. This is false if the collection may no longer be modified.
|
||||
*/
|
||||
public boolean isChangeable() {
|
||||
return isChangeable;
|
||||
}//isChangeable()//
|
||||
/**
|
||||
* Determines whether the collection may be changed or not.
|
||||
* @param isChangeable Whether the collection may be changed. This is false if the collection may no longer be modified.
|
||||
*/
|
||||
public void isChangeable(boolean isChangeable) {
|
||||
if(!isChangeable) {
|
||||
this.isChangeable = isChangeable;
|
||||
}//if//
|
||||
else if(this.isChangeable == isChangeable) {
|
||||
//Do nothing as nothing has changed.//
|
||||
}//else if//
|
||||
else {
|
||||
throw new RuntimeException("You may not change the collection to be changeable after it has been locked.");
|
||||
}//else//
|
||||
}//isChangeable()//
|
||||
/**
|
||||
* Verifies that the collection may be modified.
|
||||
* @throws IllegalOperationException If the isImmutable flag is set.
|
||||
*/
|
||||
protected void verifyIsChangeable() {
|
||||
if(!isChangeable) {
|
||||
throw new IllegalOperationException("The collection is immutable which prevents the collection from being modified.");
|
||||
}//if//
|
||||
}//verifyIsChangeable()//
|
||||
/**
|
||||
* Adds an entry to the map.
|
||||
* @param entry The entry to add to the map.
|
||||
*/
|
||||
protected void addEntry(int index, IBasicEntry entry) {
|
||||
entry.setNext(entries[index]);
|
||||
entries[index] = entry;
|
||||
size++;
|
||||
}//addEntry()//
|
||||
/**
|
||||
* Gets the entry array for this map.
|
||||
* @return An array of entries indexed by the entry's hash value.
|
||||
*/
|
||||
protected IBasicEntry[] getEntries() {
|
||||
return entries;
|
||||
}//getEntries()//
|
||||
/**
|
||||
* Gets the comparator used to compare key values.
|
||||
* @return The comparator used to compare keys.
|
||||
*/
|
||||
public IComparator getKeyComparator() {
|
||||
return keyComparator;
|
||||
}//getKeyComparator()//
|
||||
/**
|
||||
* Gets the map's load factor.
|
||||
* @return The load factor for this map.
|
||||
*/
|
||||
public float getLoadFactor() {
|
||||
return loadFactor;
|
||||
}//getLoadFactor()//
|
||||
/**
|
||||
* @link IMap.getSize()
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}//getSize()//
|
||||
/**
|
||||
* Gets the threshold used to determine when to resize the entry array.
|
||||
* @return The map's threshold.
|
||||
*/
|
||||
protected int getThreshold() {
|
||||
return threshold;
|
||||
}//getThreshold()//
|
||||
/**
|
||||
* Gets the comparator used to compare values.
|
||||
* @return The comparator used to compare values.
|
||||
*/
|
||||
public IComparator getValueComparator() {
|
||||
return valueComparator;
|
||||
}//getValueComparator()//
|
||||
/**
|
||||
* Reads the array of entries from the stream.
|
||||
* @param in The input stream to read from.
|
||||
* @return The array of entries read from the stream.
|
||||
*/
|
||||
protected IBasicEntry[] readEntries(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
return (IBasicEntry[]) in.readObject();
|
||||
}//readEntries()//
|
||||
/**
|
||||
* Allows the serialization of this type.
|
||||
* @param in The input stream to serialize to.
|
||||
*/
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
/*byte version = */in.readByte();
|
||||
|
||||
size = in.readInt();
|
||||
threshold = in.readInt();
|
||||
loadFactor = in.readFloat();
|
||||
keyComparator = (IComparator) in.readObject();
|
||||
valueComparator = (IComparator) in.readObject();
|
||||
entries = readEntries(in);
|
||||
|
||||
rehash(entries.length);
|
||||
}//readExternal()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IExternalizable#readExternal(com.common.io.IObjectInputStream)
|
||||
*/
|
||||
public Object readExternal(IObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
|
||||
/*byte version = */in.readByte();
|
||||
|
||||
size = in.readInt();
|
||||
threshold = in.readInt();
|
||||
loadFactor = in.readFloat();
|
||||
keyComparator = (IComparator) in.readObject();
|
||||
valueComparator = (IComparator) in.readObject();
|
||||
entries = readEntries(in);
|
||||
|
||||
rehash(entries.length);
|
||||
|
||||
return null;
|
||||
}//readExternal()//
|
||||
/**
|
||||
* Optimizes the collection of Entry objects to improve access time.
|
||||
* @param arrayLength The new length of the entry array.
|
||||
*/
|
||||
protected void rehash(int arrayLength) {
|
||||
IBasicEntry[] temp = entries;
|
||||
int index;
|
||||
|
||||
entries = new IBasicEntry[arrayLength];
|
||||
threshold = (int) (entries.length * loadFactor);
|
||||
|
||||
for(int tempIndex = temp.length; tempIndex-- > 0;) {
|
||||
for(IBasicEntry nextEntry = temp[tempIndex]; nextEntry != null;) {
|
||||
IBasicEntry entry = nextEntry;
|
||||
|
||||
nextEntry = nextEntry.getNext();
|
||||
index = (entry.getHash() & 0x7FFFFFFF) % entries.length;
|
||||
entry.setNext(entries[index]);
|
||||
entries[index] = entry;
|
||||
}//for//
|
||||
}//for//
|
||||
}//rehash()//
|
||||
/**
|
||||
* Removes all entries from the map.
|
||||
*/
|
||||
protected void removeAllEntries() {
|
||||
//if(reusedEntries == null) {
|
||||
//Don't reuse the entries.//
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
entries[index] = null;
|
||||
}//for//
|
||||
/*}//if//
|
||||
else {
|
||||
//Reuse the entries.//
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
IBasicEntry entry = entries[index];
|
||||
|
||||
entries[index] = null;
|
||||
|
||||
if(entry != null) {
|
||||
for(IBasicEntry next = entry.getNext(); entry != null; entry = next, next = next.getNext()) {
|
||||
reuseEntry(entry);
|
||||
}//for//
|
||||
}//if//
|
||||
}//for//
|
||||
}//else//
|
||||
*/
|
||||
|
||||
size = 0;
|
||||
}//removeAllEntries()//
|
||||
/**
|
||||
* Removes an entry from the map.
|
||||
* @param entry The entry to remove from the map.
|
||||
*/
|
||||
protected void removeEntry(int index, IBasicEntry previousEntry) {
|
||||
IBasicEntry entry = null;
|
||||
|
||||
//Remove the entry from the map.//
|
||||
if(previousEntry == null) {
|
||||
entry = entries[index];
|
||||
entries[index] = entry.getNext();
|
||||
}//if//
|
||||
else {
|
||||
entry = previousEntry.getNext();
|
||||
previousEntry.setNext(entry.getNext());
|
||||
}//else//
|
||||
|
||||
//Decrement the entry count.//
|
||||
size--;
|
||||
//Try to reuse the entry.//
|
||||
//reuseEntry(entry);
|
||||
}//removeEntry()//
|
||||
/**
|
||||
* Adds an entry to the map.
|
||||
* @param entry The entry to add to the map.
|
||||
*/
|
||||
protected void replaceEntry(int index, IBasicEntry previousEntry, IBasicEntry newEntry) {
|
||||
if(previousEntry == null) {
|
||||
if(entries[index] != null) {
|
||||
newEntry.setNext(entries[index].getNext());
|
||||
entries[index].setNext(null);
|
||||
}//if//
|
||||
|
||||
entries[index] = newEntry;
|
||||
}//if//
|
||||
else {
|
||||
if(previousEntry.getNext() != null) {
|
||||
newEntry.setNext(previousEntry.getNext().getNext());
|
||||
previousEntry.getNext().setNext(null);
|
||||
}//if//
|
||||
|
||||
previousEntry.setNext(newEntry);
|
||||
}//else//
|
||||
}//replaceEntry()//
|
||||
/**
|
||||
* Makes sure that the map can handle the expected number of entries.
|
||||
* @param expectedSize The size of the map after the entries have been added or removed.
|
||||
* @return Will return true if the mapping has been resized.
|
||||
*/
|
||||
protected boolean resize(int expectedSize) {
|
||||
boolean retVal = false;
|
||||
|
||||
if(expectedSize > threshold) {
|
||||
int newSize = entries.length + (entries.length >> 1) + 1;
|
||||
|
||||
//Make sure it doesn't grow exponentially for ever.//
|
||||
if(newSize > 500) {
|
||||
newSize = entries.length + 500;
|
||||
}//if//
|
||||
|
||||
//Rehash the map if the threshold is going to be exceeded//
|
||||
rehash(newSize);
|
||||
//Set the return value.//
|
||||
retVal = true;
|
||||
}//if//
|
||||
|
||||
return retVal;
|
||||
}//resize()//
|
||||
/**
|
||||
* Writes the array of entries to the stream.
|
||||
* @param out The output stream to write to.
|
||||
* @param entries The array of entries to be written to the stream.
|
||||
*/
|
||||
protected void writeEntries(java.io.ObjectOutput out, IBasicEntry[] entries) throws java.io.IOException {
|
||||
out.writeObject(entries);
|
||||
}//writeEntries()//
|
||||
/**
|
||||
* Allows the serialization of this type.
|
||||
* @param out The output stream to write to.
|
||||
*/
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
out.writeByte(0);
|
||||
out.writeInt(size);
|
||||
out.writeInt(threshold);
|
||||
out.writeFloat(loadFactor);
|
||||
out.writeObject(keyComparator);
|
||||
out.writeObject(valueComparator);
|
||||
writeEntries(out, entries);
|
||||
}//writeExternal()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IExternalizable#writeExternal(com.common.io.IObjectOutputStream)
|
||||
*/
|
||||
public void writeExternal(IObjectOutputStream out) throws java.io.IOException {
|
||||
out.writeByte(0);
|
||||
out.writeInt(size);
|
||||
out.writeInt(threshold);
|
||||
out.writeFloat(loadFactor);
|
||||
out.writeObject(keyComparator);
|
||||
out.writeObject(valueComparator);
|
||||
writeEntries(out, entries);
|
||||
}//writeExternal()//
|
||||
}//Map//
|
||||
112
Common/src/com/common/util/Properties.java
Normal file
112
Common/src/com/common/util/Properties.java
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
|
||||
/**
|
||||
* Addes a few methods to the standard properties code in the JDK.
|
||||
*/
|
||||
public class Properties extends java.util.Properties {
|
||||
/**
|
||||
* Properties constructor comment.
|
||||
* @deprecated No longer using this class as anything but a platform for static helper methods.
|
||||
*/
|
||||
public Properties() {
|
||||
super();
|
||||
}//Properties()//
|
||||
/**
|
||||
* Properties constructor comment.
|
||||
* @param defaults java.util.Properties
|
||||
* @deprecated No longer using this class as anything but a platform for static helper methods.
|
||||
*/
|
||||
public Properties(java.util.Properties defaults) {
|
||||
super(defaults);
|
||||
}//Properties()//
|
||||
/**
|
||||
* Loads properties from a file.
|
||||
* @param path The path to the file.
|
||||
* @return The properties found in the file, or null if the file could not be read or found.
|
||||
*/
|
||||
public static java.util.Properties load(String path) {
|
||||
return load(path, null);
|
||||
}//load()//
|
||||
/**
|
||||
* Loads properties from a file.
|
||||
* @param path The path to the file.
|
||||
* @return The properties found in the file, or null if the file could not be read or found.
|
||||
*/
|
||||
public static java.util.Properties load(String path, java.util.Properties parent) {
|
||||
File file = new File(path);
|
||||
java.util.Properties result = null;
|
||||
|
||||
if((file.exists()) && (file.canRead())) {
|
||||
FileInputStream fin = null;
|
||||
|
||||
try {
|
||||
result = new java.util.Properties(parent);
|
||||
|
||||
fin = new FileInputStream(file);
|
||||
result.load(fin);
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
finally {
|
||||
try {fin.close();}catch(Throwable e) {}
|
||||
}//finally//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//load()//
|
||||
/**
|
||||
* Stores the properties to file.
|
||||
* @param path The path to the file.
|
||||
* @return Whether the store operation was successful.
|
||||
* @deprecated No longer using this class as anything but a platform for static helper methods.
|
||||
*/
|
||||
public boolean store(String path) {
|
||||
return store(path, this);
|
||||
}//store//
|
||||
/**
|
||||
* Stores the properties to file.
|
||||
* @param path The path to the file.
|
||||
* @param properties The properties to be stored.
|
||||
* @return Whether the store operation was successful.
|
||||
*/
|
||||
public static boolean store(String path, java.util.Properties properties) {
|
||||
FileOutputStream fout = null;
|
||||
boolean result = false;
|
||||
|
||||
try {
|
||||
fout = new FileOutputStream(path);
|
||||
properties.store(fout, null);
|
||||
result = true;
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
finally {
|
||||
try {fout.close();}catch(Throwable e) {}
|
||||
}//finally//
|
||||
|
||||
return result;
|
||||
}//store()//
|
||||
/**
|
||||
* Gets the count of properties.
|
||||
* @return The number of defined properties.
|
||||
* @deprecated No longer using this class as anything but a platform for static helper methods.
|
||||
*/
|
||||
public int getSize() {
|
||||
return size();
|
||||
}//getSize()//
|
||||
}//Properties//
|
||||
71
Common/src/com/common/util/Queue.java
Normal file
71
Common/src/com/common/util/Queue.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* Implements a standard queue - FIFO (first in first out) collection.
|
||||
*/
|
||||
public class Queue implements IQueue {
|
||||
private LiteList list = null;
|
||||
/**
|
||||
* Queue constructor.
|
||||
*/
|
||||
public Queue() {
|
||||
super();
|
||||
|
||||
list = new LiteList(10, 10);
|
||||
}//Queue()//
|
||||
/**
|
||||
* Queue constructor.
|
||||
*/
|
||||
public Queue(int initialSize) {
|
||||
super();
|
||||
|
||||
list = new LiteList(initialSize, 10);
|
||||
}//Queue()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IQueue#dequeue()
|
||||
*/
|
||||
public Object dequeue() {
|
||||
return list.remove(0);
|
||||
}//dequeue()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IQueue#enqueue(java.lang.Object)
|
||||
*/
|
||||
public boolean enqueue(Object object) {
|
||||
return list.add(object) != -1;
|
||||
}//enqueue()//
|
||||
/**
|
||||
* Gets the number of items currently in the queue.
|
||||
* @return The count of queued items.
|
||||
*/
|
||||
public int getSize() {
|
||||
return list.getSize();
|
||||
}//getSize()//
|
||||
/**
|
||||
* This method is not supported.
|
||||
* It is not valid to get an iterator over a queue.
|
||||
*/
|
||||
public IIterator iterator() {
|
||||
return null;
|
||||
}//iterator()//
|
||||
/**
|
||||
* Reads the collection from the stream.
|
||||
* @param in java.io.ObjectInput The stream that the object data can be read from.
|
||||
*/
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
list = (LiteList) in.readObject();
|
||||
}//readExternal()//
|
||||
/**
|
||||
* Writes the collection to the stream.
|
||||
* @param out java.io.ObjectOutput The stream that the object data can be written to.s
|
||||
*/
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
out.writeObject(list);
|
||||
}//writeExternal()//
|
||||
}//Queue//
|
||||
746
Common/src/com/common/util/SoftLiteHashSet.java
Normal file
746
Common/src/com/common/util/SoftLiteHashSet.java
Normal file
@@ -0,0 +1,746 @@
|
||||
/*
|
||||
* Copyright (c) 2007,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
import com.common.comparison.Comparator;
|
||||
import com.common.comparison.IComparator;
|
||||
import com.common.debug.Debug;
|
||||
import com.common.exception.MethodNotSupportedException;
|
||||
|
||||
public class SoftLiteHashSet extends LiteSet {
|
||||
public static final int DEFAULT_INITIAL_CAPACITY = 51;
|
||||
public static final float DEFAULT_LOAD_FACTOR = 0.75f;
|
||||
public static final IComparator DEFAULT_COMPARATOR = Comparator.getLogicalComparator();
|
||||
public static final SoftLiteHashSet EMPTY_SET = new SoftLiteHashSet(1);
|
||||
|
||||
/** Duplicate values added to the collection will be rejected completely. It will not be possible to have the same (or equal) value more than once. */
|
||||
public static final int STYLE_NO_DUPLICATES = 0;
|
||||
/** Duplicate values added to the collection will be counted more than once but only internally (ie: the iterator will return the value only once, but remove must be called the same number of times as the add to remove the value). */
|
||||
public static final int STYLE_COUNT_DUPLICATES = 1;
|
||||
/** Duplicate values added to the collection will be counted more than once both internally and externally (ie: the iterator will return the value more than once). */
|
||||
public static final int STYLE_ADD_DUPLICATES = 2;
|
||||
/** The default style settings. */
|
||||
public static final int DEFAULT_STYLE = STYLE_NO_DUPLICATES;
|
||||
|
||||
/** The array of hash entries. */
|
||||
private HashSetEntry[] entries;
|
||||
/** The number of hash entries in the set. Note that this only counts duplicates if using STYLE_ADD_DUPLICATES. */
|
||||
private int size;
|
||||
/** The size of the set at which the entries array requires resizing. */
|
||||
private int threshold;
|
||||
/** The ratio of size to the entries array size (size / entries.length). If this ratio is smaller than the actual ratio then the entries array will be resized. */
|
||||
private float loadFactor;
|
||||
private IComparator locateComparator = DEFAULT_COMPARATOR;
|
||||
/** Whether multiple references to the same object instance can be stored in this collection. This is normally set to reject duplicates. */
|
||||
private int style = DEFAULT_STYLE;
|
||||
private ReferenceQueue referenceQueue = new ReferenceQueue();
|
||||
|
||||
/**
|
||||
* The entry class used to store HashSet values.
|
||||
*/
|
||||
protected static class HashSetEntry extends SoftReference {
|
||||
public int hash;
|
||||
public HashSetEntry next;
|
||||
public int count;
|
||||
|
||||
protected HashSetEntry(Object value, ReferenceQueue referenceQueue) {
|
||||
super(value, referenceQueue);
|
||||
}//HashSetEntry()//
|
||||
}//HashSetEntry//
|
||||
|
||||
/**
|
||||
* An iterator that can be used to iterate over the HashSet values.
|
||||
* <p>WARNING: While this class can be serialized, it will reset its' position to the start of the HashSet.
|
||||
* Also, the HashSet will be serialized with the iterator.
|
||||
* <p>This class is NOT thread safe.
|
||||
*/
|
||||
public static class HashSetIterator implements IIterator {
|
||||
private SoftLiteHashSet hashSet = null;
|
||||
protected int currentIndex = -1;
|
||||
protected HashSetEntry currentEntry = null;
|
||||
protected int nextIndex = -1;
|
||||
protected HashSetEntry nextEntry = null;
|
||||
protected Object nextEntryValue = null;
|
||||
protected boolean hasNextEntry = false;
|
||||
|
||||
protected HashSetIterator(SoftLiteHashSet hashSet) {
|
||||
this.hashSet = hashSet;
|
||||
}//HashSetIterator()//
|
||||
public void resetToFront() {
|
||||
currentIndex = -1;
|
||||
currentEntry = null;
|
||||
nextIndex = -1;
|
||||
nextEntry = null;
|
||||
hasNextEntry = false;
|
||||
}//resetToFront()//
|
||||
public boolean remove() {
|
||||
boolean result = false;
|
||||
|
||||
if(currentEntry != null) {
|
||||
result = hashSet.remove(currentEntry.get());
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//remove()//
|
||||
public Object next() {
|
||||
loadNextEntry();
|
||||
currentEntry = nextEntry;
|
||||
currentIndex = nextIndex;
|
||||
hasNextEntry = false;
|
||||
nextEntry = null;
|
||||
|
||||
return currentEntry != null ? (nextEntryValue == NULL_VALUE ? null : nextEntryValue) : null;
|
||||
}//next()//
|
||||
public boolean hasNext() {
|
||||
loadNextEntry();
|
||||
|
||||
return nextEntry != null;
|
||||
}//hasNext()//
|
||||
/**
|
||||
* Preloads the next entry. This makes querying to see if the next entry exists and then getting the next entry much easier.
|
||||
*/
|
||||
protected void loadNextEntry() {
|
||||
if(!hasNextEntry) {
|
||||
boolean found = false;
|
||||
HashSetEntry previousEntry = currentEntry;
|
||||
|
||||
nextIndex = currentIndex;
|
||||
|
||||
while(!found) {
|
||||
found = true;
|
||||
nextEntry = null;
|
||||
|
||||
if((previousEntry != null) && (previousEntry.next != null)) {
|
||||
nextEntry = previousEntry.next;
|
||||
nextEntryValue = nextEntry.get();
|
||||
}//if//
|
||||
else {
|
||||
HashSetEntry[] entries = hashSet.entries;
|
||||
|
||||
while((nextEntry == null) && (entries.length > ++nextIndex)) {
|
||||
if(entries[nextIndex] != null) {
|
||||
nextEntry = entries[nextIndex];
|
||||
nextEntryValue = nextEntry.get();
|
||||
}//if//
|
||||
}//while//
|
||||
}//else//
|
||||
|
||||
//Check for bad next entries.//
|
||||
if((nextEntry != null) && (nextEntry.isEnqueued())) {
|
||||
found = false;
|
||||
previousEntry = nextEntry;
|
||||
}//if//
|
||||
}//while//
|
||||
|
||||
if(nextEntry != null) {
|
||||
hasNextEntry = true;
|
||||
}//if//
|
||||
}//if//
|
||||
}//loadNextEntry()//
|
||||
/**
|
||||
* Allows the iterator to peek at the next value after calling loadNextEntry.
|
||||
* <p>This is for use only by subclasses an is not intended for public consumption. The value is only valid after calling loadNextEntry().</p>
|
||||
* @return The value that will be returned by the next call to next().
|
||||
* @see #next()
|
||||
* @see #loadNextEntry()
|
||||
*/
|
||||
protected Object peekNext() {
|
||||
return nextEntry != null ? (nextEntryValue == NULL_VALUE ? null : nextEntryValue) : null;
|
||||
}//peekNext()//
|
||||
/**
|
||||
* Allows the iterator to peek at whether there is a next value after calling loadNextEntry.
|
||||
* <p>This is for use only by subclasses an is not intended for public consumption. The value is only valid after calling loadNextEntry().</p>
|
||||
* @return Whether there is a next value, otherwise the iterator is finished.
|
||||
* @see #hasNext()
|
||||
* @see #loadNextEntry()
|
||||
*/
|
||||
protected boolean peekHasNext() {
|
||||
return nextEntry != null;
|
||||
}//peekHasNext()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
out.writeObject(hashSet);
|
||||
}//writeExternal()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
hashSet = (SoftLiteHashSet) in.readObject();
|
||||
resetToFront();
|
||||
}//readExternal()//
|
||||
}//HashSetIterator//
|
||||
/**
|
||||
* SoftLiteHashSet constructor.
|
||||
*/
|
||||
public SoftLiteHashSet() {
|
||||
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_COMPARATOR, DEFAULT_STYLE);
|
||||
}//SoftLiteHashSet()//
|
||||
/**
|
||||
* SoftLiteHashSet copy constructor.
|
||||
* @param original The hash set to be copied.
|
||||
*/
|
||||
public SoftLiteHashSet(SoftLiteHashSet original) {
|
||||
this(original.getEntries().length, original.getLoadFactor(), original.getLocateComparator(), original.getStyle());
|
||||
HashSetEntry[] entries = original.getEntries();
|
||||
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
for(HashSetEntry entry = entries[index]; entry != null; entry = entry.next) {
|
||||
for(int count = 0; count < entry.count; count++) {
|
||||
Object value = entry.get();
|
||||
|
||||
if(!entry.isEnqueued()) {
|
||||
add(value);
|
||||
}//if//
|
||||
}//for//
|
||||
}//for//
|
||||
}//for//
|
||||
}//SoftLiteHashSet()//
|
||||
/**
|
||||
* SoftLiteHashSet constructor.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
*/
|
||||
public SoftLiteHashSet(int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_COMPARATOR, DEFAULT_STYLE);
|
||||
}//SoftLiteHashSet()//
|
||||
/**
|
||||
* SoftLiteHashSet constructor.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
* @throws IllegalArgumentException If the initial capacity or load factor are not within their valid ranges.
|
||||
*/
|
||||
public SoftLiteHashSet(int initialCapacity, float loadFactor, IComparator locateComparator, int style) {
|
||||
super();
|
||||
|
||||
this.style = style;
|
||||
|
||||
if(locateComparator == null) {
|
||||
locateComparator = DEFAULT_COMPARATOR;
|
||||
}//if//
|
||||
|
||||
if(loadFactor <= 0.0) {
|
||||
throw new IllegalArgumentException("Invalid load factor supplied to the HashSet.");
|
||||
}//if//
|
||||
|
||||
if(initialCapacity <= 0) {
|
||||
initialCapacity = 10;
|
||||
}//if//
|
||||
|
||||
this.locateComparator = locateComparator;
|
||||
this.loadFactor = loadFactor;
|
||||
this.entries = new HashSetEntry[initialCapacity];
|
||||
this.threshold = (int)(initialCapacity * loadFactor);
|
||||
}//SoftLiteHashSet()//
|
||||
/**
|
||||
* SoftLiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
*/
|
||||
public SoftLiteHashSet(ICollection values) {
|
||||
this(values.getSize(), DEFAULT_LOAD_FACTOR, DEFAULT_COMPARATOR, DEFAULT_STYLE);
|
||||
addAll(values);
|
||||
}//SoftLiteHashSet()//
|
||||
/**
|
||||
* SoftLiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public SoftLiteHashSet(ICollection values, int initialCapacity, float loadFactor, IComparator locateComparator, int style) {
|
||||
this(initialCapacity, loadFactor, locateComparator, style);
|
||||
addAll(values);
|
||||
}//SoftLiteHashSet()//
|
||||
/**
|
||||
* SoftLiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public SoftLiteHashSet(ICollection values, IComparator locateComparator, int style) {
|
||||
this(values.getSize(), DEFAULT_LOAD_FACTOR, locateComparator, style);
|
||||
addAll(values);
|
||||
}//SoftLiteHashSet()//
|
||||
/**
|
||||
* SoftLiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
*/
|
||||
public SoftLiteHashSet(Object[] values) {
|
||||
this(values.length, DEFAULT_LOAD_FACTOR, DEFAULT_COMPARATOR, DEFAULT_STYLE);
|
||||
addAll(values);
|
||||
}//SoftLiteHashSet()//
|
||||
/**
|
||||
* SoftLiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public SoftLiteHashSet(Object[] values, IComparator locateComparator, int style) {
|
||||
this(values.length, DEFAULT_LOAD_FACTOR, locateComparator, style);
|
||||
addAll(values);
|
||||
}//SoftLiteHashSet()//
|
||||
/**
|
||||
* SoftLiteHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
* @param locateComparator The comparator used by this collection for locating values. This may be null in which case the default comparator will be used (it uses logical equality for comparisons).
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public SoftLiteHashSet(Object[] values, int initialCapacity, float loadFactor, IComparator locateComparator, int style) {
|
||||
this(initialCapacity, loadFactor, locateComparator, style);
|
||||
addAll(values);
|
||||
}//SoftLiteHashSet()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.LiteCollection#ensureCapacity(int)
|
||||
*/
|
||||
public void ensureCapacity(int minimumCapacity) {
|
||||
}//ensureCapacity()//
|
||||
/**
|
||||
* Sweeps up old map entries that no longer reference values.
|
||||
*/
|
||||
protected void sweep() {
|
||||
HashSetEntry entry = null;
|
||||
|
||||
while((entry = (HashSetEntry) referenceQueue.poll()) != null) {
|
||||
remove(entry);
|
||||
}//while//
|
||||
}//sweep()//
|
||||
/**
|
||||
* Tests to see if the specified value is contained in the collection.
|
||||
* @param value The value to test for.
|
||||
* @return Will be true if the value is contained in the collection.
|
||||
*/
|
||||
public boolean containsValue(Object value) {
|
||||
//Ensure that null values are valid.//
|
||||
if(value == null) {
|
||||
value = NULL_VALUE;
|
||||
}//if//
|
||||
|
||||
int hash = getLocateComparator().hash(value);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(HashSetEntry e = entries[index]; e != null; e = e.next) {
|
||||
if(e.hash == hash) {
|
||||
Object hashSetValue = e.get();
|
||||
|
||||
if((!e.isEnqueued()) && (Comparator.isEqual(getLocateComparator().compare(hashSetValue, value)))) {
|
||||
return true;
|
||||
}//if//
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return false;
|
||||
}//containsValue()//
|
||||
/**
|
||||
* Gets the number of times the value has been added to the set.
|
||||
* @param value The value to look for.
|
||||
* @return The number of times the value exists in the set. Note that the comparator will be used to compare the value with other values and it determines which objects are considered equivalent.
|
||||
*/
|
||||
public int getCount(Object value) {
|
||||
//Ensure that null values are valid.//
|
||||
if(value == null) {
|
||||
value = NULL_VALUE;
|
||||
}//if//
|
||||
|
||||
sweep();
|
||||
|
||||
int hash = getLocateComparator().hash(value);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(HashSetEntry e = entries[index]; e != null; e = e.next) {
|
||||
if(e.hash == hash) {
|
||||
Object hashSetValue = e.get();
|
||||
|
||||
if((!e.isEnqueued()) && (Comparator.isEqual(getLocateComparator().compare(hashSetValue, value)))) {
|
||||
return e.count;
|
||||
}//if//
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return 0;
|
||||
}//getCount()//
|
||||
/**
|
||||
* Gets the hash set entries array.
|
||||
* @return The array referencing the indexed hash set entries.
|
||||
*/
|
||||
protected HashSetEntry[] getEntries() {
|
||||
return entries;
|
||||
}//getEntries()//
|
||||
/**
|
||||
* Gets the style used for the hash set.
|
||||
* @return The style which indicates how duplicate entries are handled.
|
||||
*/
|
||||
public int getStyle() {
|
||||
return style;
|
||||
}//getStyle()//
|
||||
/**
|
||||
* Creates an entry.
|
||||
* @param value The value the entry will reference.
|
||||
*/
|
||||
protected HashSetEntry createEntry(Object value) {
|
||||
return new HashSetEntry(value, referenceQueue);
|
||||
}//createEntry()//
|
||||
/**
|
||||
* Destroys an entry.
|
||||
*/
|
||||
protected void destroyEntry(HashSetEntry entry) {
|
||||
entry.next = null;
|
||||
entry.clear();
|
||||
}//destroyEntry()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.ICollection#getFirst()
|
||||
*/
|
||||
public Object getFirst() {
|
||||
Object result = null;
|
||||
|
||||
sweep();
|
||||
|
||||
if(getSize() > 0) {
|
||||
for(int index = 0; (index < entries.length) && (result == null); index++) {
|
||||
if(entries[index] != null) {
|
||||
Object value = entries[index].get();
|
||||
|
||||
if(!entries[index].isEnqueued()) {
|
||||
result = value;
|
||||
}//if//
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//getFirst()//
|
||||
/**
|
||||
* Gets the value in the hash set when given another logically equal value.
|
||||
* @param value The logically equivalent value.
|
||||
* @return The matching value in the collection, or <code>null</code> if none was found.
|
||||
*/
|
||||
public Object get(Object value) {
|
||||
//Ensure that null values are valid.//
|
||||
if(value == null) {
|
||||
value = NULL_VALUE;
|
||||
}//if//
|
||||
|
||||
sweep();
|
||||
|
||||
int hash = getLocateComparator().hash(value);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(HashSetEntry e = entries[index]; e != null; e = e.next) {
|
||||
if(e.hash == hash) {
|
||||
Object hashSetValue = e.get();
|
||||
|
||||
if((!e.isEnqueued()) && (Comparator.isEqual(getLocateComparator().compare(hashSetValue, value)))) {
|
||||
return hashSetValue;
|
||||
}//if//
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return null;
|
||||
}//get()//
|
||||
/**
|
||||
* Gets the comparator used to locate values in the collection.
|
||||
* @return The comparator used by this collection for locating values.
|
||||
*/
|
||||
public IComparator getLocateComparator() {
|
||||
return locateComparator;
|
||||
}//getLocateComparator()//
|
||||
/**
|
||||
* Gets the number of values in the set.
|
||||
* @return The set's size.
|
||||
*/
|
||||
public int getSize() {
|
||||
sweep();
|
||||
|
||||
return size;
|
||||
}//getSize()//
|
||||
/**
|
||||
* Sets the number of values in the set.
|
||||
* @param size The set's size.
|
||||
*/
|
||||
protected void setSize(int size) {
|
||||
this.size = size;
|
||||
}//setSize()//
|
||||
/**
|
||||
* Gets the next set size at which the set must be resized.
|
||||
* @return The next resize point.
|
||||
*/
|
||||
protected int getThreshold() {
|
||||
return threshold;
|
||||
}//getThreshold()//
|
||||
/**
|
||||
* Gets the ratio of collection size divided by array size.
|
||||
* @return The ratio indicating how loaded the set can get before it requires resizing.
|
||||
*/
|
||||
protected float getLoadFactor() {
|
||||
return loadFactor;
|
||||
}//getLoadFactor()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.LiteCollection#internalAdd(java.lang.Object)
|
||||
*/
|
||||
protected int internalAdd(Object value) {
|
||||
//Ensure that null values are valid.//
|
||||
if(value == null) {
|
||||
value = NULL_VALUE;
|
||||
}//if//
|
||||
|
||||
sweep();
|
||||
|
||||
int hash = getLocateComparator().hash(value);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
HashSetEntry entry = null;
|
||||
|
||||
if(style != STYLE_ADD_DUPLICATES) {
|
||||
for(entry = entries[index]; entry != null; entry = entry.next) {
|
||||
if(entry.hash == hash) {
|
||||
Object hashSetValue = entry.get();
|
||||
|
||||
if((!entry.isEnqueued()) && (Comparator.isEqual(getLocateComparator().compare(hashSetValue, value)))) {
|
||||
if(style == STYLE_NO_DUPLICATES) {
|
||||
return -1;
|
||||
}//if//
|
||||
else {
|
||||
entry.count++;
|
||||
return 0;
|
||||
}//else//
|
||||
}//if//
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
|
||||
if(size >= threshold) {
|
||||
rehash();
|
||||
|
||||
return add(value);
|
||||
}//if//
|
||||
|
||||
entry = createEntry(value);
|
||||
entry.hash = hash;
|
||||
entry.next = entries[index];
|
||||
entry.count = 1;
|
||||
entries[index] = entry;
|
||||
size++;
|
||||
|
||||
return 0;
|
||||
}//internalAdd()//
|
||||
/**
|
||||
* Handles removing a value from the collection.
|
||||
* @param value The value to remove.
|
||||
* @return Will be <code>true</code> upon success.
|
||||
*/
|
||||
protected boolean internalRemove(Object value) {
|
||||
//Ensure that null values are valid.//
|
||||
if(value == null) {
|
||||
value = NULL_VALUE;
|
||||
}//if//
|
||||
|
||||
sweep();
|
||||
|
||||
int hash = getLocateComparator().hash(value);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
HashSetEntry entry = null;
|
||||
HashSetEntry previous = null;
|
||||
|
||||
for(entry = entries[index], previous = null; entry != null; previous = entry, entry = entry.next) {
|
||||
if(entry.hash == hash) {
|
||||
Object hashSetValue = entry.get();
|
||||
|
||||
if((!entry.isEnqueued()) && (Comparator.isEqual(getLocateComparator().compare(hashSetValue, value)))) {
|
||||
entry.count--;
|
||||
|
||||
if(entry.count == 0) {
|
||||
if(previous != null) {
|
||||
previous.next = entry.next;
|
||||
}//if//
|
||||
else {
|
||||
entries[index] = entry.next;
|
||||
}//else//
|
||||
|
||||
size--;
|
||||
destroyEntry(entry);
|
||||
}//if//
|
||||
|
||||
return true;
|
||||
}//if//
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return false;
|
||||
}//internalRemove()//
|
||||
/**
|
||||
* Handles removing a value from the collection.
|
||||
* @param value The value to remove.
|
||||
* @return Will be <code>true</code> upon success.
|
||||
*/
|
||||
protected boolean internalRemove(HashSetEntry removedEntry) {
|
||||
int hash = removedEntry.hash;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
HashSetEntry entry = null;
|
||||
HashSetEntry previous = null;
|
||||
|
||||
for(entry = entries[index], previous = null; entry != null; previous = entry, entry = entry.next) {
|
||||
if(entry == removedEntry) {
|
||||
entry.count = 0;
|
||||
|
||||
if(entry.count == 0) {
|
||||
if(previous != null) {
|
||||
previous.next = entry.next;
|
||||
}//if//
|
||||
else {
|
||||
entries[index] = entry.next;
|
||||
}//else//
|
||||
|
||||
size--;
|
||||
destroyEntry(entry);
|
||||
}//if//
|
||||
|
||||
return true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return false;
|
||||
}//internalRemove()//
|
||||
/**
|
||||
* Handles removing all values from the collection.
|
||||
* @return Will be <code>true</code> upon success.
|
||||
*/
|
||||
protected void internalRemoveAll() {
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
if(entries[index] != null) {
|
||||
HashSetEntry entry = entries[index];
|
||||
|
||||
while(entry != null) {
|
||||
entry.clear();
|
||||
entry = entry.next;
|
||||
}//while//
|
||||
|
||||
entries[index] = null;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
size = 0;
|
||||
|
||||
//Remove all queued references.//
|
||||
while(referenceQueue.poll() != null) {
|
||||
//Do nothing.//
|
||||
}//while//
|
||||
}//internalRemoveAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.LiteCollection#internalReplace(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
protected boolean internalReplace(Object oldValue, Object newValue) {
|
||||
//Note: If this is ever supported, don't forget to replace null's with NULL_VALUE.//
|
||||
throw new MethodNotSupportedException();
|
||||
}//internalReplace()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.LiteCollection#internalReplaceAll(com.common.util.ICollection)
|
||||
*/
|
||||
protected boolean internalReplaceAll(ICollection values) {
|
||||
//Note: If this is ever supported, don't forget to replace null's with NULL_VALUE.//
|
||||
throw new MethodNotSupportedException();
|
||||
}//internalReplaceAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.LiteCollection#internalReplaceAll(com.common.util.ICollection, com.common.util.ICollection)
|
||||
*/
|
||||
protected boolean internalReplaceAll(ICollection removedValues, ICollection addedValues) {
|
||||
//Note: If this is ever supported, don't forget to replace null's with NULL_VALUE.//
|
||||
throw new MethodNotSupportedException();
|
||||
}//internalReplaceAll()//
|
||||
/**
|
||||
* Gets a new iterator over the values in this collection.
|
||||
* @return IIterator The iterator that may be used to iterate over the collection values.
|
||||
*/
|
||||
public IIterator iterator() {
|
||||
sweep();
|
||||
|
||||
return new HashSetIterator(this);
|
||||
}//iterator()//
|
||||
/**
|
||||
* Will rehash the collection so that new items may be added without going over the recommended ratio of values to list entries.
|
||||
*/
|
||||
protected void rehash() {
|
||||
int oldCapacity = entries.length;
|
||||
HashSetEntry[] oldEntries = entries;
|
||||
int newCapacity = (oldCapacity << 1) + 1;
|
||||
HashSetEntry[] newEntries = new HashSetEntry[newCapacity];
|
||||
|
||||
threshold = (int)(newCapacity * loadFactor);
|
||||
entries = newEntries;
|
||||
|
||||
for(int oldIndex = oldCapacity; oldIndex-- > 0; ) {
|
||||
for(HashSetEntry oldEntry = oldEntries[oldIndex]; oldEntry != null; ) {
|
||||
HashSetEntry newEntry = oldEntry;
|
||||
int newIndex;
|
||||
|
||||
oldEntry = oldEntry.next;
|
||||
newIndex = (newEntry.hash & 0x7FFFFFFF) % newCapacity;
|
||||
newEntry.next = newEntries[newIndex];
|
||||
newEntries[newIndex] = newEntry;
|
||||
}//for//
|
||||
}//for//
|
||||
}//rehash()//
|
||||
/**
|
||||
* Fills an array with collection values.
|
||||
* @param array An array capable of containing collection values.
|
||||
* @return The number of values placed in the array.
|
||||
*/
|
||||
public int toArray(Object array) {
|
||||
HashSetEntry entry = null;
|
||||
int position = 0;
|
||||
HashSetEntry[] entries = this.entries;
|
||||
|
||||
sweep();
|
||||
|
||||
//Iterate over the entry table.//
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
entry = entries[index];
|
||||
|
||||
//Iterate through the entries at this table position.//
|
||||
while(entry != null) {
|
||||
Object value = entry.get();
|
||||
|
||||
if(!entry.isEnqueued()) {
|
||||
java.lang.reflect.Array.set(array, position, value == NULL_VALUE ? null : value);
|
||||
position++;
|
||||
}//if//
|
||||
|
||||
entry = entry.next;
|
||||
}//while//
|
||||
}//for//
|
||||
|
||||
return position;
|
||||
}//toArray()//
|
||||
/**
|
||||
* Generates a string representing the hashset.
|
||||
* @return A debug string that represents this object.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer(100);
|
||||
|
||||
buffer.append("SoftLiteHashSet {\r\n");
|
||||
|
||||
try {
|
||||
IIterator iterator = iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
Object next = iterator.next();
|
||||
|
||||
buffer.append("\t");
|
||||
buffer.append(next == NULL_VALUE ? null : next);
|
||||
buffer.append("\r\n");
|
||||
}//while//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
|
||||
buffer.append("}");
|
||||
|
||||
return buffer.toString();
|
||||
}//toArray()//
|
||||
}//SoftLiteHashSet//
|
||||
65
Common/src/com/common/util/Stack.java
Normal file
65
Common/src/com/common/util/Stack.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* Implements a standard stack - FILO (first in last out) collection.
|
||||
*/
|
||||
public class Stack implements IStack {
|
||||
private LiteList list = null;
|
||||
/**
|
||||
* Stack constructor.
|
||||
*/
|
||||
public Stack() {
|
||||
super();
|
||||
|
||||
list = new LiteList(10, 10);
|
||||
}//Stack()//
|
||||
/**
|
||||
* Stack constructor.
|
||||
*/
|
||||
public Stack(int initialSize) {
|
||||
super();
|
||||
|
||||
list = new LiteList(initialSize, 10);
|
||||
}//Stack()//
|
||||
public int getSize() {
|
||||
return list.getSize();
|
||||
}//getSize()//
|
||||
/**
|
||||
* This method is not supported.
|
||||
* It is not valid to get an iterator over a stack.
|
||||
*/
|
||||
public IIterator iterator() {
|
||||
return null;
|
||||
}//iterator()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IStack#pop()
|
||||
*/
|
||||
public Object pop() {
|
||||
return list.remove(0);
|
||||
}//pop()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.IStack#push(java.lang.Object)
|
||||
*/
|
||||
public boolean push(Object object) {
|
||||
return list.add(0, object) != -1;
|
||||
}//push()//
|
||||
/**
|
||||
* Allows the serialization of this type.
|
||||
*/
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
list = (LiteList) in.readObject();
|
||||
}//readExternal()//
|
||||
/**
|
||||
* Allows the serialization of this type.
|
||||
*/
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
out.writeObject(list);
|
||||
}//writeExternal()//
|
||||
}//Stack//
|
||||
3139
Common/src/com/common/util/StreamBuffer.java
Normal file
3139
Common/src/com/common/util/StreamBuffer.java
Normal file
File diff suppressed because it is too large
Load Diff
213
Common/src/com/common/util/StringParser.java
Normal file
213
Common/src/com/common/util/StringParser.java
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* This string parser uses delimiter characters to parse a string into segements.
|
||||
*/
|
||||
public class StringParser {
|
||||
private int currentPosition = 0;
|
||||
private int firstPosition = 0;
|
||||
private int lastPosition = 0;
|
||||
private String string = null;
|
||||
private String delimiters = null;
|
||||
private boolean returnDelimiters = false;
|
||||
/**
|
||||
* Constructs a string parser for the specified string.
|
||||
* The delimiters will be spaces, tabs, end of line, form feeds, and carriage return characters.
|
||||
* @param string The string to parse.
|
||||
*/
|
||||
public StringParser(String string) {
|
||||
this(string, " \t\n\r\f", false);
|
||||
}//StringParser()//
|
||||
/**
|
||||
* Constructs a string parser with the given string and a collection of delimiters.
|
||||
* @param string The string to be parsed.
|
||||
* @param delimiters The delimiters used to parse the string.
|
||||
*/
|
||||
public StringParser(String string, String delimiters) {
|
||||
this(string, delimiters, false);
|
||||
}//StringParser()//
|
||||
/**
|
||||
* Constructs a string parser with the given string, delimiters, and whether the delimiters should be returned as string components.
|
||||
* @param string The string to parse.
|
||||
* @param delimiters The delimiters that break up the string.
|
||||
* @param returnDelimiters Whether the delimiters should be returned as string components.
|
||||
*/
|
||||
public StringParser(String string, String delimiters, boolean returnDelimiters) {
|
||||
this.currentPosition = 0;
|
||||
this.string = string;
|
||||
this.firstPosition = 0;
|
||||
this.lastPosition = string.length() - 1;
|
||||
this.delimiters = delimiters;
|
||||
this.returnDelimiters = returnDelimiters;
|
||||
}//StringParser()//
|
||||
/**
|
||||
* Adds a delimiter character to the collection.
|
||||
* @param character The character to add to the collection of delimiters.
|
||||
*/
|
||||
public void addDelimiter(char character) {
|
||||
delimiters += character;
|
||||
}//addDelimiter()//
|
||||
/**
|
||||
* Counts the number of times that this tokenizer's <code>nextToken</code> method can be called before it generates an exception.
|
||||
* The current position will not advance.
|
||||
* @return The number of string segments remaining in the string using the current delimiter set.
|
||||
*/
|
||||
public int countSegments() {
|
||||
int count = 0;
|
||||
int position = currentPosition;
|
||||
|
||||
while(position <= lastPosition) {
|
||||
//This is just skipDelimiters(); but it does not affect currentPosition.//
|
||||
while((!returnDelimiters) && (position <= lastPosition) && (delimiters.indexOf(string.charAt(position)) >= 0)) {
|
||||
position++;
|
||||
}//while//
|
||||
|
||||
if(position > lastPosition) {
|
||||
break;
|
||||
}//if//
|
||||
|
||||
int start = position;
|
||||
|
||||
while((position <= lastPosition) && (delimiters.indexOf(string.charAt(position)) < 0)) {
|
||||
position++;
|
||||
}//while//
|
||||
|
||||
if((returnDelimiters) && (start == position) && (delimiters.indexOf(string.charAt(position)) >= 0)) {
|
||||
position++;
|
||||
}//if//
|
||||
|
||||
count++;
|
||||
}//while//
|
||||
|
||||
return count;
|
||||
}//countSegments()//
|
||||
/**
|
||||
* Gets the parser's current position in the string.
|
||||
* @return The current index in the string (points to the next character to be looked at).
|
||||
*/
|
||||
public int getCurrentPosition() {
|
||||
return currentPosition;
|
||||
}//getCurrentPosition()//
|
||||
/**
|
||||
* Gets the delimiters used by the parser.
|
||||
* @return The delimiters used to parse the string.
|
||||
*/
|
||||
public String getDelimiters() {
|
||||
return delimiters;
|
||||
}//getDelimiters()//
|
||||
/**
|
||||
* Gets whether the delimiters will be returned as segements.
|
||||
* @return Whether the delimiters should be returned as string segments.
|
||||
*/
|
||||
public boolean getReturnDelimiters() {
|
||||
return returnDelimiters;
|
||||
}//getReturnDelimiters()//
|
||||
/**
|
||||
* Gets the string to parse.
|
||||
* @return The string to parse into segments.
|
||||
*/
|
||||
public String getString() {
|
||||
return string;
|
||||
}//getString()//
|
||||
/**
|
||||
* Determines whether there is a next segment.
|
||||
* @return Whether there is another string segment to be returned by the next() method.
|
||||
* @see #next()
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
skipDelimiters();
|
||||
|
||||
return (currentPosition <= lastPosition);
|
||||
} //hasNext//
|
||||
/**
|
||||
* Gets the next string segment in the parse operation.
|
||||
* @return The next available string segment.
|
||||
*/
|
||||
public String next() {
|
||||
int start = 0;
|
||||
|
||||
skipDelimiters();
|
||||
start = currentPosition;
|
||||
|
||||
if(currentPosition > lastPosition) {
|
||||
throw new RuntimeException("No more string segments exist. Make sure you call hasNext() before calling next. This class is also NOT thread safe.");
|
||||
}//if//
|
||||
|
||||
while((currentPosition <= lastPosition) && (delimiters.indexOf(string.charAt(currentPosition)) < 0)) {
|
||||
currentPosition++;
|
||||
}//while//
|
||||
|
||||
if((returnDelimiters) && (start == currentPosition) && (delimiters.indexOf(string.charAt(currentPosition)) >= 0)) {
|
||||
currentPosition++;
|
||||
}//if//
|
||||
|
||||
return string.substring(start, currentPosition);
|
||||
}//next()//
|
||||
/**
|
||||
* Adds a delimiter character to the collection.
|
||||
* @param character The character to add to the collection of delimiters.
|
||||
*/
|
||||
public void removeDelimiter(char character) {
|
||||
int index = delimiters.indexOf(character);
|
||||
|
||||
if(index >= 0) {
|
||||
delimiters = (index != 0 ? delimiters.substring(0, index) : "") + (index != delimiters.length() - 1 ? delimiters.substring(index + 1) : "");
|
||||
}//if//
|
||||
}//removeDelimiter()//
|
||||
/**
|
||||
* Resets the current position to the given position in the string.
|
||||
* @param index The position to move to.
|
||||
*/
|
||||
public void resetTo(int index) {
|
||||
if((index < firstPosition) || (index > lastPosition)) {
|
||||
throw new IndexOutOfBoundsException("The index " + index + " must be greater than or equal to " + firstPosition + " and less than or equal to " + lastPosition + ".");
|
||||
}//if//
|
||||
|
||||
this.currentPosition = index;
|
||||
}//resetTo()//
|
||||
/**
|
||||
* Resets the current position to the first position in the string.
|
||||
*/
|
||||
public void resetToFront() {
|
||||
this.currentPosition = firstPosition;
|
||||
}//resetToFront()//
|
||||
/**
|
||||
* Sets the delimiters used by the parser.
|
||||
* @param delimiters The delimiters used to parse the string.
|
||||
*/
|
||||
public void setDelimiters(String delimiters) {
|
||||
this.delimiters = delimiters;
|
||||
}//setDelimiters()//
|
||||
/**
|
||||
* Sets whether the delimiters will be returned as segements.
|
||||
* @param returnDelimiters Whether the delimiters should be returned as string segments.
|
||||
*/
|
||||
public void setReturnDelimiters(boolean returnDelimiters) {
|
||||
this.returnDelimiters = returnDelimiters;
|
||||
}//setReturnDelimiters()//
|
||||
/**
|
||||
* Sets the string to parse.
|
||||
* @param string The string to parse into segments.
|
||||
*/
|
||||
public void setString(String string) {
|
||||
this.string = string;
|
||||
this.firstPosition = 0;
|
||||
this.lastPosition = string.length() - 1;
|
||||
this.currentPosition = 0;
|
||||
}//setString()//
|
||||
/**
|
||||
* Skips delimiters by incrementing the current position to the next non-delimiter character.
|
||||
*/
|
||||
private void skipDelimiters() {
|
||||
while((!returnDelimiters) && (currentPosition <= lastPosition) && (delimiters.indexOf(string.charAt(currentPosition)) >= 0)) {
|
||||
currentPosition++;
|
||||
}//while//
|
||||
}//skipDelimiters()//
|
||||
}//StringParser//
|
||||
428
Common/src/com/common/util/StringSupport.java
Normal file
428
Common/src/com/common/util/StringSupport.java
Normal file
@@ -0,0 +1,428 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
import sun.io.CharToByteUTF8;
|
||||
|
||||
import com.common.system.SystemManager;
|
||||
import com.common.debug.Debug;
|
||||
import com.common.io.StreamSupport;
|
||||
|
||||
/**
|
||||
* Provides some static methods for manipulating strings.
|
||||
*/
|
||||
public class StringSupport {
|
||||
public static final String EMPTY_STRING = "";
|
||||
public static final String STRING_FORMAT_UTF8 = StreamSupport.STRING_FORMAT_UTF8;
|
||||
public static final String STRING_FORMAT_UNICODE = StreamSupport.STRING_FORMAT_UNICODE;
|
||||
public static char[] hexCharacters = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
private final static char[] BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
|
||||
/** A sparse mapping between the integer value and the character value. */
|
||||
private final static int[] BASE64_TO_INT = new int[128];
|
||||
|
||||
static {
|
||||
for(int byteIndex = 0; byteIndex < BASE64_ALPHABET.length; byteIndex++) {
|
||||
BASE64_TO_INT[BASE64_ALPHABET[byteIndex]] = byteIndex;
|
||||
}//for//
|
||||
}//static//
|
||||
/**
|
||||
* StringSupport constructor.
|
||||
*/
|
||||
private StringSupport() {
|
||||
super();
|
||||
}//StringSupport()//
|
||||
/**
|
||||
* Encodes the byte array into a Base64 string.
|
||||
* @param buffer The input bytes.
|
||||
* @return The Base64 string.
|
||||
*/
|
||||
public static String base64Encode(byte[] buffer) {
|
||||
int size = buffer.length;
|
||||
char[] array = new char[((size + 2) / 3) * 4];
|
||||
int a = 0;
|
||||
int byteIndex = 0;
|
||||
|
||||
//Encode bytes three at a time.//
|
||||
while(byteIndex < size) {
|
||||
byte byte0 = buffer[byteIndex++];
|
||||
byte byte1 = (byteIndex < size) ? buffer[byteIndex++] : 0;
|
||||
byte byte2 = (byteIndex < size) ? buffer[byteIndex++] : 0;
|
||||
|
||||
array[a++] = BASE64_ALPHABET[(byte0 >> 2) & 0x3F];
|
||||
array[a++] = BASE64_ALPHABET[((byte0 << 4) | ((byte1 & 0xFF) >> 4)) & 0x3F];
|
||||
array[a++] = BASE64_ALPHABET[((byte1 << 2) | ((byte2 & 0xFF) >> 6)) & 0x3F];
|
||||
array[a++] = BASE64_ALPHABET[byte2 & 0x3F];
|
||||
}//while//
|
||||
|
||||
//Append '=' characters if the last one or two bytes were not present.//
|
||||
switch(size % 3) {
|
||||
case 1:
|
||||
array[--a] = '=';
|
||||
case 2:
|
||||
array[--a] = '=';
|
||||
}//switch//
|
||||
|
||||
return new String(array);
|
||||
}//base64Encode()//
|
||||
/**
|
||||
* Decodes the Base64 string back into a byte array.
|
||||
* @param string The Base64 string.
|
||||
* @return The resulting bytes.
|
||||
*/
|
||||
public static byte[] base64Decode(String string) {
|
||||
byte[] buffer = new byte[string.length() * 3 / 4 - (string.endsWith("==") ? 2 : string.endsWith("=") ? 1 : 0)];
|
||||
|
||||
//Decode bytes three at a time.//
|
||||
for(int charIndex = 0, byteIndex = 0; byteIndex < buffer.length; ) {
|
||||
int char0 = BASE64_TO_INT[string.charAt(charIndex++)];
|
||||
int char1 = BASE64_TO_INT[string.charAt(charIndex++)];
|
||||
int char2;
|
||||
int char3;
|
||||
|
||||
buffer[byteIndex++] = (byte) (((char0 << 2) | (char1 >> 4)) & 0xFF);
|
||||
|
||||
if(byteIndex < buffer.length) {
|
||||
char2 = BASE64_TO_INT[string.charAt(charIndex++)];
|
||||
buffer[byteIndex++] = (byte) (((char1 << 4) | (char2 >> 2)) & 0xFF);
|
||||
|
||||
if(byteIndex < buffer.length) {
|
||||
char3 = BASE64_TO_INT[string.charAt(charIndex++)];
|
||||
buffer[byteIndex++] = (byte) (((char2 << 6) | char3) & 0xFF);
|
||||
}//if//
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return buffer;
|
||||
}//base64Decode()//
|
||||
/**
|
||||
* Appends the byte to the buffer as a hex character.
|
||||
* @param value The byte value to append.
|
||||
* @param buffer The string buffer append to.
|
||||
*/
|
||||
public static void appendByteAsHex(byte value, StringBuffer buffer) {
|
||||
byte highBits = (byte) ((value >> 4) & 0x0F);
|
||||
byte lowBits = (byte) (value & 0x0F);
|
||||
|
||||
buffer.append(hexCharacters[highBits]);
|
||||
buffer.append(hexCharacters[lowBits]);
|
||||
}//appendByteAsHex()//
|
||||
/**
|
||||
* Appends the bytes to the buffer as a hex characters.
|
||||
* <p>Note: This method does not verify that the inputs.
|
||||
* @param bytes The bytes to append.
|
||||
* @param offset The offset in the byte buffer of the first byte to be included.
|
||||
* @param length The number of bytes to include.
|
||||
* @param buffer The string buffer append to.
|
||||
*/
|
||||
public static void appendBytesAsHex(byte[] bytes, int offset, int length, StringBuffer buffer) {
|
||||
for(int index = offset; index < length; index++) {
|
||||
byte highBits = (byte) ((bytes[index] >> 4) & 0x0F);
|
||||
byte lowBits = (byte) (bytes[index] & 0x0F);
|
||||
|
||||
buffer.append(hexCharacters[highBits]);
|
||||
buffer.append(hexCharacters[lowBits]);
|
||||
}//for//
|
||||
}//appendByteAsHex()//
|
||||
/**
|
||||
* Gets a byte array from a string of hex codes.
|
||||
* <p>Note: This method assumes that there are an even number of hex codes. This is because each byte is represented by exactly two hexidecimal codes.</p>
|
||||
* @param hexCodes A string of hexidecimal codes.
|
||||
* @return The array of bytes.
|
||||
*/
|
||||
public static byte[] fromHexString(String hexCodes) {
|
||||
int length = hexCodes.length();
|
||||
int next = 0;
|
||||
byte[] bytes = new byte[length >> 1];
|
||||
|
||||
for(int index = 0; index < bytes.length; index++) {
|
||||
char ch1 = hexCodes.charAt(next++);
|
||||
char ch2 = hexCodes.charAt(next++);
|
||||
|
||||
bytes[index] = (byte) ((((Character.isDigit(ch1) ? ch1 - '0' : ch1 - 55) << 4) | (Character.isDigit(ch2) ? ch2 - '0' : ch2 - 55)) & 0xFF);
|
||||
}//for//
|
||||
|
||||
return bytes;
|
||||
}//fromHexString()//
|
||||
/**
|
||||
* Gets an integer from a string of hex codes.
|
||||
* @param hexCodes A string of hexidecimal codes.
|
||||
* @return The integer value.
|
||||
*/
|
||||
public static int fromHexStringToInt(String hexCodes) {
|
||||
int length = hexCodes.length() > 8 ? 8 : hexCodes.length();
|
||||
int next = 0;
|
||||
int result = 0;
|
||||
|
||||
for(int index = 0; index < length; index++) {
|
||||
char ch = hexCodes.charAt(next++);
|
||||
|
||||
result = result << 4;
|
||||
result |= (Character.isDigit(ch) ? ch - '0' : ch - 55);
|
||||
}//for//
|
||||
|
||||
return result;
|
||||
}//fromHexStringToInt()//
|
||||
/**
|
||||
* Gets a long from a string of hex codes.
|
||||
* @param hexCodes A string of hexidecimal codes.
|
||||
* @return The long value.
|
||||
*/
|
||||
public static long fromHexStringToLong(String hexCodes) {
|
||||
int length = hexCodes.length() > 16 ? 16 : hexCodes.length();
|
||||
int next = 0;
|
||||
long result = 0;
|
||||
|
||||
for(int index = 0; index < length; index++) {
|
||||
char ch = hexCodes.charAt(next++);
|
||||
|
||||
result = result << 4;
|
||||
result |= (Character.isDigit(ch) ? ch - '0' : ch - 55);
|
||||
}//for//
|
||||
|
||||
return result;
|
||||
}//fromHexStringToLong()//
|
||||
/**
|
||||
* Gets an integer from a string of hex codes.
|
||||
* @param hexCodes A string of hexidecimal codes.
|
||||
* @return The integer value.
|
||||
* @deprecated Use fromHexStringToInt(String) instead.
|
||||
*/
|
||||
public static int intFromHexString(String hexCodes) {
|
||||
return fromHexStringToInt(hexCodes);
|
||||
}//intFromHexString()//
|
||||
/**
|
||||
* Creates a string by reading the character bytes from a byte array beginning at a given offset.
|
||||
* @param bytes The byte array containing the character data.
|
||||
* @param offset The offset in the array where the character data begins.
|
||||
* @param length The number of bytes of character data to read.
|
||||
* @return The string represented by the character data in the byte array.
|
||||
*/
|
||||
public static String fromUnicode16Bytes(byte[] bytes, int offset, int length) {
|
||||
return SystemManager.convertUnicode16StringFromBytes(bytes, offset, length);
|
||||
}//fromUnicode16Bytes()//
|
||||
/**
|
||||
* Creates a string by reading the character bytes from a byte array beginning at a given offset.
|
||||
* @param bytes The byte array containing the character data.
|
||||
* @param offset The offset in the array where the character data begins.
|
||||
* @param length The number of bytes of character data to read.
|
||||
* @return The string represented by the character data in the byte array.
|
||||
*/
|
||||
public static String fromUtf8Bytes(byte[] bytes, int offset, int length) {
|
||||
return SystemManager.convertUtf8StringFromBytes(bytes, offset, length);
|
||||
}//fromUtf8Bytes()//
|
||||
/**
|
||||
* Gets the number of bytes in the Unicode16 string.
|
||||
* @param string The string to get the length of.
|
||||
* @return Will be the number of Unicode16 bytes in the string.
|
||||
*/
|
||||
public static int getUnicode16Length(String string) {
|
||||
return string.length() << 1;
|
||||
}//getUnicode16Length()//
|
||||
/**
|
||||
* Gets the number of bytes in the UTF8 string.
|
||||
* @param string The string to get the length of.
|
||||
* @return Will be the number of UTF8 bytes in the string.
|
||||
*/
|
||||
public static int getUtf8Length(String string) {
|
||||
return SystemManager.getUtf8StringLength(string);
|
||||
}//getUtf8Length()//
|
||||
/**
|
||||
* Performs a full hash on the stringing to produce the greatest possible accuracy.
|
||||
* <p>WARNING: The only 'A'-'Z', 'a'-'z', '_', '(', '[', '.', and ';' are hashed by this algorithm. All other characters are ignored.
|
||||
* @param stringing The stringing to be hashed.
|
||||
* @return long The hash value.
|
||||
*/
|
||||
public static long hash(String string) {
|
||||
char character;
|
||||
byte[] bytes = new byte[8];
|
||||
int bytesIndex = 0;
|
||||
|
||||
for(int index = 0; index < string.length(); index++) {
|
||||
byte characterValue = 0;
|
||||
character = string.charAt(index);
|
||||
|
||||
if((character >= 'A') && (character <= 'Z')) {
|
||||
characterValue = (byte) (character - 65); //Get on range of 0-25.//
|
||||
}//if//
|
||||
else if((character >= 'a') && (character <= 'z')) {
|
||||
characterValue = (byte) (character - 71); //Get on range of 26-51.//
|
||||
}//else if//
|
||||
else if(character == '_') {
|
||||
characterValue = 52;
|
||||
}//else if//
|
||||
else if(character == '[') {
|
||||
characterValue = 53;
|
||||
}//else if//
|
||||
else if(character == '(') {
|
||||
characterValue = 54;
|
||||
}//else if//
|
||||
else if(character == ';') {
|
||||
characterValue = 55;
|
||||
}//else if//
|
||||
else if(character == '.') {
|
||||
characterValue = 56;
|
||||
}//else if//
|
||||
else {
|
||||
//Do nothing.//
|
||||
}//else//
|
||||
|
||||
bytes[bytesIndex] += characterValue;
|
||||
|
||||
//Rotate the index in the bytes array.//
|
||||
bytesIndex++;
|
||||
|
||||
if(bytesIndex == bytes.length) {
|
||||
bytesIndex = 0;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return StreamSupport.readLong(bytes, 0);
|
||||
}//hash()//
|
||||
/**
|
||||
* Gets a string of hex codes, two for each byte in the byte array.
|
||||
* @param bytes The array of source bytes.
|
||||
* @return The hex code string.
|
||||
*/
|
||||
public static String toHexString(byte[] bytes) {
|
||||
return bytes == null ? "" : toHexString(bytes, 0, bytes.length);
|
||||
}//toHexString()//
|
||||
/**
|
||||
* Gets a string of hex codes, two for each byte in the byte array.
|
||||
* <p>Note: This method does not verify that the inputs.
|
||||
* @param bytes The array of source bytes.
|
||||
* @param offset The offset in the byte buffer of the first byte to be included.
|
||||
* @param length The number of bytes to include.
|
||||
* @return The hex code string.
|
||||
*/
|
||||
public static String toHexString(byte[] bytes, int offset, int length) {
|
||||
StringBuffer buffer = new StringBuffer(length << 1);
|
||||
|
||||
if(bytes != null) {
|
||||
appendBytesAsHex(bytes, offset, length, buffer);
|
||||
}//if//
|
||||
|
||||
return buffer.toString();
|
||||
}//toHexString()//
|
||||
/**
|
||||
* Gets a string of hex codes, two for each byte in the integer.
|
||||
* @param value The integer value to convert to a hex string.
|
||||
* @return The hex code string.
|
||||
*/
|
||||
public static String toHexString(int value) {
|
||||
StringBuffer buffer = new StringBuffer(8);
|
||||
|
||||
buffer.append(hexCharacters[((value >> 28) & 0xF)]);
|
||||
buffer.append(hexCharacters[((value >> 24) & 0xF)]);
|
||||
buffer.append(hexCharacters[((value >> 20) & 0xF)]);
|
||||
buffer.append(hexCharacters[((value >> 16) & 0xF)]);
|
||||
buffer.append(hexCharacters[((value >> 12) & 0xF)]);
|
||||
buffer.append(hexCharacters[((value >> 8) & 0xF)]);
|
||||
buffer.append(hexCharacters[((value >> 4) & 0xF)]);
|
||||
buffer.append(hexCharacters[(value & 0xF)]);
|
||||
|
||||
return buffer.toString();
|
||||
}//toHexString()//
|
||||
/**
|
||||
* Gets a string of hex codes, two for each byte in the integer.
|
||||
* @param value The integer value to convert to a hex string.
|
||||
* @return The hex code string.
|
||||
*/
|
||||
public static String toHexString(long value) {
|
||||
StringBuffer buffer = new StringBuffer(8);
|
||||
|
||||
buffer.append(hexCharacters[(int) ((value >> 60) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 56) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 52) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 48) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 44) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 40) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 36) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 32) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 28) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 24) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 20) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 16) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 12) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 8) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) ((value >> 4) & 0xF)]);
|
||||
buffer.append(hexCharacters[(int) (value & 0xF)]);
|
||||
|
||||
return buffer.toString();
|
||||
}//toHexString()//
|
||||
/**
|
||||
* Writes the character bytes to the byte array starting at the offset.
|
||||
* @param string The string to write to the byte array.
|
||||
* @param bytes The byte array that should contain the string bytes.
|
||||
* @param offset The offset in the array where the character bytes should begin.
|
||||
* @return Will be the number of bytes written.
|
||||
*/
|
||||
public static int toUnicode16Bytes(String string, byte[] bytes, int offset) {
|
||||
return SystemManager.convertUnicode16StringToBytes(string, bytes, offset);
|
||||
}//toUnicode16Bytes()//
|
||||
/**
|
||||
* Writes the character bytes to the byte array starting at the offset.
|
||||
* @param string The string to write to the byte array.
|
||||
* @param bytes The byte array that should contain the string bytes.
|
||||
* @param offset The offset in the array where the character bytes should begin.
|
||||
* @return Will be the number of bytes written.
|
||||
*/
|
||||
public static int toUtf8Bytes(String string, byte[] bytes, int offset) {
|
||||
return SystemManager.convertUtf8StringToBytes(string, bytes, offset);
|
||||
}//toUtf8Bytes()//
|
||||
/**
|
||||
* Gets the character bytes to the byte array.
|
||||
* @param string The string to get the bytes of.
|
||||
* @return The string's utf8 bytes.
|
||||
*/
|
||||
public static byte[] toUtf8Bytes(String string) {
|
||||
return SystemManager.convertUtf8StringToBytes(string);
|
||||
}//toUtf8Bytes()//
|
||||
/**
|
||||
* Gets the character bytes to the byte array.
|
||||
* @param string The string to get the bytes of.
|
||||
* @return The string's utf8 bytes, or null if there was an error.
|
||||
*/
|
||||
public static byte[] toUtf8Bytes(char[] string) {
|
||||
try {
|
||||
return new CharToByteUTF8().convertAll(string);
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
return null;
|
||||
}//catch//
|
||||
}//toUtf8Bytes()//
|
||||
/**
|
||||
* Splits the string into pieces based on the given character.
|
||||
* @param string The string to be split.
|
||||
* @param ch The character used to separate the pieces we are splitting into.
|
||||
* @return The strings that the parameter was broken into, not including the separator characters.
|
||||
*/
|
||||
public static String[] split(String string, char ch) {
|
||||
String[] result = null;
|
||||
LiteList parts = new LiteList(10, 100);
|
||||
int lastSplitIndex = 0;
|
||||
|
||||
//Search for matching characters and split the string.//
|
||||
for(int index = 0; index < string.length(); index++) {
|
||||
if(string.charAt(index) == ch) {
|
||||
parts.add(string.substring(lastSplitIndex, index));
|
||||
lastSplitIndex = index + 1;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Get the last string part.//
|
||||
if(lastSplitIndex != string.length()) {
|
||||
parts.add(string.substring(lastSplitIndex));
|
||||
}//if//
|
||||
|
||||
result = new String[parts.getSize()];
|
||||
parts.toArray(result);
|
||||
|
||||
return result;
|
||||
}//split()//
|
||||
}//StringSupport//
|
||||
359
Common/src/com/common/util/TextParser.java
Normal file
359
Common/src/com/common/util/TextParser.java
Normal file
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util;
|
||||
|
||||
/**
|
||||
* This string parser uses delimiter strings to parse a string into segements.
|
||||
*/
|
||||
public class TextParser {
|
||||
private IList delimiters = new LiteList(10, 20); //The collection of Delimiter objects used to break up the string into segments.//
|
||||
private int currentPosition = 0; //The current position in the paresed string. This index is of the next character in the string that has NOT been looked at.//
|
||||
private int firstPosition = 0; //The first position in the parsed string.//
|
||||
private int lastPosition = 0; //The last position in the parsed string.//
|
||||
private String string = null; //The string to parse.//
|
||||
private int nextPosition = -1; //The current position after the next available segement is used (only valid if nextSegment is non-null.//
|
||||
private String nextSegment = null; //The next available segement to use (this will be null if there is no known next (does not mean there is not one).//
|
||||
private int lastUpdatePosition = 0; //The last position used to update the delimiters. This allows the update method to figure out whether it can do an incremental update.//
|
||||
private Boolean isNextDelimiter = null; //Whether the next element returned is going to be a delimiter.//
|
||||
private boolean isLastDelimiter = false; //Whether the last element returned was a delimiter.//
|
||||
|
||||
/**
|
||||
* Encapsulates a delimiter and its' next occurance index.
|
||||
*/
|
||||
private static class Delimiter {
|
||||
public String delimiter = null;
|
||||
public int nextIndex = -2;
|
||||
public boolean returnDelimiter = false;
|
||||
|
||||
public Delimiter(String delimiter) {
|
||||
this.delimiter = delimiter;
|
||||
}//Delimiter()//
|
||||
public Delimiter(String delimiter, boolean returnDelimiter) {
|
||||
this.delimiter = delimiter;
|
||||
this.returnDelimiter = returnDelimiter;
|
||||
}//Delimiter()//
|
||||
public boolean equals(Object object) {
|
||||
return (object instanceof Delimiter) && (((Delimiter) object).delimiter.equals(delimiter));
|
||||
}//equals()//
|
||||
public int hashCode() {
|
||||
return delimiter.hashCode();
|
||||
}//hashCode()//
|
||||
}//Delimiter//
|
||||
/**
|
||||
* Constructs a string parser for the specified string.
|
||||
* The delimiters will be spaces, tabs, end of line, form feeds, and carriage return characters.
|
||||
* @param string The string to parse.
|
||||
*/
|
||||
public TextParser(String string) {
|
||||
this(string, (IList) null, false);
|
||||
}//StringParser()//
|
||||
/**
|
||||
* Constructs a string parser with the given string and a collection of delimiters.
|
||||
* @param string The string to be parsed.
|
||||
* @param delimiters The delimiters used to parse the string.
|
||||
*/
|
||||
public TextParser(String string, String[] delimiters) {
|
||||
this(string, delimiters, false);
|
||||
}//StringParser()//
|
||||
/**
|
||||
* Constructs a string parser with the given string, delimiters, and whether the delimiters should be returned as string components.
|
||||
* @param string The string to parse.
|
||||
* @param delimiters The delimiters that break up the string.
|
||||
* @param returnDelimiters Whether the delimiters should be returned as string components.
|
||||
*/
|
||||
public TextParser(String string, String[] delimiters, boolean returnDelimiters) {
|
||||
this.currentPosition = 0;
|
||||
this.string = string;
|
||||
this.firstPosition = 0;
|
||||
this.lastPosition = string.length() - 1;
|
||||
|
||||
if(delimiters != null) {
|
||||
setDelimiters(delimiters, returnDelimiters);
|
||||
}//if//
|
||||
}//StringParser()//
|
||||
/**
|
||||
* Constructs a string parser with the given string and a collection of delimiters.
|
||||
* @param string The string to be parsed.
|
||||
* @param delimiters The delimiters used to parse the string.
|
||||
*/
|
||||
public TextParser(String string, IList delimiters) {
|
||||
this(string, delimiters, false);
|
||||
}//StringParser()//
|
||||
/**
|
||||
* Constructs a string parser with the given string, delimiters, and whether the delimiters should be returned as string components.
|
||||
* @param string The string to parse.
|
||||
* @param delimiters The delimiters that break up the string.
|
||||
* @param returnDelimiters Whether the delimiters should be returned as string components.
|
||||
*/
|
||||
public TextParser(String string, IList delimiters, boolean returnDelimiters) {
|
||||
this.currentPosition = 0;
|
||||
this.string = string;
|
||||
this.firstPosition = 0;
|
||||
this.lastPosition = string.length() - 1;
|
||||
|
||||
if(delimiters != null) {
|
||||
setDelimiters(delimiters, returnDelimiters);
|
||||
}//if//
|
||||
}//StringParser()//
|
||||
/**
|
||||
* Adds a delimiter string to the collection.
|
||||
* @param delimiter The delimiter string to add to the collection of delimiters.
|
||||
*/
|
||||
public void addDelimiter(String delimiter, boolean returnDelimiter) {
|
||||
this.delimiters.add(new Delimiter(delimiter, returnDelimiter));
|
||||
this.nextSegment = null;
|
||||
}//addDelimiter()//
|
||||
/**
|
||||
* Adds delimiters to the collection.
|
||||
* @param delimiter The delimiter strings to add to the collection of delimiters.
|
||||
*/
|
||||
public void addDelimiters(IList delimiters, boolean returnDelimiters) {
|
||||
IIterator iterator = delimiters.iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
this.delimiters.add(new Delimiter((String) iterator.next(), returnDelimiters));
|
||||
}//while//
|
||||
|
||||
this.nextSegment = null;
|
||||
}//addDelimiters()//
|
||||
/**
|
||||
* Gets the parser's current position in the string.
|
||||
* @return The current index in the string (points to the next character to be looked at).
|
||||
*/
|
||||
public int getCurrentPosition() {
|
||||
return currentPosition;
|
||||
}//getCurrentPosition()//
|
||||
/**
|
||||
* Gets the delimiters used by the parser.
|
||||
* <p>WARNING: This is not a very efficient method because it must convert Delimiter object collections to String object collections. It should not be over used.
|
||||
* @return The delimiters used to parse the string.
|
||||
*/
|
||||
public IList getDelimiters() {
|
||||
IList delimiters = new LiteList(this.delimiters.getSize());
|
||||
IIterator iterator = this.delimiters.iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
delimiters.add(((Delimiter) iterator.next()).delimiter);
|
||||
}//while//
|
||||
|
||||
return delimiters;
|
||||
}//getDelimiters()//
|
||||
/**
|
||||
* Gets the next delimiter in the collection.
|
||||
* This method will call the updateIndexes method before deteremining the next delimiter.
|
||||
* @return The next delimiter to occur (or if more than one occur at the same index then the larger of the two delimiters).
|
||||
* @see #updateIndexes(IList, int)
|
||||
*/
|
||||
private Delimiter getNextDelimiter(int position) {
|
||||
IIterator iterator = delimiters.iterator();
|
||||
Delimiter delimiter = null;
|
||||
|
||||
updateIndexes(delimiters, position);
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
Delimiter next = (Delimiter) iterator.next();
|
||||
|
||||
if(((delimiter == null) && (next.nextIndex >= position)) || ((delimiter != null) && (next.nextIndex >= 0) && ((delimiter.nextIndex > next.nextIndex) || ((delimiter.nextIndex == next.nextIndex) && (delimiter.delimiter.length() < next.delimiter.length()))))) {
|
||||
delimiter = next;
|
||||
}//if//
|
||||
}//while//
|
||||
|
||||
return delimiter;
|
||||
}//getNextDelimiter()//
|
||||
/**
|
||||
* Gets the string to parse.
|
||||
* @return The string to parse into segments.
|
||||
*/
|
||||
public String getString() {
|
||||
return string;
|
||||
}//getString()//
|
||||
/**
|
||||
* Determines whether there is a next segment.
|
||||
* @return Whether there is another string segment to be returned by the next() method.
|
||||
* @see #next()
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
if(nextSegment == null) {
|
||||
Delimiter delimiter = null;
|
||||
|
||||
nextPosition = currentPosition;
|
||||
delimiter = getNextDelimiter(nextPosition);
|
||||
|
||||
while((nextSegment == null) && (nextPosition <= lastPosition)) {
|
||||
if(delimiter == null) {
|
||||
nextSegment = string.substring(nextPosition);
|
||||
nextPosition = lastPosition + 1;
|
||||
isNextDelimiter = Boolean.FALSE;
|
||||
}//if//
|
||||
else if(delimiter.nextIndex == nextPosition) {
|
||||
nextPosition += delimiter.delimiter.length();
|
||||
|
||||
if(delimiter.returnDelimiter) {
|
||||
nextSegment = delimiter.delimiter;
|
||||
isNextDelimiter = Boolean.TRUE;
|
||||
}//if//
|
||||
else {
|
||||
delimiter = getNextDelimiter(nextPosition);
|
||||
}//else//
|
||||
}//else if//
|
||||
else {
|
||||
nextSegment = string.substring(nextPosition, delimiter.nextIndex);
|
||||
nextPosition = delimiter.nextIndex;
|
||||
isNextDelimiter = Boolean.FALSE;
|
||||
}//else//
|
||||
}//while//
|
||||
}//if//
|
||||
|
||||
return nextSegment != null;
|
||||
} //hasNext//
|
||||
/**
|
||||
* Determines whether the last element returned was a delimiter element.
|
||||
* @return Whether the last element was a delimiter element.
|
||||
*/
|
||||
public boolean isLastDelimiter() {
|
||||
return isLastDelimiter;
|
||||
}//isLastDelimiter()//
|
||||
/**
|
||||
* Determines whether the next element returned is going to be a delimiter element.
|
||||
* @return Whether the next element will be a delimiter element. This will always be false if all delimiters are not ever returned. This will also be false if hasNext returns false.
|
||||
*/
|
||||
public boolean isNextDelimiter() {
|
||||
if(isNextDelimiter == null) {
|
||||
if(!hasNext()) {
|
||||
return false;
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
return isNextDelimiter.booleanValue();
|
||||
}//isNextDelimiter()//
|
||||
/**
|
||||
* Gets the next string segment in the parse operation.
|
||||
* @return The next available string segment.
|
||||
*/
|
||||
public String next() {
|
||||
String retVal = null;
|
||||
|
||||
//Normally this should be non-null.//
|
||||
if(nextSegment == null) {
|
||||
//Check to see if there is a next segment.//
|
||||
if(!hasNext()) {
|
||||
throw new RuntimeException("Unable to access the next segment in the parsed string because there are no more available segements.");
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
//Save the next segment, and clear the variables for next time.//
|
||||
retVal = nextSegment;
|
||||
nextSegment = null;
|
||||
currentPosition = nextPosition;
|
||||
isLastDelimiter = isNextDelimiter.booleanValue();
|
||||
isNextDelimiter = null;
|
||||
|
||||
return retVal;
|
||||
}//next()//
|
||||
/**
|
||||
* Removes a delimiter string from the collection.
|
||||
* @param delimiter The delimiter string to remove from the collection of delimiters.
|
||||
*/
|
||||
public void removeDelimiter(String delimiter) {
|
||||
this.delimiters.remove(new Delimiter(delimiter));
|
||||
this.nextSegment = null;
|
||||
}//removeDelimiter()//
|
||||
/**
|
||||
* Removes delimiters from the collection.
|
||||
* @param delimiters The delimiter strings to remove from the collection of delimiters.
|
||||
*/
|
||||
public void removeDelimiters(IList delimiters) {
|
||||
IIterator iterator = delimiters.iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
this.delimiters.remove(new Delimiter((String) iterator.next()));
|
||||
}//while//
|
||||
|
||||
this.nextSegment = null;
|
||||
}//removeDelimiters()//
|
||||
/**
|
||||
* Resets the current position to the given position in the string.
|
||||
* @param index The position to move to.
|
||||
*/
|
||||
public void resetTo(int index) {
|
||||
if((index < firstPosition) || (index > lastPosition)) {
|
||||
throw new IndexOutOfBoundsException("The index " + index + " must be greater than or equal to " + firstPosition + " and less than or equal to " + lastPosition + ".");
|
||||
}//if//
|
||||
|
||||
this.currentPosition = index;
|
||||
this.nextSegment = null;
|
||||
}//resetTo()//
|
||||
/**
|
||||
* Resets the current position to the first position in the string.
|
||||
*/
|
||||
public void resetToFront() {
|
||||
this.currentPosition = firstPosition;
|
||||
this.nextSegment = null;
|
||||
}//resetToFront()//
|
||||
/**
|
||||
* Sets the delimiters used by the parser.
|
||||
* <p>WARNING: This is not a very efficient method because it must convert Delimiter object collections to String object collections. It should not be over used.
|
||||
* @param delimiters The delimiters used to parse the string.
|
||||
* @see #addDelimiter(String, boolean)
|
||||
* @see #removeDelimiter(String)
|
||||
*/
|
||||
public void setDelimiters(String[] delimiters, boolean returnDelimiters) {
|
||||
this.delimiters = new LiteList(delimiters.length);
|
||||
|
||||
for(int index = 0; index < delimiters.length; index++) {
|
||||
this.delimiters.add(new Delimiter(delimiters[index], returnDelimiters));
|
||||
}//for//
|
||||
|
||||
this.nextSegment = null;
|
||||
}//setDelimiters()//
|
||||
/**
|
||||
* Sets the delimiters used by the parser.
|
||||
* <p>WARNING: This is not a very efficient method because it must convert Delimiter object collections to String object collections. It should not be over used.
|
||||
* @param delimiters The delimiters used to parse the string.
|
||||
* @see #addDelimiter(String, boolean)
|
||||
* @see #removeDelimiter(String)
|
||||
*/
|
||||
public void setDelimiters(IList delimiters, boolean returnDelimiters) {
|
||||
IIterator iterator = delimiters.iterator();
|
||||
|
||||
this.delimiters = new LiteList(delimiters.getSize());
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
this.delimiters.add(new Delimiter((String) iterator.next(), returnDelimiters));
|
||||
}//while//
|
||||
|
||||
this.nextSegment = null;
|
||||
}//setDelimiters()//
|
||||
/**
|
||||
* Sets the string to parse.
|
||||
* @param string The string to parse into segments.
|
||||
*/
|
||||
public void setString(String string) {
|
||||
this.string = string;
|
||||
this.firstPosition = 0;
|
||||
this.lastPosition = string.length() - 1;
|
||||
this.currentPosition = 0;
|
||||
this.nextSegment = null;
|
||||
}//setString()//
|
||||
/**
|
||||
* Calculates the next occurance index of a set of delimiters.
|
||||
* @param delimiters A collection of delimiters to update.
|
||||
*/
|
||||
private void updateIndexes(IList delimiters, int position) {
|
||||
IIterator iterator = delimiters.iterator();
|
||||
boolean updateAll = position < lastUpdatePosition;
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
Delimiter delimiter = (Delimiter) iterator.next();
|
||||
|
||||
if((updateAll) || ((delimiter.nextIndex != -1) && (delimiter.nextIndex < position))) {
|
||||
delimiter.nextIndex = string.indexOf(delimiter.delimiter, position);
|
||||
}//if//
|
||||
}//while//
|
||||
}//updateIndexes()//
|
||||
}//TextParser//
|
||||
1419
Common/src/com/common/util/TreeMap.java
Normal file
1419
Common/src/com/common/util/TreeMap.java
Normal file
File diff suppressed because it is too large
Load Diff
327
Common/src/com/common/util/optimized/BooleanArray.java
Normal file
327
Common/src/com/common/util/optimized/BooleanArray.java
Normal file
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
/**
|
||||
* <p>WARNING: This is a Lite collection and does not have any synchronization (NOT THREAD SAFE).
|
||||
* <p>This class maintains a collection of boolean values using an interface similar to IList.
|
||||
*/
|
||||
public class BooleanArray implements IBooleanArray {
|
||||
private boolean[] array = null;
|
||||
private int count = 0;
|
||||
private int incrementSize = 0;
|
||||
|
||||
public static class Iterator implements IBooleanIterator {
|
||||
private BooleanArray array = null;
|
||||
private int index = 0;
|
||||
|
||||
public Iterator(BooleanArray array) {
|
||||
this.array = array;
|
||||
}//Iterator()//
|
||||
public boolean hasNext() {
|
||||
return index < array.getSize();
|
||||
}//hasNext()//
|
||||
public boolean next() {
|
||||
return array.get(index++);
|
||||
}//next()//
|
||||
public void resetToFront() {
|
||||
this.index = 0;
|
||||
}//resetToFront()//
|
||||
}//KeyIterator//
|
||||
/**
|
||||
* IntArray constructor.
|
||||
*/
|
||||
public BooleanArray() {
|
||||
this(10, 10);
|
||||
}//IntArray()//
|
||||
/**
|
||||
* IntArray constructor.
|
||||
*/
|
||||
public BooleanArray(int initialSize) {
|
||||
this(initialSize, 10);
|
||||
}//IntArray()//
|
||||
/**
|
||||
* IntArray constructor.
|
||||
*/
|
||||
public BooleanArray(int initialSize, int incrementSize) {
|
||||
super();
|
||||
|
||||
if(initialSize <= 0) {
|
||||
//TODO: Throw exception.//
|
||||
initialSize = 1;
|
||||
}//if//
|
||||
|
||||
this.array = new boolean[initialSize];
|
||||
this.incrementSize = incrementSize;
|
||||
}//IntArray()//
|
||||
/**
|
||||
* IntArray constructor.
|
||||
* @param copy The boolean array to clone.
|
||||
*/
|
||||
public BooleanArray(BooleanArray copy) {
|
||||
super();
|
||||
|
||||
this.array = new boolean[copy.count + copy.incrementSize];
|
||||
this.incrementSize = copy.incrementSize;
|
||||
System.arraycopy(copy.array, 0, this.array, 0, copy.count);
|
||||
this.count = copy.count;
|
||||
}//IntArray()//
|
||||
/**
|
||||
* Adds a value to the collection.
|
||||
* @param value The value to add to the collection.
|
||||
*/
|
||||
public void add(boolean value) {
|
||||
internalAdd(value);
|
||||
}//add()//
|
||||
/**
|
||||
* Adds a value to the collection at the given index.
|
||||
* @param value The value to add to the collection.
|
||||
* @param index The index of the new value.
|
||||
*/
|
||||
public void add(boolean value, int index) {
|
||||
internalAdd(value, index);
|
||||
}//add()//
|
||||
/**
|
||||
* Adds values to the collection.
|
||||
* @param values The array of values to add to the collection.
|
||||
*/
|
||||
public void addAll(boolean[] values) {
|
||||
for(int index = 0; index < values.length; index++) {
|
||||
internalAdd(values[index]);
|
||||
}//for//
|
||||
}//addAll()//
|
||||
/**
|
||||
* Adds values to the collection.
|
||||
* @param values The collection of values to add to the collection.
|
||||
*/
|
||||
public void addAll(BooleanArray values) {
|
||||
for(int index = 0; index < values.getSize(); index++) {
|
||||
internalAdd(values.get(index));
|
||||
}//for//
|
||||
}//addAll()//
|
||||
/**
|
||||
* Determines whether the value is contained in the collection.
|
||||
* @param value The value to look for.
|
||||
* @return Whether the given value is in the collection.
|
||||
*/
|
||||
public boolean containsValue(boolean value) {
|
||||
return getIndexOf(value) != -1;
|
||||
}//containsValue()//
|
||||
/**
|
||||
* Gets a value at a given index.
|
||||
* @param index The index of the value to retrieve.
|
||||
* @return The value at that index.
|
||||
*/
|
||||
public boolean get(int index) {
|
||||
if((index >= 0) && (index < count)) {
|
||||
return array[index];
|
||||
}//if//
|
||||
else {
|
||||
throw new IndexOutOfBoundsException(index + " not in [0.." + count + ").");
|
||||
}//else//
|
||||
}//get()//
|
||||
/**
|
||||
* Gets a value's index in the collection.
|
||||
* @param value The value whose index is to be retrieved.
|
||||
* @return The value's index.
|
||||
*/
|
||||
public int getIndexOf(boolean value) {
|
||||
int index = 0;
|
||||
|
||||
for(; index < count; index++) {
|
||||
if(array[index] == value) {
|
||||
break;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return index < count ? index : -1;
|
||||
}//getIndexOf()//
|
||||
/**
|
||||
* Gets the number of values in the collection.
|
||||
* @return The number of values stored in this collection.
|
||||
*/
|
||||
public int getSize() {
|
||||
return count;
|
||||
}//getSize()//
|
||||
/**
|
||||
* Adds a value to the collection.
|
||||
* @param value The value to add to the collection.
|
||||
*/
|
||||
protected void internalAdd(boolean value) {
|
||||
if(count == array.length) {
|
||||
resize();
|
||||
}//if//
|
||||
|
||||
array[count++] = value;
|
||||
}//internalAdd()//
|
||||
/**
|
||||
* Adds a value to the collection at the given index.
|
||||
* @param value The value to add to the collection.
|
||||
* @param index The index of the new value.
|
||||
*/
|
||||
protected void internalAdd(boolean value, int index) {
|
||||
if(count == array.length) {
|
||||
resize();
|
||||
}//if//
|
||||
|
||||
if(index == count) {
|
||||
array[count++] = value;
|
||||
}//if//
|
||||
else {
|
||||
System.arraycopy(array, index, array, index + 1, count - index);
|
||||
array[index] = value;
|
||||
count++;
|
||||
}//else//
|
||||
}//internalAdd()//
|
||||
/**
|
||||
* Removes a value from the collection by its' index.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @return The value at the removed index.
|
||||
*/
|
||||
protected boolean internalRemove(int index) {
|
||||
boolean retVal;
|
||||
|
||||
if((index >= count) && (index < 0)) {
|
||||
throw new IndexOutOfBoundsException(index + " not in [0.." + count + ").");
|
||||
}//if//
|
||||
|
||||
if(index != count - 1) {
|
||||
System.arraycopy(array, index + 1, array, index, array.length - index - 1);
|
||||
}//if//
|
||||
|
||||
retVal = array[index];
|
||||
array[--count] = false;
|
||||
|
||||
return retVal;
|
||||
}//internalRemove()//
|
||||
/**
|
||||
* Removes all collection values.
|
||||
* @return Whether all values were properly removed.
|
||||
*/
|
||||
protected boolean internalRemoveAll() {
|
||||
boolean retVal = true;
|
||||
|
||||
while(count != 0) {
|
||||
array[--count] = false;
|
||||
}//while//
|
||||
|
||||
return retVal;
|
||||
}//internalRemoveAll()//
|
||||
/**
|
||||
* Gets an iterator over the values in this collection.
|
||||
* @return An iterator over the collection values.
|
||||
*/
|
||||
public IBooleanIterator iterator() {
|
||||
return new Iterator(this);
|
||||
}//iterator()//
|
||||
/**
|
||||
* Removes a value from the collection by its' index.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @return The value at the removed index.
|
||||
*/
|
||||
public boolean remove(int index) {
|
||||
return internalRemove(index);
|
||||
}//remove()//
|
||||
/**
|
||||
* Removes all collection values.
|
||||
* @return Whether all values were properly removed.
|
||||
*/
|
||||
public boolean removeAll() {
|
||||
return internalRemoveAll();
|
||||
}//removeAll()//
|
||||
/**
|
||||
* Replaces a value in the collection at a specific index, with a new value.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @param value The new value at the given index.
|
||||
*/
|
||||
public void replace(int index, boolean value) {
|
||||
replaceInternal(index, value);
|
||||
}//replace()//
|
||||
/**
|
||||
* Replaces a value in the collection at a specific index, with a new value.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @param value The new value at the given index.
|
||||
*/
|
||||
protected void replaceInternal(int index, boolean value) {
|
||||
if((index >= count) && (index < 0)) {
|
||||
throw new IndexOutOfBoundsException(index + " not in [0.." + count + ").");
|
||||
}//if//
|
||||
|
||||
array[count] = value;
|
||||
}//replaceInternal()//
|
||||
/**
|
||||
* Resizes the collection by adding the increment size to the current size.
|
||||
*/
|
||||
protected void resize() {
|
||||
resize(array.length + incrementSize);
|
||||
}//resize()//
|
||||
/**
|
||||
* Resizes the collection to the requested size.
|
||||
* @param newSize The new size of the collection buffer.
|
||||
*/
|
||||
protected void resize(int newSize) {
|
||||
boolean[] temp = new boolean[newSize];
|
||||
|
||||
System.arraycopy(array, 0, temp, 0, array.length);
|
||||
array = temp;
|
||||
|
||||
if(array.length < count) {
|
||||
count = array.length;
|
||||
}//if//
|
||||
}//resize()//
|
||||
/**
|
||||
* Fills an array with collection values.
|
||||
* @return An exact sized array containing all values in the collection.
|
||||
*/
|
||||
public boolean[] toArray() {
|
||||
boolean[] retVal = new boolean[count];
|
||||
|
||||
System.arraycopy(this.array, 0, retVal, 0, count);
|
||||
|
||||
return retVal;
|
||||
}//toArray()//
|
||||
/**
|
||||
* Fills an array with collection values.
|
||||
* @param array An array capable of containing collection values.
|
||||
* @return The number of elements copied into the array.
|
||||
*/
|
||||
public int toArray(boolean[] array) {
|
||||
int size = array.length;
|
||||
|
||||
size = count > size ? count : size;
|
||||
System.arraycopy(this.array, 0, array, 0, size);
|
||||
|
||||
return size;
|
||||
}//toArray()//
|
||||
/**
|
||||
* Outputs the collection of items for debugging purposes.
|
||||
* @return A string displaying the list of items.
|
||||
*/
|
||||
public String toString() {
|
||||
int max = getSize() - 1;
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
//Add a begin brace.//
|
||||
buffer.append("[");
|
||||
|
||||
for(int index = 0; index <= max; index++) {
|
||||
//Append the item to the output string.//
|
||||
buffer.append(get(index));
|
||||
|
||||
//Append a comma if this isn't the last item in the list.//
|
||||
if(index < max) {
|
||||
buffer.append(", ");
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Add a end brace.//
|
||||
buffer.append("]");
|
||||
|
||||
return buffer.toString();
|
||||
}//toString()//
|
||||
}//IntArray()//
|
||||
517
Common/src/com/common/util/optimized/CharHashSet.java
Normal file
517
Common/src/com/common/util/optimized/CharHashSet.java
Normal file
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.debug.*;
|
||||
|
||||
/**
|
||||
* <p>TODO: Make this class serializeable by implementing the read and writeExternal methods.
|
||||
*/
|
||||
public class CharHashSet extends CharLiteCollection {
|
||||
public static final char NULL_VALUE = 0;
|
||||
public static final int DEFAULT_INITIAL_CAPACITY = 51;
|
||||
public static final float DEFAULT_LOAD_FACTOR = 0.75f;
|
||||
public static final CharHashSet EMPTY_SET = new CharHashSet(1);
|
||||
|
||||
/** Duplicate values added to the collection will be rejected completely. It will not be possible to have the same (or equal) value more than once. */
|
||||
public static final int STYLE_NO_DUPLICATES = 0;
|
||||
/** Duplicate values added to the collection will be counted more than once but only internally (ie: the iterator will return the value only once, but remove must be called the same number of times as the add to remove the value). */
|
||||
public static final int STYLE_COUNT_DUPLICATES = 1;
|
||||
/** Duplicate values added to the collection will be counted more than once both internally and externally (ie: the iterator will return the value more than once). */
|
||||
public static final int STYLE_ADD_DUPLICATES = 2;
|
||||
/** The default style settings. */
|
||||
public static final int DEFAULT_STYLE = STYLE_NO_DUPLICATES;
|
||||
|
||||
/** The array of hash entries. */
|
||||
private HashSetEntry[] entries;
|
||||
/** The number of hash entries in the set. Note that this only counts duplicates if using STYLE_ADD_DUPLICATES. */
|
||||
private int size;
|
||||
/** ? */
|
||||
private int threshold;
|
||||
/** The ratio of size to the entries array size (size / entries.length). If this ratio is smaller than the actual ratio then the entries array will be resized. */
|
||||
private float loadFactor;
|
||||
/** Whether multiple references to the same object instance can be stored in this collection. This is normally set to reject duplicates. */
|
||||
private int style = DEFAULT_STYLE;
|
||||
|
||||
/**
|
||||
* The entry class used to store HashSet values.
|
||||
*/
|
||||
protected static class HashSetEntry {
|
||||
public char value;
|
||||
public HashSetEntry next;
|
||||
public int count;
|
||||
|
||||
protected HashSetEntry() {
|
||||
}//HashSetEntry()//
|
||||
}//HashSetEntry//
|
||||
|
||||
/**
|
||||
* An iterator that can be used to iterate over the HashSet values.
|
||||
* <p>WARNING: While this class can be serialized, it will reset its' position to the start of the HashSet.
|
||||
* Also, the HashSet will be serialized with the iterator.
|
||||
* <p>This class is NOT thread safe.
|
||||
*/
|
||||
public static class CharHashSetIterator implements ICharIterator {
|
||||
private CharHashSet hashSet = null;
|
||||
protected int currentIndex = -1;
|
||||
protected HashSetEntry currentEntry = null;
|
||||
protected int nextIndex = -1;
|
||||
protected HashSetEntry nextEntry = null;
|
||||
protected boolean hasNextEntry = false;
|
||||
|
||||
protected CharHashSetIterator(CharHashSet hashSet) {
|
||||
this.hashSet = hashSet;
|
||||
}//CharHashSetIterator()//
|
||||
public void resetToFront() {
|
||||
currentIndex = -1;
|
||||
currentEntry = null;
|
||||
nextIndex = -1;
|
||||
nextEntry = null;
|
||||
hasNextEntry = false;
|
||||
}//resetToFront()//
|
||||
public boolean remove() {
|
||||
boolean result = false;
|
||||
|
||||
if(currentEntry != null) {
|
||||
result = hashSet.remove(currentEntry.value);
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//remove()//
|
||||
public char next() {
|
||||
loadNextEntry();
|
||||
currentEntry = nextEntry;
|
||||
currentIndex = nextIndex;
|
||||
hasNextEntry = false;
|
||||
nextEntry = null;
|
||||
|
||||
return currentEntry.value;
|
||||
}//next()//
|
||||
public boolean hasNext() {
|
||||
loadNextEntry();
|
||||
|
||||
return nextEntry != null;
|
||||
}//hasNext()//
|
||||
/**
|
||||
* Preloads the next entry. This makes querying to see if the next entry exists and then getting the next entry much easier.
|
||||
*/
|
||||
protected void loadNextEntry() {
|
||||
if(!hasNextEntry) {
|
||||
nextEntry = null;
|
||||
nextIndex = currentIndex;
|
||||
|
||||
if((currentEntry != null) && (currentEntry.next != null)) {
|
||||
nextEntry = currentEntry.next;
|
||||
}//if//
|
||||
else {
|
||||
HashSetEntry[] entries = hashSet.entries;
|
||||
|
||||
while((nextEntry == null) && (entries.length > ++nextIndex)) {
|
||||
if(entries[nextIndex] != null) {
|
||||
nextEntry = entries[nextIndex];
|
||||
}//if//
|
||||
}//while//
|
||||
}//else//
|
||||
|
||||
if(nextEntry != null) {
|
||||
hasNextEntry = true;
|
||||
}//if//
|
||||
}//if//
|
||||
}//loadNextEntry()//
|
||||
/**
|
||||
* Allows the iterator to peek at the next value after calling loadNextEntry.
|
||||
* <p>This is for use only by subclasses an is not intended for public consumption. The value is only valid after calling loadNextEntry().</p>
|
||||
* @return The value that will be returned by the next call to next().
|
||||
* @see #next()
|
||||
* @see #loadNextEntry()
|
||||
*/
|
||||
protected char peekNext() {
|
||||
return nextEntry.value;
|
||||
}//peekNext()//
|
||||
/**
|
||||
* Allows the iterator to peek at whether there is a next value after calling loadNextEntry.
|
||||
* <p>This is for use only by subclasses an is not intended for public consumption. The value is only valid after calling loadNextEntry().</p>
|
||||
* @return Whether there is a next value, otherwise the iterator is finished.
|
||||
* @see #hasNext()
|
||||
* @see #loadNextEntry()
|
||||
*/
|
||||
protected boolean peekHasNext() {
|
||||
return nextEntry != null;
|
||||
}//peekHasNext()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
out.writeObject(hashSet);
|
||||
}//writeExternal()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
hashSet = (CharHashSet) in.readObject();
|
||||
resetToFront();
|
||||
}//readExternal()//
|
||||
}//HashSetIterator//
|
||||
/**
|
||||
* CharHashSet constructor.
|
||||
*/
|
||||
public CharHashSet() {
|
||||
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_STYLE);
|
||||
}//CharHashSet()//
|
||||
/**
|
||||
* CharHashSet copy constructor.
|
||||
* @param original The hash set to be copied.
|
||||
*/
|
||||
public CharHashSet(CharHashSet original) {
|
||||
this(original.getEntries().length, original.getLoadFactor(), original.getStyle());
|
||||
HashSetEntry[] entries = original.getEntries();
|
||||
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
for(HashSetEntry entry = entries[index]; entry != null; entry = entry.next) {
|
||||
for(int count = 0; count < entry.count; count++) {
|
||||
add(entry.value);
|
||||
}//for//
|
||||
}//for//
|
||||
}//for//
|
||||
}//CharHashSet()//
|
||||
/**
|
||||
* CharHashSet constructor.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
*/
|
||||
public CharHashSet(int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_STYLE);
|
||||
}//CharHashSet()//
|
||||
/**
|
||||
* CharHashSet constructor.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
* @throws IllegalArgumentException If the initial capacity or load factor are not within their valid ranges.
|
||||
*/
|
||||
public CharHashSet(int initialCapacity, float loadFactor, int style) {
|
||||
super();
|
||||
|
||||
this.style = style;
|
||||
|
||||
if(loadFactor <= 0.0) {
|
||||
throw new IllegalArgumentException("Invalid load factor supplied to the HashSet.");
|
||||
}//if//
|
||||
|
||||
if(initialCapacity <= 0) {
|
||||
initialCapacity = 10;
|
||||
}//if//
|
||||
|
||||
this.loadFactor = loadFactor;
|
||||
this.entries = new HashSetEntry[initialCapacity];
|
||||
this.threshold = (int)(initialCapacity * loadFactor);
|
||||
}//CharHashSet()//
|
||||
/**
|
||||
* CharHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
*/
|
||||
public CharHashSet(char[] values) {
|
||||
this(values.length, DEFAULT_LOAD_FACTOR, DEFAULT_STYLE);
|
||||
addAll(values);
|
||||
}//CharHashSet()//
|
||||
/**
|
||||
* CharHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public CharHashSet(char[] values, int style) {
|
||||
this(values.length, DEFAULT_LOAD_FACTOR, style);
|
||||
addAll(values);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* CharHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public CharHashSet(char[] values, int initialCapacity, float loadFactor, int style) {
|
||||
this(initialCapacity, loadFactor, style);
|
||||
addAll(values);
|
||||
}//CharHashSet()//
|
||||
/**
|
||||
* CharHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
*/
|
||||
public CharHashSet(ICharCollection values) {
|
||||
this(values.getSize(), DEFAULT_LOAD_FACTOR, DEFAULT_STYLE);
|
||||
addAll(values);
|
||||
}//CharHashSet()//
|
||||
/**
|
||||
* CharHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public CharHashSet(ICharCollection values, int style) {
|
||||
this(values.getSize(), DEFAULT_LOAD_FACTOR, style);
|
||||
addAll(values);
|
||||
}//LiteHashSet()//
|
||||
/**
|
||||
* CharHashSet constructor.
|
||||
* @param values The initial set of values in the set.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
* @param allowMultipleInstanceReferences Whether multiple references to the same object instance can be stored in this collection. This is normally false.
|
||||
*/
|
||||
public CharHashSet(ICharCollection values, int initialCapacity, float loadFactor, int style) {
|
||||
this(Math.max(initialCapacity, values.getSize()), loadFactor, style);
|
||||
addAll(values);
|
||||
}//CharHashSet()//
|
||||
/**
|
||||
* Tests to see if the specified value is contained in the collection.
|
||||
* @param value The value to test for.
|
||||
* @return Will be true if the value is contained in the collection.
|
||||
*/
|
||||
public boolean containsValue(char value) {
|
||||
int hash = (int) value;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(HashSetEntry e = entries[index]; e != null; e = e.next) {
|
||||
if(e.value == value) {
|
||||
return true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return false;
|
||||
}//containsValue()//
|
||||
/**
|
||||
* Gets the number of times the value has been added to the set.
|
||||
* @param value The value to look for.
|
||||
* @return The number of times the value exists in the set. Note that the comparator will be used to compare the value with other values and it determines which objects are considered equivalent.
|
||||
*/
|
||||
public int getCount(char value) {
|
||||
int hash = (int) value;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(HashSetEntry e = entries[index]; e != null; e = e.next) {
|
||||
if(e.value == value) {
|
||||
return e.count;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return 0;
|
||||
}//getCount()//
|
||||
/**
|
||||
* Gets the hash set entries array.
|
||||
* @return The array referencing the indexed hash set entries.
|
||||
*/
|
||||
protected HashSetEntry[] getEntries() {
|
||||
return entries;
|
||||
}//getEntries()//
|
||||
/**
|
||||
* Gets the style used for the hash set.
|
||||
* @return The style which indicates how duplicate entries are handled.
|
||||
*/
|
||||
public int getStyle() {
|
||||
return style;
|
||||
}//getStyle()//
|
||||
/**
|
||||
* Creates or reuses an entry.
|
||||
*/
|
||||
protected HashSetEntry createEntry() {
|
||||
return new HashSetEntry();
|
||||
}//createEntry()//
|
||||
/**
|
||||
* Creates or reuses an entry.
|
||||
*/
|
||||
protected void destroyEntry(HashSetEntry entry) {
|
||||
entry.next = null;
|
||||
}//destroyEntry()//
|
||||
/**
|
||||
* Gets the number of values in the set.
|
||||
* @return The set's size.
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}//getSize()//
|
||||
/**
|
||||
* Sets the number of values in the set.
|
||||
* @param size The set's size.
|
||||
*/
|
||||
protected void setSize(int size) {
|
||||
this.size = size;
|
||||
}//setSize()//
|
||||
/**
|
||||
* Gets the next set size at which the set must be resized.
|
||||
* @return The next resize point.
|
||||
*/
|
||||
protected int getThreshold() {
|
||||
return threshold;
|
||||
}//getThreshold()//
|
||||
/**
|
||||
* Gets the ratio of collection size divided by array size.
|
||||
* @return The ratio indicating how loaded the set can get before it requires resizing.
|
||||
*/
|
||||
protected float getLoadFactor() {
|
||||
return loadFactor;
|
||||
}//getLoadFactor()//
|
||||
/**
|
||||
* Performs an actual add of the value to the set.
|
||||
* @param value The value to be added to this set.
|
||||
* @return Whether the add was successful.
|
||||
*/
|
||||
protected boolean internalAdd(char value) {
|
||||
int hash = (int) value;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
HashSetEntry entry = null;
|
||||
|
||||
if(style != STYLE_ADD_DUPLICATES) {
|
||||
for(entry = entries[index]; entry != null; entry = entry.next) {
|
||||
if(entry.value == value) {
|
||||
if(style == STYLE_NO_DUPLICATES) {
|
||||
return false;
|
||||
}//if//
|
||||
else {
|
||||
entry.count++;
|
||||
return true;
|
||||
}//else//
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
|
||||
if(size >= threshold) {
|
||||
rehash();
|
||||
|
||||
return internalAdd(value);
|
||||
}//if//
|
||||
|
||||
entry = createEntry();
|
||||
entry.value = value;
|
||||
entry.next = entries[index];
|
||||
entry.count = 1;
|
||||
entries[index] = entry;
|
||||
size++;
|
||||
|
||||
return true;
|
||||
}//internalAdd()//
|
||||
/**
|
||||
* Handles removing a value from the collection.
|
||||
* @param value The value to remove.
|
||||
* @return Will be <code>true</code> upon success.
|
||||
*/
|
||||
protected boolean internalRemove(char value) {
|
||||
int hash = (int) value;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
HashSetEntry entry = null;
|
||||
HashSetEntry previous = null;
|
||||
|
||||
for(entry = entries[index], previous = null; entry != null; previous = entry, entry = entry.next) {
|
||||
if(entry.value == value) {
|
||||
entry.count--;
|
||||
|
||||
if(entry.count == 0) {
|
||||
if(previous != null) {
|
||||
previous.next = entry.next;
|
||||
}//if//
|
||||
else {
|
||||
entries[index] = entry.next;
|
||||
}//else//
|
||||
|
||||
size--;
|
||||
destroyEntry(entry);
|
||||
}//if//
|
||||
|
||||
return true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return false;
|
||||
}//internalRemove()//
|
||||
/**
|
||||
* Handles removing all values from the collection.
|
||||
* @return Will be <code>true</code> upon success.
|
||||
*/
|
||||
protected void internalRemoveAll() {
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
entries[index] = null;
|
||||
}//for//
|
||||
|
||||
size = 0;
|
||||
}//internalRemoveAll()//
|
||||
/**
|
||||
* Gets a new iterator over the values in this collection.
|
||||
* @return IIterator The iterator that may be used to iterate over the collection values.
|
||||
*/
|
||||
public ICharIterator iterator() {
|
||||
return new CharHashSetIterator(this);
|
||||
}//iterator()//
|
||||
/**
|
||||
* Will rehash the collection so that new items may be added without going over the recommended ratio of values to list entries.
|
||||
*/
|
||||
protected void rehash() {
|
||||
int oldCapacity = entries.length;
|
||||
HashSetEntry[] oldEntries = entries;
|
||||
int newCapacity = (oldCapacity << 1) + 1;
|
||||
HashSetEntry[] newEntries = new HashSetEntry[newCapacity];
|
||||
|
||||
threshold = (int)(newCapacity * loadFactor);
|
||||
entries = newEntries;
|
||||
|
||||
for(int oldIndex = oldCapacity; oldIndex-- > 0; ) {
|
||||
for(HashSetEntry oldEntry = oldEntries[oldIndex]; oldEntry != null; ) {
|
||||
HashSetEntry newEntry = oldEntry;
|
||||
int newIndex;
|
||||
|
||||
oldEntry = oldEntry.next;
|
||||
newIndex = (((int) newEntry.value) & 0x7FFFFFFF) % newCapacity;
|
||||
newEntry.next = newEntries[newIndex];
|
||||
newEntries[newIndex] = newEntry;
|
||||
}//for//
|
||||
}//for//
|
||||
}//rehash()//
|
||||
/**
|
||||
* Fills an array with collection values.
|
||||
* @param array An array capable of containing collection values.
|
||||
* @return The number of values placed in the array.
|
||||
*/
|
||||
public int toArray(Object array) {
|
||||
HashSetEntry entry = null;
|
||||
int position = 0;
|
||||
HashSetEntry[] entries = this.entries;
|
||||
|
||||
//Iterate over the entry table.//
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
entry = entries[index];
|
||||
|
||||
//Iterate through the entries at this table position.//
|
||||
while(entry != null) {
|
||||
java.lang.reflect.Array.setChar(array, position, entry.value);
|
||||
entry = entry.next;
|
||||
position++;
|
||||
}//while//
|
||||
}//for//
|
||||
|
||||
return position;
|
||||
}//toArray()//
|
||||
/**
|
||||
* Generates a string representing the hashset.
|
||||
* @return A debug string that represents this object.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer(100);
|
||||
|
||||
buffer.append("LiteHashSet {\r\n");
|
||||
|
||||
try {
|
||||
ICharIterator iterator = iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
char next = iterator.next();
|
||||
|
||||
buffer.append("\t");
|
||||
buffer.append(next);
|
||||
buffer.append("\r\n");
|
||||
}//while//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
|
||||
buffer.append("}");
|
||||
|
||||
return buffer.toString();
|
||||
}//toArray()//
|
||||
}//HashSet//
|
||||
283
Common/src/com/common/util/optimized/CharLiteCollection.java
Normal file
283
Common/src/com/common/util/optimized/CharLiteCollection.java
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import java.util.Arrays;
|
||||
import com.common.exception.*;
|
||||
import com.common.util.ICollection;
|
||||
|
||||
/**
|
||||
* The LiteCollection base class provides collection functionality without any event handling or synchronization.
|
||||
* If you need event handling or synchronization you should use a collection class that extends Collection.
|
||||
*/
|
||||
public abstract class CharLiteCollection implements ICharCollection {
|
||||
private boolean isChangeable = true;
|
||||
/**
|
||||
* LiteCollection constructor.
|
||||
*/
|
||||
protected CharLiteCollection() {
|
||||
super();
|
||||
}//LiteCollection()//
|
||||
/**
|
||||
* LiteCollection constructor.
|
||||
* @param isChangeable Whether the collection may be changed. This should be false if the collection may no longer be modified.
|
||||
*/
|
||||
protected CharLiteCollection(boolean isChangeable) {
|
||||
super();
|
||||
|
||||
this.isChangeable = isChangeable;
|
||||
}//LiteCollection()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ICharCollection#add(char)
|
||||
*/
|
||||
public boolean add(char value) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
return internalAdd(value);
|
||||
}//add()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ICharCollection#addAll(char[])
|
||||
*/
|
||||
public boolean addAll(char[] values) {
|
||||
boolean result = true;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Make sure that the collection has values.//
|
||||
if((values != null) && (values.length > 0)) {
|
||||
//Iterate over the items to be added and add them one at a time.//
|
||||
for(int index = 0; index < values.length; index++) {
|
||||
char next = values[index];
|
||||
|
||||
if(!internalAdd(next)) {
|
||||
result = false;
|
||||
}//if//
|
||||
}//while//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//addAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ICharCollection#addAll(com.common.util.optimized.ICharCollection)
|
||||
*/
|
||||
public boolean addAll(ICharCollection values) {
|
||||
boolean result = true;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Make sure that the collection has values.//
|
||||
if((values != null) && (values.getSize() > 0)) {
|
||||
ICharIterator iterator = values.iterator();
|
||||
|
||||
//Iterate over the items to be added and add them one at a time.//
|
||||
while(iterator.hasNext()) {
|
||||
char next = iterator.next();
|
||||
|
||||
if(!internalAdd(next)) {
|
||||
result = false;
|
||||
}//if//
|
||||
}//while//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//addAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ICharCollection#containsValue(char)
|
||||
*/
|
||||
public abstract boolean containsValue(char value);
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ICharCollection#getSize()
|
||||
*/
|
||||
public abstract int getSize();
|
||||
/**
|
||||
* Will add a value to the collection.
|
||||
* @param value The value to add.
|
||||
* @return Will return true if the operation was successful.
|
||||
*/
|
||||
protected abstract boolean internalAdd(char value);
|
||||
/**
|
||||
* Will remove a value from the collection.
|
||||
* @param value The value to remove.
|
||||
* @return Will return true if the operation was successful.
|
||||
*/
|
||||
protected abstract boolean internalRemove(char value);
|
||||
/**
|
||||
* Will remove all of the values in the collection.
|
||||
* @return Will return true if the operation was successful.
|
||||
*/
|
||||
protected abstract void internalRemoveAll();
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ICharCollection#isChangeable()
|
||||
*/
|
||||
public boolean isChangeable() {
|
||||
return isChangeable;
|
||||
}//isChangeable()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ICharCollection#isChangeable(boolean)
|
||||
*/
|
||||
public void isChangeable(boolean isChangeable) {
|
||||
if(!isChangeable) {
|
||||
this.isChangeable = isChangeable;
|
||||
}//if//
|
||||
else if(this.isChangeable == isChangeable) {
|
||||
//Do nothing as nothing has changed.//
|
||||
}//else if//
|
||||
else {
|
||||
throw new RuntimeException("You may not change the collection to be changeable after it has been locked.");
|
||||
}//else//
|
||||
}//isChangeable()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ICharCollection#iterator()
|
||||
*/
|
||||
public abstract ICharIterator iterator();
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ICharCollection#remove(char)
|
||||
*/
|
||||
public boolean remove(char value) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
return internalRemove(value);
|
||||
}//remove()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ICharCollection#removeAll()
|
||||
*/
|
||||
public void removeAll() {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
internalRemoveAll();
|
||||
}//removeAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ICharCollection#removeAll(char[])
|
||||
*/
|
||||
public boolean removeAll(char[] values) {
|
||||
boolean result = true;
|
||||
|
||||
//Verify that this collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Make sure that there are values to remove.//
|
||||
if((values != null) && (values.length > 0)) {
|
||||
//Remove the values one at a time.//
|
||||
for(int index = 0; index < values.length; index++) {
|
||||
char next = values[index];
|
||||
|
||||
if(!internalRemove(next)) {
|
||||
result = false;
|
||||
}//if//
|
||||
}//while//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//removeAll()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ICharCollection#removeAll(com.common.util.optimized.ICharCollection)
|
||||
*/
|
||||
public boolean removeAll(ICharCollection values) {
|
||||
boolean result = true;
|
||||
|
||||
//Verify that this collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Make sure that there are values to remove.//
|
||||
if((values != null) && (values.getSize() > 0)) {
|
||||
ICharIterator iterator = values.iterator();
|
||||
|
||||
//Remove the values one at a time.//
|
||||
while(iterator.hasNext()) {
|
||||
char next = iterator.next();
|
||||
|
||||
if(!internalRemove(next)) {
|
||||
result = false;
|
||||
}//if//
|
||||
}//while//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//removeAll()//
|
||||
/**
|
||||
* Converts the list to an character array.
|
||||
* @return An array of the values in the collection.
|
||||
*/
|
||||
public char[] toArray() {
|
||||
char[] result = new char[getSize()];
|
||||
|
||||
toArray(result);
|
||||
|
||||
return result;
|
||||
}//toArray()//
|
||||
/* (Non-Javadoc)
|
||||
* @see ICollection.toArray(Object)
|
||||
*/
|
||||
public abstract int toArray(Object array);
|
||||
/**
|
||||
* Verifies that the collection may be modified.
|
||||
* @throws IllegalOperationException If the isImmutable flag is set.
|
||||
*/
|
||||
protected void verifyIsChangeable() {
|
||||
if(!isChangeable) {
|
||||
throw new IllegalOperationException("The collection is immutable which prevents the collection from being modified.");
|
||||
}//if//
|
||||
}//verifyIsChangeable()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
|
||||
*/
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
}//readExternal()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
|
||||
*/
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
}//writeExternal()//
|
||||
/**
|
||||
* Calculates the diffences between the old array and new array.
|
||||
* @param oldArray The old array.
|
||||
* @param newArray The new array.
|
||||
* @param added The optional set of items that are new in the new array (that don't exist in the old array).
|
||||
* @param removed The optional set of items that are old in the old array (that don't exist in the new array).
|
||||
* @param unchanged The optional set of items that have not changed and are in both arrays.
|
||||
*/
|
||||
public static void calculateDifferences(char[] oldArray, char[] newArray, ICollection added, ICollection removed, ICollection unchanged) {
|
||||
boolean[] newMatched = new boolean[newArray.length];
|
||||
|
||||
Arrays.fill(newMatched, false);
|
||||
|
||||
//For each old item, see if it exists in the new items and add to the appropriate collections. Mark matched items so we can easily see which items are new.//
|
||||
for(int oldIndex = 0; oldIndex < oldArray.length; oldIndex++) {
|
||||
boolean found = false;
|
||||
|
||||
//Search for a match in the new collection.//
|
||||
for(int newIndex = 0; (!found) && (newIndex < newArray.length); newIndex++) {
|
||||
if((!newMatched[newIndex]) && (oldArray[oldIndex] == newArray[newIndex])) {
|
||||
found = true;
|
||||
newMatched[newIndex] = true;
|
||||
|
||||
if(unchanged != null) {
|
||||
unchanged.add(Character.valueOf(oldArray[oldIndex]));
|
||||
}//if//
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
if((!found) && (removed != null)) {
|
||||
removed.add(Character.valueOf(oldArray[oldIndex]));
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//If we need to collect added items then iterate over the new items and add those that are not marked as matched.//
|
||||
if(added != null) {
|
||||
for(int newIndex = 0; newIndex < newArray.length; newIndex++) {
|
||||
if(!newMatched[newIndex]) {
|
||||
added.add(Character.valueOf(newArray[newIndex]));
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
}//calculateDifferences()//
|
||||
}//LiteCollection//
|
||||
353
Common/src/com/common/util/optimized/DualKeyHashMap.java
Normal file
353
Common/src/com/common/util/optimized/DualKeyHashMap.java
Normal file
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.comparison.*;
|
||||
import com.common.util.IIterator;
|
||||
import com.common.util.IReversableIterator;
|
||||
import com.common.util.Map;
|
||||
|
||||
/**
|
||||
* A map collection that maps values by a key so that they may be looked up by that key.
|
||||
* <p><b>Warning:</b> This class is NOT thread safe. To use it in a multi threaded environment all access to the map should by in a synchronization block.
|
||||
*/
|
||||
public class DualKeyHashMap extends Map {
|
||||
/**
|
||||
* The Entry wrappers the key/value pair.
|
||||
*/
|
||||
protected static class Entry extends BasicEntry {
|
||||
protected Object key1 = null;
|
||||
protected Object key2 = null;
|
||||
protected Object value = null;
|
||||
|
||||
public Entry() {
|
||||
super();
|
||||
}//Entry()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
super.readExternal(in);
|
||||
key1 = in.readObject();
|
||||
key2 = in.readObject();
|
||||
value = in.readObject();
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key1 == null) {
|
||||
key2 = NULL_KEY;
|
||||
}//if//
|
||||
}//readExternal()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
super.writeExternal(out);
|
||||
out.writeObject(key1 == NULL_KEY ? null : key1);
|
||||
out.writeObject(key2 == NULL_KEY ? null : key2);
|
||||
out.writeObject(value);
|
||||
}//writeExternal()//
|
||||
public int createKeyHash() {
|
||||
return key1.hashCode() ^ key2.hashCode();
|
||||
}//createKeyHash()//
|
||||
public String toString() {
|
||||
return super.toString() + "\r\n\tKey 1: " + (key1 == NULL_KEY ? "null" : key1.toString()) + "\r\n\tKey 2: " + (key2 == NULL_KEY ? "null" : key2.toString()) + "\r\n\tValue: " + value + (next != null ? "\r\n\t" + next.toString() : "");
|
||||
}//toString()//
|
||||
}//Entry//
|
||||
|
||||
public static class KeyIterator extends Iterator implements IReversableIterator {
|
||||
private Object secondKey = null;
|
||||
|
||||
public KeyIterator(DualKeyHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//KeyIterator()//
|
||||
public Object next() {
|
||||
Entry entry = (Entry) nextEntry();
|
||||
Object result = entry.key1;
|
||||
|
||||
if(result == NULL_KEY) {
|
||||
result = null;
|
||||
}//if//
|
||||
|
||||
secondKey = entry.key2;
|
||||
|
||||
if(secondKey == NULL_KEY) {
|
||||
secondKey = null;
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//next()//
|
||||
/**
|
||||
* Gets the second key for the last next() or previous() call.
|
||||
* @return The second key.
|
||||
*/
|
||||
public Object getSecondKey() {
|
||||
return secondKey;
|
||||
}//getSecondKey()//
|
||||
public Object previous() {
|
||||
Entry entry = (Entry) previousEntry();
|
||||
Object result = entry.key1;
|
||||
|
||||
if(result == NULL_KEY) {
|
||||
result = null;
|
||||
}//if//
|
||||
|
||||
secondKey = entry.key2;
|
||||
|
||||
if(secondKey == NULL_KEY) {
|
||||
secondKey = null;
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//previous()//
|
||||
}//KeyIterator//
|
||||
|
||||
public static class ValueIterator extends Iterator implements IIterator {
|
||||
public ValueIterator(DualKeyHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//ValueIterator()//
|
||||
public Object next() {
|
||||
return ((Entry) nextEntry()).value;
|
||||
}//next()//
|
||||
public Object previous() {
|
||||
return ((Entry) previousEntry()).value;
|
||||
}//previous()//
|
||||
}//ValueIterator//
|
||||
/**
|
||||
* DualKeyHashMap constructor.
|
||||
* <p>This constructor is private because is not advisable to use the default initial size because it will not be optimal for most applications.
|
||||
*/
|
||||
public DualKeyHashMap() {
|
||||
super();
|
||||
}//DualKeyHashMap()//
|
||||
/**
|
||||
* DualKeyHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public DualKeyHashMap(int initialCapacity) {
|
||||
super(initialCapacity);
|
||||
}//DualKeyHashMap()//
|
||||
/**
|
||||
* DualKeyHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public DualKeyHashMap(int initialCapacity, float loadFactor) {
|
||||
super(initialCapacity, loadFactor);
|
||||
}//DualKeyHashMap()//
|
||||
/**
|
||||
* DualKeyHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public DualKeyHashMap(int initialCapacity, float loadFactor, IComparator keyComparator, IComparator valueComparator) {
|
||||
super(initialCapacity, loadFactor, keyComparator, valueComparator);
|
||||
}//DualKeyHashMap()//
|
||||
/**
|
||||
* DualKeyHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public DualKeyHashMap(int initialCapacity, IComparator keyComparator, IComparator valueComparator) {
|
||||
super(initialCapacity, keyComparator, valueComparator);
|
||||
}//DualKeyHashMap()//
|
||||
/**
|
||||
* DualKeyHashMap constructor.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public DualKeyHashMap(IComparator keyComparator, IComparator valueComparator) {
|
||||
super(keyComparator, valueComparator);
|
||||
}//DualKeyHashMap()//
|
||||
/**
|
||||
* DualKeyHashMap constructor.
|
||||
* This constructor will copy an existing IHashMap.
|
||||
* @param map A map to copy.
|
||||
*/
|
||||
public DualKeyHashMap(DualKeyHashMap map) {
|
||||
super(map.getSize() > 10 ? map.getSize() : 10, map.getLoadFactor(), map.getKeyComparator(), map.getValueComparator());
|
||||
KeyIterator iterator = (KeyIterator) map.keyIterator();
|
||||
|
||||
//Iterate over the existing map's keys and put the key value pairs in this map.//
|
||||
while(iterator.hasNext()) {
|
||||
Object key1 = iterator.next();
|
||||
Object key2 = iterator.getSecondKey();
|
||||
Object value = map.get(key1, key2);
|
||||
|
||||
put(key1, key2, value);
|
||||
}//while//
|
||||
}//DualKeyHashMap()//
|
||||
/**
|
||||
* Determines whether the key exists in the map.
|
||||
* @param key The key to look for.
|
||||
* @return Will be <code>true</code> if the key is already in the map.
|
||||
*/
|
||||
public boolean containsKey(Object key1, Object key2) {
|
||||
return get(key1, key2) != null;
|
||||
}//containsKey()//
|
||||
/**
|
||||
* Creates an entry object of the specific type used by this map.
|
||||
* @return An entry object that can be filled and passed to the addEntry method.
|
||||
*/
|
||||
protected IBasicEntry createEntry() {
|
||||
return new Entry();
|
||||
}//createEntry()//
|
||||
/**
|
||||
* Gets an object in the map by its' key.
|
||||
* @param key1 The primary key whose value should be retieved.
|
||||
* @param key2 The secondary key whose value should be retieved.
|
||||
* @return The value associated with the key. A <code>null</code> value will be returned only if the key was not found.
|
||||
*/
|
||||
public Object get(Object key1, Object key2) {
|
||||
//Ensure that null keys are valid.//
|
||||
if(key1 == null) {
|
||||
key1 = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
if(key2 == null) {
|
||||
key2 = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key1) ^ getKeyComparator().hash(key2);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(Entry entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key1, key1))) && (Comparator.isEqual(getKeyComparator().compare(entry.key2, key2)))) {
|
||||
return entry.value;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return null;
|
||||
}//get()//
|
||||
/**
|
||||
* Gets an iterator over the keys contained in this collection.
|
||||
* @return An iterator over the map keys.
|
||||
*/
|
||||
public IIterator keyIterator() {
|
||||
return new KeyIterator(this);
|
||||
}//keyIterator()//
|
||||
/**
|
||||
* Places a key/value pair in the map.
|
||||
* The value can be retrieved later with the given key.
|
||||
* @param key1 The primary key that will be used to map the value.
|
||||
* @param key2 The secondary key that will be used to map the value.
|
||||
* @param value The value stored in map.
|
||||
* @return The value previously associated with the key.
|
||||
*/
|
||||
public Object put(Object key1, Object key2, Object value) {
|
||||
Object retVal = null;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key1 == null) {
|
||||
key1 = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
if(key2 == null) {
|
||||
key2 = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
if(value == null) {
|
||||
//Remove the key if it exists because you cannot associate a key with a null value.//
|
||||
retVal = remove(key1, key2);
|
||||
}//if//
|
||||
else {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key1) ^ getKeyComparator().hash(key2);;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry entry = null;
|
||||
|
||||
//Try to locate an existing value.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key1, key1))) && (Comparator.isEqual(getKeyComparator().compare(entry.key2, key2)))) {
|
||||
Object oldValue = entry.value;
|
||||
|
||||
entry.value = value;
|
||||
|
||||
return oldValue;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Determine if we need to re-hash.//
|
||||
if(resize(getSize() + 1)) {
|
||||
entries = getEntries();
|
||||
//Recalculate the insertion index if the map resized.//
|
||||
index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
}//if//
|
||||
|
||||
//Create and add the new entry.//
|
||||
entry = (Entry) createEntry();
|
||||
entry.hash = hash;
|
||||
entry.key1 = key1;
|
||||
entry.key2 = key2;
|
||||
entry.value = value;
|
||||
addEntry(index, entry);
|
||||
}//else//
|
||||
|
||||
return retVal;
|
||||
}//put()//
|
||||
/**
|
||||
* Removes a key/value pair from the map.
|
||||
* @param key1 The primary key that should be removed (with its' value) from the map.
|
||||
* @param key2 The secondary key that should be removed (with its' value) from the map.
|
||||
* @return Will be the value removed from map. A <code>null</code> value is returned if the key was not found.
|
||||
*/
|
||||
public Object remove(Object key1, Object key2) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key1 == null) {
|
||||
key1 = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
if(key2 == null) {
|
||||
key2 = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key1) ^ getKeyComparator().hash(key2);;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry previousEntry = null;
|
||||
Entry entry = null;
|
||||
Object retVal = null;
|
||||
|
||||
//Iterate through the entries stored at the key's hash location and remove the given key.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key1, key1))) && (Comparator.isEqual(getKeyComparator().compare(entry.key2, key2)))) {
|
||||
//Save the removed value.//
|
||||
retVal = entry.value;
|
||||
//Remove the entry from the map.//
|
||||
removeEntry(index, previousEntry);
|
||||
//Break from the loop so we can exit.//
|
||||
break;
|
||||
}//if//
|
||||
|
||||
previousEntry = entry;
|
||||
}//for//
|
||||
|
||||
return retVal;
|
||||
}//remove()//
|
||||
/**
|
||||
* Removes all key/value pairs from the map.
|
||||
* @return Will be <code>true</code> if the method was successful.
|
||||
*/
|
||||
public boolean removeAll() {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
removeAllEntries();
|
||||
|
||||
return true;
|
||||
}//removeAll()//
|
||||
/**
|
||||
* Gets an iterator over the values contained in this collection.
|
||||
* @return An iterator over the map values.
|
||||
*/
|
||||
public IIterator valueIterator() {
|
||||
return new ValueIterator(this);
|
||||
}//valueIterator()//
|
||||
}//HashMap//
|
||||
55
Common/src/com/common/util/optimized/IBooleanArray.java
Normal file
55
Common/src/com/common/util/optimized/IBooleanArray.java
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
public interface IBooleanArray {
|
||||
/**
|
||||
* Adds a value to the collection.
|
||||
* @param value The value to add to the collection.
|
||||
*/
|
||||
public void add(boolean value);
|
||||
/**
|
||||
* Adds a value to the collection at the given index.
|
||||
* @param value The value to add to the collection.
|
||||
* @param index The index of the new value.
|
||||
*/
|
||||
public void add(boolean value, int index);
|
||||
/**
|
||||
* Gets a value at a given index.
|
||||
* @param index The index of the value to retrieve.
|
||||
* @return The value at that index.
|
||||
*/
|
||||
public boolean get(int index);
|
||||
/**
|
||||
* Gets the number of values in the collection.
|
||||
* @return The number of values stored in this collection.
|
||||
*/
|
||||
public int getSize();
|
||||
/**
|
||||
* Gets an iterator over the values in this collection.
|
||||
* @return An iterator over the collection values.
|
||||
*/
|
||||
public IBooleanIterator iterator();
|
||||
/**
|
||||
* Removes a value from the collection by its' index.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @return The value at the removed index.
|
||||
*/
|
||||
public boolean remove(int index);
|
||||
/**
|
||||
* Removes all collection values.
|
||||
* @return Whether all values were properly removed.
|
||||
*/
|
||||
public boolean removeAll();
|
||||
/**
|
||||
* Replaces a value in the collection at a specific index, with a new value.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @param value The new value at the given index.
|
||||
*/
|
||||
public void replace(int index, boolean value);
|
||||
}//IBooleanArray//
|
||||
32
Common/src/com/common/util/optimized/IBooleanIterator.java
Normal file
32
Common/src/com/common/util/optimized/IBooleanIterator.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2005,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
public interface IBooleanIterator {
|
||||
/**
|
||||
* Makes sure there is a next value in the collection.
|
||||
* This method does not ensure that the collection will not be changed by another thread.
|
||||
* @return Whether there is a next value in the collection.
|
||||
* @see #next()
|
||||
*/
|
||||
public boolean hasNext();
|
||||
/**
|
||||
* Gets the next value in the collection.
|
||||
* This method does not ensure that the collection will have a next value, even if the hasNext method has been called and returned a positive result.
|
||||
* @return The next value in the collection.
|
||||
* @see #hasNext()
|
||||
*/
|
||||
public boolean next();
|
||||
/**
|
||||
* Resets the iterator to iterate over the collection starting with the first value.
|
||||
* The first item to be returned will be the first item in the collection.
|
||||
* @see #next()
|
||||
* @see #hasNext()
|
||||
*/
|
||||
public void resetToFront();
|
||||
}//IBooleanIterator//
|
||||
89
Common/src/com/common/util/optimized/ICharCollection.java
Normal file
89
Common/src/com/common/util/optimized/ICharCollection.java
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
public interface ICharCollection extends java.io.Externalizable {
|
||||
/**
|
||||
* Will add the given item to the collection.
|
||||
* @param value A value to add to this collection.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean add(char value);
|
||||
/**
|
||||
* Will add the given items to the collection.
|
||||
* @param values An array of values to add to this collection.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean addAll(char[] values);
|
||||
/**
|
||||
* Will add the given items to the collection.
|
||||
* @param values A collection of values to add to this collection.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean addAll(ICharCollection values);
|
||||
/**
|
||||
* Will check to see if a value is contained in this collection.
|
||||
* @param value The value to check for.
|
||||
* @return Returns true if the value is a member of the collection.
|
||||
*/
|
||||
public boolean containsValue(char value);
|
||||
/**
|
||||
* Returns a the number of values contained in the Collection.
|
||||
* @return int The number of values stored in this collection.
|
||||
*/
|
||||
public int getSize();
|
||||
/**
|
||||
* Determines whether the collection may be changed or not.
|
||||
* <p>NOTE: Something that is immutable is never changing.
|
||||
* @return Whether the collection may be changed. This is false if the collection may no longer be modified.
|
||||
*/
|
||||
public boolean isChangeable();
|
||||
/**
|
||||
* Determines whether the collection may be changed or not.
|
||||
* @param isChangeable Whether the collection may be changed. This is false if the collection may no longer be modified.
|
||||
*/
|
||||
public void isChangeable(boolean isChangeable);
|
||||
/**
|
||||
* Returns an iterator which can be used to cycle over each item in the Collection.
|
||||
* @return IIterator An iterator over this collection.
|
||||
*/
|
||||
public ICharIterator iterator();
|
||||
/**
|
||||
* Removes the given item from the collection.
|
||||
* @param value Object A value to remove from this collection.
|
||||
* @return boolean Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean remove(char value);
|
||||
/**
|
||||
* Removes all of the items from the collection.
|
||||
*/
|
||||
public void removeAll();
|
||||
/**
|
||||
* Removes all of the given items from the collection.
|
||||
* @param values An array of values to remove from this collection.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean removeAll(char[] values);
|
||||
/**
|
||||
* Will remove all of the given items from the collection.
|
||||
* @param values A collection of values to remove from this collection.
|
||||
* @return Returns true if the operation was a success.
|
||||
*/
|
||||
public boolean removeAll(ICharCollection values);
|
||||
/**
|
||||
* Creates an array of the values in the collection.
|
||||
* @return char[] An array of collection values.
|
||||
*/
|
||||
public char[] toArray();
|
||||
/**
|
||||
* Fills in an array with the collection values. If the array is not large enough to hold all of the values then as many as possible will be inserted.
|
||||
* @param array An array object capable of contain collection char values.
|
||||
* @return The number of elements copied into the array.
|
||||
*/
|
||||
public int toArray(Object array);
|
||||
}//ICollection//
|
||||
32
Common/src/com/common/util/optimized/ICharIterator.java
Normal file
32
Common/src/com/common/util/optimized/ICharIterator.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
public interface ICharIterator {
|
||||
/**
|
||||
* Makes sure there is a next value in the collection.
|
||||
* This method does not ensure that the collection will not be changed by another thread.
|
||||
* @return Whether there is a next value in the collection.
|
||||
* @see #next()
|
||||
*/
|
||||
public boolean hasNext();
|
||||
/**
|
||||
* Gets the next value in the collection.
|
||||
* This method does not ensure that the collection will have a next value, even if the hasNext method has been called and returned a positive result.
|
||||
* @return The next value in the collection.
|
||||
* @see #hasNext()
|
||||
*/
|
||||
public char next();
|
||||
/**
|
||||
* Resets the iterator to iterate over the collection starting with the first value.
|
||||
* The first item to be returned will be the first item in the collection.
|
||||
* @see #next()
|
||||
* @see #hasNext()
|
||||
*/
|
||||
public void resetToFront();
|
||||
}//ICharIterator//
|
||||
72
Common/src/com/common/util/optimized/IIntArray.java
Normal file
72
Common/src/com/common/util/optimized/IIntArray.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import java.io.Externalizable;
|
||||
|
||||
public interface IIntArray extends Cloneable, Externalizable {
|
||||
/**
|
||||
* Adds a value to the collection.
|
||||
* @param value The value to add to the collection.
|
||||
*/
|
||||
public void add(int value);
|
||||
/**
|
||||
* Adds a value to the collection at the given index.
|
||||
* @param value The value to add to the collection.
|
||||
* @param index The index of the new value.
|
||||
*/
|
||||
public void add(int index, int value);
|
||||
/**
|
||||
* Gets a value at a given index.
|
||||
* @param index The index of the value to retrieve.
|
||||
* @return The value at that index.
|
||||
*/
|
||||
public int get(int index);
|
||||
/**
|
||||
* Gets the number of values in the collection.
|
||||
* @return The number of values stored in this collection.
|
||||
*/
|
||||
public int getSize();
|
||||
/**
|
||||
* Gets an iterator over the values in this collection.
|
||||
* @return An iterator over the collection values.
|
||||
*/
|
||||
public IIntIterator iterator();
|
||||
/**
|
||||
* Removes a value from the collection by its' index.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @return The value at the removed index.
|
||||
*/
|
||||
public int remove(int index);
|
||||
/**
|
||||
* Removes the first value from the array.
|
||||
* @return The value removed.
|
||||
*/
|
||||
public int removeFirst();
|
||||
/**
|
||||
* Removes the last value from the array.
|
||||
* @return The value removed.
|
||||
*/
|
||||
public int removeLast();
|
||||
/**
|
||||
* Removes all collection values.
|
||||
* @return Whether all values were properly removed.
|
||||
*/
|
||||
public boolean removeAll();
|
||||
/**
|
||||
* Replaces a value in the collection at a specific index, with a new value.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @param value The new value at the given index.
|
||||
*/
|
||||
public void replace(int index, int value);
|
||||
/**
|
||||
* Clones the collection.
|
||||
* @return The clone.
|
||||
*/
|
||||
public Object clone();
|
||||
}//IIntArray//
|
||||
55
Common/src/com/common/util/optimized/IIntIntHashMap.java
Normal file
55
Common/src/com/common/util/optimized/IIntIntHashMap.java
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.util.*;
|
||||
|
||||
public interface IIntIntHashMap extends IMap {
|
||||
public static final int NULL_VALUE = -2147483648;
|
||||
/**
|
||||
* Determines whether the key exists in the map.
|
||||
* @param key The key to look for.
|
||||
* @return Will be <code>true</code> if the key is already in the map.
|
||||
*/
|
||||
public boolean containsKey(int key);
|
||||
/**
|
||||
* Gets an object in the map by its' key.
|
||||
* @param key The key whose value should be retieved.
|
||||
* @return The value associated with the key. A <code>NULL_VALUE</code> value will be returned only if the key was not found.
|
||||
*/
|
||||
public int get(int key);
|
||||
/**
|
||||
* Gets an iterator over the keys contained in this collection.
|
||||
* @return An iterator over the map keys.
|
||||
*/
|
||||
public IIntIterator keyIterator();
|
||||
/**
|
||||
* Puts a key/value pair in the map.
|
||||
* The value can be retrieved later with the given key.
|
||||
* @param key The key that will be used to map the value.
|
||||
* @param value The value stored in map.
|
||||
* @return The value previously associated with the key.
|
||||
*/
|
||||
public int put(int key, int value);
|
||||
/**
|
||||
* Removes a key/value pair from the map.
|
||||
* @param key The key that should be removed (with its' value) from the map.
|
||||
* @return The value removed from map. A <code>NULL_VALUE</code> value is returned if the key was not found.
|
||||
*/
|
||||
public int remove(int key);
|
||||
/**
|
||||
* Removes all key/value pairs from the map.
|
||||
* @return Will be <code>true</code> if the method was successful.
|
||||
*/
|
||||
public boolean removeAll();
|
||||
/**
|
||||
* Gets an iterator over the values contained in this collection.
|
||||
* @return An iterator over the map values.
|
||||
*/
|
||||
public IIntIterator valueIterator();
|
||||
}//IIntObjectHashMap//
|
||||
32
Common/src/com/common/util/optimized/IIntIterator.java
Normal file
32
Common/src/com/common/util/optimized/IIntIterator.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
public interface IIntIterator {
|
||||
/**
|
||||
* Makes sure there is a next value in the collection.
|
||||
* This method does not ensure that the collection will not be changed by another thread.
|
||||
* @return Whether there is a next value in the collection.
|
||||
* @see #next()
|
||||
*/
|
||||
public boolean hasNext();
|
||||
/**
|
||||
* Gets the next value in the collection.
|
||||
* This method does not ensure that the collection will have a next value, even if the hasNext method has been called and returned a positive result.
|
||||
* @return The next value in the collection.
|
||||
* @see #hasNext()
|
||||
*/
|
||||
public int next();
|
||||
/**
|
||||
* Resets the iterator to iterate over the collection starting with the first value.
|
||||
* The first item to be returned will be the first item in the collection.
|
||||
* @see #next()
|
||||
* @see #hasNext()
|
||||
*/
|
||||
public void resetToFront();
|
||||
}//IIntIterator//
|
||||
55
Common/src/com/common/util/optimized/IIntObjectHashMap.java
Normal file
55
Common/src/com/common/util/optimized/IIntObjectHashMap.java
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.util.*;
|
||||
|
||||
public interface IIntObjectHashMap extends IMap {
|
||||
public static final int NULL_VALUE = -2147483648;
|
||||
/**
|
||||
* Determines whether the key exists in the map.
|
||||
* @param key The key to look for.
|
||||
* @return Will be <code>true</code> if the key is already in the map.
|
||||
*/
|
||||
public boolean containsKey(int key);
|
||||
/**
|
||||
* Gets an object in the map by its' key.
|
||||
* @param key The key whose value should be retieved.
|
||||
* @return The value associated with the key. A <code>null</code> value will be returned only if the key was not found.
|
||||
*/
|
||||
public Object get(int key);
|
||||
/**
|
||||
* Gets an iterator over the keys contained in this collection.
|
||||
* @return An iterator over the map keys.
|
||||
*/
|
||||
public IIntIterator keyIterator();
|
||||
/**
|
||||
* Puts a key/value pair in the map.
|
||||
* The value can be retrieved later with the given key.
|
||||
* @param key The key that will be used to map the value.
|
||||
* @param value The value stored in map.
|
||||
* @return The value previously associated with the key.
|
||||
*/
|
||||
public Object put(int key, Object value);
|
||||
/**
|
||||
* Removes a key/value pair from the map.
|
||||
* @param key The key that should be removed (with its' value) from the map.
|
||||
* @return The value removed from map. A <code>null</code> value is returned if the key was not found.
|
||||
*/
|
||||
public Object remove(int key);
|
||||
/**
|
||||
* Removes all key/value pairs from the map.
|
||||
* @return Will be <code>true</code> if the method was successful.
|
||||
*/
|
||||
public boolean removeAll();
|
||||
/**
|
||||
* Gets an iterator over the values contained in this collection.
|
||||
* @return An iterator over the map values.
|
||||
*/
|
||||
public IIterator valueIterator();
|
||||
}//IIntObjectHashMap//
|
||||
65
Common/src/com/common/util/optimized/ILongArray.java
Normal file
65
Common/src/com/common/util/optimized/ILongArray.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2007,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
public interface ILongArray {
|
||||
/**
|
||||
* Adds a value to the collection.
|
||||
* @param value The value to add to the collection.
|
||||
*/
|
||||
public void add(long value);
|
||||
/**
|
||||
* Adds a value to the collection at the given index.
|
||||
* @param index The index of the new value.
|
||||
* @param value The value to add to the collection.
|
||||
*/
|
||||
public void add(int index, long value);
|
||||
/**
|
||||
* Gets a value at a given index.
|
||||
* @param index The index of the value to retrieve.
|
||||
* @return The value at that index.
|
||||
*/
|
||||
public long get(int index);
|
||||
/**
|
||||
* Gets the number of values in the collection.
|
||||
* @return The number of values stored in this collection.
|
||||
*/
|
||||
public int getSize();
|
||||
/**
|
||||
* Gets an iterator over the values in this collection.
|
||||
* @return An iterator over the collection values.
|
||||
*/
|
||||
public ILongIterator iterator();
|
||||
/**
|
||||
* Removes a value from the collection by its' index.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @return The value at the removed index.
|
||||
*/
|
||||
public long remove(int index);
|
||||
/**
|
||||
* Removes the first value from the array.
|
||||
* @return The value removed.
|
||||
*/
|
||||
public long removeFirst();
|
||||
/**
|
||||
* Removes the last value from the array.
|
||||
* @return The value removed.
|
||||
*/
|
||||
public long removeLast();
|
||||
/**
|
||||
* Removes all collection values.
|
||||
* @return Whether all values were properly removed.
|
||||
*/
|
||||
public boolean removeAll();
|
||||
/**
|
||||
* Replaces a value in the collection at a specific index, with a new value.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @param value The new value at the given index.
|
||||
*/
|
||||
public void replace(int index, long value);
|
||||
}//IIntArray//
|
||||
32
Common/src/com/common/util/optimized/ILongIterator.java
Normal file
32
Common/src/com/common/util/optimized/ILongIterator.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
public interface ILongIterator {
|
||||
/**
|
||||
* Makes sure there is a next value in the collection.
|
||||
* This method does not ensure that the collection will not be changed by another thread.
|
||||
* @return Whether there is a next value in the collection.
|
||||
* @see #next()
|
||||
*/
|
||||
public boolean hasNext();
|
||||
/**
|
||||
* Gets the next value in the collection.
|
||||
* This method does not ensure that the collection will have a next value, even if the hasNext method has been called and returned a positive result.
|
||||
* @return The next value in the collection.
|
||||
* @see #hasNext()
|
||||
*/
|
||||
public long next();
|
||||
/**
|
||||
* Resets the iterator to iterate over the collection starting with the first value.
|
||||
* The first item to be returned will be the first item in the collection.
|
||||
* @see #next()
|
||||
* @see #hasNext()
|
||||
*/
|
||||
public void resetToFront();
|
||||
}//ILongIterator//
|
||||
55
Common/src/com/common/util/optimized/ILongObjectHashMap.java
Normal file
55
Common/src/com/common/util/optimized/ILongObjectHashMap.java
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.util.*;
|
||||
|
||||
public interface ILongObjectHashMap extends IMap {
|
||||
public static final long NULL_VALUE = -9223372036854775808L;
|
||||
/**
|
||||
* Determines whether the key exists in the map.
|
||||
* @param key The key to look for.
|
||||
* @return Will be <code>true</code> if the key is already in the map.
|
||||
*/
|
||||
public boolean containsKey(long key);
|
||||
/**
|
||||
* Gets an object in the map by its' key.
|
||||
* @param key The key whose value should be retieved.
|
||||
* @return The value associated with the key. A <code>null</code> value will be returned only if the key was not found.
|
||||
*/
|
||||
public Object get(long key);
|
||||
/**
|
||||
* Gets an iterator over the keys contained in this collection.
|
||||
* @return An iterator over the map keys.
|
||||
*/
|
||||
public ILongIterator keyIterator();
|
||||
/**
|
||||
* Puts a key/value pair in the map.
|
||||
* The value can be retrieved later with the given key.
|
||||
* @param key The key that will be used to map the value.
|
||||
* @param value The value stored in map.
|
||||
* @return The value previously associated with the key.
|
||||
*/
|
||||
public Object put(long key, Object value);
|
||||
/**
|
||||
* Removes a key/value pair from the map.
|
||||
* @param key The key that should be removed (with its' value) from the map.
|
||||
* @return The value removed from map. A <code>null</code> value is returned if the key was not found.
|
||||
*/
|
||||
public Object remove(long key);
|
||||
/**
|
||||
* Removes all key/value pairs from the map.
|
||||
* @return Will be <code>true</code> if the method was successful.
|
||||
*/
|
||||
public boolean removeAll();
|
||||
/**
|
||||
* Gets an iterator over the values contained in this collection.
|
||||
* @return An iterator over the map values.
|
||||
*/
|
||||
public IIterator valueIterator();
|
||||
}//ILongObjectHashMap//
|
||||
66
Common/src/com/common/util/optimized/IObjectIntHashMap.java
Normal file
66
Common/src/com/common/util/optimized/IObjectIntHashMap.java
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.util.*;
|
||||
|
||||
public interface IObjectIntHashMap extends IMap {
|
||||
public static final int NULL_VALUE = -2147483648;
|
||||
/**
|
||||
* Determines whether the key exists in the map.
|
||||
* @param key The key to look for.
|
||||
* @return Will be <code>true</code> if the key is already in the map.
|
||||
*/
|
||||
public boolean containsKey(Object key);
|
||||
/**
|
||||
* Gets an object in the map by its' key.
|
||||
* <p><b>WARNING: It is very strongly recommended that the user call containsKey(Object) before calling this method if there is any doubt as to whether the key exists in the collection.</b>
|
||||
* @param key The key whose value should be retieved.
|
||||
* @return The value associated with the key. A <code>NULL_VALUE</code> value will be returned only if the key was not found.
|
||||
* @see #NULL_VALUE
|
||||
* @see #containsKey(Object)
|
||||
*/
|
||||
public int get(Object key);
|
||||
/**
|
||||
* Gets an iterator over the keys contained in this collection.
|
||||
* @return An iterator over the map keys.
|
||||
*/
|
||||
public IIterator keyIterator();
|
||||
/**
|
||||
* Places a key/value pair in the map.
|
||||
* The value can be retrieved later with the given key.
|
||||
* <p><b>Warning: It is strongly recomended that the return value of this method be ignored. If the caller wants a properly accurate value then the containsKey(Object) and get(Object) method should be called before calling this method.</b>
|
||||
* @param key The key that will be used to map the value.
|
||||
* @param value The value stored in map.
|
||||
* @return The value previously associated with the key.
|
||||
* @see #NULL_VALUE
|
||||
* @see #containsKey(Object)
|
||||
* @see #get(Object)
|
||||
*/
|
||||
public int put(Object key, int value);
|
||||
/**
|
||||
* Removes a key/value pair from the map.
|
||||
* <p><b>Warning: It is strongly recomended that the return value of this method be ignored. If the caller wants a properly accurate value then the containsKey(Object) and get(Object) method should be called before calling this method.</b>
|
||||
* @param key The key that should be removed (with its' value) from the map.
|
||||
* @return The value removed from map. A <code>NULL_VALUE</code> value is returned if the key was not found.
|
||||
* @see #NULL_VALUE
|
||||
* @see #containsKey(Object)
|
||||
* @see #get(Object)
|
||||
*/
|
||||
public int remove(Object key);
|
||||
/**
|
||||
* Removes all key/value pairs from the map.
|
||||
* @return Will be <code>true</code> if the method was successful.
|
||||
*/
|
||||
public boolean removeAll();
|
||||
/**
|
||||
* Gets an iterator over the values contained in this collection.
|
||||
* @return An iterator over the map values.
|
||||
*/
|
||||
public IIntIterator valueIterator();
|
||||
}//IObjectIntHashMap//
|
||||
66
Common/src/com/common/util/optimized/IObjectLongHashMap.java
Normal file
66
Common/src/com/common/util/optimized/IObjectLongHashMap.java
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.util.*;
|
||||
|
||||
public interface IObjectLongHashMap extends IMap {
|
||||
public static final long NULL_VALUE = -9223372036854775808L;
|
||||
/**
|
||||
* Determines whether the key exists in the map.
|
||||
* @param key The key to look for.
|
||||
* @return Will be <code>true</code> if the key is already in the map.
|
||||
*/
|
||||
public boolean containsKey(Object key);
|
||||
/**
|
||||
* Gets an object in the map by its' key.
|
||||
* <p><b>WARNING: It is very strongly recommended that the user call containsKey(Object) before calling this method if there is any doubt as to whether the key exists in the collection.</b>
|
||||
* @param key The key whose value should be retieved.
|
||||
* @return The value associated with the key. A <code>NULL_VALUE</code> value will be returned only if the key was not found.
|
||||
* @see #NULL_VALUE
|
||||
* @see #containsKey(Object)
|
||||
*/
|
||||
public long get(Object key);
|
||||
/**
|
||||
* Gets an iterator over the keys contained in this collection.
|
||||
* @return An iterator over the map keys.
|
||||
*/
|
||||
public IIterator keyIterator();
|
||||
/**
|
||||
* Places a key/value pair in the map.
|
||||
* The value can be retrieved later with the given key.
|
||||
* <p><b>Warning: It is strongly recomended that the return value of this method be ignored. If the caller wants a properly accurate value then the containsKey(Object) and get(Object) method should be called before calling this method.</b>
|
||||
* @param key The key that will be used to map the value.
|
||||
* @param value The value stored in map.
|
||||
* @return The value previously associated with the key.
|
||||
* @see #NULL_VALUE
|
||||
* @see #containsKey(Object)
|
||||
* @see #get(Object)
|
||||
*/
|
||||
public long put(Object key, long value);
|
||||
/**
|
||||
* Removes a key/value pair from the map.
|
||||
* <p><b>Warning: It is strongly recomended that the return value of this method be ignored. If the caller wants a properly accurate value then the containsKey(Object) and get(Object) method should be called before calling this method.</b>
|
||||
* @param key The key that should be removed (with its' value) from the map.
|
||||
* @return The value removed from map. A <code>NULL_VALUE</code> value is returned if the key was not found.
|
||||
* @see #NULL_VALUE
|
||||
* @see #containsKey(Object)
|
||||
* @see #get(Object)
|
||||
*/
|
||||
public long remove(Object key);
|
||||
/**
|
||||
* Removes all key/value pairs from the map.
|
||||
* @return Will be <code>true</code> if the method was successful.
|
||||
*/
|
||||
public boolean removeAll();
|
||||
/**
|
||||
* Gets an iterator over the values contained in this collection.
|
||||
* @return An iterator over the map values.
|
||||
*/
|
||||
public ILongIterator valueIterator();
|
||||
}//IObjectIntHashMap//
|
||||
379
Common/src/com/common/util/optimized/IntArray.java
Normal file
379
Common/src/com/common/util/optimized/IntArray.java
Normal file
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
|
||||
/**
|
||||
* <p>WARNING: This is a Lite collection and does not have any synchronization (NOT THREAD SAFE).
|
||||
* <p>This class maintains a collection of int values using an interface similar to IList.
|
||||
*/
|
||||
public class IntArray implements IIntArray {
|
||||
private int[] array = null;
|
||||
private int count = 0;
|
||||
private int incrementSize = 0;
|
||||
|
||||
public static class Iterator implements IIntIterator {
|
||||
private IntArray array = null;
|
||||
private int index = 0;
|
||||
|
||||
public Iterator(IntArray array) {
|
||||
this.array = array;
|
||||
}//Iterator()//
|
||||
public boolean hasNext() {
|
||||
return index < array.getSize();
|
||||
}//hasNext()//
|
||||
public int next() {
|
||||
return array.get(index++);
|
||||
}//next()//
|
||||
public void resetToFront() {
|
||||
this.index = 0;
|
||||
}//resetToFront()//
|
||||
}//KeyIterator//
|
||||
/**
|
||||
* IntArray constructor.
|
||||
*/
|
||||
public IntArray() {
|
||||
this(10, 10);
|
||||
}//IntArray()//
|
||||
/**
|
||||
* IntArray constructor.
|
||||
*/
|
||||
public IntArray(int initialSize) {
|
||||
this(initialSize, 10);
|
||||
}//IntArray()//
|
||||
/**
|
||||
* IntArray constructor.
|
||||
*/
|
||||
public IntArray(int initialSize, int incrementSize) {
|
||||
super();
|
||||
|
||||
if(initialSize <= 0) {
|
||||
//TODO: Throw exception.//
|
||||
initialSize = 1;
|
||||
}//if//
|
||||
|
||||
this.array = new int[initialSize];
|
||||
this.incrementSize = incrementSize;
|
||||
}//IntArray()//
|
||||
/**
|
||||
* IntArray constructor.
|
||||
* @param copy The int array to clone.
|
||||
*/
|
||||
public IntArray(IntArray copy) {
|
||||
super();
|
||||
|
||||
this.array = new int[copy.count + copy.incrementSize];
|
||||
this.incrementSize = copy.incrementSize;
|
||||
System.arraycopy(copy.array, 0, this.array, 0, copy.count);
|
||||
this.count = copy.count;
|
||||
}//IntArray()//
|
||||
/**
|
||||
* Adds a value to the collection.
|
||||
* @param value The value to add to the collection.
|
||||
*/
|
||||
public void add(int value) {
|
||||
internalAdd(value);
|
||||
}//add()//
|
||||
/**
|
||||
* Adds a value to the collection at the given index.
|
||||
* @param index The index of the new value.
|
||||
* @param value The value to add to the collection.
|
||||
*/
|
||||
public void add(int index, int value) {
|
||||
internalAdd(value, index);
|
||||
}//add()//
|
||||
/**
|
||||
* Adds values to the collection.
|
||||
* @param values The array of values to add to the collection.
|
||||
*/
|
||||
public void addAll(int[] values) {
|
||||
ensureCapacity(values.length);
|
||||
|
||||
for(int index = 0; index < values.length; index++) {
|
||||
internalAdd(values[index]);
|
||||
}//for//
|
||||
}//addAll()//
|
||||
/**
|
||||
* Adds values to the collection.
|
||||
* @param values The collection of values to add to the collection.
|
||||
*/
|
||||
public void addAll(IntArray values) {
|
||||
ensureCapacity(values.getSize());
|
||||
|
||||
for(int index = 0; index < values.getSize(); index++) {
|
||||
internalAdd(values.get(index));
|
||||
}//for//
|
||||
}//addAll()//
|
||||
/**
|
||||
* Determines whether the value is contained in the collection.
|
||||
* @param value The value to look for.
|
||||
* @return Whether the given value is in the collection.
|
||||
*/
|
||||
public boolean containsValue(int value) {
|
||||
return getIndexOf(value) != -1;
|
||||
}//containsValue()//
|
||||
/**
|
||||
* Gets a value at a given index.
|
||||
* @param index The index of the value to retrieve.
|
||||
* @return The value at that index.
|
||||
*/
|
||||
public int get(int index) {
|
||||
if((index >= 0) && (index < count)) {
|
||||
return array[index];
|
||||
}//if//
|
||||
else {
|
||||
throw new IndexOutOfBoundsException(index + " not in [0.." + count + ").");
|
||||
}//else//
|
||||
}//get()//
|
||||
/**
|
||||
* Gets the last element in the collection.
|
||||
* @return The last element.
|
||||
*/
|
||||
public int getLast() {
|
||||
return array[count - 1];
|
||||
}//getLast()//
|
||||
/**
|
||||
* Gets the first element in the collection.
|
||||
* @return The first element.
|
||||
*/
|
||||
public int getFirst() {
|
||||
return array[0];
|
||||
}//getFirst()//
|
||||
/**
|
||||
* Gets a value's index in the collection.
|
||||
* @param value The value whose index is to be retrieved.
|
||||
* @return The value's index.
|
||||
*/
|
||||
public int getIndexOf(int value) {
|
||||
int index = 0;
|
||||
|
||||
for(; index < count; index++) {
|
||||
if(array[index] == value) {
|
||||
break;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return index < count ? index : -1;
|
||||
}//getIndexOf()//
|
||||
/**
|
||||
* Gets the number of values in the collection.
|
||||
* @return The number of values stored in this collection.
|
||||
*/
|
||||
public int getSize() {
|
||||
return count;
|
||||
}//getSize()//
|
||||
/**
|
||||
* Adds a value to the collection.
|
||||
* @param value The value to add to the collection.
|
||||
*/
|
||||
protected void internalAdd(int value) {
|
||||
if(count == array.length) {
|
||||
ensureCapacity(1);
|
||||
}//if//
|
||||
|
||||
array[count++] = value;
|
||||
}//internalAdd()//
|
||||
/**
|
||||
* Adds a value to the collection at the given index.
|
||||
* @param value The value to add to the collection.
|
||||
* @param index The index of the new value.
|
||||
*/
|
||||
protected void internalAdd(int value, int index) {
|
||||
if(count == array.length) {
|
||||
ensureCapacity(1);
|
||||
}//if//
|
||||
|
||||
if(index == count) {
|
||||
array[count++] = value;
|
||||
}//if//
|
||||
else {
|
||||
System.arraycopy(array, index, array, index + 1, count - index);
|
||||
array[index] = value;
|
||||
count++;
|
||||
}//else//
|
||||
}//internalAdd()//
|
||||
/**
|
||||
* Removes a value from the collection by its' index.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @return The value at the removed index.
|
||||
*/
|
||||
protected int internalRemove(int index) {
|
||||
int result;
|
||||
|
||||
if((index >= count) && (index < 0)) {
|
||||
throw new IndexOutOfBoundsException(index + " not in [0.." + count + ").");
|
||||
}//if//
|
||||
|
||||
if(index != count - 1) {
|
||||
System.arraycopy(array, index + 1, array, index, array.length - index - 1);
|
||||
}//if//
|
||||
|
||||
result = array[index];
|
||||
array[--count] = 0;
|
||||
|
||||
return result;
|
||||
}//internalRemove()//
|
||||
/**
|
||||
* Removes all collection values.
|
||||
* @return Whether all values were properly removed.
|
||||
*/
|
||||
protected boolean internalRemoveAll() {
|
||||
boolean result = true;
|
||||
|
||||
while(count != 0) {
|
||||
array[--count] = 0;
|
||||
}//while//
|
||||
|
||||
return result;
|
||||
}//internalRemoveAll()//
|
||||
/**
|
||||
* Gets an iterator over the values in this collection.
|
||||
* @return An iterator over the collection values.
|
||||
*/
|
||||
public IIntIterator iterator() {
|
||||
return new Iterator(this);
|
||||
}//iterator()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.IIntArray#remove(int)
|
||||
*/
|
||||
public int remove(int index) {
|
||||
return internalRemove(index);
|
||||
}//remove()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.IIntArray#removeFirst()
|
||||
*/
|
||||
public int removeFirst() {
|
||||
return internalRemove(0);
|
||||
}//removeFirst()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.IIntArray#removeLast()
|
||||
*/
|
||||
public int removeLast() {
|
||||
return internalRemove(count - 1);
|
||||
}//removeLast()//
|
||||
/**
|
||||
* Removes all collection values.
|
||||
* @return Whether all values were properly removed.
|
||||
*/
|
||||
public boolean removeAll() {
|
||||
return internalRemoveAll();
|
||||
}//removeAll()//
|
||||
/**
|
||||
* Replaces a value in the collection at a specific index, with a new value.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @param value The new value at the given index.
|
||||
*/
|
||||
public void replace(int index, int value) {
|
||||
replaceInternal(index, value);
|
||||
}//replace()//
|
||||
/**
|
||||
* Replaces a value in the collection at a specific index, with a new value.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @param value The new value at the given index.
|
||||
*/
|
||||
protected void replaceInternal(int index, int value) {
|
||||
if((index >= count) && (index < 0)) {
|
||||
throw new IndexOutOfBoundsException(index + " not in [0.." + count + ").");
|
||||
}//if//
|
||||
|
||||
array[index] = value;
|
||||
}//replaceInternal()//
|
||||
/**
|
||||
* Ensures that the collection is large enough to hold <code>minimumCapacity</code> items.
|
||||
* @param minimumCapacity The number of items the collection should be able to hold (above what it currently holds).
|
||||
*/
|
||||
public void ensureCapacity(int minimumCapacity) {
|
||||
if(count + minimumCapacity > array.length) {
|
||||
int oldCapacity = array.length;
|
||||
int[] oldData = array;
|
||||
int newCapacity = (incrementSize > 0 ? oldCapacity + incrementSize : oldCapacity << 1);
|
||||
|
||||
if(newCapacity < count + minimumCapacity) {
|
||||
newCapacity = count + minimumCapacity;
|
||||
}//if//
|
||||
|
||||
array = new int[newCapacity];
|
||||
System.arraycopy(oldData, 0, array, 0, count);
|
||||
}//if//
|
||||
}//ensureCapacity()//
|
||||
/**
|
||||
* Fills an array with collection values.
|
||||
* @return An exact sized array containing all values in the collection.
|
||||
*/
|
||||
public int[] toArray() {
|
||||
int[] result = new int[count];
|
||||
|
||||
System.arraycopy(this.array, 0, result, 0, count);
|
||||
|
||||
return result;
|
||||
}//toArray()//
|
||||
/**
|
||||
* Fills an array with collection values.
|
||||
* @param array An array capable of containing collection values.
|
||||
* @return The number of elements copied into the array.
|
||||
*/
|
||||
public int toArray(int[] array) {
|
||||
int size = array.length;
|
||||
|
||||
size = count > size ? count : size;
|
||||
System.arraycopy(this.array, 0, array, 0, size);
|
||||
|
||||
return size;
|
||||
}//toArray()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#clone()
|
||||
*/
|
||||
public Object clone() {
|
||||
return new IntArray(this);
|
||||
}//clone()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
|
||||
*/
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
out.writeObject(array);
|
||||
out.writeInt(count);
|
||||
out.writeInt(incrementSize);
|
||||
}//writeExternal()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
|
||||
*/
|
||||
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
array = (int[]) in.readObject();
|
||||
count = in.readInt();
|
||||
incrementSize = in.readInt();
|
||||
}//readExternal()//
|
||||
/**
|
||||
* Outputs the collection of items for debugging purposes.
|
||||
* @return A string displaying the list of items.
|
||||
*/
|
||||
public String toString() {
|
||||
int max = getSize() - 1;
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
//Add a begin brace.//
|
||||
buffer.append("[");
|
||||
|
||||
for(int index = 0; index <= max; index++) {
|
||||
//Append the item to the output string.//
|
||||
buffer.append(get(index));
|
||||
|
||||
//Append a comma if this isn't the last item in the list.//
|
||||
if(index < max) {
|
||||
buffer.append(", ");
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Add a end brace.//
|
||||
buffer.append("]");
|
||||
|
||||
return buffer.toString();
|
||||
}//toString()//
|
||||
}//IntArray()//
|
||||
493
Common/src/com/common/util/optimized/IntHashSet.java
Normal file
493
Common/src/com/common/util/optimized/IntHashSet.java
Normal file
@@ -0,0 +1,493 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.debug.*;
|
||||
import com.common.exception.*;
|
||||
|
||||
/**
|
||||
* An collection that stores values so that they can be easily found and the collection can be manipulated rapidly.
|
||||
* Collection modification is very fast, and determining whether a value is in the collection is very fast.
|
||||
* Collection iteration is a bit slower than in a standard list, and indexing is not available.
|
||||
*/
|
||||
public class IntHashSet {
|
||||
protected static final String IMMUTABLE_EXCEPTION_MESSAGE = "The collection is immutable which prevents the collection from being modified.";
|
||||
|
||||
public static final int DEFAULT_INITIAL_CAPACITY = 51;
|
||||
public static final float DEFAULT_LOAD_FACTOR = 0.75f;
|
||||
public static final IntHashSet EMPTY_INT_HASH_SET = new IntHashSet(1, 1, false);
|
||||
|
||||
private HashSetEntry[] entries;
|
||||
private int size;
|
||||
private int threshold;
|
||||
private float loadFactor;
|
||||
/** Whether the collection is not immutable. If immutable then the collection cannot be altered under any circumstance. */
|
||||
protected boolean isChangeable = true;
|
||||
|
||||
/**
|
||||
* The entry class used to store HashSet values.
|
||||
*/
|
||||
private static class HashSetEntry {
|
||||
int value;
|
||||
HashSetEntry next;
|
||||
|
||||
private HashSetEntry() {
|
||||
}//HashSetEntry()//
|
||||
}//HashSetEntry//
|
||||
|
||||
/**
|
||||
* An iterator that can be used to iterate over the HashSet values.
|
||||
* <p>WARNING: While this class can be serialized, it will reset its' position to the start of the HashSet.
|
||||
* Also, the HashSet will be serialized with the iterator.
|
||||
* <p>This class is NOT thread safe.
|
||||
*/
|
||||
public static class HashSetIterator implements IIntIterator {
|
||||
private IntHashSet hashSet = null;
|
||||
private int currentIndex = -1;
|
||||
private HashSetEntry currentEntry = null;
|
||||
private int nextIndex = -1;
|
||||
private HashSetEntry nextEntry = null;
|
||||
private boolean hasNextEntry = false;
|
||||
|
||||
private HashSetIterator(IntHashSet hashSet) {
|
||||
this.hashSet = hashSet;
|
||||
}//HashSetIterator()//
|
||||
public void resetToFront() {
|
||||
currentIndex = -1;
|
||||
currentEntry = null;
|
||||
nextIndex = -1;
|
||||
nextEntry = null;
|
||||
hasNextEntry = false;
|
||||
}//resetToFront()//
|
||||
public boolean remove() {
|
||||
boolean retVal = false;
|
||||
|
||||
if(currentEntry != null) {
|
||||
retVal = hashSet.remove(currentEntry.value);
|
||||
}//if//
|
||||
|
||||
return retVal;
|
||||
}//remove()//
|
||||
public int next() {
|
||||
loadNextEntry();
|
||||
currentEntry = nextEntry;
|
||||
currentIndex = nextIndex;
|
||||
hasNextEntry = false;
|
||||
|
||||
return currentEntry.value;
|
||||
}//next()//
|
||||
public boolean hasNext() {
|
||||
loadNextEntry();
|
||||
|
||||
return nextEntry != null;
|
||||
}//hasNext()//
|
||||
/**
|
||||
* Preloads the next entry. This makes querying to see if the next entry exists and then getting the next entry much easier.
|
||||
*/
|
||||
private void loadNextEntry() {
|
||||
if(!hasNextEntry) {
|
||||
nextEntry = null;
|
||||
nextIndex = currentIndex;
|
||||
|
||||
if((currentEntry != null) && (currentEntry.next != null)) {
|
||||
nextEntry = currentEntry.next;
|
||||
}//if//
|
||||
else {
|
||||
HashSetEntry[] entries = hashSet.entries;
|
||||
|
||||
while((nextEntry == null) && (entries.length > ++nextIndex)) {
|
||||
if(entries[nextIndex] != null) {
|
||||
nextEntry = entries[nextIndex];
|
||||
}//if//
|
||||
}//while//
|
||||
}//else//
|
||||
|
||||
hasNextEntry = true;
|
||||
}//if//
|
||||
}//hasNext()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
out.writeObject(hashSet);
|
||||
}//writeExternal()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
hashSet = (IntHashSet) in.readObject();
|
||||
resetToFront();
|
||||
}//readExternal()//
|
||||
}//HashSetIterator//
|
||||
/**
|
||||
* IntHashSet constructor.
|
||||
*/
|
||||
public IntHashSet() {
|
||||
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, true);
|
||||
}//IntHashSet()//
|
||||
/**
|
||||
* IntHashSet constructor.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
*/
|
||||
public IntHashSet(int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, true);
|
||||
}//IntHashSet()//
|
||||
/**
|
||||
* IntHashSet constructor.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
*/
|
||||
public IntHashSet(int initialCapacity, float loadFactor) {
|
||||
this(initialCapacity, loadFactor, true);
|
||||
}//IntHashSet()//
|
||||
/**
|
||||
* IntHashSet constructor.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
* @param isChangeable Whether the collection is not immutable.
|
||||
*/
|
||||
private IntHashSet(int initialCapacity, float loadFactor, boolean isChangeable) {
|
||||
super();
|
||||
|
||||
if((initialCapacity <= 0) || (loadFactor <= 0.0)) {
|
||||
throw new IllegalArgumentException("Invalid initial capacity or load factory supplied to the HashSet.");
|
||||
}//if//
|
||||
|
||||
this.loadFactor = loadFactor;
|
||||
this.entries = new HashSetEntry[initialCapacity];
|
||||
this.threshold = (int)(initialCapacity * loadFactor);
|
||||
this.isChangeable = isChangeable;
|
||||
}//IntHashSet()//
|
||||
/**
|
||||
* IntHashSet constructor.
|
||||
* @param initialValues The initial values to be placed in the collection.
|
||||
*/
|
||||
public IntHashSet(int[] initialValues) {
|
||||
this(initialValues, DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
|
||||
}//IntHashSet()//
|
||||
/**
|
||||
* IntHashSet constructor.
|
||||
* @param initialValues The initial values to be placed in the collection.
|
||||
* @param isChangeable Whether the set should be modifyable.
|
||||
*/
|
||||
public IntHashSet(int[] initialValues, boolean isChangeable) {
|
||||
this(initialValues, isChangeable ? DEFAULT_INITIAL_CAPACITY : initialValues.length, isChangeable ? DEFAULT_LOAD_FACTOR : 1);
|
||||
isChangeable(isChangeable);
|
||||
}//IntHashSet()//
|
||||
/**
|
||||
* IntHashSet constructor.
|
||||
* @param initialValues The initial values to be placed in the collection.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
*/
|
||||
public IntHashSet(int[] initialValues, int initialCapacity) {
|
||||
this(initialValues, initialCapacity, DEFAULT_LOAD_FACTOR);
|
||||
}//IntHashSet()//
|
||||
/**
|
||||
* IntHashSet constructor.
|
||||
* @param initialValues The initial values to be placed in the collection.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
*/
|
||||
public IntHashSet(int[] initialValues, int initialCapacity, float loadFactor) {
|
||||
super();
|
||||
|
||||
if((initialCapacity < 0) || (loadFactor <= 0.0)) {
|
||||
throw new IllegalArgumentException("Invalid initial capacity or load factory supplied to the HashSet.");
|
||||
}//if//
|
||||
else if(initialCapacity == 0) {
|
||||
initialCapacity = 1;
|
||||
}//else if//
|
||||
|
||||
if(initialCapacity * loadFactor < initialValues.length) {
|
||||
initialCapacity = ((int) Math.ceil(initialValues.length * loadFactor)) + 10;
|
||||
}//if//
|
||||
|
||||
this.loadFactor = loadFactor;
|
||||
this.entries = new HashSetEntry[initialCapacity];
|
||||
this.threshold = (int)(initialCapacity * loadFactor);
|
||||
addAll(initialValues);
|
||||
}//IntHashSet()//
|
||||
/**
|
||||
* Determines whether the collection may be altered.
|
||||
* @return Whether the collection can be modified.
|
||||
*/
|
||||
public boolean isChangeable() {
|
||||
return isChangeable;
|
||||
}//isChangeable()//
|
||||
/**
|
||||
* Determines whether the collection may be altered.
|
||||
* @param isChangeable Whether the collection can be modified. This may not be revoked once set to false.
|
||||
*/
|
||||
public void isChangeable(boolean isChangeable) {
|
||||
if((!isChangeable) && (this.isChangeable)) {
|
||||
this.isChangeable = isChangeable;
|
||||
}//if//
|
||||
else if((isChangeable) && (!this.isChangeable)) {
|
||||
throw new IllegalOperationException(IMMUTABLE_EXCEPTION_MESSAGE);
|
||||
}//else if//
|
||||
}//isChangeable()//
|
||||
/**
|
||||
* Verifies that the collection may be modified.
|
||||
* @throws IllegalOperationException If the isImmutable flag is set.
|
||||
*/
|
||||
protected void verifyIsChangeable() {
|
||||
//If the collection is immutable then the operation should never be allowed.//
|
||||
if(!isChangeable) {
|
||||
throw new IllegalOperationException(IMMUTABLE_EXCEPTION_MESSAGE);
|
||||
}//if//
|
||||
}//verifyIsChangeable()//
|
||||
/**
|
||||
* Adds a value to the set.
|
||||
* @param value The value to be added.
|
||||
* @return Whether the value was successfully added.
|
||||
*/
|
||||
public boolean add(int value) {
|
||||
verifyIsChangeable();
|
||||
|
||||
return internalAdd(value);
|
||||
}//add()//
|
||||
/**
|
||||
* Adds all given values to the set.
|
||||
* @param values The values to be added.
|
||||
* @return Whether all the values were successfully added (if false then some may have been added).
|
||||
*/
|
||||
public boolean addAll(int[] values) {
|
||||
boolean result = true;
|
||||
|
||||
verifyIsChangeable();
|
||||
|
||||
for(int index = 0; index < values.length; index++) {
|
||||
result &= internalAdd(values[index]);
|
||||
}//for//
|
||||
|
||||
return result;
|
||||
}//addAll()//
|
||||
/**
|
||||
* Removes a value from the set.
|
||||
* @param value The value to be removed.
|
||||
* @return Whether the value was successfully removed.
|
||||
*/
|
||||
public boolean remove(int value) {
|
||||
verifyIsChangeable();
|
||||
|
||||
return internalRemove(value);
|
||||
}//remove()//
|
||||
/**
|
||||
* Removes all given values from the set.
|
||||
* @param values The values to be removed.
|
||||
* @return Whether all the values were successfully removed.
|
||||
*/
|
||||
public boolean removeAll(int[] values) {
|
||||
boolean result = true;
|
||||
|
||||
verifyIsChangeable();
|
||||
|
||||
for(int index = 0; index < values.length; index++) {
|
||||
result &= internalRemove(values[index]);
|
||||
}//for//
|
||||
|
||||
return result;
|
||||
}//removeAll()//
|
||||
/**
|
||||
* Removes all values from the set.
|
||||
* @return Whether the values were successfully removed.
|
||||
*/
|
||||
public boolean removeAll() {
|
||||
verifyIsChangeable();
|
||||
|
||||
return internalRemoveAll();
|
||||
}//removeAll()//
|
||||
/**
|
||||
* Tests to see if the specified value is contained in the collection.
|
||||
* @param value Object The value to test for.
|
||||
* @return boolean Will return true if the value is contained in the collection.
|
||||
*/
|
||||
public boolean containsValue(int value) {
|
||||
int index = (value & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(HashSetEntry e = entries[index]; e != null; e = e.next) {
|
||||
if(e.value == value) {
|
||||
return true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return false;
|
||||
}//containsValue()//
|
||||
/**
|
||||
* Creates or reuses an entry.
|
||||
*/
|
||||
protected HashSetEntry createEntry() {
|
||||
return new HashSetEntry();
|
||||
}//createEntry()//
|
||||
/**
|
||||
* Destroys or reuses an entry.
|
||||
*/
|
||||
protected void destroyEntry(HashSetEntry entry) {
|
||||
entry.next = null;
|
||||
}//destroyEntry()//
|
||||
/**
|
||||
* Gets the number of values in the set.
|
||||
* @return The number of values in the set.
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}//getSize()//
|
||||
/**
|
||||
* Performs the actual add of the value.
|
||||
* @param value The value to be added.
|
||||
*/
|
||||
protected boolean internalAdd(int value) {
|
||||
int index = (value & 0x7FFFFFFF) % entries.length;
|
||||
HashSetEntry entry = null;
|
||||
|
||||
for(entry = entries[index]; entry != null; entry = entry.next) {
|
||||
if(entry.value == value) {
|
||||
return false;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
if(size >= threshold) {
|
||||
rehash();
|
||||
|
||||
return internalAdd(value);
|
||||
}//if//
|
||||
|
||||
entry = createEntry();
|
||||
entry.value = value;
|
||||
entry.next = entries[index];
|
||||
entries[index] = entry;
|
||||
size++;
|
||||
|
||||
return true;
|
||||
}//internalAdd()//
|
||||
/**
|
||||
* Handles removing a value from the collection.
|
||||
* @param value The value to remove.
|
||||
* @return Will be <code>true</code> upon success.
|
||||
*/
|
||||
protected boolean internalRemove(int value) {
|
||||
int index = (value & 0x7FFFFFFF) % entries.length;
|
||||
HashSetEntry entry = null;
|
||||
HashSetEntry previous = null;
|
||||
|
||||
for(entry = entries[index], previous = null; entry != null; previous = entry, entry = entry.next) {
|
||||
if(entry.value == value) {
|
||||
if(previous != null) {
|
||||
previous.next = entry.next;
|
||||
}//if//
|
||||
else {
|
||||
entries[index] = entry.next;
|
||||
}//else//
|
||||
|
||||
size--;
|
||||
destroyEntry(entry);
|
||||
|
||||
return true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return false;
|
||||
}//internalRemove()//
|
||||
/**
|
||||
* Handles removing all values from the collection.
|
||||
* @return boolean Will return <code>true</code> upon success.
|
||||
*/
|
||||
protected boolean internalRemoveAll() {
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
entries[index] = null;
|
||||
}//for//
|
||||
|
||||
size = 0;
|
||||
|
||||
return true;
|
||||
}//internalRemoveAll()//
|
||||
/**
|
||||
* Handles replacing one value with another in the collection.
|
||||
* @param oldValue The value to be replaced.
|
||||
* @param newValue The value to replace the old one.
|
||||
* @return Will be <code>true</code>
|
||||
*/
|
||||
protected boolean internalReplace(int oldValue, int newValue) {
|
||||
throw new MethodNotSupportedException();
|
||||
}//internalReplace()//
|
||||
/**
|
||||
* Gets a new iterator over the values in this collection.
|
||||
* @return IIterator The iterator that may be used to iterate over the collection values.
|
||||
*/
|
||||
public IIntIterator iterator() {
|
||||
return new HashSetIterator(this);
|
||||
}//iterator()//
|
||||
/**
|
||||
* Rehashes the collection so that new items may be added without going over the recommended ratio of values to list entries.
|
||||
*/
|
||||
protected void rehash() {
|
||||
int oldCapacity = entries.length;
|
||||
HashSetEntry[] oldEntries = entries;
|
||||
int newCapacity = (oldCapacity << 1) + 1;
|
||||
HashSetEntry[] newEntries = new HashSetEntry[newCapacity];
|
||||
|
||||
threshold = (int)(newCapacity * loadFactor);
|
||||
entries = newEntries;
|
||||
|
||||
for(int oldIndex = oldCapacity; oldIndex-- > 0; ) {
|
||||
for(HashSetEntry oldEntry = oldEntries[oldIndex]; oldEntry != null; ) {
|
||||
HashSetEntry newEntry = oldEntry;
|
||||
int newIndex;
|
||||
|
||||
oldEntry = oldEntry.next;
|
||||
newIndex = (newEntry.value & 0x7FFFFFFF) % newCapacity;
|
||||
newEntry.next = newEntries[newIndex];
|
||||
newEntries[newIndex] = newEntry;
|
||||
}//for//
|
||||
}//for//
|
||||
}//rehash()//
|
||||
/**
|
||||
* Fills an array with collection values.
|
||||
* @param array An array capable of containing collection values.
|
||||
* @return The number of values placed in the array.
|
||||
*/
|
||||
public int toArray(int[] array) {
|
||||
HashSetEntry entry = null;
|
||||
int position = 0;
|
||||
HashSetEntry[] entries = this.entries;
|
||||
|
||||
//Iterate over the entry table.//
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
entry = entries[index];
|
||||
|
||||
//Iterate through the entries at this table position.//
|
||||
while(entry != null) {
|
||||
array[position] = entry.value;
|
||||
entry = entry.next;
|
||||
position++;
|
||||
}//while//
|
||||
}//for//
|
||||
|
||||
return position;
|
||||
}//toArray()//
|
||||
/**
|
||||
* Generates a string representing the hashset.
|
||||
* @return A debug string that represents this object.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer(100);
|
||||
|
||||
buffer.append("IntHashSet {\r\n");
|
||||
|
||||
try {
|
||||
IIntIterator iterator = iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
buffer.append("\t");
|
||||
buffer.append(iterator.next());
|
||||
buffer.append("\r\n");
|
||||
}//while//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
|
||||
buffer.append("}");
|
||||
|
||||
return buffer.toString();
|
||||
}//toArray()//
|
||||
}//IntHashSet//
|
||||
286
Common/src/com/common/util/optimized/IntIntHashMap.java
Normal file
286
Common/src/com/common/util/optimized/IntIntHashMap.java
Normal file
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.util.*;
|
||||
|
||||
/**
|
||||
* This collection maps a value by a key.
|
||||
*/
|
||||
public class IntIntHashMap extends Map implements IIntIntHashMap {
|
||||
private int[] keys = null;
|
||||
private int keyCount = 0;
|
||||
|
||||
/**
|
||||
* The Entry wrappers the key/value pair.
|
||||
*/
|
||||
protected static class Entry extends BasicEntry {
|
||||
public int key = 0;
|
||||
public int value = IIntIntHashMap.NULL_VALUE;
|
||||
|
||||
protected Entry() {
|
||||
super();
|
||||
}//Entry()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
super.readExternal(in);
|
||||
key = in.readInt();
|
||||
value = in.readInt();
|
||||
}//readExternal()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
super.writeExternal(out);
|
||||
out.writeInt(key);
|
||||
out.writeInt(value);
|
||||
}//writeExternal()//
|
||||
public int createKeyHash() {
|
||||
return key;
|
||||
}//createKeyHash()//
|
||||
public String toString() {
|
||||
return super.toString() + "\r\n\thash: " + hash + "\r\n\tkey: " + key + "\r\n\tvalue: " + value + (next != null ? ("\r\n" + next.toString()) : "");
|
||||
}//toString()//
|
||||
}//Entry//
|
||||
|
||||
public static class KeyIterator extends Iterator implements IIntIterator {
|
||||
public KeyIterator(IntIntHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//KeyIterator()//
|
||||
public int next() {
|
||||
return ((Entry) nextEntry()).key;
|
||||
}//next()//
|
||||
public int previous() {
|
||||
return ((Entry) previousEntry()).key;
|
||||
}//previous()//
|
||||
}//KeyIterator//
|
||||
|
||||
public static class ValueIterator extends Iterator implements IIntIterator {
|
||||
public ValueIterator(IntIntHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//ValueIterator()//
|
||||
public int next() {
|
||||
return ((Entry) nextEntry()).value;
|
||||
}//next()//
|
||||
public int previous() {
|
||||
return ((Entry) previousEntry()).value;
|
||||
}//previous()//
|
||||
}//ValueIterator//
|
||||
/**
|
||||
* IntIntHashMap constructor.
|
||||
*/
|
||||
public IntIntHashMap() {
|
||||
this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR);
|
||||
}//IntIntHashMap()//
|
||||
/**
|
||||
* IntIntHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public IntIntHashMap(int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR);
|
||||
}//IntIntHashMap()//
|
||||
/**
|
||||
* IntIntHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public IntIntHashMap(int initialCapacity, float loadFactor) {
|
||||
super(initialCapacity, loadFactor);
|
||||
}//IntIntHashMap()//
|
||||
/**
|
||||
* @see IIntIntHashMap.containsKey(int)
|
||||
*/
|
||||
public boolean containsKey(int key) {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = key;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
boolean retVal = false;
|
||||
|
||||
for(Entry entry = (Entry) entries[index]; (!retVal) && (entry != null); entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (entry.key == key)) {
|
||||
retVal = true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return retVal;
|
||||
}//containsKey()//
|
||||
/**
|
||||
* Will create an entry object of the specific type used by this map.
|
||||
* @return BasicEntry An entry object that can be filled and passed to the addEntry method.
|
||||
*/
|
||||
protected IBasicEntry createEntry() {
|
||||
return new Entry();
|
||||
}//createEntry()//
|
||||
/**
|
||||
* @see IIntIntHashMap.get(int)
|
||||
*/
|
||||
public int get(int key) {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = key;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(Entry entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (entry.key == key)) {
|
||||
return entry.value;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return IIntIntHashMap.NULL_VALUE;
|
||||
}//get()//
|
||||
/**
|
||||
* This method will get the key at the given index.
|
||||
* <p>NOTE: This method is intended for use by the iterators and it is not advisable to use this method else where.
|
||||
* @param index The index in the list of keys.
|
||||
* @return The key at the given index.
|
||||
*/
|
||||
public int getKey(int index) {
|
||||
if(keys == null) {
|
||||
refreshKeys();
|
||||
}//if//
|
||||
|
||||
return keys[index];
|
||||
}//get()//
|
||||
/**
|
||||
* This will invalidate the collection of keys.
|
||||
* This should occur when a value is added/removed/changed in a way that invalidates the collection of keys.
|
||||
*/
|
||||
protected void invalidateKeys() {
|
||||
keys = null;
|
||||
keyCount = 0;
|
||||
}//invalidateKeys()//
|
||||
/**
|
||||
* @see IIntIntHashMap.keyIterator()
|
||||
*/
|
||||
public IIntIterator keyIterator() {
|
||||
return new KeyIterator(this);
|
||||
}//keyIterator()//
|
||||
/**
|
||||
* @see IIntIntHashMap.put(int, int)
|
||||
*/
|
||||
public int put(int key, int value) {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = key;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry entry = null;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Try to locate an existing value.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (entry.key == key)) {
|
||||
int oldValue = entry.value;
|
||||
|
||||
entry.value = value;
|
||||
|
||||
return oldValue;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Determine if we need to re-hash.//
|
||||
if(resize(getSize() + 1)) {
|
||||
entries = getEntries();
|
||||
//Recalculate the insertion index if the map resized.//
|
||||
index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
}//if//
|
||||
|
||||
//Create and add the new entry.//
|
||||
entry = (Entry) createEntry();
|
||||
entry.hash = hash;
|
||||
entry.key = key;
|
||||
entry.value = value;
|
||||
addEntry(index, entry);
|
||||
|
||||
if(keys != null) {
|
||||
//Just add the key instead of invalidating the keys collection.//
|
||||
if(keyCount == keys.length) {
|
||||
int[] temp = new int[keys.length < 50 ? keys.length << 1 : keys.length + 100];
|
||||
|
||||
System.arraycopy(keys, 0, temp, 0, keys.length);
|
||||
keys = temp;
|
||||
keys[keyCount++] = key;
|
||||
}//if//
|
||||
|
||||
keys[keyCount++] = key;
|
||||
keyCount++;
|
||||
}//if//
|
||||
|
||||
return IIntIntHashMap.NULL_VALUE;
|
||||
}//put()//
|
||||
/**
|
||||
* Will recreate the collection of keys.
|
||||
*/
|
||||
protected void refreshKeys() {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int index;
|
||||
Entry entry;
|
||||
|
||||
keys = new int[getSize() + 10];
|
||||
|
||||
for(index = 0; index < entries.length; index++) {
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
keys[index] = entry.key;
|
||||
keyCount++;
|
||||
}//for//
|
||||
}//for//
|
||||
}//refreshKeys()//
|
||||
/**
|
||||
* Will optimize the collection of Entry objects to improve access time.
|
||||
* @param arrayLength int The new length of the entry array.
|
||||
*/
|
||||
protected void rehash(int arrayLength) {
|
||||
super.rehash(arrayLength);
|
||||
//Invalidate the list of keys.//
|
||||
invalidateKeys();
|
||||
}//rehash()//
|
||||
/**
|
||||
* @see IIntIntHashMap.remove(int)
|
||||
*/
|
||||
public int remove(int key) {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = key;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry previousEntry = null;
|
||||
Entry entry = null;
|
||||
int retVal = IIntIntHashMap.NULL_VALUE;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Iterate through the entries stored at the key's hash location and remove the given key.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (entry.key == key)) {
|
||||
//Save the removed value.//
|
||||
retVal = entry.value;
|
||||
//Remove the entry from the map.//
|
||||
removeEntry(index, previousEntry);
|
||||
//Could find the key in the collection and remove it, but that may take to long.//
|
||||
invalidateKeys();
|
||||
//Break from the loop so we can exit.//
|
||||
break;
|
||||
}//if//
|
||||
|
||||
previousEntry = entry;
|
||||
}//for//
|
||||
|
||||
return retVal;
|
||||
}//remove()//
|
||||
/**
|
||||
* @see IIntIntHashMap.removeAll()
|
||||
*/
|
||||
public boolean removeAll() {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
invalidateKeys();
|
||||
removeAllEntries();
|
||||
|
||||
return true;
|
||||
}//removeAll()//
|
||||
/**
|
||||
* @see IIntIntHashMap.valueIterator()
|
||||
*/
|
||||
public IIntIterator valueIterator() {
|
||||
return new ValueIterator(this);
|
||||
}//valueIterator()//
|
||||
}//IntIntHashMap//
|
||||
316
Common/src/com/common/util/optimized/IntObjectHashMap.java
Normal file
316
Common/src/com/common/util/optimized/IntObjectHashMap.java
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.util.*;
|
||||
import com.common.comparison.*;
|
||||
|
||||
/**
|
||||
* This collection maps a value by a key.
|
||||
*/
|
||||
public class IntObjectHashMap extends Map implements IIntObjectHashMap {
|
||||
private int[] keys = null;
|
||||
private int keyCount = 0;
|
||||
|
||||
/**
|
||||
* The Entry wrappers the key/value pair.
|
||||
*/
|
||||
protected static class Entry extends BasicEntry {
|
||||
public int key = 0;
|
||||
public Object value = null;
|
||||
|
||||
protected Entry() {
|
||||
super();
|
||||
}//Entry()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
super.readExternal(in);
|
||||
key = in.readInt();
|
||||
value = in.readObject();
|
||||
}//readExternal()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
super.writeExternal(out);
|
||||
out.writeInt(key);
|
||||
out.writeObject(value);
|
||||
}//writeExternal()//
|
||||
public int createKeyHash() {
|
||||
return key;
|
||||
}//createKeyHash()//
|
||||
public String toString() {
|
||||
return super.toString() + "\r\n\thash: " + hash + "\r\n\tkey: " + key + "\r\n\tvalue: " + (value != null ? value.toString() : "null") + (next != null ? ("\r\n" + next.toString()) : "");
|
||||
}//toString()//
|
||||
}//Entry//
|
||||
|
||||
public static class KeyIterator extends Iterator implements IIntIterator {
|
||||
public KeyIterator(IntObjectHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//KeyIterator()//
|
||||
public int next() {
|
||||
return ((Entry) nextEntry()).key;
|
||||
}//next()//
|
||||
public int previous() {
|
||||
return ((Entry) previousEntry()).key;
|
||||
}//previous()//
|
||||
}//KeyIterator//
|
||||
|
||||
public static class ValueIterator extends Iterator implements IReversableIterator {
|
||||
public ValueIterator(IntObjectHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//ValueIterator()//
|
||||
public Object next() {
|
||||
return ((Entry) nextEntry()).value;
|
||||
}//next()//
|
||||
public Object previous() {
|
||||
return ((Entry) previousEntry()).value;
|
||||
}//previous()//
|
||||
}//ValueIterator//
|
||||
/**
|
||||
* IntObjectHashMap constructor.
|
||||
*/
|
||||
protected IntObjectHashMap() {
|
||||
this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, DEFAULT_VALUE_COMPARATOR);
|
||||
}//IntObjectHashMap()//
|
||||
/**
|
||||
* IntObjectHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public IntObjectHashMap(int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_VALUE_COMPARATOR);
|
||||
}//IntObjectHashMap()//
|
||||
/**
|
||||
* IntObjectHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public IntObjectHashMap(int initialCapacity, float loadFactor) {
|
||||
this(initialCapacity, loadFactor, DEFAULT_VALUE_COMPARATOR);
|
||||
}//IntObjectHashMap()//
|
||||
/**
|
||||
* IntObjectHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public IntObjectHashMap(int initialCapacity, float loadFactor, IComparator valueComparator) {
|
||||
super(initialCapacity, loadFactor, null, valueComparator);
|
||||
}//IntObjectHashMap()//
|
||||
/**
|
||||
* IntObjectHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public IntObjectHashMap(int initialCapacity, IComparator valueComparator) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, valueComparator);
|
||||
}//IntObjectHashMap()//
|
||||
/**
|
||||
* @see IIntObjectHashMap.containsKey(int)
|
||||
*/
|
||||
public boolean containsKey(int key) {
|
||||
return get(key) != null;
|
||||
}//containsKey()//
|
||||
/**
|
||||
* Will create an entry object of the specific type used by this map.
|
||||
* @return BasicEntry An entry object that can be filled and passed to the addEntry method.
|
||||
*/
|
||||
protected IBasicEntry createEntry() {
|
||||
return new Entry();
|
||||
}//createEntry()//
|
||||
/**
|
||||
* Gets the first available value in the map.
|
||||
* @return The first accessable value in the map.
|
||||
*/
|
||||
public Object getFirst() {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
for(Entry entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if(entry != null) {
|
||||
return entry.value;
|
||||
}//if//
|
||||
}//for//
|
||||
}//for//
|
||||
|
||||
return null;
|
||||
}//getFirst()//
|
||||
/**
|
||||
* @see IIntObjectHashMap.get(int)
|
||||
*/
|
||||
public Object get(int key) {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = key;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(Entry entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (entry.key == key)) {
|
||||
return entry.value;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return null;
|
||||
}//get()//
|
||||
/**
|
||||
* This method will get the key at the given index.
|
||||
* <p>NOTE: This method is intended for use by the iterators and it is not advisable to use this method else where.
|
||||
* @param index The index in the list of keys.
|
||||
* @return The key at the given index.
|
||||
*/
|
||||
public int getKey(int index) {
|
||||
if(keys == null) {
|
||||
refreshKeys();
|
||||
}//if//
|
||||
|
||||
return keys[index];
|
||||
}//get()//
|
||||
/**
|
||||
* This will invalidate the collection of keys.
|
||||
* This should occur when a value is added/removed/changed in a way that invalidates the collection of keys.
|
||||
*/
|
||||
protected void invalidateKeys() {
|
||||
keys = null;
|
||||
keyCount = 0;
|
||||
}//invalidateKeys()//
|
||||
/**
|
||||
* @see IIntObjectHashMap.keyIterator()
|
||||
*/
|
||||
public IIntIterator keyIterator() {
|
||||
return new KeyIterator(this);
|
||||
}//keyIterator()//
|
||||
/**
|
||||
* @see IIntObjectHashMap.put(int, Object)
|
||||
*/
|
||||
public Object put(int key, Object value) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
if(value == null) {
|
||||
//Remove the key if it exists because you cannot associate a key with a null value.//
|
||||
return remove(key);
|
||||
}//if//
|
||||
else {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = key;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry entry = null;
|
||||
|
||||
//Try to locate an existing value.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (entry.key == key)) {
|
||||
Object oldValue = entry.value;
|
||||
|
||||
entry.value = value;
|
||||
|
||||
return oldValue;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Determine if we need to re-hash.//
|
||||
if(resize(getSize() + 1)) {
|
||||
entries = getEntries();
|
||||
//Recalculate the insertion index if the map resized.//
|
||||
index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
}//if//
|
||||
|
||||
//Create and add the new entry.//
|
||||
entry = (Entry) createEntry();
|
||||
entry.hash = hash;
|
||||
entry.key = key;
|
||||
entry.value = value;
|
||||
addEntry(index, entry);
|
||||
|
||||
if(keys != null) {
|
||||
//Just add the key instead of invalidating the keys collection.//
|
||||
if(keyCount == keys.length) {
|
||||
int[] temp = new int[keys.length < 50 ? keys.length << 1 : keys.length + 100];
|
||||
|
||||
System.arraycopy(keys, 0, temp, 0, keys.length);
|
||||
keys = temp;
|
||||
keys[keyCount++] = key;
|
||||
}//if//
|
||||
|
||||
keys[keyCount++] = key;
|
||||
keyCount++;
|
||||
}//if//
|
||||
|
||||
return null;
|
||||
}//else//
|
||||
}//put()//
|
||||
/**
|
||||
* Will recreate the collection of keys.
|
||||
*/
|
||||
protected void refreshKeys() {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int index;
|
||||
Entry entry;
|
||||
|
||||
keys = new int[getSize() + 10];
|
||||
|
||||
for(index = 0; index < entries.length; index++) {
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
keys[index] = entry.key;
|
||||
keyCount++;
|
||||
}//for//
|
||||
}//for//
|
||||
}//refreshKeys()//
|
||||
/**
|
||||
* Will optimize the collection of Entry objects to improve access time.
|
||||
* @param arrayLength int The new length of the entry array.
|
||||
*/
|
||||
protected void rehash(int arrayLength) {
|
||||
super.rehash(arrayLength);
|
||||
//Invalidate the list of keys.//
|
||||
invalidateKeys();
|
||||
}//rehash()//
|
||||
/**
|
||||
* @see IIntObjectHashMap.remove(int)
|
||||
*/
|
||||
public Object remove(int key) {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = key;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry previousEntry = null;
|
||||
Entry entry = null;
|
||||
Object retVal = null;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Iterate through the entries stored at the key's hash location and remove the given key.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (entry.key == key)) {
|
||||
//Save the removed value.//
|
||||
retVal = entry.value;
|
||||
//Remove the entry from the map.//
|
||||
removeEntry(index, previousEntry);
|
||||
//Could find the key in the collection and remove it, but that may take to long.//
|
||||
invalidateKeys();
|
||||
//Break from the loop so we can exit.//
|
||||
break;
|
||||
}//if//
|
||||
|
||||
previousEntry = entry;
|
||||
}//for//
|
||||
|
||||
return retVal;
|
||||
}//remove()//
|
||||
/**
|
||||
* @see IIntObjectHashMap.removeAll()
|
||||
*/
|
||||
public boolean removeAll() {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
invalidateKeys();
|
||||
removeAllEntries();
|
||||
|
||||
return true;
|
||||
}//removeAll()//
|
||||
/**
|
||||
* @see IIntObjectHashMap.valueIterator()
|
||||
*/
|
||||
public IIterator valueIterator() {
|
||||
return new ValueIterator(this);
|
||||
}//valueIterator()//
|
||||
}//IntObjectHashMap//
|
||||
337
Common/src/com/common/util/optimized/LongArray.java
Normal file
337
Common/src/com/common/util/optimized/LongArray.java
Normal file
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* Copyright (c) 2007,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
/**
|
||||
* <p>WARNING: This is a Lite collection and does not have any synchronization (NOT THREAD SAFE).
|
||||
* <p>This class maintains a collection of long values using an interface similar to IList.
|
||||
*/
|
||||
public class LongArray implements ILongArray {
|
||||
private long[] array = null;
|
||||
private int count = 0;
|
||||
private int incrementSize = 0;
|
||||
|
||||
public static class Iterator implements ILongIterator {
|
||||
private LongArray array = null;
|
||||
private int index = 0;
|
||||
|
||||
public Iterator(LongArray array) {
|
||||
this.array = array;
|
||||
}//Iterator()//
|
||||
public boolean hasNext() {
|
||||
return index < array.getSize();
|
||||
}//hasNext()//
|
||||
public long next() {
|
||||
return array.get(index++);
|
||||
}//next()//
|
||||
public void resetToFront() {
|
||||
this.index = 0;
|
||||
}//resetToFront()//
|
||||
}//KeyIterator//
|
||||
/**
|
||||
* LongArray constructor.
|
||||
*/
|
||||
public LongArray() {
|
||||
this(10, 10);
|
||||
}//LongArray()//
|
||||
/**
|
||||
* LongArray constructor.
|
||||
*/
|
||||
public LongArray(int initialSize) {
|
||||
this(initialSize, 10);
|
||||
}//LongArray()//
|
||||
/**
|
||||
* LongArray constructor.
|
||||
*/
|
||||
public LongArray(int initialSize, int incrementSize) {
|
||||
super();
|
||||
|
||||
if(initialSize <= 0) {
|
||||
//TODO: Throw exception.//
|
||||
initialSize = 1;
|
||||
}//if//
|
||||
|
||||
this.array = new long[initialSize];
|
||||
this.incrementSize = incrementSize;
|
||||
}//LongArray()//
|
||||
/**
|
||||
* LongArray constructor.
|
||||
* @param copy The long array to clone.
|
||||
*/
|
||||
public LongArray(LongArray copy) {
|
||||
super();
|
||||
|
||||
this.array = new long[copy.count + copy.incrementSize];
|
||||
this.incrementSize = copy.incrementSize;
|
||||
System.arraycopy(copy.array, 0, this.array, 0, copy.count);
|
||||
this.count = copy.count;
|
||||
}//LongArray()//
|
||||
/**
|
||||
* Adds a value to the collection.
|
||||
* @param value The value to add to the collection.
|
||||
*/
|
||||
public void add(long value) {
|
||||
internalAdd(value);
|
||||
}//add()//
|
||||
/**
|
||||
* Adds a value to the collection at the given index.
|
||||
* @param index The index of the new value.
|
||||
* @param value The value to add to the collection.
|
||||
*/
|
||||
public void add(int index, long value) {
|
||||
internalAdd(value, index);
|
||||
}//add()//
|
||||
/**
|
||||
* Adds values to the collection.
|
||||
* @param values The array of values to add to the collection.
|
||||
*/
|
||||
public void addAll(long[] values) {
|
||||
for(int index = 0; index < values.length; index++) {
|
||||
internalAdd(values[index]);
|
||||
}//for//
|
||||
}//addAll()//
|
||||
/**
|
||||
* Adds values to the collection.
|
||||
* @param values The collection of values to add to the collection.
|
||||
*/
|
||||
public void addAll(LongArray values) {
|
||||
for(int index = 0; index < values.getSize(); index++) {
|
||||
internalAdd(values.get(index));
|
||||
}//for//
|
||||
}//addAll()//
|
||||
/**
|
||||
* Determines whether the value is contained in the collection.
|
||||
* @param value The value to look for.
|
||||
* @return Whether the given value is in the collection.
|
||||
*/
|
||||
public boolean containsValue(long value) {
|
||||
return getIndexOf(value) != -1;
|
||||
}//containsValue()//
|
||||
/**
|
||||
* Gets a value at a given index.
|
||||
* @param index The index of the value to retrieve.
|
||||
* @return The value at that index.
|
||||
*/
|
||||
public long get(int index) {
|
||||
if((index >= 0) && (index < count)) {
|
||||
return array[index];
|
||||
}//if//
|
||||
else {
|
||||
throw new IndexOutOfBoundsException(index + " not in [0.." + count + ").");
|
||||
}//else//
|
||||
}//get()//
|
||||
/**
|
||||
* Gets a value's index in the collection.
|
||||
* @param value The value whose index is to be retrieved.
|
||||
* @return The value's index.
|
||||
*/
|
||||
public int getIndexOf(long value) {
|
||||
int index = 0;
|
||||
|
||||
for(; index < count; index++) {
|
||||
if(array[index] == value) {
|
||||
break;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return index < count ? index : -1;
|
||||
}//getIndexOf()//
|
||||
/**
|
||||
* Gets the number of values in the collection.
|
||||
* @return The number of values stored in this collection.
|
||||
*/
|
||||
public int getSize() {
|
||||
return count;
|
||||
}//getSize()//
|
||||
/**
|
||||
* Adds a value to the collection.
|
||||
* @param value The value to add to the collection.
|
||||
*/
|
||||
protected void internalAdd(long value) {
|
||||
if(count == array.length) {
|
||||
resize();
|
||||
}//if//
|
||||
|
||||
array[count++] = value;
|
||||
}//internalAdd()//
|
||||
/**
|
||||
* Adds a value to the collection at the given index.
|
||||
* @param value The value to add to the collection.
|
||||
* @param index The index of the new value.
|
||||
*/
|
||||
protected void internalAdd(long value, int index) {
|
||||
if(count == array.length) {
|
||||
resize();
|
||||
}//if//
|
||||
|
||||
if(index == count) {
|
||||
array[count++] = value;
|
||||
}//if//
|
||||
else {
|
||||
System.arraycopy(array, index, array, index + 1, count - index);
|
||||
array[index] = value;
|
||||
count++;
|
||||
}//else//
|
||||
}//internalAdd()//
|
||||
/**
|
||||
* Removes a value from the collection by its' index.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @return The value at the removed index.
|
||||
*/
|
||||
protected long internalRemove(int index) {
|
||||
long result;
|
||||
|
||||
if((index >= count) && (index < 0)) {
|
||||
throw new IndexOutOfBoundsException(index + " not in [0.." + count + ").");
|
||||
}//if//
|
||||
|
||||
if(index != count - 1) {
|
||||
System.arraycopy(array, index + 1, array, index, array.length - index - 1);
|
||||
}//if//
|
||||
|
||||
result = array[index];
|
||||
array[--count] = 0;
|
||||
|
||||
return result;
|
||||
}//internalRemove()//
|
||||
/**
|
||||
* Removes all collection values.
|
||||
* @return Whether all values were properly removed.
|
||||
*/
|
||||
protected boolean internalRemoveAll() {
|
||||
boolean result = true;
|
||||
|
||||
while(count != 0) {
|
||||
array[--count] = 0;
|
||||
}//while//
|
||||
|
||||
return result;
|
||||
}//internalRemoveAll()//
|
||||
/**
|
||||
* Gets an iterator over the values in this collection.
|
||||
* @return An iterator over the collection values.
|
||||
*/
|
||||
public ILongIterator iterator() {
|
||||
return new Iterator(this);
|
||||
}//iterator()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ILongArray#remove(long)
|
||||
*/
|
||||
public long remove(int index) {
|
||||
return internalRemove(index);
|
||||
}//remove()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ILongArray#removeFirst()
|
||||
*/
|
||||
public long removeFirst() {
|
||||
return internalRemove(0);
|
||||
}//removeFirst()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.util.optimized.ILongArray#removeLast()
|
||||
*/
|
||||
public long removeLast() {
|
||||
return internalRemove(count - 1);
|
||||
}//removeLast()//
|
||||
/**
|
||||
* Removes all collection values.
|
||||
* @return Whether all values were properly removed.
|
||||
*/
|
||||
public boolean removeAll() {
|
||||
return internalRemoveAll();
|
||||
}//removeAll()//
|
||||
/**
|
||||
* Replaces a value in the collection at a specific index, with a new value.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @param value The new value at the given index.
|
||||
*/
|
||||
public void replace(int index, long value) {
|
||||
replaceLongInternal(index, value);
|
||||
}//replace()//
|
||||
/**
|
||||
* Replaces a value in the collection at a specific index, with a new value.
|
||||
* @param index The index of the value to remove from the collection.
|
||||
* @param value The new value at the given index.
|
||||
*/
|
||||
protected void replaceLongInternal(int index, long value) {
|
||||
if((index >= count) && (index < 0)) {
|
||||
throw new IndexOutOfBoundsException(index + " not in [0.." + count + ").");
|
||||
}//if//
|
||||
|
||||
array[count] = value;
|
||||
}//replaceLongInternal()//
|
||||
/**
|
||||
* Resizes the collection by adding the increment size to the current size.
|
||||
*/
|
||||
protected void resize() {
|
||||
resize(array.length + incrementSize);
|
||||
}//resize()//
|
||||
/**
|
||||
* Resizes the collection to the requested size.
|
||||
* @param newSize The new size of the collection buffer.
|
||||
*/
|
||||
protected void resize(int newSize) {
|
||||
long[] temp = new long[newSize];
|
||||
|
||||
System.arraycopy(array, 0, temp, 0, array.length);
|
||||
array = temp;
|
||||
|
||||
if(array.length < count) {
|
||||
count = array.length;
|
||||
}//if//
|
||||
}//resize()//
|
||||
/**
|
||||
* Fills an array with collection values.
|
||||
* @return An exact sized array containing all values in the collection.
|
||||
*/
|
||||
public long[] toArray() {
|
||||
long[] result = new long[count];
|
||||
|
||||
System.arraycopy(this.array, 0, result, 0, count);
|
||||
|
||||
return result;
|
||||
}//toArray()//
|
||||
/**
|
||||
* Fills an array with collection values.
|
||||
* @param array An array capable of containing collection values.
|
||||
* @return The number of elements copied into the array.
|
||||
*/
|
||||
public long toArray(long[] array) {
|
||||
int size = array.length;
|
||||
|
||||
size = count > size ? count : size;
|
||||
System.arraycopy(this.array, 0, array, 0, size);
|
||||
|
||||
return size;
|
||||
}//toArray()//
|
||||
/**
|
||||
* Outputs the collection of items for debugging purposes.
|
||||
* @return A string displaying the list of items.
|
||||
*/
|
||||
public String toString() {
|
||||
int max = getSize() - 1;
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
//Add a begin brace.//
|
||||
buffer.append("[");
|
||||
|
||||
for(int index = 0; index <= max; index++) {
|
||||
//Append the item to the output string.//
|
||||
buffer.append(get(index));
|
||||
|
||||
//Append a comma if this isn't the last item in the list.//
|
||||
if(index < max) {
|
||||
buffer.append(", ");
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Add a end brace.//
|
||||
buffer.append("]");
|
||||
|
||||
return buffer.toString();
|
||||
}//toString()//
|
||||
}//LongArray()//
|
||||
366
Common/src/com/common/util/optimized/LongHashSet.java
Normal file
366
Common/src/com/common/util/optimized/LongHashSet.java
Normal file
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.debug.*;
|
||||
import com.common.exception.*;
|
||||
|
||||
/**
|
||||
* An collection that stores long values so that they can be easily found and the collection can be manipulated rapidly.
|
||||
* Collection modification is very fast, and determining whether a value is in the collection is very fast.
|
||||
* Collection iteration is a bit slower than in a standard list, and indexing is not available.
|
||||
*/
|
||||
public class LongHashSet {
|
||||
public static final int DEFAULT_INITIAL_CAPACITY = 51;
|
||||
public static final float DEFAULT_LOAD_FACTOR = 0.75f;
|
||||
|
||||
private HashSetEntry[] entries;
|
||||
private int size;
|
||||
private int threshold;
|
||||
private float loadFactor;
|
||||
|
||||
/**
|
||||
* The entry class used to store HashSet values.
|
||||
*/
|
||||
private static class HashSetEntry {
|
||||
int hash;
|
||||
long value;
|
||||
HashSetEntry next;
|
||||
|
||||
private HashSetEntry() {
|
||||
}//HashSetEntry()//
|
||||
}//HashSetEntry//
|
||||
|
||||
/**
|
||||
* An iterator that can be used to iterate over the HashSet values.
|
||||
* <p>WARNING: While this class can be serialized, it will reset its' position to the start of the HashSet.
|
||||
* Also, the HashSet will be serialized with the iterator.
|
||||
* <p>This class is NOT thread safe.
|
||||
*/
|
||||
public static class HashSetIterator implements ILongIterator {
|
||||
private LongHashSet hashSet = null;
|
||||
private int currentIndex = -1;
|
||||
private HashSetEntry currentEntry = null;
|
||||
private int nextIndex = -1;
|
||||
private HashSetEntry nextEntry = null;
|
||||
private boolean hasNextEntry = false;
|
||||
|
||||
private HashSetIterator(LongHashSet hashSet) {
|
||||
this.hashSet = hashSet;
|
||||
}//HashSetIterator()//
|
||||
public void resetToFront() {
|
||||
currentIndex = -1;
|
||||
currentEntry = null;
|
||||
nextIndex = -1;
|
||||
nextEntry = null;
|
||||
hasNextEntry = false;
|
||||
}//resetToFront()//
|
||||
public boolean remove() {
|
||||
boolean retVal = false;
|
||||
|
||||
if(currentEntry != null) {
|
||||
retVal = hashSet.remove(currentEntry.value);
|
||||
}//if//
|
||||
|
||||
return retVal;
|
||||
}//remove()//
|
||||
public long next() {
|
||||
loadNextEntry();
|
||||
currentEntry = nextEntry;
|
||||
currentIndex = nextIndex;
|
||||
hasNextEntry = false;
|
||||
|
||||
return currentEntry.value;
|
||||
}//next()//
|
||||
public boolean hasNext() {
|
||||
loadNextEntry();
|
||||
|
||||
return nextEntry != null;
|
||||
}//hasNext()//
|
||||
/**
|
||||
* Preloads the next entry. This makes querying to see if the next entry exists and then getting the next entry much easier.
|
||||
*/
|
||||
private void loadNextEntry() {
|
||||
if(!hasNextEntry) {
|
||||
nextEntry = null;
|
||||
nextIndex = currentIndex;
|
||||
|
||||
if((currentEntry != null) && (currentEntry.next != null)) {
|
||||
nextEntry = currentEntry.next;
|
||||
}//if//
|
||||
else {
|
||||
HashSetEntry[] entries = hashSet.entries;
|
||||
|
||||
while((nextEntry == null) && (entries.length > ++nextIndex)) {
|
||||
if(entries[nextIndex] != null) {
|
||||
nextEntry = entries[nextIndex];
|
||||
}//if//
|
||||
}//while//
|
||||
}//else//
|
||||
|
||||
hasNextEntry = true;
|
||||
}//if//
|
||||
}//hasNext()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
out.writeObject(hashSet);
|
||||
}//writeExternal()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
hashSet = (LongHashSet) in.readObject();
|
||||
resetToFront();
|
||||
}//readExternal()//
|
||||
}//HashSetIterator//
|
||||
/**
|
||||
* LongHashSet constructor.
|
||||
*/
|
||||
public LongHashSet() {
|
||||
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
|
||||
}//LongHashSet()//
|
||||
/**
|
||||
* LongHashSet constructor.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
*/
|
||||
public LongHashSet(int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR);
|
||||
}//LongHashSet()//
|
||||
/**
|
||||
* LongHashSet constructor.
|
||||
* @param initialCapacity Determines the size of the array holding the set values.
|
||||
* @param loadFactor The ratio used to determine when to increase the size of the array holding the set values.
|
||||
*/
|
||||
public LongHashSet(int initialCapacity, float loadFactor) {
|
||||
super();
|
||||
|
||||
if((initialCapacity <= 0) || (loadFactor <= 0.0)) {
|
||||
throw new IllegalArgumentException("Invalid initial capacity or load factory supplied to the HashSet.");
|
||||
}//if//
|
||||
|
||||
this.loadFactor = loadFactor;
|
||||
this.entries = new HashSetEntry[initialCapacity];
|
||||
this.threshold = (int)(initialCapacity * loadFactor);
|
||||
}//LongHashSet()//
|
||||
/**
|
||||
* Adds a value to the set.
|
||||
* @param value The value to be added.
|
||||
* @return Whether the value was successfully added.
|
||||
*/
|
||||
public boolean add(long value) {
|
||||
return internalAdd(value);
|
||||
}//add()//
|
||||
/**
|
||||
* Removes a value from the set.
|
||||
* @param value The value to be removed.
|
||||
* @return Whether the value was successfully removed.
|
||||
*/
|
||||
public boolean remove(long value) {
|
||||
return internalRemove(value);
|
||||
}//remove()//
|
||||
/**
|
||||
* Removes all values from the set.
|
||||
* @return Whether the values were successfully removed.
|
||||
*/
|
||||
public boolean removeAll() {
|
||||
return internalRemoveAll();
|
||||
}//removeAll()//
|
||||
/**
|
||||
* Tests to see if the specified value is contained in the collection.
|
||||
* @param value Object The value to test for.
|
||||
* @return boolean Will return true if the value is contained in the collection.
|
||||
*/
|
||||
public boolean containsValue(long value) {
|
||||
int hash = (int) (((value >> 32) & 0xFFFFFFFF) ^ (value & 0xFFFFFFFF));
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(HashSetEntry e = entries[index]; e != null; e = e.next) {
|
||||
if(e.value == value) {
|
||||
return true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return false;
|
||||
}//containsValue()//
|
||||
/**
|
||||
* Creates or reuses an entry.
|
||||
*/
|
||||
protected HashSetEntry createEntry() {
|
||||
return new HashSetEntry();
|
||||
}//createEntry()//
|
||||
/**
|
||||
* Creates or reuses an entry.
|
||||
*/
|
||||
protected void destroyEntry(HashSetEntry entry) {
|
||||
entry.next = null;
|
||||
}//destroyEntry()//
|
||||
/**
|
||||
* Will get the number of values in the set.
|
||||
* @return int The number of values in the set.
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}//getSize()//
|
||||
/**
|
||||
* internalAdd method comment.
|
||||
*/
|
||||
protected boolean internalAdd(long value) {
|
||||
int hash = (int) (((value >> 32) & 0xFFFFFFFF) ^ (value & 0xFFFFFFFF));
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
HashSetEntry entry = null;
|
||||
|
||||
for(entry = entries[index]; entry != null; entry = entry.next) {
|
||||
if(entry.value == value) {
|
||||
return false;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
if(size >= threshold) {
|
||||
rehash();
|
||||
|
||||
return internalAdd(value);
|
||||
}//if//
|
||||
|
||||
entry = createEntry();
|
||||
entry.hash = hash;
|
||||
entry.value = value;
|
||||
entry.next = entries[index];
|
||||
entries[index] = entry;
|
||||
size++;
|
||||
|
||||
return true;
|
||||
}//internalAdd()//
|
||||
/**
|
||||
* Handles removing a value from the collection.
|
||||
* @param value The value to remove.
|
||||
* @return Will be <code>true</code> upon success.
|
||||
*/
|
||||
protected boolean internalRemove(long value) {
|
||||
int hash = (int) (((value >> 32) & 0xFFFFFFFF) ^ (value & 0xFFFFFFFF));
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
HashSetEntry entry = null;
|
||||
HashSetEntry previous = null;
|
||||
|
||||
for(entry = entries[index], previous = null; entry != null; previous = entry, entry = entry.next) {
|
||||
if(entry.value == value) {
|
||||
if(previous != null) {
|
||||
previous.next = entry.next;
|
||||
}//if//
|
||||
else {
|
||||
entries[index] = entry.next;
|
||||
}//else//
|
||||
|
||||
size--;
|
||||
destroyEntry(entry);
|
||||
|
||||
return true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return false;
|
||||
}//internalRemove()//
|
||||
/**
|
||||
* Handles removing all values from the collection.
|
||||
* @return Will be <code>true</code> upon success.
|
||||
*/
|
||||
protected boolean internalRemoveAll() {
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
entries[index] = null;
|
||||
}//for//
|
||||
|
||||
size = 0;
|
||||
|
||||
return true;
|
||||
}//internalRemoveAll()//
|
||||
/**
|
||||
* Handles replacing one value with another in the collection.
|
||||
* @param oldValue The value to be replaced.
|
||||
* @param newValue The value to replace the old one.
|
||||
* @return Will be <code>true</code>
|
||||
*/
|
||||
protected boolean internalReplace(long oldValue, long newValue) {
|
||||
throw new MethodNotSupportedException();
|
||||
}//internalReplace()//
|
||||
/**
|
||||
* Gets a new iterator over the values in this collection.
|
||||
* @return The iterator that may be used to iterate over the collection values.
|
||||
*/
|
||||
public ILongIterator iterator() {
|
||||
return new HashSetIterator(this);
|
||||
}//iterator()//
|
||||
/**
|
||||
* Will rehash the collection so that new items may be added without going over the recommended ratio of values to list entries.
|
||||
*/
|
||||
protected void rehash() {
|
||||
int oldCapacity = entries.length;
|
||||
HashSetEntry[] oldEntries = entries;
|
||||
int newCapacity = (oldCapacity << 1) + 1;
|
||||
HashSetEntry[] newEntries = new HashSetEntry[newCapacity];
|
||||
|
||||
threshold = (int)(newCapacity * loadFactor);
|
||||
entries = newEntries;
|
||||
|
||||
for(int oldIndex = oldCapacity; oldIndex-- > 0; ) {
|
||||
for(HashSetEntry oldEntry = oldEntries[oldIndex]; oldEntry != null; ) {
|
||||
HashSetEntry newEntry = oldEntry;
|
||||
int newIndex;
|
||||
|
||||
oldEntry = oldEntry.next;
|
||||
newIndex = (newEntry.hash & 0x7FFFFFFF) % newCapacity;
|
||||
newEntry.next = newEntries[newIndex];
|
||||
newEntries[newIndex] = newEntry;
|
||||
}//for//
|
||||
}//for//
|
||||
}//rehash()//
|
||||
/**
|
||||
* Fills an array with collection values.
|
||||
* @param array An array capable of containing collection values.
|
||||
* @return The number of values placed in the array.
|
||||
*/
|
||||
public int toArray(long[] array) {
|
||||
HashSetEntry entry = null;
|
||||
int position = 0;
|
||||
HashSetEntry[] entries = this.entries;
|
||||
|
||||
//Iterate over the entry table.//
|
||||
for(int index = 0; index < entries.length; index++) {
|
||||
entry = entries[index];
|
||||
|
||||
//Iterate through the entries at this table position.//
|
||||
while(entry != null) {
|
||||
array[position] = entry.value;
|
||||
entry = entry.next;
|
||||
position++;
|
||||
}//while//
|
||||
}//for//
|
||||
|
||||
return position;
|
||||
}//toArray()//
|
||||
/**
|
||||
* Generates a string representing the hashset.
|
||||
* @return A debug string that represents this object.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer(100);
|
||||
|
||||
buffer.append("LongHashSet {\r\n");
|
||||
|
||||
try {
|
||||
ILongIterator iterator = iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
buffer.append("\t");
|
||||
buffer.append(iterator.next());
|
||||
buffer.append("\r\n");
|
||||
}//while//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
|
||||
buffer.append("}");
|
||||
|
||||
return buffer.toString();
|
||||
}//toArray()//
|
||||
}//LongHashSet//
|
||||
299
Common/src/com/common/util/optimized/LongObjectHashMap.java
Normal file
299
Common/src/com/common/util/optimized/LongObjectHashMap.java
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.util.*;
|
||||
import com.common.comparison.*;
|
||||
|
||||
/**
|
||||
* This collection maps a value by a key.
|
||||
*/
|
||||
public class LongObjectHashMap extends Map implements ILongObjectHashMap {
|
||||
private long[] keys = null;
|
||||
private int keyCount = 0;
|
||||
|
||||
/**
|
||||
* The Entry wrappers the key/value pair.
|
||||
*/
|
||||
protected static class Entry extends BasicEntry {
|
||||
public long key = 0;
|
||||
public Object value = null;
|
||||
|
||||
protected Entry() {
|
||||
super();
|
||||
}//Entry()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
super.readExternal(in);
|
||||
key = in.readLong();
|
||||
value = in.readObject();
|
||||
}//readExternal()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
super.writeExternal(out);
|
||||
out.writeLong(key);
|
||||
out.writeObject(value);
|
||||
}//writeExternal()//
|
||||
public int createKeyHash() {
|
||||
return (int) key;
|
||||
}//createKeyHash()//
|
||||
public String toString() {
|
||||
return super.toString() + "\r\n\thash: " + hash + "\r\n\tkey: " + key + "\r\n\tvalue: " + (value != null ? value.toString() : "null") + (next != null ? ("\r\n" + next.toString()) : "");
|
||||
}//toString()//
|
||||
}//Entry//
|
||||
|
||||
public static class KeyIterator extends Iterator implements ILongIterator {
|
||||
public KeyIterator(LongObjectHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//KeyIterator()//
|
||||
public long next() {
|
||||
return ((Entry) nextEntry()).key;
|
||||
}//next()//
|
||||
public long previous() {
|
||||
return ((Entry) previousEntry()).key;
|
||||
}//previous()//
|
||||
}//KeyIterator//
|
||||
|
||||
public static class ValueIterator extends Iterator implements IReversableIterator {
|
||||
public ValueIterator(LongObjectHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//ValueIterator()//
|
||||
public Object next() {
|
||||
return ((Entry) nextEntry()).value;
|
||||
}//next()//
|
||||
public Object previous() {
|
||||
return ((Entry) previousEntry()).value;
|
||||
}//previous()//
|
||||
}//ValueIterator//
|
||||
/**
|
||||
* LongObjectHashMap constructor.
|
||||
*/
|
||||
public LongObjectHashMap() {
|
||||
this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, DEFAULT_VALUE_COMPARATOR);
|
||||
}//LongObjectHashMap()//
|
||||
/**
|
||||
* LongObjectHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public LongObjectHashMap(int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_VALUE_COMPARATOR);
|
||||
}//LongObjectHashMap()//
|
||||
/**
|
||||
* LongObjectHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public LongObjectHashMap(int initialCapacity, float loadFactor) {
|
||||
this(initialCapacity, loadFactor, DEFAULT_VALUE_COMPARATOR);
|
||||
}//LongObjectHashMap()//
|
||||
/**
|
||||
* LongObjectHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public LongObjectHashMap(int initialCapacity, float loadFactor, IComparator valueComparator) {
|
||||
super(initialCapacity, loadFactor, null, valueComparator);
|
||||
}//LongObjectHashMap()//
|
||||
/**
|
||||
* LongObjectHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param valueComparator The comparator used to compare value objects.
|
||||
*/
|
||||
public LongObjectHashMap(int initialCapacity, IComparator valueComparator) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, valueComparator);
|
||||
}//LongObjectHashMap()//
|
||||
/**
|
||||
* @see ILongObjectHashMap.containsKey(long)
|
||||
*/
|
||||
public boolean containsKey(long key) {
|
||||
return get(key) != null;
|
||||
}//containsKey()//
|
||||
/**
|
||||
* Creates an entry object of the specific type used by this map.
|
||||
* @return An entry object that can be filled and passed to the addEntry method.
|
||||
*/
|
||||
protected IBasicEntry createEntry() {
|
||||
return new Entry();
|
||||
}//createEntry()//
|
||||
/**
|
||||
* @see ILongObjectHashMap.get(long)
|
||||
*/
|
||||
public Object get(long key) {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = (int) key;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(Entry entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (entry.key == key)) {
|
||||
return entry.value;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return null;
|
||||
}//get()//
|
||||
/**
|
||||
* This method will get the key at the given index.
|
||||
* <p>NOTE: This method is intended for use by the iterators and it is not advisable to use this method else where.
|
||||
* @param index The index in the list of keys.
|
||||
* @return The key at the given index.
|
||||
*/
|
||||
public long getKey(int index) {
|
||||
if(keys == null) {
|
||||
refreshKeys();
|
||||
}//if//
|
||||
|
||||
return keys[index];
|
||||
}//get()//
|
||||
/**
|
||||
* This will invalidate the collection of keys.
|
||||
* This should occur when a value is added/removed/changed in a way that invalidates the collection of keys.
|
||||
*/
|
||||
protected void invalidateKeys() {
|
||||
keys = null;
|
||||
keyCount = 0;
|
||||
}//invalidateKeys()//
|
||||
/**
|
||||
* @see ILongObjectHashMap.keyIterator()
|
||||
*/
|
||||
public ILongIterator keyIterator() {
|
||||
return new KeyIterator(this);
|
||||
}//keyIterator()//
|
||||
/**
|
||||
* @see ILongObjectHashMap.put(long, Object)
|
||||
*/
|
||||
public Object put(long key, Object value) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
if(value == null) {
|
||||
//Remove the key if it exists because you cannot associate a key with a null value.//
|
||||
return remove(key);
|
||||
}//if//
|
||||
else {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = (int) key;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry entry = null;
|
||||
|
||||
//Try to locate an existing value.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (entry.key == key)) {
|
||||
Object oldValue = entry.value;
|
||||
|
||||
entry.value = value;
|
||||
|
||||
return oldValue;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Determine if we need to re-hash.//
|
||||
if(resize(getSize() + 1)) {
|
||||
entries = getEntries();
|
||||
//Recalculate the insertion index if the map resized.//
|
||||
index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
}//if//
|
||||
|
||||
//Create and add the new entry.//
|
||||
entry = (Entry) createEntry();
|
||||
entry.hash = hash;
|
||||
entry.key = key;
|
||||
entry.value = value;
|
||||
addEntry(index, entry);
|
||||
|
||||
if(keys != null) {
|
||||
//Just add the key instead of invalidating the keys collection.//
|
||||
if(keyCount == keys.length) {
|
||||
long[] temp = new long[keys.length < 50 ? keys.length << 1 : keys.length + 100];
|
||||
|
||||
System.arraycopy(keys, 0, temp, 0, keys.length);
|
||||
keys = temp;
|
||||
keys[keyCount++] = key;
|
||||
}//if//
|
||||
|
||||
keys[keyCount++] = key;
|
||||
keyCount++;
|
||||
}//if//
|
||||
|
||||
return null;
|
||||
}//else//
|
||||
}//put()//
|
||||
/**
|
||||
* Will recreate the collection of keys.
|
||||
*/
|
||||
protected void refreshKeys() {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int index;
|
||||
Entry entry;
|
||||
|
||||
keys = new long[getSize() + 10];
|
||||
|
||||
for(index = 0; index < entries.length; index++) {
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
keys[index] = entry.key;
|
||||
keyCount++;
|
||||
}//for//
|
||||
}//for//
|
||||
}//refreshKeys()//
|
||||
/**
|
||||
* Will optimize the collection of Entry objects to improve access time.
|
||||
* @param arrayLength int The new length of the entry array.
|
||||
*/
|
||||
protected void rehash(int arrayLength) {
|
||||
super.rehash(arrayLength);
|
||||
//Invalidate the list of keys.//
|
||||
invalidateKeys();
|
||||
}//rehash()//
|
||||
/**
|
||||
* @see ILongObjectHashMap.remove(long)
|
||||
*/
|
||||
public Object remove(long key) {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = (int) key;
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry previousEntry = null;
|
||||
Entry entry = null;
|
||||
Object retVal = null;
|
||||
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Iterate through the entries stored at the key's hash location and remove the given key.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (entry.key == key)) {
|
||||
//Save the removed value.//
|
||||
retVal = entry.value;
|
||||
//Remove the entry from the map.//
|
||||
removeEntry(index, previousEntry);
|
||||
//Could find the key in the collection and remove it, but that may take to long.//
|
||||
invalidateKeys();
|
||||
//Break from the loop so we can exit.//
|
||||
break;
|
||||
}//if//
|
||||
|
||||
previousEntry = entry;
|
||||
}//for//
|
||||
|
||||
return retVal;
|
||||
}//remove()//
|
||||
/**
|
||||
* @see IIntObjectHashMap.removeAll()
|
||||
*/
|
||||
public boolean removeAll() {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
invalidateKeys();
|
||||
removeAllEntries();
|
||||
|
||||
return true;
|
||||
}//removeAll()//
|
||||
/**
|
||||
* @see ILongObjectHashMap.valueIterator()
|
||||
*/
|
||||
public IIterator valueIterator() {
|
||||
return new ValueIterator(this);
|
||||
}//valueIterator()//
|
||||
}//LongObjectHashMap//
|
||||
342
Common/src/com/common/util/optimized/ObjectIntHashMap.java
Normal file
342
Common/src/com/common/util/optimized/ObjectIntHashMap.java
Normal file
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.util.*;
|
||||
import com.common.comparison.*;
|
||||
|
||||
/**
|
||||
* This collection maps a value by a key.
|
||||
*/
|
||||
public class ObjectIntHashMap extends Map implements IObjectIntHashMap {
|
||||
private LiteList keys = null;
|
||||
|
||||
/**
|
||||
* The Entry wrappers the key/value pair.
|
||||
*/
|
||||
protected static class Entry extends BasicEntry {
|
||||
public Object key = null;
|
||||
public int value = 0;
|
||||
|
||||
public Entry() {
|
||||
super();
|
||||
}//Entry()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
super.readExternal(in);
|
||||
key = in.readObject();
|
||||
value = in.readInt();
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
}//readExternal()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
super.writeExternal(out);
|
||||
out.writeObject(key == NULL_KEY ? null : key);
|
||||
out.writeInt(value);
|
||||
}//writeExternal()//
|
||||
public int createKeyHash() {
|
||||
return key.hashCode();
|
||||
}//createKeyHash()//
|
||||
public String toString() {
|
||||
return super.toString() + "\r\n\tKey: " + (key == NULL_KEY ? "null" : key.toString()) + "\r\n\tValue: " + value + (next != null ? "\r\n\t" + next.toString() : "");
|
||||
}//toString()//
|
||||
}//Entry//
|
||||
|
||||
public static class KeyIterator extends Iterator implements IReversableIterator {
|
||||
public KeyIterator(ObjectIntHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//KeyIterator()//
|
||||
public Object next() {
|
||||
Object result = ((Entry) nextEntry()).key;
|
||||
|
||||
if(result == NULL_KEY) {
|
||||
result = null;
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//next()//
|
||||
public Object previous() {
|
||||
Object result = ((Entry) previousEntry()).key;
|
||||
|
||||
if(result == NULL_KEY) {
|
||||
result = null;
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//previous()//
|
||||
}//KeyIterator//
|
||||
|
||||
public static class ValueIterator extends Iterator implements IIntIterator {
|
||||
public ValueIterator(ObjectIntHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//ValueIterator()//
|
||||
public int next() {
|
||||
return ((Entry) nextEntry()).value;
|
||||
}//next()//
|
||||
public int previous() {
|
||||
return ((Entry) previousEntry()).value;
|
||||
}//previous()//
|
||||
}//ValueIterator//
|
||||
/**
|
||||
* ObjectIntHashMap constructor.
|
||||
*/
|
||||
public ObjectIntHashMap() {
|
||||
this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, DEFAULT_KEY_COMPARATOR);
|
||||
}//ObjectIntHashMap()//
|
||||
/**
|
||||
* ObjectIntHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public ObjectIntHashMap(int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_KEY_COMPARATOR);
|
||||
}//ObjectIntHashMap()//
|
||||
/**
|
||||
* ObjectIntHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public ObjectIntHashMap(int initialCapacity, float loadFactor) {
|
||||
this(initialCapacity, loadFactor, DEFAULT_KEY_COMPARATOR);
|
||||
}//ObjectIntHashMap()//
|
||||
/**
|
||||
* ObjectIntHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
*/
|
||||
public ObjectIntHashMap(int initialCapacity, float loadFactor, IComparator keyComparator) {
|
||||
super(initialCapacity, loadFactor, keyComparator, null);
|
||||
}//ObjectIntHashMap()//
|
||||
/**
|
||||
* ObjectIntHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
*/
|
||||
public ObjectIntHashMap(int initialCapacity, IComparator keyComparator) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, keyComparator);
|
||||
}//ObjectIntHashMap()//
|
||||
/**
|
||||
* @see IObjectIntHashMap.containsKey(Object)
|
||||
*/
|
||||
public boolean containsKey(Object key) {
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
boolean retVal = false;
|
||||
|
||||
for(Entry entry = (Entry) entries[index]; (!retVal) && (entry != null); entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key, key)))) {
|
||||
retVal = true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return retVal;
|
||||
}//containsKey()//
|
||||
/**
|
||||
* Creates an entry object of the specific type used by this map.
|
||||
* @return An entry object that can be filled and passed to the addEntry method.
|
||||
*/
|
||||
protected IBasicEntry createEntry() {
|
||||
return new Entry();
|
||||
}//createEntry()//
|
||||
/**
|
||||
* @see IObjectIntHashMap.get(Object)
|
||||
*/
|
||||
public int get(Object key) {
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(Entry entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key, key)))) {
|
||||
return entry.value;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return IObjectIntHashMap.NULL_VALUE;
|
||||
}//get()//
|
||||
/**
|
||||
* Gets the key at the given index.
|
||||
* <p>NOTE: This method is intended for use by the iterators and it is not advisable to use this method else where.
|
||||
* @param index The index in the list of keys.
|
||||
* @return The key at the given index.
|
||||
*/
|
||||
public Object getKey(int index) {
|
||||
if(keys == null) {
|
||||
refreshKeys();
|
||||
}//if//
|
||||
|
||||
return keys.get(index);
|
||||
}//get()//
|
||||
/**
|
||||
* Invalidates the collection of keys.
|
||||
* This should occur when a value is added/removed/changed in a way that invalidates the collection of keys.
|
||||
*/
|
||||
protected void invalidateKeys() {
|
||||
keys = null;
|
||||
}//invalidateKeys()//
|
||||
/**
|
||||
* @see IObjectIntHashMap.keyIterator()
|
||||
*/
|
||||
public IIterator keyIterator() {
|
||||
return new KeyIterator(this);
|
||||
}//keyIterator()//
|
||||
/**
|
||||
* @see IObjectIntHashMap.put(Object, int)
|
||||
*/
|
||||
public int put(Object key, int value) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
if(value == IObjectIntHashMap.NULL_VALUE) {
|
||||
//Remove the key if it exists because you cannot associate a key with a null value.//
|
||||
return remove(key);
|
||||
}//if//
|
||||
else {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry entry = null;
|
||||
|
||||
//Try to locate an existing value.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key, key)))) {
|
||||
int oldValue = entry.value;
|
||||
|
||||
entry.value = value;
|
||||
|
||||
return oldValue;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Determine if we need to re-hash.//
|
||||
if(resize(getSize() + 1)) {
|
||||
//Re-get the collection of hash entries.//
|
||||
entries = getEntries();
|
||||
//Recalculate the insertion index if the map resized.//
|
||||
index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
}//if//
|
||||
|
||||
//Create and add the new entry.//
|
||||
entry = (Entry) createEntry();
|
||||
entry.hash = hash;
|
||||
entry.key = key;
|
||||
entry.value = value;
|
||||
addEntry(index, entry);
|
||||
|
||||
if(keys != null) {
|
||||
keys.add(key); //Just add the key instead of invalidating the keys collection.//
|
||||
}//if//
|
||||
|
||||
return IObjectIntHashMap.NULL_VALUE;
|
||||
}//else//
|
||||
}//put()//
|
||||
/**
|
||||
* Recreates the collection of keys.
|
||||
*/
|
||||
protected void refreshKeys() {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int index;
|
||||
Entry entry;
|
||||
|
||||
keys = new LiteList(getSize(), 20);
|
||||
|
||||
for(index = 0; index < entries.length; index++) {
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
Object key = entry.key;
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == NULL_KEY) {
|
||||
key = null;
|
||||
}//if//
|
||||
|
||||
keys.add(key);
|
||||
}//for//
|
||||
}//for//
|
||||
}//refreshKeys()//
|
||||
/**
|
||||
* Optimizes the collection of Entry objects to improve access time.
|
||||
* @param arrayLength The new length of the entry array.
|
||||
*/
|
||||
protected void rehash(int arrayLength) {
|
||||
super.rehash(arrayLength);
|
||||
//Invalidate the list of keys.//
|
||||
invalidateKeys();
|
||||
}//rehash()//
|
||||
/**
|
||||
* @see IObjectIntHashMap.remove(Object)
|
||||
*/
|
||||
public int remove(Object key) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry previousEntry = null;
|
||||
Entry entry = null;
|
||||
int retVal = IObjectIntHashMap.NULL_VALUE;
|
||||
|
||||
//Iterate through the entries stored at the key's hash location and remove the given key.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key, key)))) {
|
||||
//Save the removed value.//
|
||||
retVal = entry.value;
|
||||
//Remove the entry from the map.//
|
||||
removeEntry(index, previousEntry);
|
||||
//Could find the key in the collection and remove it, but that may take to long.//
|
||||
invalidateKeys();
|
||||
//Break from the loop so we can exit.//
|
||||
break;
|
||||
}//if//
|
||||
|
||||
previousEntry = entry;
|
||||
}//for//
|
||||
|
||||
return retVal;
|
||||
}//remove()//
|
||||
/**
|
||||
* @see IObjectIntHashMap.removeAll()
|
||||
*/
|
||||
public boolean removeAll() {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
invalidateKeys();
|
||||
removeAllEntries();
|
||||
|
||||
return true;
|
||||
}//removeAll()//
|
||||
/**
|
||||
* @see IObjectIntHashMap.valueIterator()
|
||||
*/
|
||||
public IIntIterator valueIterator() {
|
||||
return new ValueIterator(this);
|
||||
}//valueIterator()//
|
||||
}//ObjectIntHashMap//
|
||||
341
Common/src/com/common/util/optimized/ObjectLongHashMap.java
Normal file
341
Common/src/com/common/util/optimized/ObjectLongHashMap.java
Normal file
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.util.optimized;
|
||||
|
||||
import com.common.util.*;
|
||||
import com.common.comparison.*;
|
||||
|
||||
/**
|
||||
* This collection maps a value by a key.
|
||||
*/
|
||||
public class ObjectLongHashMap extends Map implements IObjectLongHashMap {
|
||||
private LiteList keys = null;
|
||||
|
||||
/**
|
||||
* The Entry wrappers the key/value pair.
|
||||
*/
|
||||
protected static class Entry extends BasicEntry {
|
||||
public Object key = null;
|
||||
public long value = 0;
|
||||
|
||||
public Entry() {
|
||||
super();
|
||||
}//Entry()//
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
super.readExternal(in);
|
||||
key = in.readObject();
|
||||
value = in.readLong();
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
}//readExternal()//
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
super.writeExternal(out);
|
||||
out.writeObject(key == NULL_KEY ? null : key);
|
||||
out.writeLong(value);
|
||||
}//writeExternal()//
|
||||
public int createKeyHash() {
|
||||
return key.hashCode();
|
||||
}//createKeyHash()//
|
||||
public String toString() {
|
||||
return super.toString() + "\r\n\tKey: " + (key == NULL_KEY ? "null" : key.toString()) + "\r\n\tValue: " + value + (next != null ? "\r\n\t" + next.toString() : "");
|
||||
}//toString()//
|
||||
}//Entry//
|
||||
|
||||
public static class KeyIterator extends Iterator implements IReversableIterator {
|
||||
public KeyIterator(ObjectLongHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//KeyIterator()//
|
||||
public Object next() {
|
||||
Object result = ((Entry) nextEntry()).key;
|
||||
|
||||
if(result == NULL_KEY) {
|
||||
result = null;
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//next()//
|
||||
public Object previous() {
|
||||
Object result = ((Entry) previousEntry()).key;
|
||||
|
||||
if(result == NULL_KEY) {
|
||||
result = null;
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//previous()//
|
||||
}//KeyIterator//
|
||||
|
||||
public static class ValueIterator extends Iterator implements ILongIterator {
|
||||
public ValueIterator(ObjectLongHashMap hashMap) {
|
||||
super(hashMap);
|
||||
}//ValueIterator()//
|
||||
public long next() {
|
||||
return ((Entry) nextEntry()).value;
|
||||
}//next()//
|
||||
public long previous() {
|
||||
return ((Entry) previousEntry()).value;
|
||||
}//previous()//
|
||||
}//ValueIterator//
|
||||
/**
|
||||
* ObjectLongHashMap constructor.
|
||||
*/
|
||||
public ObjectLongHashMap() {
|
||||
this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, DEFAULT_KEY_COMPARATOR);
|
||||
}//ObjectLongHashMap()//
|
||||
/**
|
||||
* ObjectLongHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public ObjectLongHashMap(int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_KEY_COMPARATOR);
|
||||
}//ObjectLongHashMap()//
|
||||
/**
|
||||
* ObjectLongHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
*/
|
||||
public ObjectLongHashMap(int initialCapacity, float loadFactor) {
|
||||
this(initialCapacity, loadFactor, DEFAULT_KEY_COMPARATOR);
|
||||
}//ObjectLongHashMap()//
|
||||
/**
|
||||
* ObjectLongHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
*/
|
||||
public ObjectLongHashMap(int initialCapacity, float loadFactor, IComparator keyComparator) {
|
||||
super(initialCapacity, loadFactor, keyComparator, null);
|
||||
}//ObjectLongHashMap()//
|
||||
/**
|
||||
* ObjectLongHashMap constructor.
|
||||
* @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException.
|
||||
* @param keyComparator The comparator used to compare key objects.
|
||||
*/
|
||||
public ObjectLongHashMap(int initialCapacity, IComparator keyComparator) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, keyComparator);
|
||||
}//ObjectLongHashMap()//
|
||||
/**
|
||||
* @see IObjectLongHashMap.containsKey(Object)
|
||||
*/
|
||||
public boolean containsKey(Object key) {
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
boolean retVal = false;
|
||||
|
||||
for(Entry entry = (Entry) entries[index]; (!retVal) && (entry != null); entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key, key)))) {
|
||||
retVal = true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return retVal;
|
||||
}//containsKey()//
|
||||
/**
|
||||
* Creates an entry object of the specific type used by this map.
|
||||
* @return An entry object that can be filled and passed to the addEntry method.
|
||||
*/
|
||||
protected IBasicEntry createEntry() {
|
||||
return new Entry();
|
||||
}//createEntry()//
|
||||
/**
|
||||
* @see IObjectLongHashMap.get(Object)
|
||||
*/
|
||||
public long get(Object key) {
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
|
||||
for(Entry entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key, key)))) {
|
||||
return entry.value;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
return IObjectLongHashMap.NULL_VALUE;
|
||||
}//get()//
|
||||
/**
|
||||
* Gets the key at the given index.
|
||||
* <p>NOTE: This method is intended for use by the iterators and it is not advisable to use this method else where.
|
||||
* @param index The index in the list of keys.
|
||||
* @return The key at the given index.
|
||||
*/
|
||||
public Object getKey(int index) {
|
||||
if(keys == null) {
|
||||
refreshKeys();
|
||||
}//if//
|
||||
|
||||
return keys.get(index);
|
||||
}//get()//
|
||||
/**
|
||||
* Invalidates the collection of keys.
|
||||
* This should occur when a value is added/removed/changed in a way that invalidates the collection of keys.
|
||||
*/
|
||||
protected void invalidateKeys() {
|
||||
keys = null;
|
||||
}//invalidateKeys()//
|
||||
/**
|
||||
* @see IObjectLongHashMap.keyIterator()
|
||||
*/
|
||||
public IIterator keyIterator() {
|
||||
return new KeyIterator(this);
|
||||
}//keyIterator()//
|
||||
/**
|
||||
* @see IObjectLongHashMap.put(Object, long)
|
||||
*/
|
||||
public long put(Object key, long value) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
if(value == IObjectLongHashMap.NULL_VALUE) {
|
||||
//Remove the key if it exists because you cannot associate a key with a null value.//
|
||||
return remove(key);
|
||||
}//if//
|
||||
else {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry entry = null;
|
||||
|
||||
//Try to locate an existing value.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key, key)))) {
|
||||
long oldValue = entry.value;
|
||||
|
||||
entry.value = value;
|
||||
|
||||
return oldValue;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Determine if we need to re-hash.//
|
||||
if(resize(getSize() + 1)) {
|
||||
//Refresh the local entries array.//
|
||||
entries = getEntries();
|
||||
//Recalculate the insertion index if the map resized.//
|
||||
index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
}//if//
|
||||
|
||||
//Create and add the new entry.//
|
||||
entry = (Entry) createEntry();
|
||||
entry.hash = hash;
|
||||
entry.key = key;
|
||||
entry.value = value;
|
||||
addEntry(index, entry);
|
||||
|
||||
if(keys != null) {
|
||||
keys.add(key); //Just add the key instead of invalidating the keys collection.//
|
||||
}//if//
|
||||
|
||||
return IObjectLongHashMap.NULL_VALUE;
|
||||
}//else//
|
||||
}//put()//
|
||||
/**
|
||||
* Recreates the collection of keys.
|
||||
*/
|
||||
protected void refreshKeys() {
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int index;
|
||||
Entry entry;
|
||||
|
||||
keys = new LiteList(getSize(), 20);
|
||||
|
||||
for(index = 0; index < entries.length; index++) {
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
Object key = entry.key;
|
||||
|
||||
if(key == NULL_KEY) {
|
||||
key = null;
|
||||
}//if//
|
||||
|
||||
keys.add(key);
|
||||
}//for//
|
||||
}//for//
|
||||
}//refreshKeys()//
|
||||
/**
|
||||
* Optimizes the collection of Entry objects to improve access time.
|
||||
* @param arrayLength The new length of the entry array.
|
||||
*/
|
||||
protected void rehash(int arrayLength) {
|
||||
super.rehash(arrayLength);
|
||||
//Invalidate the list of keys.//
|
||||
invalidateKeys();
|
||||
}//rehash()//
|
||||
/**
|
||||
* @see IObjectLongHashMap.remove(Object)
|
||||
*/
|
||||
public long remove(Object key) {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
|
||||
//Ensure that null keys are valid.//
|
||||
if(key == null) {
|
||||
key = NULL_KEY;
|
||||
}//if//
|
||||
|
||||
IBasicEntry[] entries = getEntries();
|
||||
int hash = getKeyComparator().hash(key);
|
||||
int index = (hash & 0x7FFFFFFF) % entries.length;
|
||||
Entry previousEntry = null;
|
||||
Entry entry = null;
|
||||
long retVal = IObjectLongHashMap.NULL_VALUE;
|
||||
|
||||
//Iterate through the entries stored at the key's hash location and remove the given key.//
|
||||
for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) {
|
||||
if((entry.hash == hash) && (Comparator.isEqual(getKeyComparator().compare(entry.key, key)))) {
|
||||
//Save the removed value.//
|
||||
retVal = entry.value;
|
||||
//Remove the entry from the map.//
|
||||
removeEntry(index, previousEntry);
|
||||
//Could find the key in the collection and remove it, but that may take to long.//
|
||||
invalidateKeys();
|
||||
//Break from the loop so we can exit.//
|
||||
break;
|
||||
}//if//
|
||||
|
||||
previousEntry = entry;
|
||||
}//for//
|
||||
|
||||
return retVal;
|
||||
}//remove()//
|
||||
/**
|
||||
* @see IObjectLongHashMap.removeAll()
|
||||
*/
|
||||
public boolean removeAll() {
|
||||
//Verify that the collection can be modified.//
|
||||
verifyIsChangeable();
|
||||
invalidateKeys();
|
||||
removeAllEntries();
|
||||
|
||||
return true;
|
||||
}//removeAll()//
|
||||
/**
|
||||
* @see IObjectLongHashMap.valueIterator()
|
||||
*/
|
||||
public ILongIterator valueIterator() {
|
||||
return new ValueIterator(this);
|
||||
}//valueIterator()//
|
||||
}//ObjectLongHashMap//
|
||||
Reference in New Issue
Block a user