Revision: 6205
http://pcgen.svn.sourceforge.net/pcgen/?rev=6205&view=rev
Author: thpr
Date: 2008-05-06 18:56:34 -0700 (Tue, 06 May 2008)
Log Message:
-----------
Graft key rules load components from CDOM branch
Added Paths:
-----------
Trunk/pcgen/code/src/java/pcgen/base/lang/StringUtil.java
Trunk/pcgen/code/src/java/pcgen/base/util/AbstractMapToList.java
Trunk/pcgen/code/src/java/pcgen/base/util/GenericMapToList.java
Trunk/pcgen/code/src/java/pcgen/base/util/HashMapToInstanceList.java
Trunk/pcgen/code/src/java/pcgen/base/util/OneToOneMap.java
Trunk/pcgen/code/src/java/pcgen/base/util/TreeMapToList.java
Trunk/pcgen/code/src/java/pcgen/base/util/TripleKeyMap.java
Trunk/pcgen/code/src/java/pcgen/base/util/TripleKeyMapToList.java
Trunk/pcgen/code/src/java/pcgen/base/util/WrappedMapSet.java
Trunk/pcgen/code/src/java/pcgen/cdom/base/AssociationSupport.java
Trunk/pcgen/code/src/java/pcgen/cdom/base/SimpleAssociatedObject.java
Trunk/pcgen/code/src/java/pcgen/cdom/reference/
Trunk/pcgen/code/src/java/pcgen/cdom/reference/AbstractReferenceManufacturer.java
Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMAllRef.java
Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMDirectSingleRef.java
Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMGroupRef.java
Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMSimpleSingleRef.java
Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMSingleRef.java
Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMTypeRef.java
Trunk/pcgen/code/src/java/pcgen/cdom/reference/ReferenceManufacturer.java
Trunk/pcgen/code/src/java/pcgen/cdom/reference/SimpleReferenceManufacturer.java
Trunk/pcgen/code/src/java/pcgen/rules/
Trunk/pcgen/code/src/java/pcgen/rules/context/
Trunk/pcgen/code/src/java/pcgen/rules/context/AssociatedChanges.java
Trunk/pcgen/code/src/java/pcgen/rules/context/AssociatedCollectionChanges.java
Trunk/pcgen/code/src/java/pcgen/rules/context/Changes.java
Trunk/pcgen/code/src/java/pcgen/rules/context/CollectionChanges.java
Trunk/pcgen/code/src/java/pcgen/rules/context/ConsolidatedListCommitStrategy.java
Trunk/pcgen/code/src/java/pcgen/rules/context/ConsolidatedObjectCommitStrategy.java
Trunk/pcgen/code/src/java/pcgen/rules/context/ListChanges.java
Trunk/pcgen/code/src/java/pcgen/rules/context/ListCommitStrategy.java
Trunk/pcgen/code/src/java/pcgen/rules/context/ListContext.java
Trunk/pcgen/code/src/java/pcgen/rules/context/LoadContext.java
Trunk/pcgen/code/src/java/pcgen/rules/context/ObjectCommitStrategy.java
Trunk/pcgen/code/src/java/pcgen/rules/context/ObjectContext.java
Trunk/pcgen/code/src/java/pcgen/rules/context/ReferenceContext.java
Trunk/pcgen/code/src/java/pcgen/rules/context/ReferenceSupport.java
Trunk/pcgen/code/src/java/pcgen/rules/context/RuntimeLoadContext.java
Trunk/pcgen/code/src/java/pcgen/rules/context/SimpleReferenceContext.java
Trunk/pcgen/code/src/java/pcgen/rules/persistence/
Trunk/pcgen/code/src/java/pcgen/rules/persistence/TokenLibrary.java
Trunk/pcgen/code/src/java/pcgen/rules/persistence/TokenSupport.java
Trunk/pcgen/code/src/java/pcgen/rules/persistence/TokenUtilities.java
Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/
Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMPrimaryToken.java
Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMSecondaryToken.java
Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMSubToken.java
Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMToken.java
Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/PreCompatibilityToken.java
Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/
Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/Revision.java
Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/TokenFamily.java
Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/TokenFamilyIterator.java
Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/TokenFamilySubIterator.java
Added: Trunk/pcgen/code/src/java/pcgen/base/lang/StringUtil.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/base/lang/StringUtil.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/base/lang/StringUtil.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,97 @@
+package pcgen.base.lang;
+
+import java.util.Collection;
+
+public final class StringUtil
+{
+
+ private StringUtil()
+ {
+ // Do not instantiate
+ }
+
+ /**
+ * Concatenates the Collection of Strings into a String using the separator
+ * as the delimiter.
+ *
+ * @param strings
+ * An Collection of strings
+ * @param separator
+ * The separating string
+ * @return A 'separator' separated String
+ */
+ public static String join(final Collection<?> strings,
+ final String separator)
+ {
+ return joinToStringBuffer(strings, separator).toString();
+ }
+
+ /**
+ * Concatenates the Collection of Strings into a StringBuffer using the
+ * separator as the delimiter.
+ *
+ * @param strings
+ * An Collection of strings
+ * @param separator
+ * The separating character
+ * @return A 'separator' separated String
+ */
+ public static StringBuilder joinToStringBuffer(final Collection<?> strings,
+ final String separator)
+ {
+ if (strings == null)
+ {
+ return new StringBuilder();
+ }
+
+ final StringBuilder result = new StringBuilder(strings.size() * 10);
+
+ boolean needjoin = false;
+
+ for (Object obj : strings)
+ {
+ if (needjoin)
+ {
+ result.append(separator);
+ }
+ needjoin = true;
+ result.append(obj.toString());
+ }
+
+ return result;
+ }
+
+ /**
+ * Concatenates the Array of Strings into a String using the separator as
+ * the delimiter.
+ *
+ * @param strings
+ * An Array of strings
+ * @param separator
+ * The separating string
+ * @return A 'separator' separated String
+ */
+ public static String join(String[] strings, String separator)
+ {
+ if (strings == null)
+ {
+ return "";
+ }
+
+ final StringBuilder result = new StringBuilder(strings.length * 10);
+
+ boolean needjoin = false;
+
+ for (Object obj : strings)
+ {
+ if (needjoin)
+ {
+ result.append(separator);
+ }
+ needjoin = true;
+ result.append(obj.toString());
+ }
+
+ return result.toString();
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/base/util/AbstractMapToList.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/base/util/AbstractMapToList.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/base/util/AbstractMapToList.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,469 @@
+/*
+ * Copyright 2004, 2005 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Created on Aug 29, 2004 Imported into PCGen on June 18, 2005.
+ */
+package pcgen.base.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Thomas Parker (thpr [at] yahoo.com)
+ *
+ * Represents a Map of objects to Lists. List management is done internally to
+ * this class (while copies are accessible, the lists are kept private to this
+ * class).
+ *
+ * This class is reference-semantic. In appropriate cases (such as calling the
+ * addToListFor method), AbstractMapToList will maintain a reference to the
+ * given Object. AbstractMapToList will not modify any of the Objects it is
+ * passed; however, it reserves the right to return references to Objects it
+ * contains to other Objects.
+ *
+ * However, when any method in which AbstractMapToList returns a Collection,
+ * ownership of the Collection itself is transferred to the calling Object, but
+ * the contents of the Collection (keys, values, etc.) are references whose
+ * ownership should be respected.
+ *
+ * NOTE: This is a convenience method for use in Java 1.4 and is less beneficial
+ * in Java 1.5 (Typed Collections may be more appropriate)
+ */
+public abstract class AbstractMapToList<K, V> implements MapToList<K, V>
+{
+
+ /**
+ * The actual map containing the map of objects to Lists
+ */
+ /*
+ * TODO Protected only due to ugliness in the CDOM core - change to private
+ * when possible
+ */
+ protected final Map<K, List<V>> mapToList;
+
+ /**
+ * Creates a new AbstractMapToList
+ */
+ protected AbstractMapToList(Map<K, List<V>> mtl)
+ {
+ super();
+ mapToList = mtl;
+ }
+
+ /**
+ * Initializes a List for the given key. The null value cannot be used as a
+ * key in a MapToList.
+ *
+ * This method is reference-semantic and this MapToList will maintain a
+ * strong reference to the key object given as an argument to this method.
+ *
+ * Overuse of this method is discouraged, as it is *not required* to
+ * initilize a List (the AbstractMapToList will automatically initialize a
+ * List if an object is added to the list for a given key).
+ *
+ * @param key
+ * The key for which a List should be initialized in this
+ * MapToList.
+ */
+ public void initializeListFor(K key)
+ {
+ if (mapToList.containsKey(key))
+ {
+ throw new IllegalArgumentException("Cannot re-initialize key: "
+ + key);
+ }
+ mapToList.put(key, new ArrayList<V>());
+ }
+
+ /**
+ * Adds the given value to the List for the given key. The null value cannot
+ * be used as a key in a MapToList. This method will automatically
+ * initialize the list for the given key if there is not already a List for
+ * that key.
+ *
+ * This method is reference-semantic and this MapToList will maintain a
+ * strong reference to both the key object and the value object given as
+ * arguments to this method.
+ *
+ * @param key
+ * The key indicating which List the given object should be added
+ * to.
+ * @param value
+ * The value to be added to the List for the given key.
+ */
+ public void addToListFor(K key, V value)
+ {
+ /*
+ * Note there is no requirement that a Key is added before this method
+ * is called
+ */
+ if (!containsListFor(key))
+ {
+ initializeListFor(key);
+ }
+ mapToList.get(key).add(value);
+ }
+
+ /**
+ * Adds all of the Objects in the given list to the (internal) List for the
+ * given key. The null value cannot be used as a key in a MapToList. This
+ * method will automatically initialize the list for the given key if there
+ * is not already a List for that key.
+ *
+ * This method is reference-semantic and this MapToList will maintain a
+ * strong reference to both the key object and the object in the given list.
+ *
+ * @param key
+ * The key indicating which List the objects in the given List
+ * should be added to.
+ * @param list
+ * A Collection containing the items to be added to the List for
+ * the given key.
+ */
+ public void addAllToListFor(K key, Collection<V> list)
+ {
+ if (list == null || list.isEmpty())
+ {
+ return;
+ }
+ /*
+ * Note there is no requirement that a Key is added before this method
+ * is called
+ */
+ if (!containsListFor(key))
+ {
+ initializeListFor(key);
+ }
+ mapToList.get(key).addAll(list);
+ }
+
+ /**
+ * Adds all of the Lists in the given MapToList to this MapToList. The
+ * resulting lists are independent, however, since MapToList is
+ * reference-semantic, the List keys and values in each list are identical.
+ *
+ * This method is reference-semantic and this MapToList will maintain a
+ * strong reference to all key objects and objects in each list of the given
+ * MapToList.
+ *
+ * @param mtl
+ * The MapToList from which all of the Lists should be imported
+ */
+ public void addAllLists(MapToList<K, V> mtl)
+ {
+ for (K key : mtl.getKeySet())
+ {
+ /*
+ * Note, this grab of the list for the key is safe regardless of
+ * whether mtl's getListFor is reference or value-semantic, as
+ * addAllToListFor is committed to be value-semantic and not keep or
+ * modify the received list.
+ */
+ addAllToListFor(key, mtl.getListFor(key));
+ }
+ }
+
+ /**
+ * Returns true if this MapToList contains a List for the given key. This
+ * method returns false if the given key is not in this MapToList.
+ *
+ * This method is value-semantic in that no changes are made to the object
+ * passed into the method.
+ *
+ * @param key
+ * The key being tested.
+ * @return true if this MapToList contains a List for the given key; false
+ * otherwise.
+ */
+ public boolean containsListFor(K key)
+ {
+ return mapToList.containsKey(key);
+ }
+
+ /**
+ * Returns true if this MapToList contains a List for the given key and that
+ * list contains the given value. Note, this method returns false if the
+ * given key is not in this MapToList.
+ *
+ * This method is value-semantic in that no changes are made to the objects
+ * passed into the method.
+ *
+ * @param key
+ * The key for the List being tested.
+ * @param value
+ * The value to find in the List for the given key.
+ * @return true if this MapToList contains a List for the given key AND that
+ * list contains the given value; false otherwise.
+ */
+ public boolean containsInList(K key, V value)
+ {
+ return containsListFor(key) && mapToList.get(key).contains(value);
+ }
+
+ /**
+ * Returns the number of objects in the List for the given key. This method
+ * will throw a NullPointerException if this MapToList does not contain a
+ * List for the given key.
+ *
+ * This method is value-semantic in that no changes are made to the object
+ * passed into the method.
+ *
+ * @param key
+ * The key being tested.
+ * @return the number of objects in the List for the given key
+ */
+ public int sizeOfListFor(K key)
+ {
+ /*
+ * FUTURE It is possible for the context of PCGen that this class should
+ * not throw a NullPointerException if the key is not in the MapToList.
+ * It is possible that better behavior might be to return -1. However,
+ * at this time, that should not be implemented (That is VERY detailed
+ * tweaking) until there is more information on how MapToList gets used
+ * around the PCGen universe (this could be considered inconsistent with
+ * getListFor below, since it doesn't throw a NPE...) - thpr 6/19/05
+ */
+ /*
+ * On the other hand, PCGen is also built with a lot of uninitialized
+ * items and at risk of NPEs... in order to fix the save problem in CVS
+ * this is currently set to zero if the key doesn't exist - thpr June
+ * 24, 2005
+ */
+ List<V> list = mapToList.get(key);
+ if (list == null)
+ {
+ return 0;
+ }
+ return list.size();
+ }
+
+ /**
+ * Returns a copy of the List contained in this MapToList for the given key.
+ * This method returns null if the given key is not in this MapToList.
+ *
+ * This method is value-semantic in that no changes are made to the object
+ * passed into the method and ownership of the returned List is transferred
+ * to the class calling this method.
+ *
+ * Note: If you are only acquiring a single instance from a given list (and
+ * acquiring that by the order in which it appears in the list) it is
+ * probably much faster to use getElementInList, as that does not require
+ * the internal list to be copied (getListFor copies the list in order to be
+ * value-semantic)
+ *
+ * @param key
+ * The key for which a copy of the list should be returned.
+ * @return a copy of the List contained in this MapToList for the given key;
+ * null if the given key is not a key in this MapToList.
+ */
+ public List<V> getListFor(K key)
+ {
+ List<V> list = mapToList.get(key);
+ return list == null ? null : new ArrayList<V>(list);
+ }
+
+ /**
+ * Removes the given value from the list for the given key. Returns true if
+ * the value was successfully removed from the list for the given key.
+ * Returns false if there is not a list for the given key object or if the
+ * list for the given key object did not contain the given value object.
+ *
+ * @param key
+ * The key indicating which List the given object should be
+ * removed from
+ * @param value
+ * The value to be removed from the List for the given key
+ * @return true if the value was successfully removed from the list for the
+ * given key; false otherwise
+ */
+ public boolean removeFromListFor(K key, V value)
+ {
+ List<V> list = mapToList.get(key);
+ /*
+ * Note there is no requirement that a Key is added before this method
+ * is called
+ */
+ if (list == null)
+ {
+ return false;
+ }
+ boolean removed = list.remove(value);
+ if (removed && list.isEmpty())
+ {
+ mapToList.remove(key);
+ }
+ return removed;
+ }
+
+ /**
+ * Removes the List for the given key. Note there is no requirement that the
+ * list for the given key be empty before this method is called.
+ *
+ * Obviously, ownership of the returned List is transferred to the object
+ * calling this method.
+ *
+ * @param key
+ * The key indicating which List the given object should be
+ * removed from
+ * @return The List which this MapToList previous mapped the given key
+ */
+ public List<V> removeListFor(K key)
+ {
+ return mapToList.remove(key);
+ }
+
+ /**
+ * Returns true if this MapToList contains no Lists.
+ *
+ * NOTE: This method checks whether this MapToList contains any Lists for
+ * any key. It DOES NOT test whether all Lists defined for all keys are
+ * empty. Therefore, it is possible that this MapToList contains one or more
+ * keys, and all of the lists associated with those keys are empty, yet this
+ * method will return false.
+ *
+ * @return true if this MapToList contains no Lists; false otherwise
+ */
+ public boolean isEmpty()
+ {
+ return mapToList.isEmpty();
+ }
+
+ /**
+ * Returns the number of lists contained by this MapToList.
+ *
+ * NOTE: This method counts the number of Lists this MapToList contains. It
+ * DOES NOT determine whether all Lists defined for all keys are empty.
+ * Therefore, it is possible that this MapToList contains one or more keys,
+ * and all of the lists associated with those keys are empty, yet this
+ * method will return a non-zero value.
+ *
+ * @return The number of lists contained by this MapToList.
+ */
+ public int size()
+ {
+ return mapToList.size();
+ }
+
+ /**
+ * Returns a specific element in the list for the given key. Note this is
+ * much faster than retrieving a list for a given key (using getListFor) and
+ * then performing a get on the returned list, because getListFor returns a
+ * clone of the list for the given key.
+ *
+ * @param key
+ * The key used to identify the list from which the specified
+ * value will be returned
+ * @param i
+ * The location in the list (for the given key) of the value to
+ * be returned
+ * @return The value in the given location in the list for the given key
+ * @throws IllegalArgumentException
+ * if the given key does not exist in this AbstractMapToList
+ * @throws IndexOutOfBoundsException
+ * if the index is out of range for the list for the given key
+ * (index is less than zero OR greater than or equal to the size
+ * of the list)
+ */
+ public V getElementInList(K key, int i)
+ {
+ List<V> subList = mapToList.get(key);
+ if (subList == null)
+ {
+ throw new IllegalArgumentException(key
+ + " is not a key in this AbstractMapToList");
+ }
+ return subList.get(i);
+ }
+
+ /**
+ * Clears this AbstractMapToList (removes all keys/list combiantions)
+ */
+ public void clear()
+ {
+ mapToList.clear();
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString()
+ {
+ return mapToList.toString();
+ }
+
+ /**
+ * Returns a Set indicating the Keys of this MapToList. Ownership of the Set
+ * is transferred to the calling Object, no association is kept between the
+ * Set and this MapToList. (Thus, removal of a key from the returned Set
+ * will not remove that key from this MapToList)
+ *
+ * NOTE: This method returns all of the keys this MapToList contains. It
+ * DOES NOT determine whether the Lists defined for the keys are empty.
+ * Therefore, it is possible that this MapToList contains one or more keys,
+ * and all of the lists associated with those keys are empty, yet this
+ * method will return a non-zero length Set.
+ *
+ * @return a Set containing the keys in this MapToList
+ */
+ public Set<K> getKeySet()
+ {
+ // Need to 'clone' the Set, since Map returns a set that is still
+ // associated with the Map
+ Set<K> set = this.getEmptySet();
+ set.addAll(mapToList.keySet());
+ return set;
+ }
+
+ protected abstract Set<K> getEmptySet();
+
+ @Override
+ public int hashCode()
+ {
+ return mapToList.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (o instanceof AbstractMapToList)
+ {
+ return mapToList.equals(((AbstractMapToList<?, ?>) o).mapToList);
+ }
+ else if (o instanceof MapToList)
+ {
+ MapToList<Object, ?> other = (MapToList<Object, ?>) o;
+ Set<K> keySet = mapToList.keySet();
+ if (keySet.equals(other.getKeySet()))
+ {
+ for (Object key : keySet)
+ {
+ if (!mapToList.get(key).equals(other.getListFor(key)))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
Added: Trunk/pcgen/code/src/java/pcgen/base/util/GenericMapToList.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/base/util/GenericMapToList.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/base/util/GenericMapToList.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2004, 2005 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Created on Aug 29, 2004 Imported into PCGen on June 18, 2005.
+ */
+package pcgen.base.util;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Thomas Parker (thpr [at] yahoo.com)
+ *
+ * Represents a Map of objects to Lists. List management is done internally to
+ * this class (while copies are accessible, the lists are kept private to this
+ * class).
+ *
+ * This class is reference-semantic. In appropriate cases (such as calling the
+ * addToListFor method), GenericMapToList will maintain a reference to the given
+ * Object. GenericMapToList will not modify any of the Objects it is passed;
+ * however, it reserves the right to return references to Objects it contains to
+ * other Objects.
+ *
+ * However, when any method in which GenericMapToList returns a Collection,
+ * ownership of the Collection itself is transferred to the calling Object, but
+ * the contents of the Collection (keys, values, etc.) are references whose
+ * ownership should be respected.
+ *
+ * CAUTION: This is a convenience method for use in Java 1.4 and is not
+ * appropriate for use in Java 1.5 (Typed Collections are probably more
+ * appropriate)
+ */
+public class GenericMapToList<K, V> extends AbstractMapToList<K, V>
+{
+
+ private final Class<? extends Map> underlyingClass;
+
+ /**
+ * Creates a new GenericMapToList
+ *
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ */
+ public GenericMapToList(Class<? extends Map> cl)
+ throws InstantiationException, IllegalAccessException
+ {
+ super(cl.newInstance());
+ underlyingClass = cl;
+ }
+
+ public static <K, V> GenericMapToList<K, V> getMapToList(
+ Class<? extends Map> cl)
+ {
+ try
+ {
+ return new GenericMapToList<K, V>(cl);
+ }
+ catch (InstantiationException e)
+ {
+ throw new IllegalArgumentException(
+ "Class for GenericMapToList must possess a zero-argument constructor",
+ e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new IllegalArgumentException(
+ "Class for GenericMapToList must possess a public zero-argument constructor",
+ e);
+ }
+ }
+
+ @Override
+ protected Set<K> getEmptySet()
+ {
+ return new WrappedMapSet<K>(underlyingClass);
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/base/util/HashMapToInstanceList.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/base/util/HashMapToInstanceList.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/base/util/HashMapToInstanceList.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2004-2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.base.util;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Thomas Parker (thpr [at] yahoo.com)
+ *
+ * Represents a Map of objects to Lists. List management is done internally to
+ * this class (while copies are accessible, the lists are kept private to this
+ * class).
+ *
+ * This class is reference-semantic. In appropriate cases (such as calling the
+ * addToListFor method), HashMapToList will maintain a reference to the given
+ * Object. HashMapToList will not modify any of the Objects it is passed;
+ * however, it reserves the right to return references to Objects it contains to
+ * other Objects.
+ *
+ * However, when any method in which HashMapToList returns a Collection,
+ * ownership of the Collection itself is transferred to the calling Object, but
+ * the contents of the Collection (keys, values, etc.) are references whose
+ * ownership should be respected.
+ *
+ * Note: For purposes of containing and removing an object from a List, this
+ * Class performs instance tests (meaning the use of == not .equals()).
+ *
+ * CAUTION: This is a convenience method for use in Java 1.4 and is not
+ * appropriate for use in Java 1.5 (Typed Collections are probably more
+ * appropriate)
+ */
+public class HashMapToInstanceList<K, V> extends AbstractMapToList<K, V>
+{
+
+ /**
+ * Creates a new HashMapToList
+ */
+ public HashMapToInstanceList()
+ {
+ super(new HashMap<K, List<V>>());
+ }
+
+ @Override
+ protected Set<K> getEmptySet()
+ {
+ return new HashSet<K>();
+ }
+
+ /**
+ * Returns true if this MapToList contains a List for the given key and that
+ * list contains the given object (this is an instance test against the
+ * specific object, not the value of the object). Note, this method returns
+ * false if the given key is not in this MapToList.
+ *
+ * This method is value-semantic in that no changes are made to the objects
+ * passed into the method.
+ *
+ * @param key
+ * The key for the List being tested.
+ * @param object
+ * The object to find in the List for the given key.
+ * @return true if this MapToList contains a List for the given key AND that
+ * list contains the given value; false otherwise.
+ */
+ @Override
+ public boolean containsInList(K key, V object)
+ {
+ if (!containsListFor(key))
+ {
+ return false;
+ }
+ for (V o : getListFor(key))
+ {
+ if (o == object)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Removes the given object from the list for the given key. This is done
+ * based on an instance test against the given object, not the value of the
+ * object. Returns true if the object was successfully removed from the list
+ * for the given key. Returns false if there is not a list for the given key
+ * object or if the list for the given key object did not contain the given
+ * value object.
+ *
+ * @param key
+ * The key indicating which List the given object should be
+ * removed from
+ * @param object
+ * The object to be removed from the List for the given key
+ * @return true if the value was successfully removed from the list for the
+ * given key; false otherwise
+ */
+ @Override
+ public boolean removeFromListFor(K key, V object)
+ {
+ /*
+ * Note there is no requirement that a Key is added before this method
+ * is called
+ */
+ if (!containsListFor(key))
+ {
+ return false;
+ }
+ List<V> list = mapToList.get(key);
+ for (Iterator<V> it = list.iterator(); it.hasNext();)
+ {
+ if (it.next() == object)
+ {
+ it.remove();
+ if (list.isEmpty())
+ {
+ removeListFor(key);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/base/util/OneToOneMap.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/base/util/OneToOneMap.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/base/util/OneToOneMap.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,87 @@
+package pcgen.base.util;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class OneToOneMap<K, V>
+{
+ private final HashMap<K, V> forwardMap = new HashMap<K, V>();
+ private final HashMap<V, K> reverseMap = new HashMap<V, K>();
+
+ public void clear()
+ {
+ forwardMap.clear();
+ reverseMap.clear();
+ }
+
+ public boolean containsKey(Object key)
+ {
+ return forwardMap.containsKey(key);
+ }
+
+ public boolean containsValue(Object value)
+ {
+ return reverseMap.containsKey(value);
+ }
+
+ public V get(Object key)
+ {
+ return forwardMap.get(key);
+ }
+
+ public K getKeyFor(Object key)
+ {
+ return reverseMap.get(key);
+ }
+
+ public boolean isEmpty()
+ {
+ return forwardMap.isEmpty();
+ }
+
+ public Set<K> keySet()
+ {
+ return new HashSet<K>(forwardMap.keySet());
+ }
+
+ public V put(K key, V value)
+ {
+ reverseMap.put(value, key);
+ return forwardMap.put(key, value);
+ }
+
+ public void putAll(Map<? extends K, ? extends V> m)
+ {
+ for (Map.Entry<? extends K, ? extends V> me : m.entrySet())
+ {
+ put(me.getKey(), me.getValue());
+ }
+ }
+
+ public V remove(Object key)
+ {
+ V value = forwardMap.remove(key);
+ reverseMap.remove(value);
+ return value;
+ }
+
+ public int size()
+ {
+ return forwardMap.size();
+ }
+
+ public Collection<V> values()
+ {
+ return new HashSet<V>(reverseMap.keySet());
+ }
+
+ @Override
+ public String toString()
+ {
+ return "OneToOneMap: " + forwardMap.toString();
+ }
+
+}
Added: Trunk/pcgen/code/src/java/pcgen/base/util/TreeMapToList.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/base/util/TreeMapToList.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/base/util/TreeMapToList.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2004, 2005 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Created on Aug 29, 2004 Imported into PCGen on June 18, 2005.
+ */
+package pcgen.base.util;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ * @author Thomas Parker (thpr [at] yahoo.com)
+ *
+ * Represents a Map of objects to Lists. List management is done internally to
+ * this class (while copies are accessible, the lists are kept private to this
+ * class).
+ *
+ * This class is reference-semantic. In appropriate cases (such as calling the
+ * addToListFor method), TreeMapToList will maintain a reference to the given
+ * Object. TreeMapToList will not modify any of the Objects it is passed;
+ * however, it reserves the right to return references to Objects it contains to
+ * other Objects.
+ *
+ * However, when any method in which TreeMapToList returns a Collection,
+ * ownership of the Collection itself is transferred to the calling Object, but
+ * the contents of the Collection (keys, values, etc.) are references whose
+ * ownership should be respected.
+ *
+ * Note that this sorts keys in the same fashion as TreeMap: according to the
+ * natural order for the key's class (see Comparable), or by the comparator
+ * provided at construction. Thus, the keys in the TreeMapToList must be
+ * Comparable, or a Comparator must be provided. All association cautions with
+ * TreeMap (such as consistent-with-equals operation) must also be observed in
+ * TreeMapToList (see TreeMap)
+ *
+ * CAUTION: This is a convenience method for use in Java 1.4 and is not
+ * appropriate for use in Java 1.5 (Typed Collections are probably more
+ * appropriate)
+ */
+public class TreeMapToList<K, V> extends AbstractMapToList<K, V>
+{
+
+ private final Comparator<? super K> comparator;
+
+ /**
+ * Creates a new TreeMapToList
+ */
+ public TreeMapToList()
+ {
+ super(new TreeMap<K, List<V>>());
+ comparator = null;
+ }
+
+ /**
+ * Creates a new TreeMapToList using the given Comparator as the Comparator
+ * for the underlying TreeSet
+ *
+ * @param comp
+ * The Comparator to be used as the Comparator for the keys in
+ * this TreeMapToList
+ */
+ public TreeMapToList(Comparator<? super K> comp)
+ {
+ super(new TreeMap<K, List<V>>(comp));
+ comparator = comp;
+ }
+
+ @Override
+ protected Set<K> getEmptySet()
+ {
+ return new TreeSet<K>(comparator);
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/base/util/TripleKeyMap.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/base/util/TripleKeyMap.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/base/util/TripleKeyMap.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,421 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.base.util;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+/**
+ * @author Thomas Parker (thpr [at] yahoo.com)
+ *
+ * Represents a map where the objects are stored using three keys rather than
+ * the traditional single key (single key is provided by the Map interface from
+ * java.util).
+ *
+ * This class protects its internal structure from modification, but
+ * TripleKeyMap is generally reference-semantic. TripleKeyMap will not modify
+ * any of the Objects it is passed; however, it reserves the right to return
+ * references to Objects it contains to other Objects.
+ *
+ * In order to protect its internal structure, any Collection returned by the
+ * methods of TripleKeyMap (with the exception of actual keys or values that
+ * happen to be Collections) is NOT associated with the TripleKeyMap, and
+ * modification of the returned Collection will not modify the internal
+ * structure of TripleKeyMap.
+ *
+ * CAUTION: If you are not looking for the value-semantic protection of this
+ * class (of preventing accidental modification of underlying parts of a
+ * three-key Map structure, then this is a convenience method and is not
+ * appropriate for use in Java 1.5 (Typed Collections are probably more
+ * appropriate).
+ */
+public class TripleKeyMap<K1, K2, K3, V> implements Cloneable
+{
+
+ /**
+ * The underlying map - of primary keys to Maps - for the TripleKeyMap. This
+ * class protects its internal structure, so no method should ever return an
+ * object capable of modifying the maps. All modifications should be done
+ * through direct calls to the methods of TripleKeyMap.
+ */
+ private Map<K1, Map<K2, Map<K3, V>>> map =
+ new HashMap<K1, Map<K2, Map<K3, V>>>();
+
+ /**
+ * Constructs a new (empty) TripleKeyMap
+ */
+ public TripleKeyMap()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new TripleKeyMap, with the same contents as the given
+ * TripleKeyMap.
+ *
+ * The given TripleKeyMap is not modified and the constructed TripleKeyMap
+ * will be independent of the given TripleKeyMap other than the Objects used
+ * to represent the keys and values. (In other words, modification of the
+ * given TripleKeyMap will not alter the constructed TripleKeyMap, and vice
+ * versa)
+ *
+ * @param otherMap
+ * The TripleKeyMap whose contents should be copied into this
+ * TripleKeyMap.
+ */
+ public TripleKeyMap(final TripleKeyMap<K1, K2, K3, V> otherMap)
+ {
+ for (Entry<K1, Map<K2, Map<K3, V>>> me : otherMap.map.entrySet())
+ {
+ HashMap<K2, Map<K3, V>> localMap = new HashMap<K2, Map<K3, V>>();
+ map.put(me.getKey(), localMap);
+ for (Entry<K2, Map<K3, V>> subME : me.getValue().entrySet())
+ {
+ localMap.put(subME.getKey(), new HashMap<K3, V>(subME
+ .getValue()));
+ }
+ }
+ }
+
+ /**
+ * Puts a new object into the TripleKeyMap.
+ *
+ * @param key1
+ * The primary key used to store the value in this TripleKeyMap.
+ * @param key2
+ * The secondary key used to store the value in this
+ * TripleKeyMap.
+ * @param key3
+ * The tertiary key used to store the value in this TripleKeyMap.
+ * @param value
+ * The value to be stored in this TripleKeyMap.
+ * @return the Object previously stored in this TripleKeyMap with the given
+ * keys. null if this TripleKeyMap did not previously have an object
+ * stored with the given keys.
+ */
+ public V put(K1 key1, K2 key2, K3 key3, V value)
+ {
+ Map<K2, Map<K3, V>> localMap = map.get(key1);
+ Map<K3, V> subMap = null;
+ if (localMap == null)
+ {
+ localMap = new HashMap<K2, Map<K3, V>>();
+ map.put(key1, localMap);
+ }
+ else
+ {
+ subMap = localMap.get(key2);
+ }
+ if (subMap == null)
+ {
+ subMap = new HashMap<K3, V>();
+ localMap.put(key2, subMap);
+ }
+ return subMap.put(key3, value);
+ }
+
+ /**
+ * Gets an object from the TripleKeyMap.
+ *
+ * @param key1
+ * The primary key used to get the value in this TripleKeyMap.
+ * @param key2
+ * The secondary key used to get the value in this TripleKeyMap.
+ * @param key3
+ * The tertiary key used to get the value in this TripleKeyMap.
+ * @param value
+ * The value stored in this TripleKeyMap for the given keys.
+ * @return the Object stored in this TripleKeyMap for the given keys. null
+ * if this TripleKeyMap does not have an object stored with the
+ * given keys.
+ */
+ public V get(K1 key1, K2 key2, K3 key3)
+ {
+ Map<K2, Map<K3, V>> localMap = map.get(key1);
+ if (localMap == null)
+ {
+ return null;
+ }
+ Map<K3, V> subMap = localMap.get(key2);
+ if (subMap == null)
+ {
+ return null;
+ }
+ return subMap.get(key3);
+ }
+
+ /**
+ * Returns true if an object is stored in this TripleKeyMap for the given
+ * keys.
+ *
+ * @param key1
+ * The primary key to be tested for containing a value in this
+ * TripleKeyMap.
+ * @param key2
+ * The secondary key to be tested for containing a value in this
+ * TripleKeyMap.
+ * @param key3
+ * The tertiary key to be tested for containing a value in this
+ * TripleKeyMap.
+ * @return true if this TripleKeyMap has an Object stored in this
+ * TripleKeyMap for the given keys; false otherwise
+ */
+ public boolean containsKey(K1 key1, K2 key2, K3 key3)
+ {
+ Map<K2, Map<K3, V>> localMap = map.get(key1);
+ if (localMap == null)
+ {
+ return false;
+ }
+ Map<K3, V> subMap = localMap.get(key2);
+ if (subMap == null)
+ {
+ return false;
+ }
+ return subMap.containsKey(key3);
+ }
+
+ /**
+ * Removes an object from the TripleKeyMap.
+ *
+ * @param key1
+ * The primary key used to remove the value in this TripleKeyMap.
+ * @param key2
+ * The secondary key used to remove the value in this
+ * TripleKeyMap.
+ * @param key3
+ * The tertiary key used to remove the value in this
+ * TripleKeyMap.
+ * @return the Object stored in this TripleKeyMap for the given keys. null
+ * if this TripleKeyMap does not have an object stored with the
+ * given keys.
+ */
+ public V remove(K1 key1, K2 key2, K3 key3)
+ {
+ Map<K2, Map<K3, V>> localMap = map.get(key1);
+ if (localMap == null)
+ {
+ return null;
+ }
+ Map<K3, V> subMap = localMap.get(key2);
+ if (subMap == null)
+ {
+ return null;
+ }
+ V o = subMap.remove(key3);
+ /*
+ * Clean up the primary maps if the secondary maps are empty. This is
+ * required to avoid a false report from get*KeySet. Generally, if an
+ * object is added with the keys KEY1 and KEY2, then subsequently
+ * removed (and no other objects were stored with those keys), then
+ * getKeySet() should never return KEY1 (and there is a corollary for
+ * KEY2 cleanup, though that is implicit and does not require special
+ * code)
+ */
+ if (subMap.isEmpty())
+ {
+ localMap.remove(key2);
+ }
+ if (localMap.isEmpty())
+ {
+ map.remove(key1);
+ }
+ return o;
+ }
+
+ /**
+ * Returns a Set which contains the primary keys for this TripleKeyMap.
+ * Returns an empty Set if this TripleKeyMap is empty (has no primary keys)
+ *
+ * Ownership of the returned Set is transferred to the Object that called
+ * this method. Modification of the returned Set will not modify this
+ * TripleKeyMap, and modification of this TripleKeyMap will not alter the
+ * returned Set.
+ *
+ * @return A Set containing the primary keys for this TripleKeyMap.
+ */
+ public Set<K1> getKeySet()
+ {
+ return new HashSet<K1>(map.keySet());
+ }
+
+ /**
+ * Returns a Set which contains the secondary keys for the given primary key
+ * within this TripleKeyMap. Returns an empty Set if there are no objects
+ * stored in the TripleKeyMap with the given primary key.
+ *
+ * Ownership of the returned Set is transferred to the Object that called
+ * this method. Modification of the returned Set will not modify this
+ * TripleKeyMap, and modification of this TripleKeyMap will not alter the
+ * returned Set.
+ *
+ * @param key1
+ * The primary key used to identify the secondary Key Set in this
+ * TripleKeyMap.
+ * @return A Set containing the secondary keys for the given primary key
+ * within this TripleKeyMap.
+ */
+ public Set<K2> getSecondaryKeySet(final K1 aPrimaryKey)
+ {
+ final Map<K2, Map<K3, V>> localMap = map.get(aPrimaryKey);
+ if (localMap == null)
+ {
+ return Collections.emptySet();
+ }
+ return new HashSet<K2>(localMap.keySet());
+ }
+
+ /**
+ * Returns a Set which contains the tertiary keys for the given primary key
+ * within this TripleKeyMap. Returns an empty Set if there are no objects
+ * stored in the TripleKeyMap with the given primary key.
+ *
+ * Ownership of the returned Set is transferred to the Object that called
+ * this method. Modification of the returned Set will not modify this
+ * TripleKeyMap, and modification of this TripleKeyMap will not alter the
+ * returned Set.
+ *
+ * @param key1
+ * The primary key used to identify the Tertiary Key Set in this
+ * TripleKeyMap.
+ * @param key2
+ * The secondary key used to identify the Tertiary Key Set in
+ * this TripleKeyMap.
+ * @return A Set containing the Tertiary keys for the given primary and
+ * secondary keys within this TripleKeyMap.
+ */
+ public Set<K3> getTertiaryKeySet(K1 key1, K2 key2)
+ {
+ final Map<K2, Map<K3, V>> localMap = map.get(key1);
+ if (localMap == null)
+ {
+ return Collections.emptySet();
+ }
+ Map<K3, V> subMap = localMap.get(key2);
+ if (subMap == null)
+ {
+ return Collections.emptySet();
+ }
+ return new HashSet<K3>(subMap.keySet());
+ }
+
+ /**
+ * Clears this TripleKeyMap.
+ */
+ public void clear()
+ {
+ map.clear();
+ }
+
+ /**
+ * Returns true if the TripleKeyMap is empty
+ *
+ * @return true if the TripleKeyMap is empty; false otherwise
+ */
+ public boolean isEmpty()
+ {
+ return map.isEmpty();
+ }
+
+ /**
+ * Returns the number of primary keys in this TripleKeyMap
+ *
+ * @return the number of primary keys in this TripleKeyMap
+ */
+ public int firstKeyCount()
+ {
+ return map.size();
+ }
+
+ /**
+ * Clones this TripleKeyMap. The contents of the TripleKeyMap (the keys and
+ * values) are not cloned - this is not a truly deep clone. However, the
+ * internal structure of the TripleKeyMap is sufficiently cloned in order to
+ * protect the internal structure of the original or the clone from being
+ * modified by the other object.
+ *
+ * @return A clone of this TripleKeyMap that contains the same keys and
+ * values as the original TripleKeyMap.
+ */
+ @Override
+ public TripleKeyMap<K1, K2, K3, V> clone()
+ throws CloneNotSupportedException
+ {
+ /*
+ * This cast will cause a Generic type safety warning. This is
+ * impossible to avoid, given that super.clone() will not return a
+ * TripleKeyMap with the proper Generic arguments. - Thomas Parker
+ * 1/26/07
+ */
+ TripleKeyMap<K1, K2, K3, V> tkm =
+ (TripleKeyMap<K1, K2, K3, V>) super.clone();
+ /*
+ * This provides a semi-deep clone of the TripleKeyMap, in order to
+ * protect the internal structure of the TripleKeyMap from modification.
+ * Note the key and value objects are not cloned, so this is not truly a
+ * deep clone, but is deep enough to protect the internal structure.
+ */
+ tkm.map = new HashMap<K1, Map<K2, Map<K3, V>>>();
+ for (Entry<K1, Map<K2, Map<K3, V>>> me : map.entrySet())
+ {
+ HashMap<K2, Map<K3, V>> localMap = new HashMap<K2, Map<K3, V>>();
+ tkm.map.put(me.getKey(), localMap);
+ for (Entry<K2, Map<K3, V>> subME : me.getValue().entrySet())
+ {
+ localMap.put(subME.getKey(), new HashMap<K3, V>(subME
+ .getValue()));
+ }
+ }
+ return tkm;
+ }
+
+ /**
+ * Returns a Set of the values stored in this TripleKeyMap for the given
+ * primary and secondary keys.
+ *
+ * Note: This Set is reference-semantic. The ownership of the Set is
+ * transferred to the calling Object; therefore, changes to the returned Set
+ * will NOT impact the TripleKeyMap.
+ *
+ * @param key1
+ * The primary key for which the values will be returned
+ * @param key2
+ * The secondary key for which the values will be returned
+ * @return a Set of the values stored in this TripleKeyMap for the given
+ * primary and secondary keys
+ */
+ public Set<V> values(K1 key1, K2 key2)
+ {
+ final Map<K2, Map<K3, V>> localMap = map.get(key1);
+ if (localMap == null)
+ {
+ return Collections.emptySet();
+ }
+ Map<K3, V> subMap = localMap.get(key2);
+ if (subMap == null)
+ {
+ return Collections.emptySet();
+ }
+ return new HashSet<V>(subMap.values());
+ }
+
+}
Added: Trunk/pcgen/code/src/java/pcgen/base/util/TripleKeyMapToList.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/base/util/TripleKeyMapToList.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/base/util/TripleKeyMapToList.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,320 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.base.util;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Thomas Parker (thpr [at] yahoo.com)
+ *
+ * Represents a TripleKeyMap of objects to Lists. List management is done
+ * internally to this class (while copies are accessible, the lists are kept
+ * private to this class).
+ *
+ * This class is reference-semantic. In appropriate cases (such as calling the
+ * addToListFor method), TripleKeyMapToList will maintain a reference to the
+ * given Object. TripleKeyMapToList will not modify any of the Objects it is
+ * passed; however, it reserves the right to return references to Objects it
+ * contains to other Objects.
+ *
+ * However, when any method in which TripleKeyMapToList returns a Collection,
+ * ownership of the Collection itself is transferred to the calling Object, but
+ * the contents of the Collection (keys, values, etc.) are references whose
+ * ownership should be respected.
+ *
+ * @param <K1>
+ * The type of the primary keys in this TripleKeyMapToList
+ * @param <K2>
+ * The type of the secondary keys in this TripleKeyMapToList
+ * @param <K3>
+ * The type of the tertiary keys in this TripleKeyMapToList
+ * @param <V>
+ * The type of the values in this TripleKeyMapToList
+ */
+public class TripleKeyMapToList<K1, K2, K3, V> implements Cloneable
+{
+
+ private final Class<? extends Map> firstClass;
+ private final Class<? extends Map> secondClass;
+ private final Class<? extends Map> thirdClass;
+
+ /**
+ * The underlying map for the TripleKeyMapToList. This class protects its
+ * internal structure, so no method should ever return an object capable of
+ * modifying the maps. All modifications should be done through direct calls
+ * to the methods of TripleKeyMapToList.
+ */
+ private final DoubleKeyMap<K1, K2, MapToList<K3, V>> map;
+
+ /**
+ * Constructs a new (empty) TripleKeyMapToList
+ */
+ public TripleKeyMapToList()
+ {
+ super();
+ firstClass = secondClass = thirdClass = HashMap.class;
+ map = new DoubleKeyMap<K1, K2, MapToList<K3, V>>(firstClass,
+ secondClass);
+ }
+
+ /**
+ * Constructs a new (empty) TripleKeyMapToList
+ */
+ public TripleKeyMapToList(Class<? extends Map> cl1,
+ Class<? extends Map> cl2, Class<? extends Map> cl3)
+ {
+ super();
+ firstClass = cl1;
+ secondClass = cl2;
+ thirdClass = cl3;
+ map = new DoubleKeyMap<K1, K2, MapToList<K3, V>>(firstClass,
+ secondClass);
+ }
+
+ /**
+ * Adds the given value to the List for the given keys. The null value
+ * cannot be used as a key in a TripleKeyMapToList. This method will
+ * automatically initialize the list for the given key if there is not
+ * already a List for that key.
+ *
+ * This method is reference-semantic and this TripleKeyMapToList will
+ * maintain a strong reference to both the key object and the value object
+ * given as arguments to this method.
+ *
+ * @param key1
+ * The primary key indicating which List the given object should
+ * be added to.
+ * @param key2
+ * The secondary key indicating which List the given object
+ * should be added to.
+ * @param key3
+ * The tertiary key indicating which List the given object should
+ * be added to.
+ * @param value
+ * The value to be added to the List for the given keys.
+ */
+ public void addToListFor(K1 key1, K2 key2, K3 key3, V value)
+ {
+ MapToList<K3, V> localMap = map.get(key1, key2);
+ if (localMap == null)
+ {
+ localMap = GenericMapToList.getMapToList(thirdClass);
+ map.put(key1, key2, localMap);
+ }
+ localMap.addToListFor(key3, value);
+ }
+
+ /**
+ * Returns a copy of the List contained in this TripleKeyMapToList for the
+ * given keys. This method returns null if the given key is not in this
+ * TripleKeyMapToList.
+ *
+ * This method is value-semantic in that no changes are made to the object
+ * passed into the method and ownership of the returned List is transferred
+ * to the class calling this method.
+ *
+ * @param key1
+ * The primary key for retrieving the given List
+ * @param key2
+ * The secondary key for retrieving the given List
+ * @param key3
+ * The tertiary key for retrieving the given List
+ * @return a copy of the List contained in this TripleKeyMapToList for the
+ * given key; null if the given key is not a key in this
+ * TripleKeyMapToList.
+ */
+ public List<V> getListFor(K1 key1, K2 key2, K3 key3)
+ {
+ MapToList<K3, V> localMap = map.get(key1, key2);
+ return localMap == null ? null : localMap.getListFor(key3);
+ }
+
+ /**
+ * Returns true if this TripleKeyMapToList contains a List for the given
+ * keys. This method returns false if the given keys are not in this
+ * TripleKeyMapToList.
+ *
+ * This method is value-semantic in that no changes are made to the objects
+ * passed into the method.
+ *
+ * @param key1
+ * The primary key for testing presence of a List
+ * @param key2
+ * The secondary key for testing presence of a List
+ * @param key3
+ * The tertiary key for testing presence of a List
+ * @return true if this TripleKeyMapToList contains a List for the given
+ * keys; false otherwise.
+ */
+ public boolean containsListFor(K1 key1, K2 key2, K3 key3)
+ {
+ MapToList<K3, V> localMap = map.get(key1, key2);
+ return localMap == null ? false : localMap.containsListFor(key3);
+ }
+
+ /**
+ * Removes the List for the given keys. Note there is no requirement that
+ * the list for the given keys be empty before this method is called.
+ *
+ * Obviously, ownership of the returned List is transferred to the object
+ * calling this method.
+ *
+ * @param key1
+ * The primary key indicating the List to remove
+ * @param key2
+ * The secondary key indicating the List to remove
+ * @param key3
+ * The tertiary key indicating the List to remove
+ * @return The List which this TripleKeyMapToList previous mapped the given
+ * keys
+ */
+ public List<V> removeListFor(K1 key1, K2 key2, K3 key3)
+ {
+ MapToList<K3, V> localMap = map.get(key1, key2);
+ return localMap == null ? null : localMap.removeListFor(key3);
+ }
+
+ /**
+ * Returns a Set which contains the primary keys for this
+ * TripleKeyMapToList. Returns an empty Set if this TripleKeyMapToList is
+ * empty (has no primary keys)
+ *
+ * NOTE: This method returns all of the primary keys this TripleKeyMapToList
+ * contains. It DOES NOT determine whether the Lists defined for the keys
+ * are empty. Therefore, it is possible that this TripleKeyMapToList
+ * contains one or more keys, and all of the lists associated with those
+ * keys are empty, yet this method will return a non-zero length Set.
+ *
+ * Ownership of the returned Set is transferred to the Object that called
+ * this method. Modification of the returned Set will not modify this
+ * TripleKeyMapToList, and modification of this TripleKeyMapToList will not
+ * alter the returned Set.
+ *
+ * @return A Set containing the primary keys for this TripleKeyMapToList.
+ */
+ public Set<K1> getKeySet()
+ {
+ return map.getKeySet();
+ }
+
+ /**
+ * Returns a Set which contains the secondary keys for the given primary key
+ * within this TripleKeyMapToList. Returns an empty Set if there are no
+ * objects stored in the TripleKeyMapToList with the given primary key.
+ *
+ * NOTE: This method returns all of the secondary keys this
+ * TripleKeyMapToList contains for the given primary key. It DOES NOT
+ * determine whether the Lists defined for the keys are empty. Therefore, it
+ * is possible that this TripleKeyMapToList contains one or more keys, and
+ * all of the lists associated with those keys are empty, yet this method
+ * will return a non-zero length Set.
+ *
+ * Ownership of the returned Set is transferred to the Object that called
+ * this method. Modification of the returned Set will not modify this
+ * TripleKeyMapToList, and modification of this TripleKeyMapToList will not
+ * alter the returned Set.
+ *
+ * @return A Set containing the secondary keys for the given primary key
+ * within this TripleKeyMapToList.
+ */
+ public Set<K2> getSecondaryKeySet(K1 aPrimaryKey)
+ {
+ return map.getSecondaryKeySet(aPrimaryKey);
+ }
+
+ /**
+ * Returns a Set which contains the tertiary keys for the given primary key
+ * within this TripleKeyMapToList. Returns an empty Set if there are no
+ * objects stored in the TripleKeyMapToList with the given primary key.
+ *
+ * NOTE: This method returns all of the tertiary keys this
+ * TripleKeyMapToList contains for the given primary and secondary keys. It
+ * DOES NOT determine whether the Lists defined for the keys are empty.
+ * Therefore, it is possible that this TripleKeyMapToList contains one or
+ * more keys, and all of the lists associated with those keys are empty, yet
+ * this method will return a non-zero length Set.
+ *
+ * Ownership of the returned Set is transferred to the Object that called
+ * this method. Modification of the returned Set will not modify this
+ * TripleKeyMapToList, and modification of this TripleKeyMapToList will not
+ * alter the returned Set.
+ *
+ * @param key1
+ * The primary key used to identify the Tertiary Key Set in this
+ * TripleKeyMapToList.
+ * @param key2
+ * The secondary key used to identify the Tertiary Key Set in
+ * this TripleKeyMapToList.
+ * @return A Set containing the Tertiary keys for the given primary and
+ * secondary keys within this TripleKeyMapToList.
+ */
+ public Set<K3> getTertiaryKeySet(K1 key1, K2 key2)
+ {
+ MapToList<K3, V> localMap = map.get(key1, key2);
+ if (localMap == null)
+ {
+ return Collections.emptySet();
+ }
+ return localMap.getKeySet();
+ }
+
+ /**
+ * Clears this TripleKeyMapToList.
+ */
+ public void clear()
+ {
+ map.clear();
+ }
+
+ /**
+ * Returns true if the TripleKeyMapToList is empty
+ *
+ * NOTE: This method checks whether this TripleKeyMapToList contains any
+ * Lists for any key. It DOES NOT test whether all Lists defined for all
+ * keys are empty. Therefore, it is possible that this TripleKeyMapToList
+ * contains one or more keys, and all of the lists associated with those
+ * keys are empty, yet this method will return false.
+ *
+ * @return true if the TripleKeyMapToList is empty; false otherwise
+ */
+ public boolean isEmpty()
+ {
+ return map.isEmpty();
+ }
+
+ /**
+ * Returns the number of primary key maps contained by this
+ * TripleKeyMapToList.
+ *
+ * NOTE: This method counts the number of Lists this TripleKeyMapToList
+ * contains. It DOES NOT determine whether all Lists defined for all keys
+ * are empty. Therefore, it is possible that this TripleKeyMapToList
+ * contains one or more keys, and all of the lists associated with those
+ * keys are empty, yet this method will return a non-zero value.
+ *
+ * @return The number of lists contained by this TripleKeyMapToList.
+ */
+ public int firstKeyCount()
+ {
+ return map.primaryKeyCount();
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/base/util/WrappedMapSet.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/base/util/WrappedMapSet.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/base/util/WrappedMapSet.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,82 @@
+package pcgen.base.util;
+
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+public class WrappedMapSet<T> extends AbstractSet<T> implements Set<T>
+{
+ private static final Object PRESENCE = new Object();
+
+ private Map<T, Object> map;
+
+ public <C extends Map> WrappedMapSet(Class<C> cl)
+ {
+ try
+ {
+ map = cl.newInstance();
+ }
+ catch (InstantiationException e)
+ {
+ throw new IllegalArgumentException(
+ "Expected a Class passed to WrappedMapSet to "
+ + "have a zero argument constructor", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new IllegalArgumentException(
+ "Expected a Class passed to WrappedMapSet to "
+ + "have a public, zero argument constructor", e);
+ }
+ }
+
+ public <C extends Map> WrappedMapSet(Class<C> cl, Collection<? extends T> c)
+ {
+ this(cl);
+ addAll(c);
+ }
+
+ @Override
+ public Iterator<T> iterator()
+ {
+ return map.keySet().iterator();
+ }
+
+ @Override
+ public int size()
+ {
+ return map.size();
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return map.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o)
+ {
+ return map.containsKey(o);
+ }
+
+ @Override
+ public boolean add(T o)
+ {
+ return map.put(o, PRESENCE) == null;
+ }
+
+ @Override
+ public boolean remove(Object o)
+ {
+ return map.remove(o) == PRESENCE;
+ }
+
+ @Override
+ public void clear()
+ {
+ map.clear();
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/cdom/base/AssociationSupport.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/cdom/base/AssociationSupport.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/cdom/base/AssociationSupport.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.cdom.base;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import pcgen.cdom.enumeration.AssociationKey;
+
+public class AssociationSupport implements AssociatedObject
+{
+ private Map<AssociationKey<?>, Object> associationMap;
+
+ public <T> void setAssociation(AssociationKey<T> name, T value)
+ {
+ if (associationMap == null)
+ {
+ associationMap = new HashMap<AssociationKey<?>, Object>();
+ }
+ associationMap.put(name, value);
+ }
+
+ public <T> T getAssociation(AssociationKey<T> name)
+ {
+ return (T) (associationMap == null ? null : associationMap.get(name));
+ }
+
+ public Collection<AssociationKey<?>> getAssociationKeys()
+ {
+ return new HashSet<AssociationKey<?>>(associationMap.keySet());
+ }
+
+ public boolean hasAssociations()
+ {
+ return associationMap != null && !associationMap.isEmpty();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return associationMap == null ? 0 : associationMap.size();
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+ if (o instanceof AssociationSupport)
+ {
+ AssociationSupport other = (AssociationSupport) o;
+ if (associationMap == null || associationMap.isEmpty())
+ {
+ return other.associationMap == null
+ || other.associationMap.isEmpty();
+ }
+ return associationMap.equals(other.associationMap);
+ }
+ return false;
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/cdom/base/SimpleAssociatedObject.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/cdom/base/SimpleAssociatedObject.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/cdom/base/SimpleAssociatedObject.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,49 @@
+package pcgen.cdom.base;
+
+import java.util.Collection;
+
+import pcgen.cdom.enumeration.AssociationKey;
+
+public class SimpleAssociatedObject extends ConcretePrereqObject implements
+ AssociatedPrereqObject
+{
+
+ private final AssociationSupport assoc = new AssociationSupport();
+
+ public <T> T getAssociation(AssociationKey<T> name)
+ {
+ return assoc.getAssociation(name);
+ }
+
+ public Collection<AssociationKey<?>> getAssociationKeys()
+ {
+ return assoc.getAssociationKeys();
+ }
+
+ public boolean hasAssociations()
+ {
+ return assoc.hasAssociations();
+ }
+
+ public <T> void setAssociation(AssociationKey<T> name, T value)
+ {
+ assoc.setAssociation(name, value);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return assoc.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (o instanceof SimpleAssociatedObject)
+ {
+ SimpleAssociatedObject other = (SimpleAssociatedObject) o;
+ return assoc.equals(other.assoc) && equalsPrereqObject(other);
+ }
+ return false;
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/cdom/reference/AbstractReferenceManufacturer.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/cdom/reference/AbstractReferenceManufacturer.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/cdom/reference/AbstractReferenceManufacturer.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,93 @@
+package pcgen.cdom.reference;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import pcgen.cdom.base.PrereqObject;
+import pcgen.util.Logging;
+
+public class AbstractReferenceManufacturer<T extends PrereqObject>
+{
+ private final Class<T> refClass;
+
+ private Map<String[], CDOMTypeRef<T>> typeReferences = new HashMap<String[], CDOMTypeRef<T>>();
+
+ private CDOMAllRef<T> allRef;
+
+ public AbstractReferenceManufacturer(Class<T> cl)
+ {
+ refClass = cl;
+ }
+
+ public CDOMTypeRef<T> getTypeReference(String... types)
+ {
+ for (String type : types)
+ {
+ if (type.length() == 0)
+ {
+ Logging.errorPrint("Attempt to acquire empty Type "
+ + "(the type String contains an empty element)");
+ return null;
+ }
+ if (type.indexOf('.') != -1)
+ {
+ throw new IllegalArgumentException(
+ "Cannot build Reference with type conaining a period: "
+ + type);
+ }
+ if (type.indexOf('=') != -1)
+ {
+ throw new IllegalArgumentException(
+ "Cannot build Reference with type conaining an equals: "
+ + type);
+ }
+ if (type.indexOf(',') != -1)
+ {
+ throw new IllegalArgumentException(
+ "Cannot build Reference with type conaining a comma: "
+ + type);
+ }
+ if (type.indexOf('|') != -1)
+ {
+ throw new IllegalArgumentException(
+ "Cannot build Reference with type conaining a pipe: "
+ + type);
+ }
+ }
+ Arrays.sort(types);
+ /*
+ * TODO FIXME This is the SLOW method - better to actually use Jakarta
+ * Commons Collections and create a map that does the lookup based on
+ * deepEquals of an Array...
+ */
+ for (Entry<String[], CDOMTypeRef<T>> me : typeReferences.entrySet())
+ {
+ if (Arrays.deepEquals(me.getKey(), types))
+ {
+ return me.getValue();
+ }
+ }
+ // Didn't find the appropriate key, create new
+ CDOMTypeRef<T> cgr = new CDOMTypeRef<T>(refClass, types);
+ typeReferences.put(types, cgr);
+ return cgr;
+ }
+
+ public CDOMAllRef<T> getAllReference()
+ {
+ if (allRef == null)
+ {
+ allRef = new CDOMAllRef<T>(refClass);
+ }
+ return allRef;
+ }
+
+ public Class<T> getCDOMClass()
+ {
+ return refClass;
+ }
+
+
+}
Added: Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMAllRef.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMAllRef.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMAllRef.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2007 Tom Parker <thpr@...>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package pcgen.cdom.reference;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import pcgen.cdom.base.PrereqObject;
+
+public final class CDOMAllRef<T extends PrereqObject> extends CDOMGroupRef<T>
+{
+ private List<T> referencedList = null;
+
+ public CDOMAllRef(Class<T> cl)
+ {
+ super(cl, "ALL: " + cl.getSimpleName());
+ }
+
+ @Override
+ public String getLSTformat()
+ {
+ return "ALL";
+ }
+
+ @Override
+ public String getPrimitiveFormat()
+ {
+ return "ALL";
+ }
+
+ @Override
+ public boolean contains(T obj)
+ {
+ if (referencedList == null)
+ {
+ throw new IllegalStateException(
+ "Cannot ask for contains: Reference has not been resolved");
+ }
+ return referencedList.contains(obj);
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ return o instanceof CDOMAllRef
+ && getReferenceClass().equals(((CDOMAllRef) o).getReferenceClass());
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return getReferenceClass().hashCode();
+ }
+
+ @Override
+ public void addResolution(T obj)
+ {
+ if (obj.getClass().equals(getReferenceClass()))
+ {
+ if (referencedList == null)
+ {
+ referencedList = new ArrayList<T>();
+ }
+ referencedList.add(obj);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot resolve a "
+ + getReferenceClass().getSimpleName() + " Reference to a "
+ + obj.getClass().getSimpleName());
+ }
+ }
+
+ @Override
+ public int getObjectCount()
+ {
+ return referencedList == null ? 0 : referencedList.size();
+ }
+
+ @Override
+ public Collection<T> getContainedObjects()
+ {
+ return Collections.unmodifiableList(referencedList);
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMDirectSingleRef.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMDirectSingleRef.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMDirectSingleRef.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2007 Tom Parker <thpr@...>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package pcgen.cdom.reference;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import pcgen.cdom.base.PrereqObject;
+
+public class CDOMDirectSingleRef<T extends PrereqObject> extends
+ CDOMSingleRef<T>
+{
+
+ private final T referencedObject;
+
+ public CDOMDirectSingleRef(T obj)
+ {
+ super((Class<T>) obj.getClass(), "*Direct");
+ referencedObject = obj;
+ }
+
+ @Override
+ public boolean contains(T obj)
+ {
+ return referencedObject.equals(obj);
+ }
+
+ @Override
+ public T resolvesTo()
+ {
+ return referencedObject;
+ }
+
+ @Override
+ public String getPrimitiveFormat()
+ {
+ return getName();
+ }
+
+ @Override
+ public String getLSTformat()
+ {
+ return getName();
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ return o instanceof CDOMDirectSingleRef
+ && getReferenceClass().equals(
+ ((CDOMDirectSingleRef) o).getReferenceClass());
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return getReferenceClass().hashCode();
+ }
+
+ @Override
+ public void addResolution(T obj)
+ {
+ throw new IllegalStateException("Cannot resolve a Direct Reference");
+ }
+
+ @Override
+ public Collection<T> getContainedObjects()
+ {
+ return Collections.singleton(referencedObject);
+ }
+
+ public static <R extends PrereqObject> CDOMDirectSingleRef<R> getRef(R obj)
+ {
+ return new CDOMDirectSingleRef<R>(obj);
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMGroupRef.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMGroupRef.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMGroupRef.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2007 (c) Thomas Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package pcgen.cdom.reference;
+
+import pcgen.cdom.base.CDOMReference;
+import pcgen.cdom.base.PrereqObject;
+
+public abstract class CDOMGroupRef<T extends PrereqObject> extends
+ CDOMReference<T>
+{
+
+ public CDOMGroupRef(Class<T> cl, String nm)
+ {
+ super(cl, nm);
+ }
+
+ @Override
+ public abstract boolean contains(T obj);
+}
Added: Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMSimpleSingleRef.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMSimpleSingleRef.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMSimpleSingleRef.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2007 Tom Parker <thpr@...>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package pcgen.cdom.reference;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import pcgen.cdom.base.PrereqObject;
+
+public class CDOMSimpleSingleRef<T extends PrereqObject> extends
+ CDOMSingleRef<T>
+{
+
+ private T referencedObject = null;
+
+ public CDOMSimpleSingleRef(Class<T> cl, String nm)
+ {
+ super(cl, nm);
+ }
+
+ @Override
+ public boolean contains(T obj)
+ {
+ if (referencedObject == null)
+ {
+ throw new IllegalStateException(
+ "Cannot ask for contains: Reference has not been resolved");
+ }
+ return referencedObject.equals(obj);
+ }
+
+ @Override
+ public T resolvesTo()
+ {
+ if (referencedObject == null)
+ {
+ throw new IllegalStateException(
+ "Cannot ask for resolution: Reference has not been resolved");
+ }
+ return referencedObject;
+ }
+
+ @Override
+ public String getPrimitiveFormat()
+ {
+ return getName();
+ }
+
+ @Override
+ public String getLSTformat()
+ {
+ return getName();
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (o instanceof CDOMSimpleSingleRef)
+ {
+ CDOMSimpleSingleRef<?> ref = (CDOMSimpleSingleRef) o;
+ return getReferenceClass().equals(ref.getReferenceClass())
+ && getName().equals(ref.getName());
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return getReferenceClass().hashCode() ^ getName().hashCode();
+ }
+
+ @Override
+ public void addResolution(T obj)
+ {
+ if (referencedObject == null)
+ {
+ if (obj.getClass().equals(getReferenceClass()))
+ {
+ referencedObject = obj;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot resolve a "
+ + getReferenceClass().getSimpleName() + " Reference to a "
+ + obj.getClass().getSimpleName());
+ }
+ }
+ else
+ {
+ throw new IllegalStateException(
+ "Cannot resolve a Single Reference twice");
+ }
+ }
+
+ @Override
+ public Collection<T> getContainedObjects()
+ {
+ return Collections.singleton(referencedObject);
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMSingleRef.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMSingleRef.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMSingleRef.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007 Tom Parker <thpr@...>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package pcgen.cdom.reference;
+
+import pcgen.cdom.base.CDOMReference;
+import pcgen.cdom.base.PrereqObject;
+
+public abstract class CDOMSingleRef<T extends PrereqObject> extends
+ CDOMReference<T>
+{
+
+ public CDOMSingleRef(Class<T> cl, String nm)
+ {
+ super(cl, nm);
+ }
+
+ @Override
+ public int getObjectCount()
+ {
+ return 1;
+ }
+
+ public abstract T resolvesTo();
+}
Added: Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMTypeRef.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMTypeRef.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/cdom/reference/CDOMTypeRef.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2007 Tom Parker <thpr@...>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package pcgen.cdom.reference;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import pcgen.base.lang.StringUtil;
+import pcgen.cdom.base.PrereqObject;
+
+public final class CDOMTypeRef<T extends PrereqObject> extends CDOMGroupRef<T>
+{
+
+ private List<T> referencedList = null;
+
+ private String[] types;
+
+ public CDOMTypeRef(Class<T> cl, String[] val)
+ {
+ super(cl, cl.getSimpleName() + " " + Arrays.deepToString(val));
+ types = new String[val.length];
+ System.arraycopy(val, 0, types, 0, val.length);
+ }
+
+ @Override
+ public String getPrimitiveFormat()
+ {
+ return StringUtil.join(types, ".");
+ }
+
+ @Override
+ public String getLSTformat()
+ {
+ return "TYPE=" + getPrimitiveFormat();
+ }
+
+ @Override
+ public boolean contains(T obj)
+ {
+ if (referencedList == null)
+ {
+ throw new IllegalStateException(
+ "Cannot ask for contains: Reference has not been resolved");
+ }
+ return referencedList.contains(obj);
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (o instanceof CDOMTypeRef)
+ {
+ CDOMTypeRef<?> ref = (CDOMTypeRef) o;
+ return getReferenceClass().equals(ref.getReferenceClass())
+ && getName().equals(ref.getName())
+ && Arrays.deepEquals(types, ref.types);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return getReferenceClass().hashCode() ^ getName().hashCode();
+ }
+
+ @Override
+ public void addResolution(T obj)
+ {
+ if (obj.getClass().equals(getReferenceClass()))
+ {
+ if (referencedList == null)
+ {
+ referencedList = new ArrayList<T>();
+ }
+ referencedList.add(obj);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot resolve a "
+ + getReferenceClass().getSimpleName() + " Reference to a "
+ + obj.getClass().getSimpleName());
+ }
+ }
+
+ @Override
+ public int getObjectCount()
+ {
+ return referencedList == null ? 0 : referencedList.size();
+ }
+
+ @Override
+ public Collection<T> getContainedObjects()
+ {
+ return Collections.unmodifiableList(referencedList);
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/cdom/reference/ReferenceManufacturer.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/cdom/reference/ReferenceManufacturer.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/cdom/reference/ReferenceManufacturer.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007 Tom Parker <thpr@...>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package pcgen.cdom.reference;
+
+import pcgen.cdom.base.CDOMObject;
+
+public interface ReferenceManufacturer<T extends CDOMObject, RT extends CDOMSingleRef<T>>
+{
+ public RT getReference(String key);
+
+ public CDOMTypeRef<T> getTypeReference(String... types);
+
+ public CDOMAllRef<T> getAllReference();
+
+ public Class<T> getCDOMClass();
+}
Added: Trunk/pcgen/code/src/java/pcgen/cdom/reference/SimpleReferenceManufacturer.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/cdom/reference/SimpleReferenceManufacturer.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/cdom/reference/SimpleReferenceManufacturer.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,94 @@
+/**
+ *
+ */
+package pcgen.cdom.reference;
+
+import pcgen.cdom.base.CDOMObject;
+import pcgen.core.PCClass;
+
+public class SimpleReferenceManufacturer<T extends CDOMObject> extends
+ AbstractReferenceManufacturer<T> implements
+ ReferenceManufacturer<T, CDOMSimpleSingleRef<T>>
+{
+ public SimpleReferenceManufacturer(Class<T> cl)
+ {
+ super(cl);
+ }
+
+ public CDOMSimpleSingleRef<T> getReference(String val)
+ {
+ // TODO Auto-generated method stub
+ // TODO This is incorrect, but a hack for now :)
+ if (val.equals(""))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ try
+ {
+ Integer.parseInt(val);
+ throw new IllegalArgumentException(val);
+ }
+ catch (NumberFormatException nfe)
+ {
+ // ok
+ }
+ if (val.startsWith("TYPE"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (val.equalsIgnoreCase("ANY"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (val.equalsIgnoreCase("ALL"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (val.startsWith("PRE"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (val.startsWith("CHOOSE"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (val.startsWith("TIMES="))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (val.startsWith("TIMEUNIT="))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (val.startsWith("CASTERLEVEL="))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (getCDOMClass().equals(PCClass.class))
+ {
+ if (val.startsWith("CLASS"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ else if (val.startsWith("SUB"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ else
+ {
+ try
+ {
+ Integer.parseInt(val);
+ throw new IllegalArgumentException(val);
+ }
+ catch (NumberFormatException nfe)
+ {
+ // Want this!
+ }
+ }
+ }
+
+ return new CDOMSimpleSingleRef<T>(getCDOMClass(), val);
+ }
+
+}
\ No newline at end of file
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/AssociatedChanges.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/AssociatedChanges.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/AssociatedChanges.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,20 @@
+package pcgen.rules.context;
+
+import java.util.Collection;
+
+import pcgen.base.util.MapToList;
+import pcgen.cdom.base.AssociatedPrereqObject;
+
+public interface AssociatedChanges<T>
+{
+ public boolean includesGlobalClear();
+
+ public Collection<T> getAdded();
+
+ public Collection<T> getRemoved();
+
+ public MapToList<T, AssociatedPrereqObject> getAddedAssociations();
+
+ public MapToList<T, AssociatedPrereqObject> getRemovedAssociations();
+
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/AssociatedCollectionChanges.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/AssociatedCollectionChanges.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/AssociatedCollectionChanges.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,63 @@
+package pcgen.rules.context;
+
+import java.util.Collection;
+
+import pcgen.base.util.MapToList;
+import pcgen.cdom.base.AssociatedPrereqObject;
+
+public class AssociatedCollectionChanges<T> implements AssociatedChanges<T>
+{
+ private MapToList<T, AssociatedPrereqObject> positive;
+ private MapToList<T, AssociatedPrereqObject> negative;
+ private boolean clear;
+
+ public AssociatedCollectionChanges(
+ MapToList<T, AssociatedPrereqObject> added,
+ MapToList<T, AssociatedPrereqObject> removed,
+ boolean globallyCleared)
+ {
+ positive = added;
+ negative = removed;
+ clear = globallyCleared;
+ }
+
+ public boolean includesGlobalClear()
+ {
+ return clear;
+ }
+
+ public boolean isEmpty()
+ {
+ return !clear && !hasAddedItems() && !hasRemovedItems();
+ }
+
+ public Collection<T> getAdded()
+ {
+ return positive.getKeySet();
+ }
+
+ public boolean hasAddedItems()
+ {
+ return positive != null && !positive.isEmpty();
+ }
+
+ public Collection<T> getRemoved()
+ {
+ return negative == null ? null : negative.getKeySet();
+ }
+
+ public boolean hasRemovedItems()
+ {
+ return negative != null && !negative.isEmpty();
+ }
+
+ public MapToList<T, AssociatedPrereqObject> getAddedAssociations()
+ {
+ return positive;
+ }
+
+ public MapToList<T, AssociatedPrereqObject> getRemovedAssociations()
+ {
+ return negative;
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/Changes.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/Changes.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/Changes.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,19 @@
+package pcgen.rules.context;
+
+import java.util.Collection;
+
+public interface Changes<T>
+{
+ public boolean hasAddedItems();
+
+ public boolean hasRemovedItems();
+
+ public boolean includesGlobalClear();
+
+ public Collection<T> getAdded();
+
+ public Collection<T> getRemoved();
+
+ public boolean isEmpty();
+
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/CollectionChanges.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/CollectionChanges.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/CollectionChanges.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,49 @@
+package pcgen.rules.context;
+
+import java.util.Collection;
+
+
+public class CollectionChanges<T> implements Changes<T>
+{
+ private Collection<T> positive;
+ private Collection<T> negative;
+ private boolean clear;
+
+ public CollectionChanges(Collection<T> added, Collection<T> removed,
+ boolean globallyCleared)
+ {
+ positive = added;
+ negative = removed;
+ clear = globallyCleared;
+ }
+
+ public boolean includesGlobalClear()
+ {
+ return clear;
+ }
+
+ public boolean isEmpty()
+ {
+ return !clear && !hasAddedItems() && !hasRemovedItems();
+ }
+
+ public Collection<T> getAdded()
+ {
+ return positive;
+ }
+
+ public boolean hasAddedItems()
+ {
+ return positive != null && !positive.isEmpty();
+ }
+
+ public Collection<T> getRemoved()
+ {
+ return negative;
+ }
+
+ public boolean hasRemovedItems()
+ {
+ return negative != null && !negative.isEmpty();
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/ConsolidatedListCommitStrategy.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/ConsolidatedListCommitStrategy.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/ConsolidatedListCommitStrategy.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,186 @@
+package pcgen.rules.context;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import pcgen.base.util.DoubleKeyMapToList;
+import pcgen.base.util.MapToList;
+import pcgen.base.util.TreeMapToList;
+import pcgen.cdom.base.AssociatedPrereqObject;
+import pcgen.cdom.base.CDOMList;
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.base.CDOMReference;
+import pcgen.cdom.base.SimpleAssociatedObject;
+import pcgen.cdom.enumeration.AssociationKey;
+import pcgen.rules.persistence.TokenUtilities;
+
+public class ConsolidatedListCommitStrategy implements ListCommitStrategy
+{
+ private URI sourceURI;
+
+ private URI extractURI;
+
+ public URI getExtractURI()
+ {
+ return extractURI;
+ }
+
+ public void setExtractURI(URI extractURI)
+ {
+ this.extractURI = extractURI;
+ }
+
+ public URI getSourceURI()
+ {
+ return sourceURI;
+ }
+
+ public void setSourceURI(URI sourceURI)
+ {
+ this.sourceURI = sourceURI;
+ }
+
+ private final DoubleKeyMapToList<CDOMReference, CDOMObject, AssociatedPrereqObject> masterList =
+ new DoubleKeyMapToList<CDOMReference, CDOMObject, AssociatedPrereqObject>();
+
+ public <T extends CDOMObject> AssociatedPrereqObject addToMasterList(String tokenName,
+ CDOMObject owner, CDOMReference<? extends CDOMList<T>> list,
+ T allowed)
+ {
+ SimpleAssociatedObject a = new SimpleAssociatedObject();
+ a.setAssociation(AssociationKey.OWNER, owner);
+ a.setAssociation(AssociationKey.TOKEN, tokenName);
+ masterList.addToListFor(list, allowed, a);
+ return a;
+ }
+
+ public Changes<CDOMReference> getMasterListChanges(String tokenName,
+ CDOMObject owner, Class<? extends CDOMList<?>> cl)
+ {
+ ArrayList<CDOMReference> list = new ArrayList<CDOMReference>();
+ LIST: for (CDOMReference<? extends CDOMList<?>> ref : masterList
+ .getKeySet())
+ {
+ if (!cl.equals(ref.getReferenceClass()))
+ {
+ continue;
+ }
+ for (CDOMObject allowed : masterList.getSecondaryKeySet(ref))
+ {
+ for (AssociatedPrereqObject assoc : masterList.getListFor(ref,
+ allowed))
+ {
+ if (owner
+ .equals(assoc.getAssociation(AssociationKey.OWNER))
+ && tokenName.equals(assoc
+ .getAssociation(AssociationKey.TOKEN)))
+ {
+ list.add(ref);
+ continue LIST;
+ }
+ }
+ }
+ }
+ return new CollectionChanges<CDOMReference>(list, null, false);
+ }
+
+ public void clearAllMasterLists(String tokenName, CDOMObject owner)
+ {
+ for (CDOMReference<? extends CDOMList<?>> ref : masterList.getKeySet())
+ {
+ for (CDOMObject allowed : masterList.getSecondaryKeySet(ref))
+ {
+ for (AssociatedPrereqObject assoc : masterList.getListFor(ref,
+ allowed))
+ {
+ if (owner
+ .equals(assoc.getAssociation(AssociationKey.OWNER))
+ && tokenName.equals(assoc
+ .getAssociation(AssociationKey.TOKEN)))
+ {
+ masterList.removeFromListFor(ref, allowed, assoc);
+ }
+ }
+ }
+ }
+ }
+
+ public <T extends CDOMObject> AssociatedChanges<T> getChangesInMasterList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<T>> swl)
+ {
+ Set<CDOMObject> added = masterList.getSecondaryKeySet(swl);
+ MapToList<T, AssociatedPrereqObject> owned =
+ new TreeMapToList<T, AssociatedPrereqObject>(
+ TokenUtilities.WRITEABLE_SORTER);
+ for (CDOMObject lw : added)
+ {
+ List<AssociatedPrereqObject> list = masterList.getListFor(swl, lw);
+ for (AssociatedPrereqObject assoc : list)
+ {
+ if (owner.equals(assoc.getAssociation(AssociationKey.OWNER)))
+ {
+ owned.addToListFor((T) lw, assoc);
+ break;
+ }
+ }
+ }
+ return new AssociatedCollectionChanges<T>(owned, null, false);
+ }
+
+ public boolean hasMasterLists()
+ {
+ return !masterList.isEmpty();
+ }
+
+ public <T extends CDOMObject> AssociatedPrereqObject addToList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<? super T>> list, CDOMReference<T> allowed)
+ {
+ SimpleAssociatedObject a = new SimpleAssociatedObject();
+ a.setAssociation(AssociationKey.TOKEN, tokenName);
+ owner.putToList(list, allowed, a);
+ return a;
+ }
+
+ public <T extends CDOMObject> void removeFromList(String tokenName,
+ CDOMObject owner, CDOMReference<? extends CDOMList<? super T>> swl,
+ CDOMReference<T> ref)
+ {
+ owner.removeFromList(swl, ref);
+ }
+
+ public void removeAllFromList(String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<?>> swl)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public Collection<CDOMReference<? extends CDOMList<? extends CDOMObject>>> getChangedLists(
+ CDOMObject owner, Class<? extends CDOMList<?>> cl)
+ {
+ ArrayList<CDOMReference<? extends CDOMList<? extends CDOMObject>>> list =
+ new ArrayList<CDOMReference<? extends CDOMList<? extends CDOMObject>>>();
+ for (CDOMReference<? extends CDOMList<? extends CDOMObject>> ref : owner
+ .getModifiedLists())
+ {
+ if (cl.equals(ref.getReferenceClass()))
+ {
+ list.add(ref);
+ }
+ }
+ return list;
+ }
+
+ public <T extends CDOMObject> AssociatedChanges<CDOMReference<T>> getChangesInList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<T>> swl)
+ {
+ // TODO Deal with matching the token... :/
+ return new ListChanges<T>(tokenName, owner, null, swl, false);
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/ConsolidatedObjectCommitStrategy.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/ConsolidatedObjectCommitStrategy.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/ConsolidatedObjectCommitStrategy.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.rules.context;
+
+import java.net.URI;
+import java.util.Set;
+
+import pcgen.base.formula.Formula;
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.base.ConcretePrereqObject;
+import pcgen.cdom.base.Constants;
+import pcgen.cdom.enumeration.FormulaKey;
+import pcgen.cdom.enumeration.IntegerKey;
+import pcgen.cdom.enumeration.ListKey;
+import pcgen.cdom.enumeration.ObjectKey;
+import pcgen.cdom.enumeration.StringKey;
+import pcgen.cdom.enumeration.VariableKey;
+import pcgen.core.prereq.Prerequisite;
+
+public class ConsolidatedObjectCommitStrategy implements ObjectCommitStrategy
+{
+ private URI sourceURI;
+
+ private URI extractURI;
+
+ public URI getExtractURI()
+ {
+ return extractURI;
+ }
+
+ public void setExtractURI(URI extractURI)
+ {
+ this.extractURI = extractURI;
+ }
+
+ public URI getSourceURI()
+ {
+ return sourceURI;
+ }
+
+ public void setSourceURI(URI sourceURI)
+ {
+ this.sourceURI = sourceURI;
+ }
+
+ public String getString(CDOMObject cdo, StringKey sk)
+ {
+ return cdo.get(sk);
+ }
+
+ public Integer getInteger(CDOMObject cdo, IntegerKey ik)
+ {
+ return cdo.get(ik);
+ }
+
+ public Formula getFormula(CDOMObject cdo, FormulaKey fk)
+ {
+ return cdo.get(fk);
+ }
+
+ public Formula getVariable(CDOMObject obj, VariableKey key)
+ {
+ return obj.get(key);
+ }
+
+ public Set<VariableKey> getVariableKeys(CDOMObject obj)
+ {
+ return obj.getVariableKeys();
+ }
+
+ public <T> T getObject(CDOMObject cdo, ObjectKey<T> ik)
+ {
+ return cdo.get(ik);
+ }
+
+ public <T> Changes<T> getListChanges(CDOMObject cdo, ListKey<T> lk)
+ {
+ return new CollectionChanges<T>(cdo.getListFor(lk), null, false);
+ }
+
+ public void put(CDOMObject cdo, StringKey sk, String s)
+ {
+ if (s == null)
+ {
+ cdo.remove(sk);
+ }
+ else if (s.startsWith(Constants.LST_DOT_CLEAR))
+ {
+ throw new IllegalArgumentException("Cannot set a value to " + s);
+ }
+ else
+ {
+ cdo.put(sk, s);
+ }
+ }
+
+ public <T> void put(CDOMObject cdo, ObjectKey<T> sk, T s)
+ {
+ cdo.put(sk, s);
+ }
+
+ public void put(CDOMObject cdo, IntegerKey ik, Integer i)
+ {
+ cdo.put(ik, i);
+ }
+
+ public void put(CDOMObject cdo, FormulaKey fk, Formula f)
+ {
+ cdo.put(fk, f);
+ }
+
+ public void put(CDOMObject obj, VariableKey vk, Formula f)
+ {
+ obj.put(vk, f);
+ }
+
+ public boolean containsListFor(CDOMObject cdo, ListKey<?> key)
+ {
+ return cdo.containsListFor(key);
+ }
+
+ public <T> void addToList(CDOMObject cdo, ListKey<T> key, T value)
+ {
+ cdo.addToListFor(key, value);
+ }
+
+ public void removeList(CDOMObject cdo, ListKey<?> lk)
+ {
+ cdo.removeListFor(lk);
+ }
+
+ public <T> void removeFromList(CDOMObject cdo, ListKey<T> lk, T val)
+ {
+ cdo.removeFromListFor(lk, val);
+ }
+
+ public void put(ConcretePrereqObject cpo, Prerequisite p)
+ {
+ cpo.addPrerequisite(p);
+ }
+
+ public Changes<Prerequisite> getPrerequisiteChanges(ConcretePrereqObject obj)
+ {
+ return new CollectionChanges<Prerequisite>(obj.getPrerequisiteList(),
+ null, false);
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/ListChanges.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/ListChanges.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/ListChanges.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,177 @@
+package pcgen.rules.context;
+
+import java.util.Collection;
+import java.util.TreeSet;
+
+import pcgen.base.util.MapToList;
+import pcgen.base.util.TreeMapToList;
+import pcgen.cdom.base.AssociatedPrereqObject;
+import pcgen.cdom.base.CDOMList;
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.base.CDOMReference;
+import pcgen.cdom.enumeration.AssociationKey;
+import pcgen.rules.persistence.TokenUtilities;
+
+public class ListChanges<T extends CDOMObject> implements
+ AssociatedChanges<CDOMReference<T>>
+{
+ private String tokenName;
+ private CDOMObject positive;
+ private CDOMObject negative;
+ private CDOMReference<? extends CDOMList<T>> list;
+ private boolean clear;
+
+ public ListChanges(String token, CDOMObject added, CDOMObject removed,
+ CDOMReference<? extends CDOMList<T>> listref,
+ boolean globallyCleared)
+ {
+ tokenName = token;
+ positive = added;
+ negative = removed;
+ list = listref;
+ clear = globallyCleared;
+ }
+
+ public boolean includesGlobalClear()
+ {
+ return clear;
+ }
+
+ public boolean isEmpty()
+ {
+ /*
+ * TODO This lies :P
+ */
+ return !clear && !hasAddedItems() && !hasRemovedItems();
+ }
+
+ public Collection<CDOMReference<T>> getAdded()
+ {
+ TreeSet<CDOMReference<T>> set = new TreeSet<CDOMReference<T>>(
+ TokenUtilities.REFERENCE_SORTER);
+ Collection<CDOMReference<T>> listMods = positive.getListMods(list);
+ if (listMods != null)
+ {
+ for (CDOMReference<T> ref : listMods)
+ {
+ for (AssociatedPrereqObject assoc : positive
+ .getListAssociations(list, ref))
+ {
+ if (tokenName.equals(assoc
+ .getAssociation(AssociationKey.TOKEN)))
+ {
+ set.add(ref);
+ }
+ }
+ }
+ }
+ return set;
+ }
+
+ public boolean hasAddedItems()
+ {
+ /*
+ * TODO This lies :P
+ */
+ return positive != null && positive.getListMods(list) != null
+ && !positive.getListMods(list).isEmpty();
+ }
+
+ public Collection<CDOMReference<T>> getRemoved()
+ {
+ TreeSet<CDOMReference<T>> set = new TreeSet<CDOMReference<T>>(
+ TokenUtilities.REFERENCE_SORTER);
+ if (negative == null)
+ {
+ return set;
+ }
+ Collection<CDOMReference<T>> listMods = negative.getListMods(list);
+ if (listMods != null)
+ {
+ for (CDOMReference<T> ref : listMods)
+ {
+ for (AssociatedPrereqObject assoc : negative
+ .getListAssociations(list, ref))
+ {
+ if (tokenName.equals(assoc
+ .getAssociation(AssociationKey.TOKEN)))
+ {
+ set.add(ref);
+ }
+ }
+ }
+ }
+ return set;
+ }
+
+ public boolean hasRemovedItems()
+ {
+ /*
+ * TODO This lies :P
+ */
+ return negative != null && negative.getListMods(list) != null
+ && !negative.getListMods(list).isEmpty();
+ }
+
+ public MapToList<CDOMReference<T>, AssociatedPrereqObject> getAddedAssociations()
+ {
+ MapToList<CDOMReference<T>, AssociatedPrereqObject> owned = new TreeMapToList<CDOMReference<T>, AssociatedPrereqObject>(
+ TokenUtilities.REFERENCE_SORTER);
+ Collection<CDOMReference<T>> mods = positive.getListMods(list);
+ if (mods == null)
+ {
+ return null;
+ }
+ for (CDOMReference<T> lw : mods)
+ {
+ Collection<AssociatedPrereqObject> assocs = positive
+ .getListAssociations(list, lw);
+ for (AssociatedPrereqObject assoc : assocs)
+ {
+ if (tokenName
+ .equals(assoc.getAssociation(AssociationKey.TOKEN)))
+ {
+ owned.addToListFor(lw, assoc);
+ }
+ }
+ }
+ if (owned.isEmpty())
+ {
+ return null;
+ }
+ return owned;
+ }
+
+ public MapToList<CDOMReference<T>, AssociatedPrereqObject> getRemovedAssociations()
+ {
+ MapToList<CDOMReference<T>, AssociatedPrereqObject> owned = new TreeMapToList<CDOMReference<T>, AssociatedPrereqObject>(
+ TokenUtilities.REFERENCE_SORTER);
+ if (negative == null)
+ {
+ return owned;
+ }
+ Collection<CDOMReference<T>> mods = negative.getListMods(list);
+ if (mods == null)
+ {
+ return owned;
+ }
+ for (CDOMReference<T> lw : mods)
+ {
+ Collection<AssociatedPrereqObject> assocs = negative
+ .getListAssociations(list, lw);
+ for (AssociatedPrereqObject assoc : assocs)
+ {
+ if (tokenName
+ .equals(assoc.getAssociation(AssociationKey.TOKEN)))
+ {
+ owned.addToListFor(lw, assoc);
+ }
+ }
+ }
+ if (owned.isEmpty())
+ {
+ return null;
+ }
+ return owned;
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/ListCommitStrategy.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/ListCommitStrategy.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/ListCommitStrategy.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,50 @@
+package pcgen.rules.context;
+
+import java.net.URI;
+import java.util.Collection;
+
+import pcgen.cdom.base.AssociatedPrereqObject;
+import pcgen.cdom.base.CDOMList;
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.base.CDOMReference;
+
+public interface ListCommitStrategy
+{
+
+ public <T extends CDOMObject> AssociatedPrereqObject addToMasterList(String tokenName,
+ CDOMObject owner, CDOMReference<? extends CDOMList<T>> list,
+ T allowed);
+
+ public Changes<CDOMReference> getMasterListChanges(
+ String tokenName, CDOMObject owner, Class<? extends CDOMList<?>> cl);
+
+ public boolean hasMasterLists();
+
+ public <T extends CDOMObject> AssociatedChanges<T> getChangesInMasterList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<T>> swl);
+
+ public <T extends CDOMObject> AssociatedPrereqObject addToList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<? super T>> list, CDOMReference<T> allowed);
+
+ public Collection<CDOMReference<? extends CDOMList<? extends CDOMObject>>> getChangedLists(
+ CDOMObject owner, Class<? extends CDOMList<?>> cl);
+
+ public void removeAllFromList(String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<?>> swl);
+
+ public <T extends CDOMObject> void removeFromList(String tokenName,
+ CDOMObject owner, CDOMReference<? extends CDOMList<? super T>> swl,
+ CDOMReference<T> ref);
+
+ public <T extends CDOMObject> AssociatedChanges<CDOMReference<T>> getChangesInList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<T>> swl);
+
+ public void setSourceURI(URI sourceURI);
+
+ public void setExtractURI(URI sourceURI);
+
+ public void clearAllMasterLists(String tokenName, CDOMObject owner);
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/ListContext.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/ListContext.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/ListContext.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,591 @@
+package pcgen.rules.context;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Set;
+
+import pcgen.base.util.DoubleKeyMap;
+import pcgen.base.util.DoubleKeyMapToList;
+import pcgen.base.util.HashMapToList;
+import pcgen.base.util.MapToList;
+import pcgen.base.util.TreeMapToList;
+import pcgen.base.util.TripleKeyMap;
+import pcgen.cdom.base.AssociatedPrereqObject;
+import pcgen.cdom.base.CDOMList;
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.base.CDOMReference;
+import pcgen.cdom.base.PrereqObject;
+import pcgen.cdom.base.SimpleAssociatedObject;
+import pcgen.cdom.enumeration.AssociationKey;
+import pcgen.cdom.reference.CDOMDirectSingleRef;
+import pcgen.rules.persistence.TokenUtilities;
+
+public class ListContext
+{
+
+// private static final CDOMReference<? extends CDOMList<CDOMObject>> GRANTED = new CDOMDirectSingleRef<CDOMList<CDOMObject>>(
+// new GrantedList());
+
+ private final TrackingListCommitStrategy edits = new TrackingListCommitStrategy();
+
+ private final ListCommitStrategy commit;
+
+ public ListContext()
+ {
+ commit = new TrackingListCommitStrategy();
+ }
+
+ public ListContext(ListCommitStrategy commitStrategy)
+ {
+ if (commitStrategy == null)
+ {
+ throw new IllegalArgumentException("Commit Strategy cannot be null");
+ }
+ commit = commitStrategy;
+ }
+
+ public URI getSourceURI()
+ {
+ return edits.getSourceURI();
+ }
+
+ public void setSourceURI(URI sourceURI)
+ {
+ edits.setSourceURI(sourceURI);
+ commit.setSourceURI(sourceURI);
+ }
+
+ public URI getExtractURI()
+ {
+ return edits.getExtractURI();
+ }
+
+ public void setExtractURI(URI extractURI)
+ {
+ edits.setExtractURI(extractURI);
+ commit.setExtractURI(extractURI);
+ }
+
+ public <T extends CDOMObject> AssociatedPrereqObject addToMasterList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<T>> list, T allowed)
+ {
+ return edits.addToMasterList(tokenName, owner, list, allowed);
+ }
+
+ public void clearAllMasterLists(String tokenName, CDOMObject owner)
+ {
+ edits.clearAllMasterLists(tokenName, owner);
+ }
+
+ public <T extends CDOMObject> void clearMasterList(String tokenName,
+ CDOMObject owner, CDOMReference<? extends CDOMList<T>> list)
+ {
+ edits.clearMasterList(tokenName, owner, list);
+ }
+
+ public <T extends CDOMObject> AssociatedPrereqObject addToList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<? super T>> list,
+ CDOMReference<T> allowed)
+ {
+ return edits.addToList(tokenName, owner, list, allowed);
+ }
+
+ public <T extends CDOMObject> void removeFromList(String tokenName,
+ CDOMObject owner,
+ CDOMReference<? extends CDOMList<? super T>> list,
+ CDOMReference<T> ref)
+ {
+ edits.removeFromList(tokenName, owner, list, ref);
+ }
+
+ public void removeAllFromList(String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<?>> swl)
+ {
+ edits.removeAllFromList(tokenName, owner, swl);
+ }
+
+// public <T extends CDOMObject> AssociatedPrereqObject grant(
+// String sourceToken, CDOMObject obj, CDOMReference<T> pro)
+// {
+// return addToList(sourceToken, obj, GRANTED, pro);
+// }
+//
+// public <T extends CDOMObject> void remove(String sourceToken,
+// CDOMObject obj, CDOMReference<T> pro)
+// {
+// removeFromList(sourceToken, obj, GRANTED, pro);
+// }
+//
+// public void removeAll(String tokenName, CDOMObject obj)
+// {
+// removeAllFromList(tokenName, obj, GRANTED);
+// }
+
+// public <T extends PrereqObject> AssociatedChanges<CDOMReference<T>> getChangesFromToken(
+// String tokenName, CDOMObject source, Class<T> cl)
+// {
+// AssociatedChanges<CDOMReference<CDOMObject>> assoc = getChangesInList(
+// tokenName, source, GRANTED);
+// boolean globalClear = assoc.includesGlobalClear();
+// MapToList<CDOMReference<CDOMObject>, AssociatedPrereqObject> added = assoc
+// .getAddedAssociations();
+// MapToList<CDOMReference<T>, AssociatedPrereqObject> add = new TreeMapToList<CDOMReference<T>, AssociatedPrereqObject>(
+// TokenUtilities.REFERENCE_SORTER);
+// if (added != null)
+// {
+// for (CDOMReference<CDOMObject> key : added.getKeySet())
+// {
+// if (cl.equals(key.getReferenceClass()))
+// {
+// add.addAllToListFor((CDOMReference<T>) key, added.getListFor(key));
+// }
+// }
+// }
+//
+// MapToList<CDOMReference<T>, AssociatedPrereqObject> remove = new TreeMapToList<CDOMReference<T>, AssociatedPrereqObject>(
+// TokenUtilities.REFERENCE_SORTER);
+// MapToList<CDOMReference<CDOMObject>, AssociatedPrereqObject> removed = assoc
+// .getRemovedAssociations();
+// if (removed != null)
+// {
+// for (CDOMReference<CDOMObject> key : removed.getKeySet())
+// {
+// if (cl.equals(key.getReferenceClass()))
+// {
+// remove.addAllToListFor((CDOMReference<T>) key, removed.getListFor(key));
+// }
+// }
+// }
+//
+// return new AssociatedCollectionChanges<CDOMReference<T>>(add, remove, globalClear);
+// }
+
+ public void commit()
+ {
+ for (CDOMReference list : edits.positiveMasterMap.getKeySet())
+ {
+ commitDirect(list);
+ }
+ for (URI uri : edits.globalClearSet.getKeySet())
+ {
+ for (CDOMObject owner : edits.globalClearSet
+ .getSecondaryKeySet(uri))
+ {
+ for (CDOMReference<? extends CDOMList<?>> list : edits.globalClearSet
+ .getListFor(uri, owner))
+ {
+ commit.removeAllFromList("FOO", owner, list);
+ }
+ }
+ }
+ for (URI uri : edits.negativeMap.getKeySet())
+ {
+ for (CDOMObject owner : edits.negativeMap.getSecondaryKeySet(uri))
+ {
+ CDOMObject neg = edits.negativeMap.get(uri, owner);
+ Collection<CDOMReference<? extends CDOMList<? extends CDOMObject>>> modifiedLists = neg
+ .getModifiedLists();
+ for (CDOMReference list : modifiedLists)
+ {
+ remove(owner, neg, list);
+ }
+ }
+ }
+ for (URI uri : edits.positiveMap.getKeySet())
+ {
+ for (CDOMObject owner : edits.positiveMap.getSecondaryKeySet(uri))
+ {
+ CDOMObject neg = edits.positiveMap.get(uri, owner);
+ Collection<CDOMReference<? extends CDOMList<? extends CDOMObject>>> modifiedLists = neg
+ .getModifiedLists();
+ for (CDOMReference list : modifiedLists)
+ {
+ add(owner, neg, list);
+ }
+ }
+ }
+ for (String token : edits.masterAllClear.getKeySet())
+ {
+ for (OwnerURI ou : edits.masterAllClear.getListFor(token))
+ {
+ commit.clearAllMasterLists(token, ou.owner);
+ }
+ }
+ decommit();
+ }
+
+ private <T extends CDOMObject> void commitDirect(
+ CDOMReference<? extends CDOMList<T>> list)
+ {
+ for (OwnerURI ou : edits.positiveMasterMap.getSecondaryKeySet(list))
+ {
+ for (CDOMObject child : edits.positiveMasterMap.getTertiaryKeySet(
+ list, ou))
+ {
+ AssociatedPrereqObject assoc = edits.positiveMasterMap.get(
+ list, ou, child);
+ AssociatedPrereqObject edge = commit.addToMasterList(assoc
+ .getAssociation(AssociationKey.TOKEN), ou.owner, list,
+ (T) child);
+ Collection<AssociationKey<?>> associationKeys = assoc
+ .getAssociationKeys();
+ for (AssociationKey<?> ak : associationKeys)
+ {
+ setAssoc(assoc, edge, ak);
+ }
+ edge.addAllPrerequisites(assoc.getPrerequisiteList());
+ }
+ }
+ }
+
+ public void decommit()
+ {
+ edits.decommit();
+ }
+
+ public Collection<CDOMReference<? extends CDOMList<? extends CDOMObject>>> getChangedLists(
+ CDOMObject owner, Class<? extends CDOMList<?>> cl)
+ {
+ return commit.getChangedLists(owner, cl);
+ }
+
+ public <T extends CDOMObject> AssociatedChanges<CDOMReference<T>> getChangesInList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<T>> swl)
+ {
+ return commit.getChangesInList(tokenName, owner, swl);
+ }
+
+ public <T extends CDOMObject> AssociatedChanges<T> getChangesInMasterList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<T>> swl)
+ {
+ return commit.getChangesInMasterList(tokenName, owner, swl);
+ }
+
+ public Changes<CDOMReference> getMasterListChanges(String tokenName,
+ CDOMObject owner, Class<? extends CDOMList<?>> cl)
+ {
+ return commit.getMasterListChanges(tokenName, owner, cl);
+ }
+
+ public boolean hasMasterLists()
+ {
+ return commit.hasMasterLists();
+ }
+
+ private <BT extends CDOMObject> void remove(CDOMObject owner,
+ CDOMObject neg, CDOMReference<CDOMList<BT>> list)
+ {
+ Collection<CDOMReference<BT>> mods = neg.getListMods(list);
+ for (CDOMReference<BT> ref : mods)
+ {
+ for (AssociatedPrereqObject assoc : neg.getListAssociations(list,
+ ref))
+ {
+ commit
+ .removeFromList(assoc
+ .getAssociation(AssociationKey.TOKEN), owner,
+ list, ref);
+ }
+ }
+ }
+
+ private <BT extends CDOMObject> void add(CDOMObject owner, CDOMObject neg,
+ CDOMReference<CDOMList<BT>> list)
+ {
+ Collection<CDOMReference<BT>> mods = neg.getListMods(list);
+ for (CDOMReference<BT> ref : mods)
+ {
+ for (AssociatedPrereqObject assoc : neg.getListAssociations(list,
+ ref))
+ {
+ String token = assoc.getAssociation(AssociationKey.TOKEN);
+ AssociatedPrereqObject edge = commit.addToList(token, owner,
+ list, ref);
+ Collection<AssociationKey<?>> associationKeys = assoc
+ .getAssociationKeys();
+ for (AssociationKey<?> ak : associationKeys)
+ {
+ setAssoc(assoc, edge, ak);
+ }
+ edge.addAllPrerequisites(assoc.getPrerequisiteList());
+ }
+ }
+ }
+
+ private <T> void setAssoc(AssociatedPrereqObject assoc,
+ AssociatedPrereqObject edge, AssociationKey<T> ak)
+ {
+ edge.setAssociation(ak, assoc.getAssociation(ak));
+ }
+
+ public class TrackingListCommitStrategy implements ListCommitStrategy
+ {
+
+ protected class CDOMShell extends CDOMObject
+ {
+ @Override
+ public CDOMObject clone() throws CloneNotSupportedException
+ {
+ throw new CloneNotSupportedException();
+ }
+ }
+
+ private URI sourceURI;
+
+ private URI extractURI;
+
+ public URI getExtractURI()
+ {
+ return extractURI;
+ }
+
+ public void setExtractURI(URI extractURI)
+ {
+ this.extractURI = extractURI;
+ }
+
+ public URI getSourceURI()
+ {
+ return sourceURI;
+ }
+
+ public void setSourceURI(URI sourceURI)
+ {
+ this.sourceURI = sourceURI;
+ }
+
+ /*
+ * TODO These maps (throughout this entire class) are probably problems
+ * because they are not using Identity characteristics
+ */
+ private TripleKeyMap<CDOMReference<? extends CDOMList<?>>, OwnerURI, CDOMObject, AssociatedPrereqObject> positiveMasterMap = new TripleKeyMap<CDOMReference<? extends CDOMList<?>>, OwnerURI, CDOMObject, AssociatedPrereqObject>();
+
+ private HashMapToList<CDOMReference<? extends CDOMList<?>>, OwnerURI> masterClearSet = new HashMapToList<CDOMReference<? extends CDOMList<?>>, OwnerURI>();
+
+ private HashMapToList<String, OwnerURI> masterAllClear = new HashMapToList<String, OwnerURI>();
+
+ public <T extends CDOMObject> AssociatedPrereqObject addToMasterList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<T>> list, T allowed)
+ {
+ SimpleAssociatedObject a = new SimpleAssociatedObject();
+ a.setAssociation(AssociationKey.OWNER, owner);
+ a.setAssociation(AssociationKey.TOKEN, tokenName);
+ positiveMasterMap.put(list, new OwnerURI(sourceURI, owner),
+ allowed, a);
+ return a;
+ }
+
+ public Changes<CDOMReference> getMasterListChanges(String tokenName,
+ CDOMObject owner, Class<? extends CDOMList<?>> cl)
+ {
+ OwnerURI lo = new OwnerURI(extractURI, owner);
+ ArrayList<CDOMReference> list = new ArrayList<CDOMReference>();
+ Set<CDOMReference<? extends CDOMList<?>>> set = positiveMasterMap
+ .getKeySet();
+ if (set != null)
+ {
+ LIST: for (CDOMReference<? extends CDOMList<?>> ref : set)
+ {
+ if (!cl.equals(ref.getReferenceClass()))
+ {
+ continue;
+ }
+ for (CDOMObject allowed : positiveMasterMap
+ .getTertiaryKeySet(ref, lo))
+ {
+ AssociatedPrereqObject assoc = positiveMasterMap.get(
+ ref, lo, allowed);
+ if (owner.equals(assoc
+ .getAssociation(AssociationKey.OWNER))
+ && tokenName.equals(assoc
+ .getAssociation(AssociationKey.TOKEN)))
+ {
+ list.add(ref);
+ continue LIST;
+ }
+ }
+ }
+ }
+ return new CollectionChanges<CDOMReference>(list, null,
+ masterAllClear.containsInList(tokenName, lo));
+ }
+
+ public <T extends CDOMObject> AssociatedChanges<T> getChangesInMasterList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<T>> swl)
+ {
+ MapToList<T, AssociatedPrereqObject> map = new TreeMapToList<T, AssociatedPrereqObject>(
+ TokenUtilities.WRITEABLE_SORTER);
+ OwnerURI lo = new OwnerURI(extractURI, owner);
+ Set<CDOMObject> added = positiveMasterMap
+ .getTertiaryKeySet(swl, lo);
+ for (CDOMObject lw : added)
+ {
+ AssociatedPrereqObject apo = positiveMasterMap.get(swl, lo, lw);
+ if (tokenName.equals(apo.getAssociation(AssociationKey.TOKEN)))
+ {
+ map.addToListFor((T) lw, apo);
+ }
+ }
+ return new AssociatedCollectionChanges<T>(map, null, masterClearSet
+ .containsInList(swl, lo));
+ }
+
+ public <T extends CDOMObject> void clearMasterList(String tokenName,
+ CDOMObject owner, CDOMReference<? extends CDOMList<T>> list)
+ {
+ masterClearSet.addToListFor(list, new OwnerURI(sourceURI, owner));
+ }
+
+ public void clearAllMasterLists(String tokenName, CDOMObject owner)
+ {
+ masterAllClear.addToListFor(tokenName, new OwnerURI(sourceURI,
+ owner));
+ }
+
+ private DoubleKeyMap<URI, CDOMObject, CDOMObject> positiveMap = new DoubleKeyMap<URI, CDOMObject, CDOMObject>();
+
+ private DoubleKeyMap<URI, CDOMObject, CDOMObject> negativeMap = new DoubleKeyMap<URI, CDOMObject, CDOMObject>();
+
+ private DoubleKeyMapToList<URI, CDOMObject, CDOMReference<? extends CDOMList<?>>> globalClearSet = new DoubleKeyMapToList<URI, CDOMObject, CDOMReference<? extends CDOMList<?>>>();
+
+ private CDOMObject getPositive(URI source, CDOMObject cdo)
+ {
+ CDOMObject positive = positiveMap.get(source, cdo);
+ if (positive == null)
+ {
+ positive = new CDOMShell();
+ positiveMap.put(source, cdo, positive);
+ }
+ return positive;
+ }
+
+ private CDOMObject getNegative(URI source, CDOMObject cdo)
+ {
+ CDOMObject negative = negativeMap.get(source, cdo);
+ if (negative == null)
+ {
+ negative = new CDOMShell();
+ negativeMap.put(source, cdo, negative);
+ }
+ return negative;
+ }
+
+ public <T extends CDOMObject> AssociatedPrereqObject addToList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<? super T>> list,
+ CDOMReference<T> allowed)
+ {
+ SimpleAssociatedObject a = new SimpleAssociatedObject();
+ a.setAssociation(AssociationKey.TOKEN, tokenName);
+ getPositive(sourceURI, owner).putToList(list, allowed, a);
+ return a;
+ }
+
+ public <T extends CDOMObject> void removeFromList(String tokenName,
+ CDOMObject owner,
+ CDOMReference<? extends CDOMList<? super T>> list,
+ CDOMReference<T> ref)
+ {
+ SimpleAssociatedObject a = new SimpleAssociatedObject();
+ a.setAssociation(AssociationKey.TOKEN, tokenName);
+ getNegative(sourceURI, owner).putToList(list, ref, a);
+ }
+
+ public Collection<CDOMReference<? extends CDOMList<? extends CDOMObject>>> getChangedLists(
+ CDOMObject owner, Class<? extends CDOMList<?>> cl)
+ {
+ ArrayList<CDOMReference<? extends CDOMList<? extends CDOMObject>>> list = new ArrayList<CDOMReference<? extends CDOMList<? extends CDOMObject>>>();
+ for (CDOMReference<? extends CDOMList<? extends CDOMObject>> ref : getPositive(
+ extractURI, owner).getModifiedLists())
+ {
+ if (cl.equals(ref.getReferenceClass()))
+ {
+ list.add(ref);
+ }
+ }
+ return list;
+ }
+
+ public void removeAllFromList(String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<?>> swl)
+ {
+ globalClearSet.addToListFor(sourceURI, owner, swl);
+ }
+
+ public <T extends CDOMObject> AssociatedChanges<CDOMReference<T>> getChangesInList(
+ String tokenName, CDOMObject owner,
+ CDOMReference<? extends CDOMList<T>> swl)
+ {
+ return new ListChanges<T>(tokenName,
+ getPositive(extractURI, owner), getNegative(extractURI,
+ owner), swl, globalClearSet.containsInList(
+ extractURI, owner, swl));
+ }
+
+ public boolean hasMasterLists()
+ {
+ return !positiveMasterMap.isEmpty() && !masterClearSet.isEmpty()
+ && !masterAllClear.isEmpty();
+ }
+
+ public void decommit()
+ {
+ masterAllClear.clear();
+ masterClearSet.clear();
+ positiveMasterMap.clear();
+ positiveMap.clear();
+ negativeMap.clear();
+ globalClearSet.clear();
+ }
+ }
+
+ private static class OwnerURI
+ {
+ public final CDOMObject owner;
+ public final URI source;
+
+ public OwnerURI(URI sourceURI, CDOMObject cdo)
+ {
+ source = sourceURI;
+ owner = cdo;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return owner.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (o instanceof OwnerURI)
+ {
+ OwnerURI other = (OwnerURI) o;
+ if (source == null)
+ {
+ if (other.source != null)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!source.equals(other.source))
+ {
+ return false;
+ }
+ }
+ return owner.equals(other.owner);
+ }
+ return false;
+ }
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/LoadContext.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/LoadContext.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/LoadContext.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.rules.context;
+
+import java.net.URI;
+import java.util.Collection;
+
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.base.PrereqObject;
+import pcgen.cdom.reference.CDOMGroupRef;
+import pcgen.core.prereq.Prerequisite;
+import pcgen.persistence.PersistenceLayerException;
+import pcgen.rules.persistence.TokenSupport;
+
+public abstract class LoadContext
+{
+
+ public final ListContext list;
+
+ public final ObjectContext obj;
+
+ public final ReferenceContext ref;
+
+ public LoadContext(ListContext lc, ObjectContext oc)
+ {
+ ref = new ReferenceContext();
+ list = lc;
+ obj = oc;
+ }
+
+ public <T extends PrereqObject> CDOMGroupRef<T> groupChildNodesOfClass(
+ PrereqObject parent, Class<T> child)
+ {
+ /*
+ * Create a new Group in the graph and then (defer to end of build)
+ * create edges between the new Group and all of the children of the
+ * given parent.
+ */
+ // TODO FIXME
+ return null;
+ }
+
+ private int writeMessageCount = 0;
+
+ public void addWriteMessage(String string)
+ {
+ System.err.println("!!" + string);
+ // TODO FIXME Silently consume for now - these are message generated
+ // during LST write...
+ writeMessageCount++;
+ }
+
+ public int getWriteMessageCount()
+ {
+ return writeMessageCount;
+ }
+
+ /**
+ * Sets the extract URI. This is a shortcut for setting the URI on both the
+ * graph and obj members.
+ *
+ * @param extractURI
+ */
+ public void setExtractURI(URI extractURI)
+ {
+ getObjectContext().setExtractURI(extractURI);
+ ref.setExtractURI(extractURI);
+ getGraphContext().setExtractURI(extractURI);
+ getListContext().setExtractURI(extractURI);
+ }
+
+ /**
+ * Sets the source URI. This is a shortcut for setting the URI on both the
+ * graph and obj members.
+ *
+ * @param sourceURI
+ */
+ public void setSourceURI(URI sourceURI)
+ {
+ getObjectContext().setSourceURI(sourceURI);
+ ref.setSourceURI(sourceURI);
+ getGraphContext().setSourceURI(sourceURI);
+ getListContext().setSourceURI(sourceURI);
+ }
+
+ /*
+ * Get the type of context we're running in (either Editor or Runtime)
+ */
+ public abstract String getContextType();
+
+ public ListContext getGraphContext()
+ {
+ return list;
+ }
+
+ public ObjectContext getObjectContext()
+ {
+ return obj;
+ }
+
+ public ListContext getListContext()
+ {
+ return list;
+ }
+
+ public void commit()
+ {
+ getGraphContext().commit();
+ getListContext().commit();
+ getObjectContext().commit();
+ }
+
+ public void decommit()
+ {
+ getGraphContext().decommit();
+ getListContext().decommit();
+ getObjectContext().decommit();
+ }
+
+ public void resolveReferences()
+ {
+
+ }
+
+ public void resolveDeferredTokens()
+ {
+// for (DeferredToken<? extends CDOMObject> token : TokenLibrary
+// .getDeferredTokens())
+// {
+// processRes(token);
+// }
+// for (CDOMObject cdo : ref.getAllConstructedObjects())
+// {
+// String cs = cdo.get(StringKey.CHOOSE_BACKUP);
+// if (cs == null)
+// {
+// // Nothing to do (didn't have a CHOOSE that broke)
+// continue;
+// }
+// ChooseActionContainer container = cdo.getChooseContainer();
+// if (container.getChoiceSet() != null)
+// {
+// // Indicates a CHOOSE token worked (except mod cases in runtime)
+// continue;
+// }
+// // System.err.println(container.getActors());
+// // System.err.println("@" + cs);
+// }
+ }
+
+// private <T extends CDOMObject> void processRes(DeferredToken<T> token)
+// {
+// Class<T> cl = token.getObjectClass();
+// for (T po : ref.getConstructedCDOMObjects(cl))
+// {
+// token.process(this, po);
+// }
+// }
+
+ private TokenSupport support = new TokenSupport();
+
+// public <T extends CDOMObject> PrimitiveChoiceSet<T> getChoiceSet(
+// Class<T> poClass, String value)
+// {
+// return support.getChoiceSet(this, poClass, value);
+// }
+//
+// public <T extends CDOMObject> PrimitiveChoiceFilter<T> getPrimitiveChoiceFilter(
+// Class<T> cl, String key)
+// {
+// return support.getPrimitive(this, cl, key);
+// }
+
+ public <T> boolean processSubToken(T cdo, String tokenName,
+ String key, String value) throws PersistenceLayerException
+ {
+ return support.processSubToken(this, cdo, tokenName, key, value);
+ }
+
+ public <T extends CDOMObject> boolean processToken(T derivative,
+ String typeStr, String argument) throws PersistenceLayerException
+ {
+ return support.processToken(this, derivative, typeStr, argument);
+ }
+
+ public <T> String[] unparse(T cdo, String tokenName)
+ {
+ return support.unparse(this, cdo, tokenName);
+ }
+
+ public <T> Collection<String> unparse(T cdo)
+ {
+ return support.unparse(this, cdo);
+ }
+
+// public <T extends CDOMObject> PrimitiveChoiceSet<?> getChoiceSet(
+// CDOMObject cdo, String key, String val)
+// throws PersistenceLayerException
+// {
+// return support.getChoiceSet(this, cdo, key, val);
+// }
+
+ public Prerequisite getPrerequisite(String string, String value)
+ throws PersistenceLayerException
+ {
+ return support.getPrerequisite(this, string, value);
+ }
+
+ public <T extends CDOMObject> T cloneConstructedCDOMObject(T cdo, String newName)
+ {
+ T newObj = obj.cloneConstructedCDOMObject(cdo, newName);
+ ref.importObject(newObj);
+ return newObj;
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/ObjectCommitStrategy.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/ObjectCommitStrategy.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/ObjectCommitStrategy.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.rules.context;
+
+import java.net.URI;
+import java.util.Set;
+
+import pcgen.base.formula.Formula;
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.base.ConcretePrereqObject;
+import pcgen.cdom.enumeration.FormulaKey;
+import pcgen.cdom.enumeration.IntegerKey;
+import pcgen.cdom.enumeration.ListKey;
+import pcgen.cdom.enumeration.ObjectKey;
+import pcgen.cdom.enumeration.StringKey;
+import pcgen.cdom.enumeration.VariableKey;
+import pcgen.core.prereq.Prerequisite;
+
+public interface ObjectCommitStrategy
+{
+
+ public void put(CDOMObject cdo, StringKey sk, String s);
+
+ public <T> void put(CDOMObject cdo, ObjectKey<T> sk, T s);
+
+ public void put(CDOMObject cdo, IntegerKey ik, Integer i);
+
+ public void put(CDOMObject cdo, FormulaKey fk, Formula f);
+
+ public void put(CDOMObject obj, VariableKey vk, Formula f);
+
+ public <T> void addToList(CDOMObject cdo, ListKey<T> key, T value);
+
+ public void removeList(CDOMObject cdo, ListKey<?> lk);
+
+ public <T> void removeFromList(CDOMObject cdo, ListKey<T> lk, T val);
+
+ public Integer getInteger(CDOMObject cdo, IntegerKey ik);
+
+ public Formula getFormula(CDOMObject cdo, FormulaKey fk);
+
+ public Formula getVariable(CDOMObject obj, VariableKey key);
+
+ public Set<VariableKey> getVariableKeys(CDOMObject obj);
+
+ public <T> T getObject(CDOMObject cdo, ObjectKey<T> ik);
+
+ public <T> Changes<T> getListChanges(CDOMObject cdo, ListKey<T> lk);
+
+ public void setExtractURI(URI extractURI);
+
+ public void setSourceURI(URI sourceURI);
+
+ public void put(ConcretePrereqObject cpo, Prerequisite p);
+
+ public Changes<Prerequisite> getPrerequisiteChanges(ConcretePrereqObject obj);
+
+ public String getString(CDOMObject cdo, StringKey sk);
+
+ public boolean containsListFor(CDOMObject obj, ListKey<?> lk);
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/ObjectContext.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/ObjectContext.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/ObjectContext.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,621 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.rules.context;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Set;
+
+import pcgen.base.formula.Formula;
+import pcgen.base.util.DoubleKeyMap;
+import pcgen.base.util.DoubleKeyMapToList;
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.base.ConcretePrereqObject;
+import pcgen.cdom.base.Constants;
+import pcgen.cdom.base.PrereqObject;
+import pcgen.cdom.enumeration.FormulaKey;
+import pcgen.cdom.enumeration.IntegerKey;
+import pcgen.cdom.enumeration.ListKey;
+import pcgen.cdom.enumeration.ObjectKey;
+import pcgen.cdom.enumeration.StringKey;
+import pcgen.cdom.enumeration.VariableKey;
+import pcgen.core.prereq.Prerequisite;
+
+public class ObjectContext
+{
+ private final TrackingObjectCommitStrategy edits = new TrackingObjectCommitStrategy();
+
+ private final ObjectCommitStrategy commit;
+
+ public ObjectContext()
+ {
+ commit = new TrackingObjectCommitStrategy();
+ }
+
+ public ObjectContext(ObjectCommitStrategy commitStrategy)
+ {
+ if (commitStrategy == null)
+ {
+ throw new IllegalArgumentException("Commit Strategy cannot be null");
+ }
+ commit = commitStrategy;
+ }
+
+ public URI getSourceURI()
+ {
+ return edits.getSourceURI();
+ }
+
+ public void setSourceURI(URI sourceURI)
+ {
+ edits.setSourceURI(sourceURI);
+ commit.setSourceURI(sourceURI);
+ }
+
+ public URI getExtractURI()
+ {
+ return edits.getExtractURI();
+ }
+
+ public void setExtractURI(URI extractURI)
+ {
+ edits.setExtractURI(extractURI);
+ commit.setExtractURI(extractURI);
+ }
+
+ public <T> void addToList(CDOMObject cdo, ListKey<T> key, T value)
+ {
+ edits.addToList(cdo, key, value);
+ }
+
+ public void put(CDOMObject cdo, FormulaKey fk, Formula f)
+ {
+ edits.put(cdo, fk, f);
+ }
+
+ public void put(ConcretePrereqObject cpo, Prerequisite p)
+ {
+ edits.put(cpo, p);
+ }
+
+ public void put(CDOMObject cdo, IntegerKey ik, Integer i)
+ {
+ edits.put(cdo, ik, i);
+ }
+
+ public <T> void put(CDOMObject cdo, ObjectKey<T> sk, T s)
+ {
+ edits.put(cdo, sk, s);
+ }
+
+ public void put(CDOMObject cdo, StringKey sk, String s)
+ {
+ edits.put(cdo, sk, s);
+ }
+
+ public void put(CDOMObject cdo, VariableKey vk, Formula f)
+ {
+ edits.put(cdo, vk, f);
+ }
+
+// public void give(String sourceToken, CDOMObject cdo, PrereqObject target)
+// {
+// addToList(cdo, ListKey.GIVEN, new SourceWrapper(target, sourceToken));
+// }
+//
+// public void revoke(String sourceToken, CDOMObject cdo, PrereqObject target)
+// {
+// removeFromList(cdo, ListKey.GIVEN, new SourceWrapper(target, sourceToken));
+// }
+//
+// public void revokeAll(final String tokenName, CDOMObject cdo)
+// {
+// /*
+// * TODO This is broken for the ConsolidatedObjectCommitStrategy, as it
+// * doesn't properly filter by tokenName...
+// */
+// removeList(cdo, ListKey.GIVEN);
+// }
+
+ public <T> void removeFromList(CDOMObject cdo, ListKey<T> lk, T val)
+ {
+ edits.removeFromList(cdo, lk, val);
+ }
+
+ public void removeList(CDOMObject cdo, ListKey<?> lk)
+ {
+ edits.removeList(cdo, lk);
+ }
+
+ public void commit()
+ {
+ for (URI uri : edits.globalClearSet.getKeySet())
+ {
+ for (CDOMObject cdo : edits.globalClearSet.getSecondaryKeySet(uri))
+ {
+ for (ListKey<?> lk : edits.globalClearSet.getListFor(uri, cdo))
+ {
+ commit.removeList(cdo, lk);
+ }
+ }
+ }
+ for (URI uri : edits.negativeMap.getKeySet())
+ {
+ for (ConcretePrereqObject cpo : edits.negativeMap
+ .getSecondaryKeySet(uri))
+ {
+ if (cpo instanceof CDOMObject)
+ {
+ CDOMObject cdo = (CDOMObject) cpo;
+ CDOMObject neg = edits.negativeMap.get(uri, cdo);
+ for (StringKey key : neg.getStringKeys())
+ {
+ commit.put(cdo, key, null);
+ }
+ for (ListKey<?> key : neg.getListKeys())
+ {
+ removeListKey(cdo, key, neg);
+ }
+ }
+ }
+ }
+ for (URI uri : edits.positiveMap.getKeySet())
+ {
+ for (ConcretePrereqObject cpo : edits.positiveMap
+ .getSecondaryKeySet(uri))
+ {
+ CDOMObject pos = edits.positiveMap.get(uri, cpo);
+ for (Prerequisite p : pos.getPrerequisiteList())
+ {
+ commit.put(cpo, p);
+ }
+ if (cpo instanceof CDOMObject)
+ {
+ CDOMObject cdo = (CDOMObject) cpo;
+ for (StringKey key : pos.getStringKeys())
+ {
+ commit.put(cdo, key, pos.get(key));
+ }
+ for (IntegerKey key : pos.getIntegerKeys())
+ {
+ commit.put(cdo, key, pos.get(key));
+ }
+ for (FormulaKey key : pos.getFormulaKeys())
+ {
+ commit.put(cdo, key, pos.get(key));
+ }
+ for (VariableKey key : pos.getVariableKeys())
+ {
+ commit.put(cdo, key, pos.get(key));
+ }
+ for (ObjectKey<?> key : pos.getObjectKeys())
+ {
+ putObjectKey(cdo, key, pos);
+ }
+ for (ListKey<?> key : pos.getListKeys())
+ {
+ putListKey(cdo, key, pos);
+ }
+ /*
+ * TODO CDOM List Mods
+ */
+ /*
+ * TODO Deal with cloned objects
+ */
+ }
+ }
+ }
+ decommit();
+ }
+
+ private <T> void removeListKey(CDOMObject cdo, ListKey<T> key,
+ CDOMObject neg)
+ {
+ for (T obj : neg.getListFor(key))
+ {
+ commit.removeFromList(cdo, key, obj);
+ }
+ }
+
+ private <T> void putListKey(CDOMObject cdo, ListKey<T> key, CDOMObject neg)
+ {
+ for (T obj : neg.getListFor(key))
+ {
+ commit.addToList(cdo, key, obj);
+ }
+ }
+
+ private <T> void putObjectKey(CDOMObject cdo, ObjectKey<T> key,
+ CDOMObject neg)
+ {
+ commit.put(cdo, key, neg.get(key));
+ }
+
+ public void decommit()
+ {
+ edits.decommit();
+ }
+
+ public Formula getFormula(CDOMObject cdo, FormulaKey fk)
+ {
+ return commit.getFormula(cdo, fk);
+ }
+
+ public Integer getInteger(CDOMObject cdo, IntegerKey ik)
+ {
+ return commit.getInteger(cdo, ik);
+ }
+
+ public <T> Changes<T> getListChanges(CDOMObject cdo, ListKey<T> lk)
+ {
+ return commit.getListChanges(cdo, lk);
+ }
+
+// public <T> Changes<T> getGivenChanges(String sourceToken, CDOMObject cdo, Class<T> cl)
+// {
+// return new GivenChanges<T>(cl, sourceToken, commit.getListChanges(cdo, ListKey.GIVEN));
+// }
+//
+ public <T> T getObject(CDOMObject cdo, ObjectKey<T> ik)
+ {
+ return commit.getObject(cdo, ik);
+ }
+
+ public String getString(CDOMObject cdo, StringKey sk)
+ {
+ return commit.getString(cdo, sk);
+ }
+
+ public Formula getVariable(CDOMObject obj, VariableKey key)
+ {
+ return commit.getVariable(obj, key);
+ }
+
+ public Set<VariableKey> getVariableKeys(CDOMObject obj)
+ {
+ return commit.getVariableKeys(obj);
+ }
+
+ <T extends CDOMObject> T cloneConstructedCDOMObject(T obj, String newName)
+ {
+ return edits.cloneConstructedCDOMObject(obj, newName);
+ }
+
+ private static class SimpleCDOMObject extends CDOMObject
+ {
+ }
+
+ public static class TrackingObjectCommitStrategy implements
+ ObjectCommitStrategy
+ {
+ private static String CLEAR = ".CLEAR";
+
+ private DoubleKeyMap<URI, ConcretePrereqObject, CDOMObject> positiveMap = new DoubleKeyMap<URI, ConcretePrereqObject, CDOMObject>(
+ HashMap.class, IdentityHashMap.class);
+
+ private DoubleKeyMap<URI, ConcretePrereqObject, CDOMObject> negativeMap = new DoubleKeyMap<URI, ConcretePrereqObject, CDOMObject>(
+ HashMap.class, IdentityHashMap.class);
+
+ private DoubleKeyMapToList<URI, CDOMObject, ListKey<?>> globalClearSet = new DoubleKeyMapToList<URI, CDOMObject, ListKey<?>>(
+ HashMap.class, IdentityHashMap.class);
+
+ private URI sourceURI;
+
+ private URI extractURI;
+
+ private CDOMObject getNegative(URI source, CDOMObject cdo)
+ {
+ CDOMObject negative = negativeMap.get(source, cdo);
+ if (negative == null)
+ {
+ negative = new SimpleCDOMObject();
+ negativeMap.put(source, cdo, negative);
+ }
+ return negative;
+ }
+
+ public void put(ConcretePrereqObject cpo, Prerequisite p)
+ {
+ getPositive(sourceURI, cpo).addPrerequisite(p);
+ }
+
+ private CDOMObject getPositive(URI source, ConcretePrereqObject cdo)
+ {
+ CDOMObject positive = positiveMap.get(source, cdo);
+ if (positive == null)
+ {
+ positive = new SimpleCDOMObject();
+ positiveMap.put(source, cdo, positive);
+ }
+ return positive;
+ }
+
+ public void put(CDOMObject cdo, StringKey sk, String s)
+ {
+ if (s == null)
+ {
+ getNegative(sourceURI, cdo).put(sk, Constants.LST_DOT_CLEAR);
+ cdo.remove(sk);
+ }
+ else if (s.startsWith(Constants.LST_DOT_CLEAR))
+ {
+ throw new IllegalArgumentException("Cannot set a value to " + s);
+ }
+ else
+ {
+ getPositive(sourceURI, cdo).put(sk, s);
+ }
+ }
+
+ public <T> void put(CDOMObject cdo, ObjectKey<T> sk, T s)
+ {
+ getPositive(sourceURI, cdo).put(sk, s);
+ }
+
+ public void put(CDOMObject cdo, IntegerKey ik, Integer i)
+ {
+ getPositive(sourceURI, cdo).put(ik, i);
+ }
+
+ public void put(CDOMObject cdo, FormulaKey fk, Formula f)
+ {
+ getPositive(sourceURI, cdo).put(fk, f);
+ }
+
+ public void put(CDOMObject cdo, VariableKey vk, Formula f)
+ {
+ getPositive(sourceURI, cdo).put(vk, f);
+ }
+
+ public boolean containsListFor(CDOMObject cdo, ListKey<?> key)
+ {
+ return cdo.containsListFor(key);
+ }
+
+ public <T> void addToList(CDOMObject cdo, ListKey<T> key, T value)
+ {
+ getPositive(sourceURI, cdo).addToListFor(key, value);
+ }
+
+ public void removeList(CDOMObject cdo, ListKey<?> lk)
+ {
+ globalClearSet.addToListFor(sourceURI, cdo, lk);
+ }
+
+ public <T> void removeFromList(CDOMObject cdo, ListKey<T> lk, T val)
+ {
+ getNegative(sourceURI, cdo).addToListFor(lk, val);
+ }
+
+ public String getString(CDOMObject cdo, StringKey sk)
+ {
+ String added = getPositive(extractURI, cdo).get(sk);
+ boolean hasClear = CLEAR.equals(getNegative(extractURI, cdo)
+ .get(sk));
+ if (hasClear)
+ {
+ if (added == null)
+ {
+ return Constants.LST_DOT_CLEAR;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ if (added == null)
+ {
+ return null;
+ }
+ else
+ {
+ return added;
+ }
+ }
+ }
+
+ public Integer getInteger(CDOMObject cdo, IntegerKey ik)
+ {
+ return getPositive(extractURI, cdo).get(ik);
+ }
+
+ public Formula getFormula(CDOMObject cdo, FormulaKey fk)
+ {
+ return getPositive(extractURI, cdo).get(fk);
+ }
+
+ public Formula getVariable(CDOMObject cdo, VariableKey key)
+ {
+ return getPositive(extractURI, cdo).get(key);
+ }
+
+ public Set<VariableKey> getVariableKeys(CDOMObject cdo)
+ {
+ return getPositive(extractURI, cdo).getVariableKeys();
+ }
+
+ public <T> T getObject(CDOMObject cdo, ObjectKey<T> ik)
+ {
+ return getPositive(extractURI, cdo).get(ik);
+ }
+
+ public <T> Changes<T> getListChanges(CDOMObject cdo, ListKey<T> lk)
+ {
+ return new CollectionChanges<T>(getPositive(extractURI, cdo)
+ .getListFor(lk), getNegative(extractURI, cdo)
+ .getListFor(lk), globalClearSet.containsInList(extractURI,
+ cdo, lk));
+ }
+
+ public URI getExtractURI()
+ {
+ return extractURI;
+ }
+
+ public void setExtractURI(URI extractURI)
+ {
+ this.extractURI = extractURI;
+ }
+
+ public URI getSourceURI()
+ {
+ return sourceURI;
+ }
+
+ public void setSourceURI(URI sourceURI)
+ {
+ this.sourceURI = sourceURI;
+ }
+
+ public void decommit()
+ {
+ positiveMap.clear();
+ negativeMap.clear();
+ globalClearSet.clear();
+ }
+
+ public <T extends CDOMObject> T cloneConstructedCDOMObject(T obj,
+ String newName)
+ {
+ Class<T> cl = (Class<T>) obj.getClass();
+ try
+ {
+ T newObj = cl.newInstance();
+ newObj.setName(newName);
+ /*
+ * TODO Need to store this clone somewhere
+ */
+ return newObj;
+ }
+ catch (InstantiationException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ catch (IllegalAccessException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public Changes<Prerequisite> getPrerequisiteChanges(
+ ConcretePrereqObject obj)
+ {
+ return new CollectionChanges<Prerequisite>(getPositive(extractURI,
+ obj).getPrerequisiteList(), null, false);
+ }
+ }
+
+ public Changes<Prerequisite> getPrerequisiteChanges(ConcretePrereqObject obj)
+ {
+ return commit.getPrerequisiteChanges(obj);
+ }
+
+ public boolean containsListFor(CDOMObject obj, ListKey<?> lk)
+ {
+ return commit.containsListFor(obj, lk);
+ }
+
+// private class GivenChanges<T> implements Changes<T>
+// {
+//
+// private final ArrayList<T> added = new ArrayList<T>();
+// private final ArrayList<T> removed = new ArrayList<T>();
+// private final String token;
+// private final Class<T> targetClass;
+// private final boolean clear;
+//
+// public GivenChanges(Class<T> cl, String sourceToken,
+// Changes<SourceWrapper> listChanges)
+// {
+// targetClass = cl;
+// token = sourceToken;
+// clear = listChanges.includesGlobalClear();
+// Collection<SourceWrapper> allAdded = listChanges.getAdded();
+// if (allAdded != null)
+// {
+// for (SourceWrapper add : allAdded)
+// {
+// PrereqObject target = add.getTarget();
+// if (targetClass.isAssignableFrom(target.getClass())
+// && token.equals(add.getSourceToken()))
+// {
+// added.add((T) target);
+// }
+// }
+// }
+// Collection<SourceWrapper> allRemoved = listChanges.getRemoved();
+// if (allRemoved != null)
+// {
+// for (SourceWrapper rem : allRemoved)
+// {
+// PrereqObject target = rem.getTarget();
+// if (targetClass.equals(target.getClass())
+// && token.equals(rem.getSourceToken()))
+// {
+// removed.add((T) target);
+// }
+// }
+// }
+// }
+//
+// public Collection<T> getAdded()
+// {
+// return Collections.unmodifiableList(added);
+// }
+//
+// public Collection<T> getRemoved()
+// {
+// return Collections.unmodifiableList(removed);
+// }
+//
+// public boolean hasAddedItems()
+// {
+// return !added.isEmpty();
+// }
+//
+// public boolean hasRemovedItems()
+// {
+// return !removed.isEmpty();
+// }
+//
+// public boolean includesGlobalClear()
+// {
+// return clear;
+// }
+//
+// public boolean isEmpty()
+// {
+// return added.isEmpty() && removed.isEmpty();
+// }
+//
+// }
+
+ public interface Remover<T>
+ {
+ public boolean matches(T obj);
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/ReferenceContext.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/ReferenceContext.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/ReferenceContext.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,318 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.rules.context;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import pcgen.base.util.OneToOneMap;
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.enumeration.ObjectKey;
+import pcgen.cdom.enumeration.StringKey;
+import pcgen.cdom.reference.CDOMDirectSingleRef;
+import pcgen.cdom.reference.CDOMGroupRef;
+import pcgen.cdom.reference.CDOMSimpleSingleRef;
+import pcgen.cdom.reference.CDOMSingleRef;
+import pcgen.cdom.reference.ReferenceManufacturer;
+
+public class ReferenceContext
+{
+
+ private SimpleReferenceContext simple = new SimpleReferenceContext();
+// private CategorizedReferenceContext categorized = new CategorizedReferenceContext();
+ private Map<Class<?>, OneToOneMap<CDOMObject, String>> abbMap = new HashMap<Class<?>, OneToOneMap<CDOMObject, String>>();
+
+ public Class<?> getClassFor(String key)
+ {
+ return null; // return StringPClassUtil.getCDOMClassFor(key);
+ }
+
+ public void clear()
+ {
+ simple.clear();
+// categorized.clear();
+ }
+
+ public boolean validate()
+ {
+ return simple.validate();
+ //&& categorized.validate();
+ }
+
+// public <T extends CDOMObject & CategorizedCDOMObject<T>> CDOMGroupRef<T> getCDOMAllReference(
+// Class<T> c, Category<T> cat)
+// {
+// return categorized.getManufacturer(c, cat).getAllReference();
+// }
+
+// public <T extends CDOMObject & CategorizedCDOMObject<T>> CDOMGroupRef<T> getCDOMTypeReference(
+// Class<T> c, Category<T> cat, String... val)
+// {
+// return categorized.getManufacturer(c, cat).getTypeReference(val);
+// }
+
+ public <T extends CDOMObject> CDOMGroupRef<T> getCDOMAllReference(Class<T> c)
+ {
+ return simple.getManufacturer(c).getAllReference();
+ }
+
+ public <T extends CDOMObject> CDOMGroupRef<T> getCDOMTypeReference(
+ Class<T> c, String... val)
+ {
+ return simple.getManufacturer(c).getTypeReference(val);
+ }
+
+ public <T extends CDOMObject> T constructCDOMObject(Class<T> c, String val)
+ {
+ T obj;
+// if (CategorizedCDOMObject.class.isAssignableFrom(c))
+// {
+// obj = (T) categorized.constructCDOMObject((Class) c, null, val);
+// }
+// else
+// {
+ obj = simple.constructCDOMObject(c, val);
+// }
+ obj.put(ObjectKey.SOURCE_URI, sourceURI);
+ return obj;
+ }
+
+ public <T extends CDOMObject> void constructIfNecessary(Class<T> cl,
+ String value)
+ {
+ simple.constructIfNecessary(cl, value);
+ }
+
+ public <T extends CDOMObject> CDOMSingleRef<T> getCDOMReference(Class<T> c,
+ String val)
+ {
+ return simple.getCDOMReference(c, val);
+ }
+
+ public <T extends CDOMObject> void reassociateKey(String value, T obj)
+ {
+// if (CategorizedCDOMObject.class.isAssignableFrom(obj.getClass()))
+// {
+// categorized.reassociateKey(obj, value);
+// }
+// else
+// {
+ simple.reassociateKey(obj, value);
+// }
+ }
+
+ public <T extends CDOMObject> T silentlyGetConstructedCDOMObject(
+ Class<T> c, String val)
+ {
+ return simple.silentlyGetConstructedCDOMObject(c, val);
+ }
+
+// public <T extends CDOMObject & CategorizedCDOMObject<T>> CDOMSingleRef<T> getCDOMReference(
+// Class<T> c, Category<T> cat, String val)
+// {
+// return categorized.getCDOMReference(c, cat, val);
+// }
+//
+// public <T extends CDOMObject & CategorizedCDOMObject<T>> void reassociateCategory(
+// Category<T> cat, T obj)
+// {
+// categorized.reassociateCategory(cat, obj);
+// }
+
+ // public <T extends CDOMObject> T cloneConstructedCDOMObject(T orig,
+ // String newKey)
+ // {
+ // Class cl = (Class) orig.getClass();
+ // if (CategorizedCDOMObject.class.isAssignableFrom(cl))
+ // {
+ // return (T) cloneCategorized(cl, ((CategorizedCDOMObject) orig)
+ // .getCDOMCategory(), orig, newKey);
+ // }
+ // else
+ // {
+ // return (T) simple.cloneConstructedCDOMObject(cl, orig, newKey);
+ // }
+ // }
+
+ public <T extends CDOMObject> void importObject(T orig)
+ {
+// if (CategorizedCDOMObject.class.isAssignableFrom(orig.getClass()))
+// {
+// throw new IllegalArgumentException();
+// }
+// else
+// {
+ simple.importObject(orig);
+// }
+ }
+
+ // public <T extends CDOMObject & CategorizedCDOMObject<T>> T
+ // cloneCategorized(
+ // Class<T> cl, Category<T> cat, Object o, String newKey)
+ // {
+ // return categorized.cloneConstructedCDOMObject(cl, cat, (T) o, newKey);
+ // }
+
+ public <T extends CDOMObject> ReferenceManufacturer<T, CDOMSimpleSingleRef<T>> getReferenceManufacturer(
+ Class<T> c)
+ {
+ return simple.getManufacturer(c);
+ }
+
+// public <T extends CDOMObject & CategorizedCDOMObject<T>> ReferenceManufacturer<T, CDOMCategorizedSingleRef<T>> getReferenceManufacturer(
+// Class<T> c, Category<T> cat)
+// {
+// return categorized.getManufacturer(c, cat);
+// }
+
+ public <T extends CDOMObject> Collection<T> getConstructedCDOMObjects(
+ Class<T> c)
+ {
+// if (CategorizedCDOMObject.class.isAssignableFrom(c))
+// {
+// return categorized.getAllConstructedCDOMObjects((Class) c);
+// }
+// else
+// {
+ return simple.getConstructedCDOMObjects(c);
+// }
+ }
+
+// public <T extends CDOMObject & CategorizedCDOMObject<T>> Collection<T> getConstructedCDOMObjects(
+// Class<T> c, Category<T> cat)
+// {
+// return categorized.getConstructedCDOMObjects(c, cat);
+// }
+
+ public Set<CDOMObject> getAllConstructedObjects()
+ {
+ Set<CDOMObject> set = new HashSet<CDOMObject>();
+ set.addAll(simple.getAllConstructedCDOMObjects());
+// Collection otherSet = categorized.getAllConstructedCDOMObjects();
+// set.addAll(otherSet);
+ return set;
+ }
+
+ public <T extends CDOMObject> boolean containsConstructedCDOMObject(
+ Class<T> c, String s)
+ {
+ return simple.containsConstructedCDOMObject(c, s);
+ }
+
+ public void buildDerivedObjects()
+ {
+// Collection<CDOMDomain> domains = simple
+// .getConstructedCDOMObjects(CDOMDomain.class);
+// for (CDOMDomain d : domains)
+// {
+// simple.constructCDOMObject(DOMAINSPELLLIST_CLASS, d.getKeyName());
+// }
+// Collection<CDOMPCClass> classes = simple
+// .getConstructedCDOMObjects(CDOMPCClass.class);
+// for (CDOMPCClass pcc : classes)
+// {
+// String key = pcc.getKeyName();
+// simple.constructCDOMObject(CLASSSKILLLIST_CLASS, key);
+// // TODO Need to limit which are built to only spellcasters...
+// simple.constructCDOMObject(CLASSSPELLLIST_CLASS, key);
+// simple.constructCDOMObject(SPELLPROGRESSION_CLASS, key);
+// Collection<CDOMSubClass> subclasses = categorized
+// .getConstructedCDOMObjects(SUBCLASS_CLASS, SubClassCategory
+// .getConstant(key));
+// for (CDOMSubClass subcl : subclasses)
+// {
+// String subKey = subcl.getKeyName();
+// simple.constructCDOMObject(CLASSSKILLLIST_CLASS, subKey);
+// // TODO Need to limit which are built to only
+// // spellcasters...
+// simple.constructCDOMObject(CLASSSPELLLIST_CLASS, subKey);
+// simple.constructCDOMObject(SPELLPROGRESSION_CLASS, subKey);
+// }
+// }
+ }
+
+// public <T extends CDOMObject> CDOMAddressedSingleRef<T> getCDOMAddressedReference(
+// CDOMObject obj, Class<T> name, String string)
+// {
+// return simple.getAddressedReference(obj, name, string);
+// }
+
+ private HashMap<CDOMObject, CDOMSingleRef<?>> directRef = new HashMap<CDOMObject, CDOMSingleRef<?>>();
+
+ public <T extends CDOMObject> CDOMSingleRef<T> getCDOMDirectReference(T obj)
+ {
+ CDOMSingleRef<?> ref = directRef.get(obj);
+ if (ref == null)
+ {
+ ref = new CDOMDirectSingleRef<T>(obj);
+ }
+ return (CDOMSingleRef<T>) ref;
+ }
+
+ public void registerAbbreviation(CDOMObject obj, String value)
+ {
+ OneToOneMap<CDOMObject, String> map = abbMap.get(obj.getClass());
+ if (map == null)
+ {
+ map = new OneToOneMap<CDOMObject, String>();
+ abbMap.put(obj.getClass(), map);
+ }
+ map.put(obj, value);
+ obj.put(StringKey.ABB, value);
+ }
+
+ public String getAbbreviation(CDOMObject obj)
+ {
+ OneToOneMap<CDOMObject, String> map = abbMap.get(obj.getClass());
+ return map == null ? null : map.get(obj);
+ }
+
+ public <T> T getAbbreviatedObject(Class<T> cl, String value)
+ {
+ OneToOneMap<T, String> map = (OneToOneMap<T, String>) abbMap.get(cl);
+ return map == null ? null : map.getKeyFor(value);
+ }
+
+ private URI sourceURI;
+
+ private URI extractURI;
+
+ public URI getExtractURI()
+ {
+ return extractURI;
+ }
+
+ public void setExtractURI(URI extractURI)
+ {
+ this.extractURI = extractURI;
+ }
+
+ public URI getSourceURI()
+ {
+ return sourceURI;
+ }
+
+ public void setSourceURI(URI sourceURI)
+ {
+ this.sourceURI = sourceURI;
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/ReferenceSupport.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/ReferenceSupport.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/ReferenceSupport.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,373 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.rules.context;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import pcgen.base.lang.CaseInsensitiveString;
+import pcgen.base.util.HashMapToInstanceList;
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.enumeration.StringKey;
+import pcgen.cdom.reference.CDOMSingleRef;
+import pcgen.cdom.reference.ReferenceManufacturer;
+import pcgen.core.PCClass;
+import pcgen.util.Logging;
+
+public class ReferenceSupport<T extends CDOMObject, RT extends CDOMSingleRef<T>>
+{
+
+ private HashMapToInstanceList<CaseInsensitiveString, T> duplicates = new HashMapToInstanceList<CaseInsensitiveString, T>();
+
+ private Map<CaseInsensitiveString, T> active = new HashMap<CaseInsensitiveString, T>();
+
+ private List<CaseInsensitiveString> deferred = new ArrayList<CaseInsensitiveString>();
+
+ private Map<CaseInsensitiveString, RT> referenced = new HashMap<CaseInsensitiveString, RT>();
+
+ private final Class<T> baseClass;
+
+ private final ReferenceManufacturer<T, RT> referenceMfg;
+
+ public ReferenceSupport(ReferenceManufacturer<T, RT> mfg)
+ {
+ referenceMfg = mfg;
+ baseClass = mfg.getCDOMClass();
+ }
+
+ public void registerWithKey(T obj, String key)
+ {
+ if (!baseClass.isInstance(obj))
+ {
+ Logging.errorPrint("Attempted to register a "
+ + obj.getClass().getName() + " in " + baseClass.getName()
+ + " ReferenceSupport");
+ return;
+ }
+ CaseInsensitiveString cik = new CaseInsensitiveString(key);
+ if (active.containsKey(cik))
+ {
+ duplicates.addToListFor(cik, obj);
+ }
+ else
+ {
+ active.put(cik, obj);
+ }
+ }
+
+ public T silentlyGetConstructedCDOMObject(String val)
+ {
+ CaseInsensitiveString civ = new CaseInsensitiveString(val);
+ T po = active.get(civ);
+ if (po != null)
+ {
+ if (duplicates.containsListFor(civ))
+ {
+ Logging.errorPrint("Reference to Constructed "
+ + baseClass.getSimpleName() + " " + val
+ + " is ambiguous");
+ }
+ return po;
+ }
+ return null;
+ }
+
+ public T getConstructedCDOMObject(String val)
+ {
+ T obj = silentlyGetConstructedCDOMObject(val);
+ if (obj == null)
+ {
+ Logging.errorPrint("Someone expected " + baseClass.getSimpleName()
+ + " " + val + " to exist.");
+ }
+ return obj;
+ }
+
+ public T constructCDOMObject(String val)
+ {
+ if (val.equals(""))
+ {
+ throw new IllegalArgumentException("Cannot build empty name");
+ }
+ try
+ {
+ T obj = baseClass.newInstance();
+ obj.setName(val);
+ registerWithKey(obj, val);
+ return obj;
+ }
+ catch (InstantiationException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ catch (IllegalAccessException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ throw new IllegalArgumentException(baseClass + " " + val);
+ }
+
+ public void reassociateKey(String value, T obj)
+ {
+ String oldKey = obj.getKeyName();
+ if (oldKey.equalsIgnoreCase(value))
+ {
+ Logging.debugPrint("Worthless Key change encountered: "
+ + obj.getDisplayName() + " " + oldKey);
+ }
+ forgetObject(obj);
+ registerWithKey(obj, value);
+ }
+
+ public void forgetObject(T obj) throws InternalError
+ {
+ if (!baseClass.isInstance(obj))
+ {
+ // TODO Error
+ }
+ /*
+ * TODO This is a bug - the key name is not necessarily loaded into the
+ * object, it may have been consumed by the object context... :P
+ */
+ String key = obj.getKeyName();
+ CaseInsensitiveString ocik = new CaseInsensitiveString(key);
+ CDOMObject act = active.get(ocik);
+ if (act == null)
+ {
+ throw new InternalError("Did not find " + obj + " under " + key);
+ }
+ if (act.equals(obj))
+ {
+ List<T> list = duplicates.getListFor(ocik);
+ if (list == null)
+ {
+ // No replacement
+ active.remove(ocik);
+ }
+ else
+ {
+ T newActive = duplicates.getElementInList(ocik, 0);
+ duplicates.removeFromListFor(ocik, newActive);
+ active.put(ocik, newActive);
+ }
+ }
+ else
+ {
+ duplicates.removeFromListFor(ocik, obj);
+ }
+ }
+
+ public void forgetCDOMObjectKeyed(String forgetKey)
+ {
+ CaseInsensitiveString cis = new CaseInsensitiveString(forgetKey);
+ active.remove(cis);
+ duplicates.removeListFor(cis);
+ }
+
+ public Collection<T> getConstructedCDOMObjects()
+ {
+ return active.values();
+ }
+
+ public boolean containsConstructedCDOMObject(String key)
+ {
+ return active.containsKey(new CaseInsensitiveString(key));
+ }
+
+ public CDOMSingleRef<T> getCDOMReference(String val)
+ {
+ // TODO Auto-generated method stub
+ // TODO This is incorrect, but a hack for now :)
+ if (val.equals(""))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ try
+ {
+ Integer.parseInt(val);
+ throw new IllegalArgumentException(val);
+ }
+ catch (NumberFormatException nfe)
+ {
+ // ok
+ }
+ if (val.startsWith("TYPE"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (val.equalsIgnoreCase("ANY"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (val.equalsIgnoreCase("ALL"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (val.startsWith("PRE"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (val.startsWith("CHOOSE"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (val.startsWith("TIMES="))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ if (baseClass.equals(PCClass.class))
+ {
+ if (val.startsWith("CLASS"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ else if (val.startsWith("SUB"))
+ {
+ throw new IllegalArgumentException(val);
+ }
+ else
+ {
+ try
+ {
+ Integer.parseInt(val);
+ throw new IllegalArgumentException(val);
+ }
+ catch (NumberFormatException nfe)
+ {
+ // Want this!
+ }
+ }
+ }
+
+ CaseInsensitiveString cis = new CaseInsensitiveString(val);
+ RT ref = referenced.get(cis);
+ if (ref == null)
+ {
+ ref = referenceMfg.getReference(val);
+ referenced.put(cis, ref);
+ }
+ return ref;
+ }
+
+ public boolean validate()
+ {
+ boolean returnGood = true;
+// for (CaseInsensitiveString second : duplicates.getKeySet())
+// {
+// if (SettingsHandler.isAllowOverride())
+// {
+// List<T> list = duplicates.getListFor(second);
+// T good = active.get(second);
+// for (int i = 0; i < list.size(); i++)
+// {
+// T dupe = list.get(i);
+// // If the new object is more recent than the current
+// // one, use the new object
+// final Date origDate = good.getSourceEntry().getSourceBook()
+// .getDate();
+// final Date dupeDate = dupe.getSourceEntry().getSourceBook()
+// .getDate();
+// if ((dupeDate != null)
+// && ((origDate == null) || ((dupeDate
+// .compareTo(origDate) > 0))))
+// {
+// duplicates.removeFromListFor(second, good);
+// good = dupe;
+// }
+// else
+// {
+// duplicates.removeFromListFor(second, dupe);
+// }
+// }
+// if (!good.equals(active.get(second)))
+// {
+// active.put(second, good);
+// }
+// }
+// else
+// {
+// Logging.errorPrint("More than one " + baseClass.getSimpleName()
+// + " with key/name " + second + " was built");
+// returnGood = false;
+// }
+// }
+ for (CaseInsensitiveString second : active.keySet())
+ {
+ T activeObj = active.get(second);
+ String keyName = activeObj.getKeyName();
+ if (keyName == null)
+ {
+ System.err.println(activeObj.getClass() + " "
+ + activeObj.get(StringKey.NAME));
+ }
+ else if (!keyName.equalsIgnoreCase(second.toString()))
+ {
+ Logging.errorPrint("Magical Key Change: " + second + " to "
+ + keyName);
+ returnGood = false;
+ }
+ }
+ for (CaseInsensitiveString s : referenced.keySet())
+ {
+ if (!active.containsKey(s) && !deferred.contains(s)
+ && !s.toString().startsWith("*"))
+ {
+ Logging.errorPrint("Unconstructed Reference: "
+ + baseClass.getSimpleName() + " " + s);
+ returnGood = false;
+ }
+ }
+ return returnGood;
+ }
+
+ public void constructIfNecessary(String value)
+ {
+ /*
+ * TODO FIXME Need to ensure that items that are built here are tagged
+ * as manufactured, so that they are not written out to LST files
+ */
+ deferred.add(new CaseInsensitiveString(value));
+ }
+
+ public void clear()
+ {
+ duplicates.clear();
+ active.clear();
+ deferred.clear();
+ referenced.clear();
+ }
+
+ public ReferenceManufacturer<T, RT> getReferenceManufacturer()
+ {
+ return referenceMfg;
+ }
+
+ public Collection<T> getAllConstructedCDOMObjects()
+ {
+ Set<T> set = new HashSet<T>();
+ set.addAll(active.values());
+ return set;
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/RuntimeLoadContext.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/RuntimeLoadContext.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/RuntimeLoadContext.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,23 @@
+package pcgen.rules.context;
+
+public class RuntimeLoadContext extends LoadContext
+{
+ private final String contextType;
+
+ public RuntimeLoadContext()
+ {
+ super(new ListContext(new ConsolidatedListCommitStrategy()),
+ new ObjectContext(new ConsolidatedObjectCommitStrategy()));
+ contextType = "Runtime";
+ }
+
+ /*
+ * Get the type of context we're running in (either Editor or Runtime)
+ */
+ @Override
+ public String getContextType()
+ {
+ return contextType;
+ }
+
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/context/SimpleReferenceContext.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/context/SimpleReferenceContext.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/context/SimpleReferenceContext.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.rules.context;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.reference.CDOMSimpleSingleRef;
+import pcgen.cdom.reference.CDOMSingleRef;
+import pcgen.cdom.reference.SimpleReferenceManufacturer;
+
+public class SimpleReferenceContext
+{
+
+ private Map<Class<?>, SimpleReferenceManufacturer<?>> map =
+ new HashMap<Class<?>, SimpleReferenceManufacturer<?>>();
+
+ public <T extends CDOMObject> SimpleReferenceManufacturer<T> getManufacturer(Class<T> cl)
+ {
+ SimpleReferenceManufacturer<T> mfg = (SimpleReferenceManufacturer<T>) map.get(cl);
+ if (mfg == null)
+ {
+ mfg = new SimpleReferenceManufacturer<T>(cl);
+ map.put(cl, mfg);
+ }
+ return mfg;
+ }
+
+
+ private Map<Class<?>, ReferenceSupport<?, ?>> refMap = new HashMap<Class<?>, ReferenceSupport<?, ?>>();
+
+// private DoubleKeyMap<CDOMObject, Class, CDOMAddressedSingleRef> addressed = new DoubleKeyMap<CDOMObject, Class, CDOMAddressedSingleRef>();
+
+ public SimpleReferenceContext()
+ {
+ initialize();
+ }
+
+ private void initialize()
+ {
+ // TODO Need to reproduce this effect...
+ // GameMode game = SettingsHandler.getGame();
+ // List<CDOMStat> statList = game.getUnmodifiableStatList();
+ // for (CDOMStat stat : statList)
+ // {
+ // active.put(CDOMStat.class, new CaseInsensitiveString(stat
+ // .get(StringKey.ABB)), stat);
+ // }
+ // for (int i = 0; i < game.getSizeAdjustmentListSize(); i++)
+ // {
+ // CDOMSizeAdjustment sa = game.getSizeAdjustmentAtIndex(i);
+ // active.put(CDOMSizeAdjustment.class, new CaseInsensitiveString(sa
+ // .getAbbreviation()), sa);
+ // }
+ }
+
+ private <T extends CDOMObject> ReferenceSupport<T, CDOMSimpleSingleRef<T>> getRefSupport(
+ Class<T> cl)
+ {
+ ReferenceSupport<T, CDOMSimpleSingleRef<T>> ref = (ReferenceSupport<T, CDOMSimpleSingleRef<T>>) refMap
+ .get(cl);
+ if (ref == null)
+ {
+ ref = new ReferenceSupport<T, CDOMSimpleSingleRef<T>>(
+ getManufacturer(cl));
+ refMap.put(cl, ref);
+ }
+ return ref;
+ }
+
+ public <T extends CDOMObject> void importObject(T obj)
+ {
+ getRefSupport((Class<T>) obj.getClass()).registerWithKey(obj,
+ obj.getKeyName());
+ }
+
+ public <T extends CDOMObject> void reassociateKey(T obj, String key)
+ {
+ getRefSupport((Class<T>) obj.getClass()).reassociateKey(key, obj);
+ }
+
+ public <T extends CDOMObject> T silentlyGetConstructedCDOMObject(
+ Class<T> c, String val)
+ {
+ return getRefSupport(c).silentlyGetConstructedCDOMObject(val);
+ }
+
+ public <T extends CDOMObject> T getConstructedCDOMObject(Class<T> c,
+ String val)
+ {
+ return getRefSupport(c).getConstructedCDOMObject(val);
+ }
+
+ public <T extends CDOMObject> T constructCDOMObject(Class<T> c, String val)
+ {
+ return getRefSupport(c).constructCDOMObject(val);
+ }
+
+ public <T extends CDOMObject> void forgetCDOMObjectKeyed(Class<T> cl,
+ String forgetKey)
+ {
+ getRefSupport(cl).forgetCDOMObjectKeyed(forgetKey);
+ }
+
+ public <T extends CDOMObject> Collection<T> getConstructedCDOMObjects(
+ Class<T> name)
+ {
+ return getRefSupport(name).getConstructedCDOMObjects();
+ }
+
+ public <T extends CDOMObject> boolean containsConstructedCDOMObject(
+ Class<T> name, String key)
+ {
+ return getRefSupport(name).containsConstructedCDOMObject(key);
+ }
+
+ public <T extends CDOMObject> CDOMSingleRef<T> getCDOMReference(Class<T> c,
+ String val)
+ {
+ return getRefSupport(c).getCDOMReference(val);
+ }
+
+ public boolean validate()
+ {
+ boolean returnGood = true;
+ for (ReferenceSupport<?, ?> ref : refMap.values())
+ {
+ returnGood &= ref.validate();
+ }
+ return returnGood;
+ }
+
+ public <T extends CDOMObject> void constructIfNecessary(Class<T> cl,
+ String value)
+ {
+ getRefSupport(cl).constructIfNecessary(value);
+ }
+
+ public void clear()
+ {
+ refMap.clear();
+ }
+
+// public <T extends CDOMObject> CDOMAddressedSingleRef<T> getAddressedReference(
+// CDOMObject obj, Class<T> name, String addressName)
+// {
+// CDOMAddressedSingleRef<T> addr = addressed.get(obj, name);
+// if (addr == null)
+// {
+// addr = new CDOMAddressedSingleRef<T>(obj, name, addressName);
+// addressed.put(obj, name, addr);
+// }
+// return addr;
+// }
+
+ public Collection<CDOMObject> getAllConstructedCDOMObjects()
+ {
+ Set<CDOMObject> set = new HashSet<CDOMObject>();
+ for (ReferenceSupport<?, ?> ref : refMap.values())
+ {
+ set.addAll(ref.getAllConstructedCDOMObjects());
+ }
+ return set;
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/persistence/TokenLibrary.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/persistence/TokenLibrary.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/persistence/TokenLibrary.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,377 @@
+package pcgen.rules.persistence;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.TreeSet;
+
+import pcgen.cdom.base.CDOMObject;
+import pcgen.persistence.lst.prereq.PrerequisiteParserInterface;
+import pcgen.rules.persistence.token.CDOMPrimaryToken;
+import pcgen.rules.persistence.token.CDOMSecondaryToken;
+import pcgen.rules.persistence.token.CDOMSubToken;
+import pcgen.rules.persistence.token.CDOMToken;
+import pcgen.rules.persistence.token.PreCompatibilityToken;
+import pcgen.rules.persistence.util.TokenFamily;
+
+public class TokenLibrary
+{
+// private static final Class<CDOMPCClass> PCCLASS_CLASS = CDOMPCClass.class;
+
+ static final Class<CDOMObject> CDOMOBJECT_CLASS = CDOMObject.class;
+
+// private final static List<DeferredToken<? extends CDOMObject>> deferredTokens = new ArrayList<DeferredToken<? extends CDOMObject>>();
+//
+// private final static DoubleKeyMap<Class<?>, String, Class<ChooseLstQualifierToken<?>>> qualifierMap = new DoubleKeyMap<Class<?>, String, Class<ChooseLstQualifierToken<?>>>();
+//
+// private final static DoubleKeyMap<Class<?>, String, Class<PrimitiveToken<?>>> primitiveMap = new DoubleKeyMap<Class<?>, String, Class<PrimitiveToken<?>>>();
+
+ private final static Set<TokenFamily> tokenSources = new TreeSet<TokenFamily>();
+
+ static
+ {
+ tokenSources.add(TokenFamily.CURRENT);
+ tokenSources.add(TokenFamily.REV514);
+ }
+
+// public static <T> PrimitiveToken<T> getPrimitive(Class<T> name,
+// String tokKey)
+// {
+// Class<PrimitiveToken<?>> cptc = primitiveMap.get(name, tokKey);
+// if (cptc == null)
+// {
+// return null;
+// }
+// try
+// {
+// return (PrimitiveToken<T>) cptc.newInstance();
+// }
+// catch (InstantiationException e)
+// {
+// throw new UnreachableError("new Instance on " + cptc
+// + " should not fail in getPrimitive", e);
+// }
+// catch (IllegalAccessException e)
+// {
+// throw new UnreachableError("new Instance on " + cptc
+// + " should not fail due to access", e);
+// }
+// }
+//
+// public static <T extends CDOMObject> ChooseLstQualifierToken<T> getChooseQualifier(
+// Class<T> domain_class, String key)
+// {
+// Class<ChooseLstQualifierToken<?>> clqtc = qualifierMap.get(
+// domain_class, key);
+// if (clqtc == null)
+// {
+// return null;
+// }
+// try
+// {
+// return (ChooseLstQualifierToken<T>) clqtc.newInstance();
+// }
+// catch (InstantiationException e)
+// {
+// throw new UnreachableError("new Instance on " + clqtc
+// + " should not fail in getChooseQualifier", e);
+// }
+// catch (IllegalAccessException e)
+// {
+// throw new UnreachableError("new Instance on " + clqtc
+// + " should not fail due to access", e);
+// }
+// }
+//
+// public static List<DeferredToken<? extends CDOMObject>> getDeferredTokens()
+// {
+// return new ArrayList<DeferredToken<? extends CDOMObject>>(
+// deferredTokens);
+// }
+//
+// public static void addToPrimitiveMap(PrimitiveToken<?> p)
+// {
+// Class<? extends PrimitiveToken> newTokClass = p.getClass();
+// if (PrimitiveToken.class.isAssignableFrom(newTokClass))
+// {
+// String name = p.getTokenName();
+// Class cl = ((PrimitiveToken) p).getReferenceClass();
+// Class<PrimitiveToken<?>> prev = primitiveMap.put(cl, name,
+// (Class<PrimitiveToken<?>>) newTokClass);
+// if (prev != null)
+// {
+// Logging.errorPrint("Found a second " + name + " Primitive for "
+// + cl);
+// }
+// }
+// }
+//
+// public static void addToQualifierMap(QualifierToken<?> p)
+// {
+// Class<? extends QualifierToken> newTokClass = p.getClass();
+// if (ChooseLstQualifierToken.class.isAssignableFrom(newTokClass))
+// {
+// Class<?> cl = ((ChooseLstQualifierToken<?>) p).getChoiceClass();
+// String name = p.getTokenName();
+// Class<ChooseLstQualifierToken<?>> prev = qualifierMap.put(cl, name,
+// (Class<ChooseLstQualifierToken<?>>) newTokClass);
+// if (prev != null)
+// {
+// Logging.errorPrint("Found a second " + name + " Primitive for "
+// + cl);
+// }
+// }
+// }
+
+ public static void addToTokenMap(Object newToken)
+ {
+// if (newToken instanceof DeferredToken)
+// {
+// deferredTokens.add((DeferredToken<?>) newToken);
+// }
+ if (newToken instanceof CDOMPrimaryToken)
+ {
+ CDOMPrimaryToken<?> tok = (CDOMPrimaryToken<?>) newToken;
+ TokenFamily.CURRENT.putToken(tok);
+// if (PCCLASS_CLASS.equals(tok.getTokenClass()))
+// {
+// addToTokenMap(new ClassWrappedToken(
+// (CDOMPrimaryToken<CDOMPCClass>) tok));
+// }
+ }
+ if (newToken instanceof CDOMSecondaryToken)
+ {
+ TokenFamily.CURRENT.putSubToken((CDOMSecondaryToken<?>) newToken);
+ }
+// if (newToken instanceof ChoiceSetToken)
+// {
+// TokenFamily.CURRENT.putChooseToken((ChoiceSetToken<?>) newToken);
+// }
+ if (newToken instanceof PrerequisiteParserInterface)
+ {
+ PrerequisiteParserInterface prereqToken = (PrerequisiteParserInterface) newToken;
+ TokenFamily.CURRENT.putPrerequisiteToken(prereqToken);
+ for (String s : prereqToken.kindsHandled())
+ {
+ /*
+ * TODO Theoretically these belong in REV514, but put into
+ * current for unparse testing
+ */
+ PreCompatibilityToken pos = new PreCompatibilityToken(s,
+ prereqToken, false);
+ TokenFamily.CURRENT.putToken(pos);
+ TokenFamily.CURRENT.putSubToken(pos);
+ PreCompatibilityToken neg = new PreCompatibilityToken(s,
+ prereqToken, true);
+ TokenFamily.CURRENT.putToken(neg);
+ TokenFamily.CURRENT.putSubToken(neg);
+ }
+ }
+// if (newToken instanceof CDOMCompatibilityToken)
+// {
+// CDOMCompatibilityToken<?> tok = (CDOMCompatibilityToken<?>) newToken;
+// TokenFamily fam = TokenFamily.getConstant(tok.compatibilityLevel(),
+// tok.compatibilitySubLevel(), tok.compatibilityPriority());
+// fam.putToken(tok);
+// tokenSources.add(fam);
+// if (fam.compareTo(TokenFamily.REV514) <= 0
+// && PCCLASS_CLASS.equals(tok.getTokenClass()))
+// {
+// addToTokenMap(new ClassWrappedToken(
+// (CDOMCompatibilityToken<CDOMPCClass>) tok));
+// }
+// }
+// if (newToken instanceof CDOMCompatibilitySubToken)
+// {
+// CDOMCompatibilitySubToken<?> tok = (CDOMCompatibilitySubToken<?>) newToken;
+// TokenFamily fam = TokenFamily.getConstant(tok.compatibilityLevel(),
+// tok.compatibilitySubLevel(), tok.compatibilityPriority());
+// fam.putSubToken(tok);
+// tokenSources.add(fam);
+// }
+// if (newToken instanceof ChoiceSetCompatibilityToken)
+// {
+// ChoiceSetCompatibilityToken tok = (ChoiceSetCompatibilityToken) newToken;
+// TokenFamily fam = TokenFamily.getConstant(tok.compatibilityLevel(),
+// tok.compatibilitySubLevel(), tok.compatibilityPriority());
+// fam.putChooseToken(tok);
+// tokenSources.add(fam);
+// }
+ }
+
+ abstract static class AbstractTokenIterator<C, T> implements Iterator<T>
+ {
+// private static final Class<Object> OBJECT_CLASS = Object.class;
+ private final Class<C> rootClass;
+ private final String tokenKey;
+ private T nextToken = null;
+ private boolean needNewToken = true;
+ private Class<?> stopClass;
+ private final Iterator<TokenFamily> subIterator;
+
+ public AbstractTokenIterator(Class<C> cl, String key)
+ {
+ rootClass = cl;
+ subIterator = tokenSources.iterator();
+ tokenKey = key;
+ }
+
+ public boolean hasNext()
+ {
+ setNextToken();
+ return !needNewToken;
+ }
+
+ protected void setNextToken()
+ {
+ while (needNewToken && subIterator.hasNext())
+ {
+ TokenFamily family = subIterator.next();
+ Class<?> actingClass = rootClass;
+ nextToken = grabToken(family, actingClass, tokenKey);
+ while (nextToken == null && actingClass != null
+ && !actingClass.equals(stopClass))
+ {
+ actingClass = actingClass.getSuperclass();
+ nextToken = grabToken(family, actingClass, tokenKey);
+ }
+ if (stopClass == null)
+ {
+ stopClass = actingClass;
+ }
+ needNewToken = nextToken == null;
+ }
+ }
+
+ protected abstract T grabToken(TokenFamily family, Class<?> cl,
+ String key);
+
+ public T next()
+ {
+ setNextToken();
+ if (needNewToken)
+ {
+ throw new NoSuchElementException();
+ }
+ needNewToken = true;
+ return nextToken;
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException(
+ "Iterator does not support remove");
+ }
+ }
+
+ static class TokenIterator<C extends CDOMObject, T extends CDOMToken<? super C>>
+ extends TokenLibrary.AbstractTokenIterator<C, T>
+ {
+
+ public TokenIterator(Class<C> cl, String key)
+ {
+ super(cl, key);
+ }
+
+ @Override
+ protected T grabToken(TokenFamily family, Class<?> cl, String key)
+ {
+ return (T) family.getToken(cl, key);
+ }
+
+ }
+
+ static class SubTokenIterator<C, T extends CDOMSubToken<? super C>> extends
+ TokenLibrary.AbstractTokenIterator<C, T>
+ {
+ private final String subTokenKey;
+
+ public SubTokenIterator(Class<C> cl, String key, String subKey)
+ {
+ super(cl, key);
+ subTokenKey = subKey;
+ }
+
+ @Override
+ protected T grabToken(TokenFamily family, Class<?> cl, String key)
+ {
+ return (T) family.getSubToken(cl, key, subTokenKey);
+ }
+ }
+
+// static class ChooseTokenIterator<C extends CDOMObject> extends
+// TokenLibrary.AbstractTokenIterator<C, ChoiceSetToken<? super C>>
+// {
+// public ChooseTokenIterator(Class<C> cl, String key)
+// {
+// super(cl, key);
+// }
+//
+// @Override
+// protected ChoiceSetToken<? super C> grabToken(TokenFamily family,
+// Class<?> cl, String key)
+// {
+// return (ChoiceSetToken<? super C>) family.getChooseToken(cl, key);
+// }
+// }
+
+// static class QualifierTokenIterator<C extends CDOMObject, T extends ChooseLstQualifierToken<? super C>>
+// extends TokenLibrary.AbstractTokenIterator<C, T>
+// {
+// public QualifierTokenIterator(Class<C> cl, String key)
+// {
+// super(cl, key);
+// }
+//
+// @Override
+// protected T grabToken(TokenFamily family, Class<?> cl, String key)
+// {
+// if (!TokenFamily.CURRENT.equals(family))
+// {
+// return null;
+// }
+// Class<ChooseLstQualifierToken<?>> cl1 = qualifierMap.get(cl, key);
+// if (cl1 == null)
+// {
+// return null;
+// }
+// try
+// {
+// return (T) cl1.newInstance();
+// }
+// catch (InstantiationException e)
+// {
+// throw new UnreachableError("new Instance on " + cl1
+// + " should not fail", e);
+// }
+// catch (IllegalAccessException e)
+// {
+// throw new UnreachableError("new Instance on " + cl1
+// + " should not fail due to access", e);
+// }
+// }
+// }
+
+ static class PreTokenIterator
+ extends
+ TokenLibrary.AbstractTokenIterator<CDOMObject, PrerequisiteParserInterface>
+ {
+ public PreTokenIterator(String key)
+ {
+ super(CDOMOBJECT_CLASS, key);
+ }
+
+ @Override
+ protected PrerequisiteParserInterface grabToken(TokenFamily family,
+ Class<?> cl, String key)
+ {
+ return family.getPrerequisiteToken(key);
+ }
+ }
+
+ public Class<CDOMObject> getTokenClass()
+ {
+ return CDOMObject.class;
+ }
+
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/persistence/TokenSupport.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/persistence/TokenSupport.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/persistence/TokenSupport.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,437 @@
+package pcgen.rules.persistence;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.base.Constants;
+import pcgen.core.prereq.Prerequisite;
+import pcgen.persistence.PersistenceLayerException;
+import pcgen.persistence.lst.prereq.PrerequisiteParserInterface;
+import pcgen.rules.context.LoadContext;
+import pcgen.rules.persistence.TokenLibrary.PreTokenIterator;
+import pcgen.rules.persistence.TokenLibrary.SubTokenIterator;
+import pcgen.rules.persistence.TokenLibrary.TokenIterator;
+import pcgen.rules.persistence.token.CDOMPrimaryToken;
+import pcgen.rules.persistence.token.CDOMSecondaryToken;
+import pcgen.rules.persistence.token.CDOMSubToken;
+import pcgen.rules.persistence.token.CDOMToken;
+import pcgen.rules.persistence.util.TokenFamilyIterator;
+import pcgen.rules.persistence.util.TokenFamilySubIterator;
+import pcgen.util.Logging;
+
+public class TokenSupport
+{
+ public static final Class<CDOMObject> CDOM_OBJECT_CLASS = CDOMObject.class;
+
+ public <T extends CDOMObject> boolean processToken(LoadContext context,
+ T derivative, String typeStr, String argument)
+ throws PersistenceLayerException
+ {
+ Class<T> cl = (Class<T>) derivative.getClass();
+ for (Iterator<? extends CDOMToken<T>> it = new TokenIterator<T, CDOMToken<T>>(
+ cl, typeStr); it.hasNext();)
+ {
+ CDOMToken<T> token = it.next();
+ if (token.parse(context, derivative, argument))
+ {
+ return true;
+ }
+ Logging.addParseMessage(Logging.LST_INFO,
+ "Failed in parsing typeStr: " + typeStr + " " + argument);
+ }
+ Logging.addParseMessage(Logging.LST_ERROR, "Illegal Token '" + typeStr
+ + "' '" + argument + "' for " + cl.getName() + " "
+ + derivative.getDisplayName());
+ return false;
+ }
+
+ public <T> boolean processSubToken(LoadContext context, T cdo,
+ String tokenName, String key, String value)
+ throws PersistenceLayerException
+ {
+ for (Iterator<CDOMSubToken<T>> it = new SubTokenIterator<T, CDOMSubToken<T>>(
+ (Class<T>) cdo.getClass(), tokenName, key); it.hasNext();)
+ {
+ CDOMSubToken<T> token = it.next();
+ if (token.parse(context, cdo, value))
+ {
+ return true;
+ }
+ Logging.addParseMessage(Logging.LST_ERROR,
+ "Failed in parsing typeStr: " + key + " " + value);
+ }
+ /*
+ * CONSIDER Better option than toString, given that T != CDOMObject
+ */
+ Logging.errorPrint("Illegal " + tokenName + " subtoken '" + key + "' '"
+ + value + "' for " + cdo.toString());
+ return false;
+ }
+
+ public <T> String[] unparse(LoadContext context, T cdo, String tokenName)
+ {
+ char separator = tokenName.startsWith("*") ? ':' : '|';
+ Set<String> set = new TreeSet<String>();
+ Class<T> cl = (Class<T>) cdo.getClass();
+ TokenFamilySubIterator<T> it = new TokenFamilySubIterator<T>(cl,
+ tokenName);
+ while (it.hasNext())
+ {
+ CDOMSecondaryToken<? super T> token = it.next();
+ String[] s = token.unparse(context, cdo);
+ if (s != null)
+ {
+ for (String aString : s)
+ {
+ set.add(token.getTokenName() + separator + aString);
+ }
+ }
+ }
+ if (set.isEmpty())
+ {
+ return null;
+ }
+ return set.toArray(new String[set.size()]);
+ }
+
+ public <T> Collection<String> unparse(LoadContext context, T cdo)
+ {
+ Set<String> set = new TreeSet<String>();
+ Class<T> cl = (Class<T>) cdo.getClass();
+ TokenFamilyIterator<T> it = new TokenFamilyIterator<T>(cl);
+ while (it.hasNext())
+ {
+ CDOMPrimaryToken<? super T> token = it.next();
+ String[] s = token.unparse(context, cdo);
+ if (s != null)
+ {
+ for (String aString : s)
+ {
+ set.add(token.getTokenName() + ':' + aString);
+ }
+ }
+ }
+ if (set.isEmpty())
+ {
+ return null;
+ }
+ return set;
+ }
+
+ public Prerequisite getPrerequisite(LoadContext context, String key,
+ String value) throws PersistenceLayerException
+ {
+ for (Iterator<PrerequisiteParserInterface> it = new PreTokenIterator(
+ key); it.hasNext();)
+ {
+ PrerequisiteParserInterface token = it.next();
+ Prerequisite p = token.parse(key, value, false, false);
+ if (p == null)
+ {
+ Logging.addParseMessage(Logging.LST_ERROR,
+ "Failed in parsing Prereq: " + key + " " + value);
+ }
+ return p;
+ }
+ Logging.addParseMessage(Logging.LST_ERROR, "Illegal Choice Token '"
+ + key + "' '" + value + "'");
+ return null;
+ }
+
+// public <T extends CDOMObject> PrimitiveChoiceSet<T> getChoiceSet(
+// LoadContext context, Class<T> poClass, String joinedOr)
+// {
+// if (joinedOr.equals(Constants.LST_ANY) || joinedOr.equals(Constants.LST_ALL))
+// {
+// /*
+// * TODO Categorized items break here :(
+// */
+// return new AnyChoiceSet<T>(poClass);
+// }
+// List<PrimitiveChoiceSet<T>> orList = new ArrayList<PrimitiveChoiceSet<T>>();
+// List<PrimitiveChoiceFilter<T>> pcfOrList = new ArrayList<PrimitiveChoiceFilter<T>>();
+// for (ChooseSeparator pipe = new ChooseSeparator(joinedOr, '|'); pipe
+// .hasNext();)
+// {
+// String joinedAnd = pipe.next();
+// List<PrimitiveChoiceSet<T>> andList = new ArrayList<PrimitiveChoiceSet<T>>();
+// List<PrimitiveChoiceFilter<T>> pcfAndList = new ArrayList<PrimitiveChoiceFilter<T>>();
+// for (ChooseSeparator comma = new ChooseSeparator(joinedAnd, ','); comma
+// .hasNext();)
+// {
+// String primitive = comma.next();
+// ChooseLstQualifierToken<T> qual = getQualifier(context, poClass, primitive);
+// if (qual == null)
+// {
+// PrimitiveChoiceFilter<T> pcf = getPrimitive(context, poClass,
+// primitive);
+// if (pcf == null)
+// {
+// Logging.addParseMessage(Logging.LST_ERROR,
+// "Choice argument was not valid : " + primitive);
+// return null;
+// }
+// else
+// {
+// pcfAndList.add(pcf);
+// }
+// }
+// else
+// {
+// andList.add(qual);
+// }
+// }
+// if (!pcfAndList.isEmpty())
+// {
+// if (pcfAndList.size() == 1 && andList.isEmpty())
+// {
+// pcfOrList.add(pcfAndList.get(0));
+// }
+// else
+// {
+// RetainingChooser<T> ret = new RetainingChooser<T>(poClass);
+// ret.addRetainingChoiceFilter(new CompoundAndFilter<T>(pcfAndList));
+// andList.add(ret);
+// }
+// }
+// if (andList.size() == 1)
+// {
+// orList.add(andList.get(0));
+// }
+// else if (!andList.isEmpty())
+// {
+// orList.add(new CompoundAndChoiceSet<T>(andList));
+// }
+// }
+// if (!pcfOrList.isEmpty())
+// {
+// RetainingChooser<T> ret = new RetainingChooser<T>(poClass);
+// ret.addAllRetainingChoiceFilters(pcfOrList);
+// orList.add(ret);
+// }
+// if (orList.isEmpty())
+// {
+// return null;
+// }
+// else if (orList.size() == 1)
+// {
+// return orList.get(0);
+// }
+// else
+// {
+// return new CompoundOrChoiceSet<T>(orList);
+// }
+// }
+//
+// public <T extends CDOMObject> PrimitiveChoiceFilter<T> getPrimitive(
+// LoadContext context, Class<T> cl, String key)
+// {
+// int openBracketLoc = key.indexOf('[');
+// int closeBracketLoc = key.indexOf(']');
+// int equalLoc = key.indexOf('=');
+// String tokKey;
+// String tokValue;
+// String tokRestriction;
+// if (openBracketLoc == -1)
+// {
+// if (closeBracketLoc != -1)
+// {
+// Logging.errorPrint("Found error in Primitive Choice: " + key
+// + " has a close bracket but no open bracket");
+// return null;
+// }
+// if (equalLoc == -1)
+// {
+// tokKey = key;
+// tokValue = null;
+// }
+// else
+// {
+// tokKey = key.substring(0, equalLoc);
+// tokValue = key.substring(equalLoc + 1);
+// }
+// tokRestriction = null;
+// }
+// else
+// {
+// if (closeBracketLoc == -1)
+// {
+// Logging.errorPrint("Found error in Primitive Choice: " + key
+// + " has an open bracket but no close bracket");
+// return null;
+// }
+// if (closeBracketLoc != key.length() - 1)
+// {
+// Logging.errorPrint("Found error in Primitive Choice: " + key
+// + " had close bracket, but had characters "
+// + "following the close bracket");
+// return null;
+// }
+// if (equalLoc == -1 || equalLoc > openBracketLoc)
+// {
+// tokKey = key.substring(0, openBracketLoc);
+// tokValue = null;
+// tokRestriction = key.substring(openBracketLoc + 1,
+// closeBracketLoc);
+// }
+// else
+// {
+// tokKey = key.substring(0, equalLoc);
+// tokValue = key.substring(equalLoc + 1, openBracketLoc);
+// tokRestriction = key.substring(openBracketLoc + 1,
+// closeBracketLoc);
+// }
+// }
+// PrimitiveToken<T> prim = TokenLibrary.getPrimitive(cl, tokKey);
+// if (prim == null)
+// {
+// if (tokRestriction != null)
+// {
+// Logging.errorPrint("Didn't expect tokRestriction here: "
+// + tokRestriction);
+// }
+// if ("TYPE".equals(tokKey))
+// {
+// return TokenUtilities.getTypeReference(context, cl, tokValue);
+// }
+// else if ("!TYPE".equals(tokKey))
+// {
+// return new NegatingFilter<T>(TokenUtilities.getTypeReference(
+// context, cl, tokValue));
+// }
+// if (tokValue != null)
+// {
+// Logging.errorPrint("Didn't expect Arguments here: " + tokValue);
+// }
+// if (key.startsWith(Constants.LST_TYPE_OLD))
+// {
+// return TokenUtilities.getTypeReference(context, cl, key
+// .substring(5));
+// }
+// else if (key.startsWith(Constants.LST_NOT_TYPE_OLD))
+// {
+// return new NegatingFilter<T>(TokenUtilities.getTypeReference(
+// context, cl, key.substring(6)));
+// }
+// if (key.indexOf('%') != -1)
+// {
+// return new PatternMatchFilter<T>(cl, key);
+// }
+// else
+// {
+// return context.ref.getCDOMReference(cl, key);
+// }
+// }
+// else
+// {
+// if (!prim.initialize(context, tokValue, tokRestriction))
+// {
+// return null;
+// }
+// }
+// return prim;
+// }
+//
+// public <T extends CDOMObject> ChooseLstQualifierToken<T> getQualifier(
+// LoadContext loadContext, Class<T> cl, String key)
+// {
+// int openBracketLoc = key.indexOf('[');
+// int closeBracketLoc = key.indexOf(']');
+// int equalLoc = key.indexOf('=');
+// String tokKey;
+// String tokValue;
+// String tokRestriction;
+// if (openBracketLoc == -1)
+// {
+// if (closeBracketLoc != -1)
+// {
+// Logging.errorPrint("Found error in Primitive Choice: " + key
+// + " has a close bracket but no open bracket");
+// return null;
+// }
+// if (equalLoc == -1)
+// {
+// tokKey = key;
+// tokValue = null;
+// }
+// else
+// {
+// tokKey = key.substring(0, equalLoc);
+// tokValue = key.substring(equalLoc + 1);
+// }
+// tokRestriction = null;
+// }
+// else
+// {
+// if (closeBracketLoc == -1)
+// {
+// Logging.errorPrint("Found error in Primitive Choice: " + key
+// + " has an open bracket but no close bracket");
+// return null;
+// }
+// if (closeBracketLoc != key.length() - 1)
+// {
+// Logging.errorPrint("Found error in Primitive Choice: " + key
+// + " had close bracket, but had characters "
+// + "following the close bracket");
+// return null;
+// }
+// if (equalLoc == -1 || equalLoc > openBracketLoc)
+// {
+// tokKey = key.substring(0, openBracketLoc);
+// tokValue = null;
+// tokRestriction = key.substring(openBracketLoc + 1,
+// closeBracketLoc);
+// }
+// else
+// {
+// tokKey = key.substring(0, equalLoc);
+// tokValue = key.substring(equalLoc + 1, openBracketLoc);
+// tokRestriction = key.substring(openBracketLoc + 1,
+// closeBracketLoc);
+// }
+// }
+// for (Iterator<ChooseLstQualifierToken<T>> it = new QualifierTokenIterator<T, ChooseLstQualifierToken<T>>(
+// cl, tokKey); it.hasNext();)
+// {
+// ChooseLstQualifierToken<T> token = it.next();
+// if (token.initialize(loadContext, cl, tokValue, tokRestriction))
+// {
+// return token;
+// }
+// Logging.addParseMessage(Logging.LST_ERROR,
+// "Failed in parsing typeStr: " + key);
+// }
+// return null;
+// }
+//
+// public <T extends CDOMObject> PrimitiveChoiceSet<?> getChoiceSet(LoadContext loadContext,
+// T cdo, String key, String val) throws PersistenceLayerException
+// {
+// Class<T> cl = (Class<T>) cdo.getClass();
+//
+// for (Iterator<ChoiceSetToken<? super T>> it = new ChooseTokenIterator<T>(
+// cl, key); it.hasNext();)
+// {
+// ChoiceSetToken<? super T> token = it.next();
+// PrimitiveChoiceSet<?> ret = token.parse(loadContext, cdo, val);
+// if (ret != null)
+// {
+// return ret;
+// }
+// Logging.addParseMessage(Logging.LST_ERROR,
+// "Failed in parsing typeStr: " + key + " " + val);
+// }
+// /*
+// * CONSIDER Better option than toString, given that T != CDOMObject
+// */
+// Logging.addParseMessage(Logging.LST_ERROR, "Illegal subtoken '" + key
+// + "' '" + val + "' for " + cdo.toString());
+// return null;
+// }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/persistence/TokenUtilities.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/persistence/TokenUtilities.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/persistence/TokenUtilities.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.rules.persistence;
+
+import java.util.Comparator;
+
+import pcgen.cdom.base.CDOMObject;
+import pcgen.cdom.base.CDOMReference;
+import pcgen.cdom.base.Constants;
+import pcgen.cdom.base.LSTWriteable;
+import pcgen.cdom.reference.CDOMSingleRef;
+import pcgen.rules.context.LoadContext;
+import pcgen.util.Logging;
+
+public final class TokenUtilities
+{
+
+ public static final Comparator<LSTWriteable> WRITEABLE_SORTER =
+ new Comparator<LSTWriteable>()
+ {
+
+ public int compare(LSTWriteable arg0, LSTWriteable arg1)
+ {
+ return compareWriteable(arg0, arg1);
+ }
+ };
+
+ public static final Comparator<CDOMReference<?>> REFERENCE_SORTER =
+ new Comparator<CDOMReference<?>>()
+ {
+
+ public int compare(CDOMReference<?> arg0, CDOMReference<?> arg1)
+ {
+ return compareRefs(arg0, arg1);
+ }
+ };
+
+// public static final Comparator<CategorizedCDOMReference<?>> CAT_REFERENCE_SORTER =
+// new Comparator<CategorizedCDOMReference<?>>()
+// {
+//
+// public int compare(CategorizedCDOMReference<?> arg0,
+// CategorizedCDOMReference<?> arg1)
+// {
+// if (arg0 instanceof CDOMSingleRef)
+// {
+// if (!(arg1 instanceof CDOMSingleRef))
+// {
+// return -1;
+// }
+// return arg0.getName().compareTo(arg1.getName());
+// }
+// if (arg1 instanceof CDOMSingleRef)
+// {
+// return 1;
+// }
+// return arg0.getName().compareTo(arg1.getName());
+// }
+// };
+
+ private TokenUtilities()
+ {
+ // Can't instantiate utility classes
+ }
+
+ public static <T extends CDOMObject> CDOMReference<T> getTypeOrPrimitive(
+ LoadContext context, Class<T> cl, String s)
+ {
+ if (s.startsWith(Constants.LST_TYPE_OLD)
+ || s.startsWith(Constants.LST_TYPE))
+ {
+ return getTypeReference(context, cl, s.substring(5));
+ }
+ else
+ {
+ return context.ref.getCDOMReference(cl, s);
+ }
+ }
+
+ public static <T extends CDOMObject> CDOMReference<T> getTypeReference(
+ LoadContext context, Class<T> cl, String subStr)
+ {
+ if (subStr.length() == 0)
+ {
+ Logging.errorPrint("Type may not be empty in: " + subStr);
+ return null;
+ }
+ if (subStr.charAt(0) == '.'
+ || subStr.charAt(subStr.length() - 1) == '.')
+ {
+ Logging
+ .errorPrint("Type may not start or end with . in: " + subStr);
+ return null;
+ }
+ String[] types = subStr.split("\\.");
+ for (String type : types)
+ {
+ if (type.length() == 0)
+ {
+ Logging.errorPrint("Attempt to acquire empty Type "
+ + "(the type String contains '..') in: " + subStr);
+ return null;
+ }
+ }
+ return context.ref.getCDOMTypeReference(cl, types);
+ }
+
+// public static <T extends CDOMObject & CategorizedCDOMObject<T>> CDOMReference<T> getTypeOrPrimitive(
+// LoadContext context, Class<T> cl, Category<T> cat, String s)
+// {
+// if (s.startsWith(Constants.LST_TYPE_OLD)
+// || s.startsWith(Constants.LST_TYPE))
+// {
+// String subStr = s.substring(5);
+// if (subStr.length() == 0)
+// {
+// Logging.errorPrint("Type may not be empty in: " + s);
+// return null;
+// }
+// if (subStr.charAt(0) == '.'
+// || subStr.charAt(subStr.length() - 1) == '.')
+// {
+// Logging.errorPrint("Type may not start or end with . in: " + s);
+// return null;
+// }
+// String[] types = subStr.split("\\.");
+// for (String type : types)
+// {
+// if (type.length() == 0)
+// {
+// Logging
+// .errorPrint("Attempt to acquire empty Type in: " + s);
+// return null;
+// }
+// }
+// return context.ref.getCDOMTypeReference(cl, cat, types);
+// }
+// else
+// {
+// return context.ref.getCDOMReference(cl, cat, s);
+// }
+// }
+//
+ public static int compareRefs(CDOMReference<?> arg0, CDOMReference<?> arg1)
+ {
+ if (arg0 instanceof CDOMSingleRef)
+ {
+ if (!(arg1 instanceof CDOMSingleRef))
+ {
+ return -1;
+ }
+ return arg0.getName().compareTo(arg1.getName());
+ }
+ if (arg1 instanceof CDOMSingleRef)
+ {
+ return 1;
+ }
+ return arg0.getName().compareTo(arg1.getName());
+ }
+
+ public static int compareWriteable(LSTWriteable arg0, LSTWriteable arg1)
+ {
+ if (arg0 instanceof CDOMSingleRef || arg0 instanceof CDOMObject)
+ {
+ if (!(arg1 instanceof CDOMSingleRef || arg1 instanceof CDOMObject))
+ {
+ return -1;
+ }
+ return compareLSTformats(arg0, arg1);
+ }
+ if (arg1 instanceof CDOMSingleRef)
+ {
+ return 1;
+ }
+ /*
+ * BUG TODO This is NOT Consistent with equals :(
+ */
+ return compareLSTformats(arg0, arg1);
+ }
+
+ private static int compareLSTformats(LSTWriteable arg0, LSTWriteable arg1)
+ {
+ String base = arg0.getLSTformat();
+ if (base == null)
+ {
+ if (arg1.getLSTformat() == null)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ if (arg1.getLSTformat() == null)
+ {
+ return 1;
+ }
+ else
+ {
+ return base.compareTo(arg1.getLSTformat());
+ }
+ }
+ }
+
+// public static <T extends CDOMObject> CDOMReference<T> getCompoundReference(
+// LoadContext context, Class<T> cl, String value)
+// {
+// if (value == null || value.length() == 0)
+// {
+// Logging
+// .errorPrint("Compound Reference arguments may not be empty : "
+// + value);
+// return null;
+// }
+// if (value.indexOf(',') == -1)
+// {
+// return getTypeOrPrimitive(context, cl, value);
+// }
+// if (value.charAt(0) == ',')
+// {
+// Logging
+// .errorPrint("Compound Reference arguments may not start with , : "
+// + value);
+// return null;
+// }
+// if (value.charAt(value.length() - 1) == ',')
+// {
+// Logging
+// .errorPrint("Compound Reference arguments may not end with , : "
+// + value);
+// return null;
+// }
+// if (value.indexOf(",,") != -1)
+// {
+// Logging
+// .errorPrint("Compound Reference arguments uses double separator ,, : "
+// + value);
+// return null;
+// }
+// StringTokenizer st = new StringTokenizer(value, ",");
+// CDOMCompoundAndReference<T> andRef =
+// new CDOMCompoundAndReference<T>(cl, value);
+// while (st.hasMoreTokens())
+// {
+// String tokString = st.nextToken();
+// // TODO Need to implement !TYPE parsing and how that is handled in
+// // the CompoundReference
+// CDOMReference<T> ref = getTypeOrPrimitive(context, cl, tokString);
+// if (ref == null)
+// {
+// Logging
+// .errorPrint("Compound Reference arguments has invalid reference : "
+// + tokString);
+// return null;
+// }
+// andRef.addReference(ref);
+// }
+// return andRef;
+// }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMPrimaryToken.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMPrimaryToken.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMPrimaryToken.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.rules.persistence.token;
+
+import pcgen.rules.context.LoadContext;
+
+public interface CDOMPrimaryToken<T> extends CDOMToken<T>
+{
+ public String[] unparse(LoadContext context, T obj);
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMSecondaryToken.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMSecondaryToken.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMSecondaryToken.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.rules.persistence.token;
+
+import pcgen.rules.context.LoadContext;
+
+public interface CDOMSecondaryToken<T> extends CDOMToken<T>, CDOMSubToken<T>
+{
+ public String[] unparse(LoadContext context, T obj);
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMSubToken.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMSubToken.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMSubToken.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,7 @@
+package pcgen.rules.persistence.token;
+
+
+public interface CDOMSubToken<T> extends CDOMToken<T>
+{
+ public String getParentToken();
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMToken.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMToken.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/CDOMToken.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2007 (C) Tom Parker <thpr@...>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package pcgen.rules.persistence.token;
+
+import pcgen.persistence.PersistenceLayerException;
+import pcgen.persistence.lst.LstToken;
+import pcgen.rules.context.LoadContext;
+
+public interface CDOMToken<T> extends LstToken
+{
+ public boolean parse(LoadContext context, T obj, String value)
+ throws PersistenceLayerException;
+
+ public Class<T> getTokenClass();
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/PreCompatibilityToken.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/PreCompatibilityToken.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/persistence/token/PreCompatibilityToken.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,122 @@
+/**
+ *
+ */
+package pcgen.rules.persistence.token;
+
+import java.io.StringWriter;
+import java.util.Set;
+import java.util.TreeSet;
+
+import pcgen.cdom.base.ConcretePrereqObject;
+import pcgen.core.prereq.Prerequisite;
+import pcgen.persistence.PersistenceLayerException;
+import pcgen.persistence.lst.output.prereq.PrerequisiteWriterFactory;
+import pcgen.persistence.lst.output.prereq.PrerequisiteWriterInterface;
+import pcgen.persistence.lst.prereq.PrerequisiteParserInterface;
+import pcgen.rules.context.Changes;
+import pcgen.rules.context.LoadContext;
+
+public class PreCompatibilityToken implements
+ CDOMPrimaryToken<ConcretePrereqObject>,
+ CDOMSecondaryToken<ConcretePrereqObject>
+{
+ private static PrerequisiteWriterFactory factory = PrerequisiteWriterFactory
+ .getInstance();
+
+ private final String tokenRoot;
+ private final String tokenName;
+ private final PrerequisiteParserInterface token;
+ private final boolean invert;
+
+ public PreCompatibilityToken(String s,
+ PrerequisiteParserInterface prereqToken, boolean inv)
+ {
+ tokenRoot = s.toUpperCase();
+ token = prereqToken;
+ invert = inv;
+ tokenName = (invert ? "!" : "") + "PRE" + tokenRoot;
+ }
+
+ public Class<ConcretePrereqObject> getTokenClass()
+ {
+ return ConcretePrereqObject.class;
+ }
+
+ public boolean parse(LoadContext context, ConcretePrereqObject obj,
+ String value) throws PersistenceLayerException
+ {
+ Prerequisite p = token.parse(tokenRoot, value, invert, false);
+ if (p == null)
+ {
+ return false;
+ }
+ context.obj.put(obj, p);
+ return true;
+ }
+
+ public String getTokenName()
+ {
+ return tokenName;
+ }
+
+ public int compatibilityLevel()
+ {
+ return 5;
+ }
+
+ public int compatibilityPriority()
+ {
+ return 0;
+ }
+
+ public int compatibilitySubLevel()
+ {
+ return 14;
+ }
+
+ public String getParentToken()
+ {
+ return "*KITTOKEN";
+ }
+
+ public String[] unparse(LoadContext context, ConcretePrereqObject obj)
+ {
+ Set<String> set = new TreeSet<String>();
+ Changes<Prerequisite> changes = context.obj.getPrerequisiteChanges(obj);
+ if (changes == null || changes.isEmpty())
+ {
+ return null;
+ }
+ for (Prerequisite p : changes.getAdded())
+ {
+ String kind = p.getKind();
+ if (kind == null || kind.regionMatches(true, 0, tokenRoot, 0, Math.min(tokenRoot
+ .length(), kind.length())))
+ {
+ final StringWriter capture = new StringWriter();
+ try
+ {
+ PrerequisiteWriterInterface writer = factory
+ .getWriter(kind);
+ writer.write(capture, p);
+ }
+ catch (PersistenceLayerException e)
+ {
+ e.printStackTrace();
+ }
+ String output = capture.toString();
+ int colonLoc = output.indexOf(':');
+ if (tokenName.equalsIgnoreCase(output.substring(0, colonLoc)))
+ {
+ set.add(output.substring(colonLoc + 1));
+ }
+ }
+ }
+ if (set.isEmpty())
+ {
+ return null;
+ }
+ return set.toArray(new String[set.size()]);
+ }
+
+}
\ No newline at end of file
Added: Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/Revision.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/Revision.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/Revision.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,54 @@
+/**
+ *
+ */
+package pcgen.rules.persistence.util;
+
+class Revision implements Comparable<Revision>
+{
+ private final int primarySequence;
+ private final int secondarySequence;
+ private final int tertiarySequence;
+
+ public Revision(int a, int b, int c)
+ {
+ primarySequence = a;
+ secondarySequence = b;
+ tertiarySequence = c;
+ }
+
+ public int compareTo(Revision r)
+ {
+ if (primarySequence > r.primarySequence)
+ {
+ return -1;
+ }
+ else if (primarySequence < r.primarySequence)
+ {
+ return 1;
+ }
+ else if (secondarySequence > r.secondarySequence)
+ {
+ return -1;
+ }
+ else if (secondarySequence < r.secondarySequence)
+ {
+ return 1;
+ }
+ else if (tertiarySequence > r.tertiarySequence)
+ {
+ return -1;
+ }
+ else if (tertiarySequence < r.tertiarySequence)
+ {
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override
+ public String toString()
+ {
+ return primarySequence + "." + secondarySequence + "-"
+ + tertiarySequence;
+ }
+}
\ No newline at end of file
Added: Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/TokenFamily.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/TokenFamily.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/TokenFamily.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,225 @@
+package pcgen.rules.persistence.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import pcgen.base.lang.CaseInsensitiveString;
+import pcgen.base.lang.UnreachableError;
+import pcgen.base.util.DoubleKeyMap;
+import pcgen.base.util.TripleKeyMap;
+import pcgen.persistence.lst.prereq.PrerequisiteParserInterface;
+import pcgen.rules.persistence.token.CDOMSubToken;
+import pcgen.rules.persistence.token.CDOMToken;
+
+public class TokenFamily implements Comparable<TokenFamily>
+{
+
+ public static final TokenFamily CURRENT = new TokenFamily(new Revision(
+ Integer.MAX_VALUE, 0, 0));
+
+ public static final TokenFamily REV514 = new TokenFamily(new Revision(5,
+ 14, Integer.MIN_VALUE));
+
+ /**
+ * The Map of Constants
+ */
+ private static SortedMap<Revision, TokenFamily> typeMap;
+
+ /**
+ * The name of this Constant
+ */
+ private final Revision rev;
+
+ private final DoubleKeyMap<Class<?>, String, CDOMToken<?>> tokenMap = new DoubleKeyMap<Class<?>, String, CDOMToken<?>>();
+
+ private static final TripleKeyMap<Class<?>, String, String, CDOMSubToken<?>> subTokenMap = new TripleKeyMap<Class<?>, String, String, CDOMSubToken<?>>();
+
+// private final DoubleKeyMap<Class<?>, String, ChoiceSetToken> chooseTokenMap = new DoubleKeyMap<Class<?>, String, ChoiceSetToken>();
+
+ private final Map<CaseInsensitiveString, PrerequisiteParserInterface> preTokenMap = new HashMap<CaseInsensitiveString, PrerequisiteParserInterface>();
+
+ private TokenFamily(Revision r)
+ {
+ rev = r;
+ }
+
+ public <T> CDOMToken<T> putToken(CDOMToken<T> tok)
+ {
+ return (CDOMToken<T>) tokenMap.put(tok.getTokenClass(), tok
+ .getTokenName(), tok);
+ }
+
+ public CDOMToken<?> getToken(Class<?> cl, String name)
+ {
+ return tokenMap.get(cl, name);
+ }
+
+ public Set<CDOMToken<?>> getTokens(Class<?> cl)
+ {
+ return tokenMap.values(cl);
+ }
+
+ public <U, T extends CDOMSubToken<U>> void putSubToken(T tok)
+ {
+ subTokenMap.put(tok.getTokenClass(), tok.getParentToken(), tok
+ .getTokenName(), tok);
+ }
+
+ public <T> CDOMSubToken<T> getSubToken(Class<? extends T> cl, String token,
+ String key)
+ {
+ return (CDOMSubToken<T>) subTokenMap.get(cl, token, key);
+ }
+
+ public Set<CDOMSubToken<?>> getSubTokens(Class<?> cl, String token)
+ {
+ return subTokenMap.values(cl, token);
+ }
+
+// public void putChooseToken(ChoiceSetToken<?> token)
+// {
+// chooseTokenMap.put(token.getTokenClass(), token.getTokenName(), token);
+// }
+//
+// public <T> ChoiceSetToken<T> getChooseToken(Class<T> cl, String key)
+// {
+// return chooseTokenMap.get(cl, key);
+// }
+
+ public void putPrerequisiteToken(PrerequisiteParserInterface token)
+ {
+ for (String s : token.kindsHandled())
+ {
+ preTokenMap.put(new CaseInsensitiveString(s), token);
+ }
+ }
+
+ public PrerequisiteParserInterface getPrerequisiteToken(String key)
+ {
+ return preTokenMap.get(new CaseInsensitiveString(key));
+ }
+
+ /**
+ * Constructs a new SequencedConstant with the given String as the Constant
+ * name and the given integer as the Sequence
+ *
+ * @param s
+ * The String to be used as the SequencedConstants name
+ * @return The new SequencedConstant built with the given name and sequence
+ * number
+ */
+ public static TokenFamily getConstant(int primary, int secondary,
+ int tertiary)
+ {
+ if (typeMap == null)
+ {
+ buildMap();
+ }
+ Revision r = new Revision(primary, secondary, tertiary);
+ TokenFamily o = typeMap.get(r);
+ if (o == null)
+ {
+ o = new TokenFamily(r);
+ typeMap.put(r, o);
+ }
+ return o;
+ }
+
+ /**
+ * Actually build the set of Constants, using any "public static final"
+ * constants within the child (extending) class as initial values in the
+ * Constant pool.
+ */
+ private static void buildMap()
+ {
+ typeMap = new TreeMap<Revision, TokenFamily>();
+ Class<TokenFamily> cl = TokenFamily.class;
+ Field[] fields = cl.getDeclaredFields();
+ for (int i = 0; i < fields.length; i++)
+ {
+ int mod = fields[i].getModifiers();
+
+ if (Modifier.isStatic(mod) && Modifier.isFinal(mod)
+ && Modifier.isPublic(mod))
+ {
+ try
+ {
+ Object o = fields[i].get(null);
+ if (cl.equals(o.getClass()))
+ {
+ TokenFamily tObj = cl.cast(o);
+ if (typeMap.containsKey(tObj.rev))
+ {
+ throw new UnreachableError(
+ "Attempt to redefine constant value "
+ + tObj.rev + " to "
+ + fields[i].getName()
+ + ", value was "
+ + typeMap.get(tObj.rev));
+ }
+ typeMap.put(tObj.rev, tObj);
+ }
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new InternalError();
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new InternalError();
+ }
+ }
+ }
+ }
+
+ /**
+ * Clears all of the Constants defined by this class. Note that this does
+ * not remove any Constants declared in the Constant class (as those are
+ * considered 'permanent' members of the Sequenced Constant collection.
+ *
+ * Note that this *will not* reset the ordinal count, because that is a
+ * dangerous operation. As there could be outstanding references to
+ * constants that would be removed from the Constant pool, no reuse of
+ * ordinals is driven by this method. As a result, calling this method may
+ * result in a Constant Pool which does not have sequentially numbered
+ * ordinal values.
+ */
+ public static void clearConstants()
+ {
+ buildMap();
+ }
+
+ /**
+ * Returns a Collection of all of the Constants for this class. The returned
+ * Collection is unmodifiable.
+ *
+ * @return an unmodifiable Collection of all of the Constants for this class
+ */
+ public static Collection<TokenFamily> getAllConstants()
+ {
+ return Collections.unmodifiableCollection(typeMap.values());
+ }
+
+ public int compareTo(TokenFamily tf)
+ {
+ return rev.compareTo(tf.rev);
+ }
+
+ /*
+ * Note there is no reason to do .hashCode or .equals because this is Type
+ * Safe (meaning it can only build one object per Revision)
+ */
+
+ @Override
+ public String toString()
+ {
+ return "Token Family: " + rev.toString();
+ }
+}
Added: Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/TokenFamilyIterator.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/TokenFamilyIterator.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/TokenFamilyIterator.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,95 @@
+/**
+ *
+ */
+package pcgen.rules.persistence.util;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import pcgen.rules.persistence.token.CDOMPrimaryToken;
+import pcgen.rules.persistence.token.CDOMToken;
+
+public class TokenFamilyIterator<C> implements
+ Iterator<CDOMPrimaryToken<? super C>>
+{
+ private static final Class<Object> OBJECT_CLASS = Object.class;
+ private CDOMPrimaryToken<? super C> nextToken = null;
+ private boolean needNewToken = true;
+ private Class<?> actingClass;
+ private Iterator<CDOMToken<?>> subIterator;
+ private Set<String> used = new HashSet<String>();
+
+ public TokenFamilyIterator(Class<C> cl)
+ {
+ actingClass = cl;
+ subIterator = TokenFamily.CURRENT.getTokens(cl).iterator();
+ }
+
+ public CDOMPrimaryToken<? super C> next()
+ {
+ setNext();
+ if (nextToken == null)
+ {
+ throw new NoSuchElementException();
+ }
+ needNewToken = true;
+ return nextToken;
+ }
+
+ private void setNext()
+ {
+ if (needNewToken)
+ {
+ nextToken = getNext();
+ if (nextToken != null)
+ {
+ String tokenName = nextToken.getTokenName();
+ if (used.contains(tokenName))
+ {
+ /*
+ * Don't use a super-class token in write
+ */
+ setNext();
+ }
+ else
+ {
+ used.add(nextToken.getTokenName());
+ }
+ }
+ }
+ }
+
+ private CDOMPrimaryToken<? super C> getNext()
+ {
+ needNewToken = false;
+ while (subIterator.hasNext())
+ {
+ CDOMToken<?> tok = subIterator.next();
+ if (tok instanceof CDOMPrimaryToken)
+ {
+ return (CDOMPrimaryToken<? super C>) tok;
+ }
+ }
+ if (OBJECT_CLASS.equals(actingClass))
+ {
+ return null;
+ }
+ actingClass = actingClass.getSuperclass();
+ subIterator = TokenFamily.CURRENT.getTokens(actingClass).iterator();
+ return getNext();
+ }
+
+ public boolean hasNext()
+ {
+ setNext();
+ return nextToken != null;
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException(
+ "Iterator does not support remove");
+ }
+}
\ No newline at end of file
Added: Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/TokenFamilySubIterator.java
===================================================================
--- Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/TokenFamilySubIterator.java (rev 0)
+++ Trunk/pcgen/code/src/java/pcgen/rules/persistence/util/TokenFamilySubIterator.java 2008-05-07 01:56:34 UTC (rev 6205)
@@ -0,0 +1,100 @@
+/**
+ *
+ */
+package pcgen.rules.persistence.util;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import pcgen.rules.persistence.token.CDOMSecondaryToken;
+import pcgen.rules.persistence.token.CDOMSubToken;
+import pcgen.rules.persistence.token.CDOMToken;
+
+public class TokenFamilySubIterator<C> implements
+ Iterator<CDOMSecondaryToken<? super C>>
+{
+ private static final Class<Object> OBJECT_CLASS = Object.class;
+ private CDOMSecondaryToken<? super C> nextToken = null;
+ private boolean needNewToken = true;
+ private Class<?> actingClass;
+ private final String parentToken;
+ private Iterator<CDOMSubToken<?>> subIterator;
+ private Set<String> used = new HashSet<String>();
+
+ public TokenFamilySubIterator(Class<C> cl, String parentName)
+ {
+ actingClass = cl;
+ parentToken = parentName;
+ subIterator = TokenFamily.CURRENT.getSubTokens(cl, parentToken)
+ .iterator();
+ }
+
+ public CDOMSecondaryToken<? super C> next()
+ {
+ setNext();
+ if (nextToken == null)
+ {
+ throw new NoSuchElementException();
+ }
+ needNewToken = true;
+ return nextToken;
+ }
+
+ private void setNext()
+ {
+ if (needNewToken)
+ {
+ nextToken = getNext();
+ if (nextToken != null)
+ {
+ String tokenName = nextToken.getTokenName();
+ if (used.contains(tokenName))
+ {
+ /*
+ * Don't use a super-class token in write
+ */
+ setNext();
+ }
+ else
+ {
+ used.add(nextToken.getTokenName());
+ }
+ }
+ }
+ }
+
+ private CDOMSecondaryToken<? super C> getNext()
+ {
+ needNewToken = false;
+ while (subIterator.hasNext())
+ {
+ CDOMToken<?> tok = subIterator.next();
+ if (tok instanceof CDOMSecondaryToken)
+ {
+ return (CDOMSecondaryToken<? super C>) tok;
+ }
+ }
+ if (OBJECT_CLASS.equals(actingClass))
+ {
+ return null;
+ }
+ actingClass = actingClass.getSuperclass();
+ subIterator = TokenFamily.CURRENT
+ .getSubTokens(actingClass, parentToken).iterator();
+ return getNext();
+ }
+
+ public boolean hasNext()
+ {
+ setNext();
+ return nextToken != null;
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException(
+ "Iterator does not support remove");
+ }
+}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|