[jboss-cvs] JBossAS SVN: r68604 - in projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint: graph and 7 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Thu Jan 3 14:07:18 EST 2008
Author: flavia.rainone at jboss.com
Date: 2008-01-03 14:07:18 -0500 (Thu, 03 Jan 2008)
New Revision: 68604
Added:
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/ExtendedLengthRange.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/InternalNode.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/KeyPart.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/LeafNode.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/Node.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/SlotCollection.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/SlotFlagSystem.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/Tree.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/insertion/
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/insertion/InsertionKey.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/insertion/package.html
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/package.html
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/Flags.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/SearchKey.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/PrefixFunctionImpl.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/PrefixFunctionLoader.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/package.html
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/ComparableElement.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/ComparableElementFactory.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/package.html
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/Comparable.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparableFactory.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonAlgorithm.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonEndState.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonResult.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonStart.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonStartState.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/Index.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/LengthRange.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/LengthRestriction.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/Matcher.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatcherFactory.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatcherProfile.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatcherSequenceProfile.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatchingResult.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatchingState.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/PrefixFunction.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/State.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/package.html
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/package.html
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/ComparableKeyPart.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/ComparableKeyPartFactory.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/KeyPartIndex.java
projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/package.html
Log:
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/ExtendedLengthRange.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/ExtendedLengthRange.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/ExtendedLengthRange.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,103 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree;
+
+import org.jboss.aop.joinpoint.graph.tree.search.match.LengthRange;
+
+/**
+ * <b>Despite being public, this class is meant for internal use of the
+ * tree only.</b><p>
+ * Extends <code>LengthRange</code> by adding element length range info.
+ * <p>
+ * Every key part has a length range associated with it, that stores info about
+ * its suffixes and post-prefixes length. If its last element is not complete,
+ * not only the key part has suffixes, as the last element also has. These
+ * suffixes are the first element of the key part suffixes. In such case, the
+ * key part needs to store its length range info and the length range info of
+ * its last element. So, this class is used by key part when its last element is
+ * incomplete.
+ *
+ * @author Flavia Rainone
+ * @see KeyPart
+ * @see LengthRange
+ */
+public class ExtendedLengthRange extends LengthRange
+{
+ /**
+ * The length range of the last (and incomplete) element of a key part.
+ */
+ private LengthRange elementLengthRange;
+
+ /**
+ * Construtor. Creates an instance to be associated with a specific <code>
+ * KeyPart</code> instance.
+ *
+ * @param length the length of the key part
+ * @param postPrefixMinLength the minimum length of the key part
+ * post-prefixes
+ * @param postPrefixMaxLength the maximum length of the key part
+ * post-prefixes
+ * @param elementLengthRange the length range of the last key part element
+ */
+ public ExtendedLengthRange(byte length, byte postPrefixMinLength,
+ byte postPrefixMaxLength, LengthRange elementLengthRange)
+ {
+ super(length, postPrefixMinLength, postPrefixMaxLength);
+ this.elementLengthRange = elementLengthRange;
+ }
+
+ /**
+ * Returns the length range of the last (and incomplete) element of the
+ * key part associated with this length range.
+ *
+ * @return the length range of the last (and incomplete) element of the
+ * key part associated with this length range
+ */
+ public final LengthRange getElementLengthRange()
+ {
+ return elementLengthRange;
+ }
+
+ /**
+ * Overwrites the superclass method because, since the key part has an
+ * incomplete last element, the length of one of its suffixes minus
+ * the correspondent post-prefix length is not equal to the key part length.
+ * <p>
+ * As the last element of the key part is not complete, the length of this
+ * key part concatenated with one of its suffixes is equal to the sum of
+ * its length with the suffix length subtracted by 1. Consequently, the
+ * difference between the suffix and the post-prefix length equals the key
+ * part length minus 1.
+ *
+ * @return the length of the key part minus 1
+ */
+ public byte getPostPrefix_SuffixDiff()
+ {
+ return (byte) (super.getLength() - 1);
+ }
+
+ public String toString()
+ {
+ return super.toString().substring(0, super.toString().length() - 1) +
+ ", " + this.elementLengthRange + "]";
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/InternalNode.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/InternalNode.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/InternalNode.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,117 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.aop.joinpoint.graph.tree;
+
+import java.util.Collection;
+
+import org.jboss.aop.joinpoint.graph.tree.insertion.InsertionKey;
+import org.jboss.aop.joinpoint.graph.tree.search.Flags;
+import org.jboss.aop.joinpoint.graph.tree.search.SearchKey;
+
+
+/**
+ * Internal node of the tree, represents a prefix common to all keys inserted
+ * in this node subtree.
+ * <p>
+ * Refer to the <i>Internal Tree Structure</i> section of
+ * {@link org.jboss.aop.joinpoint.graph.tree} for more information.
+ *
+ * @author Flavia Rainone
+ */
+class InternalNode<E> extends Node<E>
+{
+ /**
+ * The subnodes of this node.
+ */
+ private SlotCollection<Node<E>> children;
+
+ /**
+ * Creates a new internal node.
+ * <p>
+ * This method is invoked after a node is broken into two parts (prefix and
+ * suffix) because of a key insertion.
+ *
+ * @param keyPart the content of this node, the prefix part of the
+ * broken key part
+ * @param keyPartSuffix the suffix of <code>keyPart</code>, the second part
+ * of the broken key part
+ * @param newSuffix the new suffix of this node key part represents a key
+ * that is being inserted in the tree.
+ */
+ public InternalNode(KeyPart keyPart, Node<E> keyPartSuffix, Node<E> newSuffix)
+ {
+ super(keyPart);
+ keyPart.newSuffix(newSuffix.keyPart);
+ children = new SlotCollection<Node<E>>(keyPartSuffix,
+ keyPartSuffix.getIdentifier(), newSuffix,
+ newSuffix.getIdentifier());
+ }
+
+ /**
+ * Inserts <code>value</code>, identified by <code>insertionKey</code>, in
+ * one of the child nodes.
+ */
+ protected Node<E> internalInsert(InsertionKey insertionKey, E value)
+ {
+ char nextChar = insertionKey.getNextChar();
+ if (nextChar == InsertionKey.INSERTION_COMPLETE)
+ {
+ nextChar = KeyPart.KEY_ELEMENT_END;
+ }
+ children.loadSlot(nextChar);
+ if (!children.isSlotEmpty())
+ {
+ Node<E> child = children.getSlotContent();
+ child = child.insert(insertionKey, value);
+ children.replaceSlotContent(child);
+ keyPart.newSuffix(child.keyPart);
+
+ }
+ else
+ {
+ Node<E> newNode = new LeafNode<E>(insertionKey.toKeyPart(), value);
+ children.fillSlot(newNode);
+ keyPart.newSuffix(newNode.keyPart);
+ }
+ return this;
+ }
+
+ public void search(Collection<E> result, SearchKey searchKey)
+ {
+ char nextChar = searchKey.matches(super.keyPart);
+ //Collection result = new ArrayList();
+ if (nextChar == Flags.ALL)
+ {
+ Object[] all = children.getAllContents();
+ SearchKey wildcardSearchKey = searchKey.getWildcardInstance();
+ for (int i = 0; i < all.length; i++)
+ {
+ searchKey.prepareWildcardInstance(wildcardSearchKey);
+ // TODO refazer isso... força a criação de várias coleções...
+ // sugestão: colocar em Tree uma coleção e passá-la como
+ // argumento para os métodos search... uma coleção que pertence
+ // à Tree e que será sempre resetada, e não recriada.
+ /*result.addAll(*/((Node<E>) all[i]).search(result, wildcardSearchKey)/*)*/;
+ }
+ }
+ else if (nextChar != Flags.POSITIVE && nextChar != Flags.NEGATIVE)
+ {
+ children.loadSlot(nextChar);
+ if (!children.isSlotEmpty())
+ {
+ /*return */children.getSlotContent().search(result, searchKey);
+ }
+ }
+ //return result;
+ }
+
+ public String toString()
+ {
+ return "(" + this.keyPart + ", " + this.children + ")";
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/KeyPart.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/KeyPart.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/KeyPart.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,399 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.jboss.aop.joinpoint.graph.tree.search.match.LengthRange;
+
+
+/**
+ * <b>Despite being public, this class is meant for internal use of the
+ * tree only.</b><p>
+ * This class represents a part of a key contained in the tree.
+ * <p>
+ * Each tree node contains a key part. For more details, refer to the <i>
+ * Internal Tree Structure</i> section in {@link org.jboss.aop.joinpoint.graph.tree}.
+ *
+ * @author Flavia Rainone
+ * @see Tree
+ * @see org.jboss.aop.joinpoint.graph.tree
+ */
+public class KeyPart
+{
+ /**
+ * Empty key end, represents the end of a key.
+ * Used in cases where a key is a prefix of another one.
+ */
+ public static KeyPart EMPTY_KEY_END = new KeyPart(new String[0]);
+
+ /**
+ * Indicates the end of an element, utilized to identify key parts whose
+ * first element is an empty string and to identify <code>
+ * EMPTY_KEY_END</code>.
+ */
+ public static final char KEY_ELEMENT_END = '#';
+
+ /** Contains elements of a key. */
+ private String[] keyElements;
+
+ /**
+ * Indicates if the last element of <code>keyElements</code> is complete
+ * or is splitten.<p>
+ * If this value is </code>false</code>, there are more than one possible
+ * suffixes to this element on the tree. The possible endings of the last
+ * element can be found in the subnodes of the node containing this key part.
+ */
+ private boolean lastElementComplete;
+
+ /**
+ * The maximum-minimum range of this key part suffixes and post-prefixes.
+ *
+ * @see LengthRange
+ * @see ExtendedLengthRange
+ */
+ private LengthRange lengthRange;
+
+ /**
+ * Constructor. Creates a key part that contains <code>
+ * keyPartExpression</code>.
+ * @param keyPartExpression the element that will be represented by the
+ * instance created. This element is allowed to
+ * contain any valid Java class name character,
+ * besides the element separator char <code>'.'
+ * </code>. Should never end with <code>'.'</code>.
+ * TODO (new: nor even should it
+ * be an empty string? right?)
+ */
+ public KeyPart(String keyPartExpression)
+ {
+ // splits the key into keyElements
+ Collection keyElements = new ArrayList();
+ // split element
+ int begin = 0;
+ int end = keyPartExpression.indexOf('.');
+ while(end >= 0)
+ {
+ keyElements.add(keyPartExpression.substring(begin, end));
+ begin = end + 1;
+ end = keyPartExpression.indexOf('.', begin + 1);
+ }
+ if (begin >= 0)
+ {
+ keyElements.add(keyPartExpression.substring(begin));
+ }
+ // initialize fields
+ this.keyElements = new String[keyElements.size()];
+ this.keyElements = (String[]) keyElements.toArray(this.keyElements);
+ this.lastElementComplete = true;
+ this.lengthRange = new
+ LengthRange((byte) this.keyElements.length,
+ (byte) this.keyElements.length);
+ }
+
+ /**
+ * Private constructor, for internal use only.
+ *
+ * @param keyElements the elements of the key part.
+ * @param lastElementComplete indicates if the last element is complete. If
+ * it is not, then there are more than one
+ * possible endings to this last element in the
+ * tree. These endings can be found on the
+ * subnodes of the node that will contain the
+ * instance to be created.
+ * @param suffixPart the unique suffix of the key part to be
+ * created.
+ */
+ private KeyPart(String[] keyElements, boolean lastElementComplete,
+ KeyPart suffixPart)
+ {
+ // initialize elements data
+ this.keyElements = keyElements;
+ this.lastElementComplete = lastElementComplete;
+
+ // initialize length range
+ byte ppMinLength = (byte) (keyElements.length +
+ suffixPart.lengthRange.getPostPrefixMinLength());
+ byte ppMaxLength = (byte) (keyElements.length +
+ suffixPart.lengthRange.getPostPrefixMaxLength());
+ this.lengthRange = lastElementComplete? new LengthRange(
+ (byte) keyElements.length, ppMinLength, ppMaxLength):
+ new ExtendedLengthRange((byte) keyElements.length,
+ (byte) (ppMinLength - 1), (byte) (ppMaxLength - 1),
+ createElementLengthRange(suffixPart));
+ }
+
+ /**
+ * Private constructor, for internal use only.
+ *
+ * @param keyElements the elements of the key part
+ */
+ private KeyPart(String[] keyElements)
+ {
+ this.keyElements = keyElements;
+ this.lastElementComplete = true;
+ this.lengthRange = new LengthRange((byte) keyElements.length,
+ (byte) keyElements.length);
+ }
+
+ /**
+ * Returns the first character contained in this key part. It is used by
+ * internal nodes for sub nodes identification.
+ *
+ * @return the first character of the first key element. May return <code>
+ * KeyPart.KEY_ELEMENT_END</code> if the first element is empty,
+ * which means that this <code>KeyPart</code> determines the end of a
+ * key (<code>EMPTY_KEY_END</code>), or that it starts with the end
+ * of the last element of the <code>KeyPart</code> contained in the
+ * super node.
+ */
+ public char getFirstCharacter()
+ {
+ if (keyElements.length == 0 || keyElements[0].length() == 0)
+ {
+ return KeyPart.KEY_ELEMENT_END;
+ }
+ return keyElements[0].charAt(0);
+ }
+
+ /**
+ * Returns the key elements of this key part.
+ *
+ * @return the key elements array.
+ */
+ public String[] getKeyElements()
+ {
+ return this.keyElements;
+ }
+
+ /**
+ * Indicates if the last element is complete. If it is not, then there are
+ * more than one possible ending to the last element. These endings can be
+ * found in the subnodes of the node carrying this key part instance.
+ *
+ * @return <code>true</code> if the last element is complete.
+ */
+ public boolean isLastElementComplete()
+ {
+ return this.lastElementComplete;
+ }
+
+ /**
+ * Returns the minimum-maximum range of the length of the suffixes and
+ * post-prefixes of this key part.
+ *
+ * @return the minimum-maximum range of the length of the suffixes and
+ * post-prefixes of this key part. May be a {@link
+ * ExtendedLengthRange} instance if <code>lastElementComplete</code>
+ * is <code>false</code>.
+ *
+ * @see LengthRange
+ * @see ExtendedLengthRange
+ */
+ public LengthRange getLengthRange()
+ {
+ return lengthRange;
+ }
+
+ /**
+ * Notifies this key part that a new suffix was added to it.
+ * <p>
+ * This method updates the length range data accordingly.
+ *
+ * @param newSuffix the new suffix of this key part.
+ */
+ public void newSuffix(KeyPart newSuffix)
+ {
+ LengthRange suffixLengthRange = newSuffix.getLengthRange();
+ // update length range
+ byte diff = lastElementComplete? (byte) 0: (byte) 1;
+ byte ppMinLength = (byte) (suffixLengthRange.getPostPrefixMinLength() +
+ this.lengthRange.getLength() - diff);
+ byte ppMaxLength = (byte) (suffixLengthRange.getPostPrefixMaxLength() +
+ this.lengthRange.getLength() - diff);
+ this.lengthRange.update(ppMinLength, ppMaxLength);
+
+ if (!this.lastElementComplete)
+ {
+ // update element length range
+ LengthRange elementLengthRange = ((ExtendedLengthRange) lengthRange).
+ getElementLengthRange();
+ byte[] lengthRange = getElementLengthRange(newSuffix);
+ if (lengthRange.length == 2)
+ {
+ elementLengthRange.update(lengthRange[1]);
+ }
+ else
+ {
+ elementLengthRange.update(lengthRange[1], lengthRange[2]);
+ }
+ }
+ }
+
+ /**
+ * Extracts a prefix part of this part.
+ * <p>
+ * After this method executes, this key part will contain only the remainder
+ * key part suffix.
+ *
+ * @param element the element index. The prefix will be extracted from
+ * the first element until the one identified by this
+ * index.
+ * @param elementChar the element char index, identifies until which char
+ * of <code>element</code> the prefix will be extracted.
+ * @return the extracted prefix.
+ */
+ public KeyPart extractPrefixPart(int element, int elementChar)
+ {
+ if (element == 0 && elementChar == 0)
+ {
+ String[] emptyElement = new String[1];
+ emptyElement[0] = "";
+ return new KeyPart(new String[]{""}, false, this);
+ }
+ String[] oldKeyElements = keyElements;
+ boolean oldLastElementComplete = lastElementComplete;
+ String[] extractedKeyElements = (elementChar == 0)?
+ new String[element]: new String[element + 1];;
+ boolean extractedLastElementComplete;
+
+ for (int j = 0; j < element; j++)
+ {
+ extractedKeyElements[j] = oldKeyElements[j];
+ }
+ this.keyElements = new String[oldKeyElements.length - element];
+ int startIndex = 0;
+ if (elementChar > 0)
+ {
+ extractedKeyElements[element] =
+ oldKeyElements[element].substring(0, elementChar);
+ extractedLastElementComplete = false;
+ this.keyElements[0] = oldKeyElements[element].substring(elementChar);
+ startIndex ++;
+ }
+ else
+ {
+ extractedLastElementComplete = true;
+ }
+ for (int i = startIndex; i < keyElements.length; i++)
+ {
+ keyElements[i] = oldKeyElements[element + i];
+ }
+
+ byte lengthDiff = (byte) (this.lengthRange.getLength() -
+ keyElements.length);
+ byte postPrefixMinLength = (byte)
+ (this.lengthRange.getPostPrefixMinLength() - lengthDiff);
+ byte postPrefixMaxLength = (byte)
+ (this.lengthRange.getPostPrefixMaxLength() - lengthDiff);
+ this.lengthRange.reset((byte) keyElements.length, postPrefixMinLength,
+ postPrefixMaxLength);
+
+ if (!lastElementComplete && element == (oldKeyElements.length - 1))
+ {
+ // element length range affected
+ LengthRange elementLengthRange = ((ExtendedLengthRange) lengthRange).
+ getElementLengthRange();
+ postPrefixMinLength = (byte) (
+ elementLengthRange.getPostPrefixMinLength() - elementChar);
+ postPrefixMaxLength = (byte) (
+ elementLengthRange.getPostPrefixMaxLength() - elementChar);
+ elementLengthRange.reset( (byte)
+ this.keyElements[this.keyElements.length - 1].length(),
+ postPrefixMinLength, postPrefixMaxLength);
+ }
+
+ return new
+ KeyPart(extractedKeyElements, extractedLastElementComplete, this);
+ }
+
+ /**
+ * Creates an element length range for the unique suffix of this part.
+ * <p>
+ * Is called only when <code>lastElementComplete</code> equals false.
+ *
+ * @param suffixPart the unique suffix of this part
+ * @return the element length range of this part
+ */
+ private LengthRange createElementLengthRange(KeyPart suffixPart)
+ {
+ byte[] lengthRange = getElementLengthRange(suffixPart);
+ if (lengthRange.length == 2)
+ return new LengthRange(lengthRange[0], lengthRange[1]);
+ return new LengthRange(lengthRange[0], lengthRange[1], lengthRange[2]);
+ }
+
+ /**
+ * Returns the element length range data for <code>suffixPart</code>. This
+ * data is calculated based on <code>suffixPart</code> only, so other
+ * suffixes are not considered in the calculation.
+ * <p>
+ * This method is called only when there is an element length range, i.e.,
+ * when <code>lastElementComplete</code> is <code>false</code>.
+ *
+ * @param suffixPart the suffix that will be used for the element length
+ * range calculation
+ * @return a byte array composed of two or three values. The first one is the
+ * length of the element. When there are two values, the second one
+ * is the new post-prefix length. If three values are returned, the
+ * second and third ones are the minimum and maximum post-prefix
+ * length, respectively. Three values are returned only when <code>
+ * suffixPart</code> represents more than one element suffix.
+ */
+ private byte[] getElementLengthRange(KeyPart suffixPart)
+ {
+ byte length = (byte)
+ this.keyElements[this.keyElements.length - 1].length();
+ // if suffix part represents more than one element suffix...
+ if (suffixPart.getKeyElements().length == 1 &&
+ !suffixPart.isLastElementComplete())
+ {
+ // calculate minimum and maximum post prefix length
+ LengthRange newElementLR = ((ExtendedLengthRange)
+ suffixPart.getLengthRange()).getElementLengthRange();
+ byte ppMinLength = (byte) (newElementLR.getPostPrefixMinLength()
+ + length);
+ byte ppMaxLength = (byte) (newElementLR.getPostPrefixMaxLength()
+ + length);
+ return new byte[] {length, ppMinLength, ppMaxLength};
+ }
+
+ // calculate the unique post prefix length otherwise
+ return new byte[] {length,
+ // notice that the 0 element may not exist if newSuffix is
+ // EMPTY_KEY_END, but an EMPTY_KEY_END is always preceeded by
+ // lastElementComplete true values
+ (byte) (suffixPart.getKeyElements()[0].length() + length)};
+ }
+
+ public String toString()
+ {
+ String result = "[";
+ for (int i = 0; i < keyElements.length; i++)
+ {
+ result += "\"" + keyElements[i] + "\", ";
+ }
+ result += this.lastElementComplete + "]";
+ return result;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/LeafNode.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/LeafNode.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/LeafNode.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,103 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree;
+
+import java.util.Collection;
+
+import org.jboss.aop.joinpoint.graph.tree.insertion.InsertionKey;
+import org.jboss.aop.joinpoint.graph.tree.search.Flags;
+import org.jboss.aop.joinpoint.graph.tree.search.SearchKey;
+
+
+/**
+ * Leaf node of the tree, represents a unique key in the tree and contains the
+ * value identified by this key.
+ * <p>
+ * Refer to the <i>Internal Tree Structure</i> section of
+ * {@link org.jboss.aop.joinpoint.graph.tree} for more information.
+ *
+ *
+ * @author Flavia Rainone
+ * @see Node
+ * @see Tree
+ */
+class LeafNode<E> extends Node<E>
+{
+ /**
+ * The value contained in this leaf.
+ */
+ private E value;
+
+ /**
+ * Constructor. Creates a node representing a unique key in the tree, and
+ * containing the value identified by this key.
+ *
+ * @param keyPart the part of the key that is uncommon to the other keys
+ * in the tree.
+ * @param value the value identified by the key.
+ */
+ public LeafNode(KeyPart keyPart, E value)
+ {
+ super(keyPart);
+ this.value = value;
+ }
+
+ /**
+ * Proceeds insertion when this leaf represents a key that is a prefix
+ * of or equal to the key to be inserted in the tree.
+ */
+ public Node<E> internalInsert(InsertionKey insertionKey, E value)
+ {
+ // if this leaf represents a key different from the key to be inserted...
+ if (insertionKey.getNextChar() != InsertionKey.INSERTION_COMPLETE)
+ {
+ // creates a new leaf for the insertion key
+ Node leafNode = new LeafNode<E>(insertionKey.toKeyPart(), value);
+ // this leaf will contain only an empty key end
+ KeyPart fatherKeyPart = this.keyPart;
+ this.keyPart = KeyPart.EMPTY_KEY_END; // TODO this may generate more than one EMPTY KEY PART in a row... is this a problem?
+ fatherKeyPart.newSuffix(this.keyPart);// TODO is this necessary?
+ Node<E> newNode = new InternalNode<E>(fatherKeyPart, this, leafNode);
+ return newNode;
+ }
+ // if this leaf represents a key equal to the key to be inserted...
+ // just redefine value
+ this.value = value;
+ return this;
+ }
+
+ public void search(Collection<E> result, SearchKey searchKey)
+ {
+ char nextChar = searchKey.matches(super.keyPart);
+ //Collection result = new ArrayList();
+ if (nextChar == Flags.POSITIVE)
+ {
+ result.add(value);
+ }
+ //return result;
+ }
+
+ public String toString()
+ {
+ return "(" + this.keyPart + ", " + this.value + ")";
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/Node.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/Node.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/Node.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,113 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree;
+
+import java.util.Collection;
+
+import org.jboss.aop.joinpoint.graph.tree.insertion.InsertionKey;
+import org.jboss.aop.joinpoint.graph.tree.search.SearchKey;
+
+
+/**
+ * Represents a node of the tree, and provides insertion and search
+ * functionality.
+ * Every node can be seen as the root of a subtree.
+ *
+ * @author Flavia Rainone
+ * @see Tree
+ */
+abstract class Node<E>
+{
+ /**
+ * The contents of the node.
+ */
+ protected KeyPart keyPart;
+
+ /**
+ * Constructor.
+ *
+ * @param keyPart the key part to be contained in the created node.
+ */
+ public Node(KeyPart keyPart) {
+ this.keyPart = keyPart;
+ }
+
+ /**
+ * Searchs by <code>searchKey<code> on this node subtree.
+ *
+ * @param searchKey represents a search element
+ * @return a <code>Collection</code> of the objects identified by the keys
+ * matched by the search key
+ */
+ public abstract void search(Collection<E> result, SearchKey searchKey);
+
+ /**
+ * Returns the identifier char of this node.
+ *
+ * @return the char that identifies this node
+ */
+ public char getIdentifier()
+ {
+ return keyPart.getFirstCharacter();
+ }
+
+ /**
+ * Insert <code>value</code> in the tree, identified by the key <code>
+ * insertionKey</code>.
+ *
+ * @param insertionKey the key that identifies <code>value</code>, provides
+ * insertion mechanisms for the tree
+ * @param value the object to be inserted in the tree
+ * @return as the insertion may afect the node subtree structure,
+ * returns the new subtree root after insertion.
+ */
+ public Node<E> insert(InsertionKey insertionKey, E value)
+ {
+ // if the whole key part is a prefix of insertion key...
+ KeyPart commonKeyPart = insertionKey.extractCommonPrefix(this.keyPart);
+ if (commonKeyPart == this.keyPart)
+ { // proceed according to the node type
+ return internalInsert(insertionKey, value);
+ }
+ // otherwise, create a leaf with the insertion key unmatched part
+ Node<E> leafNode = new LeafNode<E>(insertionKey.toKeyPart(), value);
+ // and create a new internal node, containing the common prefix as
+ // its data, and this node and the created node as contents
+ Node<E> newNode = new InternalNode<E>(commonKeyPart, this, leafNode);
+ return newNode;
+ }
+
+ /**
+ * Performs the insertion of <code>value</code> in this node subtree.
+ * <p>
+ * Is called whenever the node contents represent a prefix of <code>
+ * insertionKey</code>.
+ *
+ * @param insertionKey the key that identifies <code>value</code>, provides
+ * insertion mechanisms for the tree
+ * @param value the object to be inserted in the tree
+ * @return as the insertion may afect the node subtree structure,
+ * returns the new subtree root after insertion.
+ */
+ protected abstract Node<E> internalInsert(InsertionKey insertionKey,
+ E value);
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/SlotCollection.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/SlotCollection.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/SlotCollection.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,193 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree;
+
+/**
+ * Represents a collection of slots.<p>
+ * Each slot is identified by a unicode character (all characters with values
+ * bigger than <code>'"'</code> have a slot available).
+ * A slot may be empty or not. When it is empty, it can be filled with content,
+ * but the reverse is not true. On the other hand, a filled slot can have its
+ * content replaced.
+ *
+ * @author Flavia Rainone
+ */
+class SlotCollection<E>
+{
+ /**
+ * SlotFlagSystem that indicates whether a slot is empty.
+ */
+ SlotFlagSystem flagSystem;
+
+ /**
+ * The contents vector, its size is exatcly the number of filled slots.
+ */
+ Object[] contents;
+
+ /**
+ * The index of a filled slot.
+ */
+ int slotIndex;
+
+ /**
+ * Constructs a collection with only two slots occupied: the one identified
+ * by <code>id1</code>, filled with <code>content1</code>; and the one
+ * identified by <code>id2</code>, filled with <code>content2</code>.
+ *
+ * @param content1 one of the contents to be inserted in the created
+ * collection
+ * @param id1 identifies the slot in which <code>content1</code> will be
+ * placed.
+ * @param content2 one of the contents to be inserted in the created
+ * collection
+ * @param id2 identifies the slot in which <code>content2</code> will be
+ * placed.
+ */
+ public SlotCollection(E content1, char id1, E content2, char id2)
+ {
+ flagSystem = new SlotFlagSystem(id1, id2);
+ contents = new Object[2];
+ if (id1 < id2)
+ {
+ this.contents[0] = content1;
+ this.contents[1] = content2;
+ }
+ else
+ {
+ this.contents[0] = content2;
+ this.contents[1] = content1;
+ }
+ }
+
+ /**
+ * Loads the slot identified by <code>identifier</code>.
+ * <p>
+ * This operation must be executed before any other operation on a slot.
+ *
+ * @param identifier the identifier char of the slot to be loaded
+ * @see #isSlotEmpty()
+ * @see #fillSlot(Object)
+ * @see #getSlotContent()
+ * @see #replaceSlotContent(Object)
+ */
+ public final void loadSlot(char identifier)
+ {
+ flagSystem.loadFlag(identifier);
+ }
+
+ /**
+ * Indicates whether the loaded slot is empty (load a slot by calling
+ * {@link #loadSlot(char)}).
+ *
+ * @return <code>true</code> if the loaded slot is empty; false otherwise
+ * @see #loadSlot(char)
+ */
+ public final boolean isSlotEmpty()
+ {
+ return !flagSystem.getFlagValue();
+ }
+
+ /**
+ * Returns the content of the slot that is loaded (load a slot by
+ * calling {@link #loadSlot(char)}).
+ * <p>
+ * This method can be called only if the slot is not empty.
+ *
+ * @return the content of the loaded slot.
+ * @see #loadSlot(char)
+ * @see #isSlotEmpty()
+ */
+ public final E getSlotContent()
+ {
+ slotIndex = flagSystem.calculateFlagIndex();
+ return (E) contents[slotIndex];
+ }
+
+ /**
+ * Fills the loaded slot (load a slot by calling {@link #loadSlot(char)})
+ * with <code>content</code>.<p>
+ * This method mustn't be called if the loaded slot is not empty, or the
+ * collection will enter an inconsistent state. To redefine the content
+ * of a not empty slot, refer to {@link #replaceSlotContent(Object)}.
+ *
+ * @param content the content that will be used to fill the loaded slot
+ * @see #loadSlot(char)
+ * @see #isSlotEmpty()
+ */
+ public final void fillSlot(E content)
+ {
+ flagSystem.setFlagPositive();
+ slotIndex = flagSystem.calculateFlagIndex();
+ Object[] oldContents = this.contents;
+ this.contents = new Object[oldContents.length + 1];
+ for (int i = 0; i < slotIndex; i++)
+ {
+ this.contents[i] = oldContents[i];
+ }
+ this.contents[slotIndex] = content;
+ for (int i = slotIndex + 1; i < contents.length; i++)
+ {
+ this.contents[i] = oldContents[i - 1];
+ }
+ }
+
+ /**
+ * Replaces the content of the loaded slot with <code>content</code>.
+ * <p>
+ * This method must be called only after <code>getSlotContent<code>.
+ *
+ * @param content the content that will replace the current content of the
+ * loaded slot.
+ * @see #getSlotContent()
+ */
+ public final void replaceSlotContent(E content)
+ {
+ contents[slotIndex] = content;
+ }
+
+ /**
+ * Returns the contents of all not empty slots.
+ * <p>
+ * The client should not modify the returned array.
+ *
+ * @return an array containing all contents.
+ */
+ public Object[] getAllContents()
+ {
+ return contents;
+ }
+
+ public String toString()
+ {
+ String result = "(";
+ int i = 0;
+ if (i < contents.length)
+ {
+ result += contents[i++];
+ }
+ for (;i < contents.length; i++)
+ {
+ result += ", " + contents[i];
+ }
+ return result + ")";
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/SlotFlagSystem.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/SlotFlagSystem.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/SlotFlagSystem.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,300 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree;
+
+/**
+ * Defines the flag system that is utilized by {@link SlotCollection}
+ * to indicate which slots are empty and which are not.
+ * <p>
+ * In this flag system, a flag is identified by a char.
+ *
+ * @author Flavia Rainone
+ * @see SlotCollection
+ */
+class SlotFlagSystem
+{
+ /**
+ * The offset of the flags. All flags should have an identifier greater than
+ * or equal to this offset.
+ */
+ private static final char OFFSET = '#';
+
+ /**
+ * The initial flags array size.
+ */
+ private static final byte INITIAL_FLAGS_SIZE = 6;
+
+ /**
+ * The flags array.
+ */
+ char[] flags;
+
+ /**
+ * Counts the number of positive flags.
+ */
+ private byte [] count;
+
+ /**
+ * The currently loaded flag.
+ */
+ private Flag flag;
+
+ /**
+ * Creates a flag system with <code>id1</code> and <code>id2</code> flags
+ * set to positive.
+ *
+ * @param id1 indentifies a flag that should be set to positive
+ * @param id2 indentifies a flag that should be set to positive
+ */
+ public SlotFlagSystem(char id1, char id2)
+ {
+ // calculate flags length
+ int flagsLength = Math.max(INITIAL_FLAGS_SIZE, id1/16 + 1);
+ flagsLength = Math.max(flagsLength, id2/16 + 1);
+ // create and initialize vectors
+ this.flags = new char[flagsLength];
+ for (int i = 0; i < flagsLength; i++)
+ this.flags[i] = 0;
+ this.count = new byte[flagsLength];
+ flag = new Flag();
+ flag.initialize(id1);
+ flag.setPositive();
+ flag.initialize(id2);
+ flag.setPositive();
+ }
+
+ /**
+ * Loads a flag identified by <code>id</code>.
+ * <p>
+ * This operation must be executed before any other operation on a flag.
+ *
+ * @param id identifies the flag to be loaded.
+ * @see #getFlagValue()
+ * @see #setFlagPositive()
+ * @see #calculateFlagIndex()
+ */
+ public final void loadFlag(char id)
+ {
+ flag.initialize(id);
+ }
+
+ /**
+ * Returns the value of the loaded flag (load a flag by calling {@link
+ * #loadFlag(char)}).
+ *
+ * @return <code>true</code> only if the loaded flag is positive; <code>
+ * false</code> otherwise.
+ * @see #loadFlag(char)
+ */
+ public final boolean getFlagValue()
+ {
+ return flag.getValue();
+ }
+
+ /**
+ * Sets the loaded flag value as positive (load a flag by calling {@link
+ * #loadFlag(char)}).
+ * <p>
+ * Should be called only when the flag value is positive.
+ *
+ * @see #loadFlag(char)
+ * @see #getFlagValue()
+ */
+ public final void setFlagPositive()
+ {
+ this.updateSupportedIdRange(flag.getId());
+ flag.setPositive();
+ }
+
+ /**
+ * Calculates the index that stores the contents of the slot identified
+ * by the loaded flag (load a flag by calling {@link
+ * #loadFlag(char)}).
+ * <p>
+ * Should be called only when the flag value is positive.
+ *
+ * @return the index that stores the contents of the slot identified
+ * by the loaded flag
+ * @see #loadFlag(char)
+ * @see #getFlagValue()
+ * @see #setFlagPositive()
+ */
+ public final int calculateFlagIndex()
+ {
+ return flag.calculateIndex();
+ }
+
+ /**
+ * Updates the range of ids that can be set as positive, in such a way that
+ * <code>id</code> is inside this range.
+ *
+ * @param id the id that must be in the suported id range.
+ */
+ private final void updateSupportedIdRange(char id)
+ {
+ char maximumIdSupported = (char) (flags.length * 16 + OFFSET - 1);
+ if (id <= maximumIdSupported)
+ {
+ return;
+ }
+ int flagsNeeded = this.flags.length + (int) Math.ceil((double)
+ (id - maximumIdSupported) / 16.0);
+ char oldFlags[] = this.flags;
+ this.flags = new char[flagsNeeded];
+ for (int i = 0; i < oldFlags.length; i++)
+ {
+ this.flags[i] = oldFlags[i];
+ }
+ byte[] oldCount = this.count;
+ this.count = new byte[flagsNeeded];
+ for (int i = 0; i < oldCount.length; i++)
+ {
+ this.count[i] = oldCount[i];
+ }
+ byte newCountValue = (byte) (oldCount[oldCount.length -1] +
+ countFlagValues(oldCount.length - 1, 16));
+ for (int i = oldCount.length; i < count.length; i++)
+ {
+ count[i] = newCountValue;
+ }
+ }
+
+ /**
+ * Returns the number of positive flags in <code>flags[flagNumber]</code>
+ * with id smaller than <code>flagMask</code>.
+ *
+ * @param flagNumber identifies where are the flags to be counted
+ * @param flagMask the upper limit mask of the flags to be counted
+ * @return the number of positive flags in <code>flags[flagNumber]</code>
+ * with id smaller than <code>flagMask</code>
+ */
+ private final int countFlagValues(int flagNumber, int flagMask)
+ {
+ char flag = flags[flagNumber];
+ int total = 0;
+ for (int i = 0; i < flagMask; i++)
+ {
+ if (flag % 2 == 1)
+ {
+ total ++;
+ }
+ flag = (char) (flag >> 1);
+ }
+ return total;
+ }
+
+ /**
+ * Represents a flag of the flag system. A flag is identified by a character
+ * and indicates if the character slot is empty or not, besides being able
+ * of calculating the index of the slot contents in an array.
+ *
+ * @author Flavia Rainone
+ */
+ class Flag
+ {
+ /**
+ * The number of the flag, indicates an index in the <code>flags</code>
+ * array.
+ */
+ private int flagNumber;
+
+ /**
+ * The mask of the flag, indicates which bit of <code>flags[flagNumber]
+ * </code>contains the value of this flag.
+ */
+ private int flagMask;
+
+ /**
+ * The character that identifies this flag.
+ */
+ private char id;
+
+ /**
+ * Initializes the flag with <code>id</code>. The initialization results
+ * in this flag representing the flag identifed by <code>id</code>.
+ * <p>
+ * Any operation on this flag must be called only after this flag is
+ * initialized.
+ *
+ * @param id the id of the flag that this object will represent
+ */
+ public final void initialize(char id)
+ {
+ this.id = id;
+ id -= OFFSET;
+ this.flagNumber = id / 16;
+ this.flagMask = id % 16;//(short) Math.pow(2.0, id % 16);
+ }
+
+ /**
+ * Returns the value of this flag.
+ *
+ * @return the value of this flag
+ */
+ public final boolean getValue()
+ {
+ if (flagNumber >= flags.length)
+ {
+ return false;
+ }
+ return (flags[flagNumber] >> flagMask) % 2 == 1;
+ }
+
+ /**
+ * Set this flag as positive.
+ */
+ public final void setPositive()
+ {
+ flags[flagNumber] += (char) (1 << flagMask);
+ {
+ // TODO: replace by a class whose count is int (very rare scenario)
+ }
+ for (int i = flagNumber + 1; i < count.length; i++)
+ {
+ count[i] ++;
+ }
+ }
+
+ /**
+ * Returns the identifier of the flag that this object represents.
+ * @return the identifier of the flag that this object represents
+ */
+ public final char getId()
+ {
+ return id;
+ }
+
+ /**
+ * Calculates the index of an array indicating where is the content
+ * of the slot represented by this flag.
+ *
+ * @return the index of an array indicating where is the content
+ * of the slot represented by this flag
+ */
+ private final int calculateIndex()
+ {
+ int index = countFlagValues(flagNumber, flagMask);
+ index += count[flagNumber];
+ return index;
+ }
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/Tree.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/Tree.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/Tree.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,177 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.jboss.aop.joinpoint.graph.tree.insertion.InsertionKey;
+import org.jboss.aop.joinpoint.graph.tree.search.SearchKey;
+
+
+/**
+ * A search tree, this is the unique class in this package that should be
+ * used by the client.
+ * This tree allows search using expresions with one or more wildcards.
+ *
+ * @author Flavia Rainone
+ */
+public class Tree<E>
+{
+ /**
+ * Root of the tree.
+ */
+ private Node root;
+
+ /**
+ * State of the tree: empty or not.
+ */
+ private State state;
+
+ /**
+ * Constructs an empty tree.
+ */
+ public Tree()
+ {
+ this.root = null;
+ this.state = new EmptyState();
+ }
+
+ /**
+ * Inserts <code>value</code> in the tree. This value is uniquely identified
+ * by <code>key</code>, that can contain one or more valid Java names
+ * separated by the <code>'.'</code> character. If a value was already
+ * inserted with the same key, the previous value will be overwritten.
+ *
+ * @param key identifies <code>value</code>. This key is used during
+ * search. <b>Should not be an empty string.</b>
+ * @param value the object that will be inserted in the tree
+ */
+ public void insert(String key, E value)
+ {
+ InsertionKey insertionKey = new InsertionKey(key);
+ state.insert(insertionKey, value);
+ }
+
+ /**
+ * Searches for all values whose key matches the <code>
+ * searchKeyExpresion</code>.
+ *
+ * @param searchKeyExpression element that defines the search; may contain
+ * zero or more wildcards (<code>'*'</code>) to
+ * indicate zero or more characters in the key.
+ * @return a collection of all values whose key matches the <code>
+ * searchKeyExpresion</code>
+ */
+ public Collection<E> search(String searchKeyExpression)
+ {
+ SearchKey searchKey = new SearchKey(searchKeyExpression);
+ return state.search(searchKey);
+ }
+
+ public boolean isEmpty()
+ {
+ return this.root == null;
+ }
+ // TODO create a node method for this type of search and test it.
+ public E searchElement(String elementName)
+ {
+ Collection<E> elements = search(elementName);
+ if (elements.isEmpty())
+ {
+ return null;
+ }
+ if (elements.size() > 1)
+ {
+ throw new RuntimeException("Element name shouldn't contain wildcards:" + elementName);
+ }
+ return elements.iterator().next();
+ }
+
+ /**
+ * The state of the tree, defines how the insertion and search operations
+ * should be carried out.
+ *
+ * @author Flavia Rainone
+ *
+ */
+ interface State
+ {
+ /**
+ * Performs an insertion in the tree.
+ * @see Tree#insert(String, Object)
+ */
+ <E> void insert(InsertionKey insertionKey, E value);
+
+ /**
+ * Performs a search in the tree.
+ * @see Tree#search(String)
+ */
+ <E> Collection<E> search(SearchKey searchKey);
+ }
+
+ /**
+ * Indicates that the tree is empty. Answers to the insertion and search
+ * operations accordingly.
+ *
+ * @author Flavia Rainone
+ */
+ class EmptyState implements State
+ {
+ public <E> void insert(InsertionKey insertionKey, E value)
+ {
+ root = new LeafNode(insertionKey.toKeyPart(), value);
+ state = new NotEmptyState();
+
+ }
+ public <E> Collection<E> search(SearchKey searchKey)
+ {
+ return new ArrayList<E>();
+ }
+ }
+
+ /**
+ * Indicates that the tree is not empty. Answers to the insertion and search
+ * operations accordingly.
+ *
+ * @author Flavia Rainone
+ */
+ class NotEmptyState implements State
+ {
+ public <E> void insert(InsertionKey insertionKey, E value)
+ {
+ root = root.insert(insertionKey, value);
+ }
+ public <E> Collection<E> search(SearchKey searchKey)
+ {
+ //return root.search(searchKey);
+ Collection<E> result = new ArrayList<E>();
+ root.search(result, searchKey);
+ return result;
+ }
+ }
+
+ public String toString()
+ {
+ return "" + root;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/insertion/InsertionKey.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/insertion/InsertionKey.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/insertion/InsertionKey.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,202 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.aop.joinpoint.graph.tree.insertion;
+
+import org.jboss.aop.joinpoint.graph.tree.KeyPart;
+
+/**
+ * Represents a key to be inserted in the tree.<p>
+ * This key is capable of providing a way of searching for each char of it in
+ * the tree, indicating whether a node contains chars common to it (
+ * {@link #extractCommonPrefix(KeyPart)}) and, if it does, which subnode should
+ * be analyzed next ({@link #getNextChar()}). This search finishes when a
+ * node that contains chars uncommon to this insertion key is found, which means
+ * that a char of the key was not found on the tree. When this happens, the
+ * unmatched part of this insertion key can be retrieved ({@link #toKeyPart()})
+ * and inserted in the tree.
+ *
+ * @author Flavia Rainone
+ */
+public class InsertionKey
+{
+ /**
+ * Indicates that the insertion is complete.
+ */
+ public static final char INSERTION_COMPLETE = '.';
+
+ /**
+ * The key to be inserted in the tree.
+ */
+ private String key;
+
+ /**
+ * Indicates from which index the key data wasn't found on the tree.
+ * This means that the prefix of <code>key</code> contained in the interval
+ * <code>0,keyIndex-1</code> is already in the tree.
+ */
+ private int keyIndex;
+
+ /**
+ * Indicates if the end of the <code>key</code> was found on the tree.
+ */
+ private boolean endRead = false;
+
+ /**
+ * Constructor.
+ *
+ * @param key the key to be inserted in the tree.
+ */
+ public InsertionKey(String key)
+ {
+ this.key = key;
+ this.keyIndex = 0;
+ }
+
+ /**
+ * Extracts the prefix common to <code>keyPart</code> and to this insertion
+ * key.
+ *
+ * @param keyPart the <code>keyPart</code> that may be broken into two
+ * parts: the prefix common to this insertion key; and the
+ * suffix, which contains the uncommon data. If broken during
+ * this method execution, this key part will contain the
+ * uncommon suffix only.
+ * @return the extracted common prefix, or <code>keyPart</code> itself if
+ * it is a prefix of this insertion key.
+ */
+ public KeyPart extractCommonPrefix(KeyPart keyPart)
+ {
+ if (keyPart == KeyPart.EMPTY_KEY_END && endRead)
+ {
+ // this insertion key is already in the tree
+ return keyPart;
+ }
+
+ String[] keyElements = keyPart.getKeyElements();
+ int element;
+ int i = 0;
+ // compares insertion key with elements until the key elements end or
+ // the insertion key end is reached
+ elementLoop:
+ for (element = 0; element < keyElements.length && !endRead; element++)
+ {
+ for (i = 0; i < keyElements[element].length(); i++)
+ {
+ // no more insertion key chars to compare...
+ if (keyIndex == key.length())
+ {
+ break elementLoop;
+ }
+ // a mismatch is found
+ if (keyElements[element].charAt(i) != key.charAt(keyIndex))
+ {
+ break elementLoop;
+ }
+ keyIndex ++;
+ }
+ // look for the '.' that separates the elements from one another
+ if (keyIndex < key.length())
+ {
+ if (key.charAt(keyIndex) != '.')
+ {
+ break;
+ }
+ }
+ // the end is reached
+ else
+ {
+ endRead = true;
+ }
+ i = 0;
+ keyIndex ++;
+ }
+ // extracts the common prefix part...
+ if (element < keyElements.length)
+ {
+ // if the common prefix isn't keyPart
+ if (element == (keyElements.length - 1) &&
+ i == keyElements[element].length() &&
+ !keyPart.isLastElementComplete())
+ {
+ return keyPart;
+ }
+ return keyPart.extractPrefixPart(element, i);
+ }
+ //(element == keyElements.length)
+ if (!keyPart.isLastElementComplete())
+ {
+ // the last element wasn't complete, so...
+ // ... the '.' found on the end of the loop needs to be reconsidered
+ keyIndex--;
+ // ... or the end read needs to be reconsidered
+ endRead = false;
+ }
+ return keyPart;
+ }
+
+ /**
+ * Returns the next char of the key to be searched on the tree.
+ *
+ * @return the next char of the key to be searched on the tree. May be <code>
+ * INSERTION_COMPLETE</code> to indicate that the insertion is
+ * already complete (because the whole insertion key is already
+ * contained in the tree). May return </code>KEY_ELEMENT_END</code>
+ * to indicate that the end of the element of the previous processed
+ * <code>keyPart</code> is what should be searched for in the tree.
+ */
+ public char getNextChar()
+ {
+ if (keyIndex >= key.length())
+ {
+ if (endRead)
+ {
+ return INSERTION_COMPLETE;
+ }
+ return KeyPart.KEY_ELEMENT_END;
+ }
+ char nextChar = key.charAt(keyIndex);
+ if (nextChar == '.')
+ {
+ return KeyPart.KEY_ELEMENT_END;
+ }
+ return nextChar;
+ }
+
+ /**
+ * Transforms the unmatched part of this key into a key part, to be inserted
+ * in the tree.
+ * <p>
+ * Should be called when <code>extractCommonPrefix</code> returns something
+ * different from its <code>keyPart</code> parameter value.
+ *
+ * @return a key part containing the unmatched part of this insertion key
+ */
+ public KeyPart toKeyPart()
+ {
+ if (endRead)
+ {
+ return KeyPart.EMPTY_KEY_END;
+ }
+ return new KeyPart(key.substring(keyIndex));
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/insertion/package.html
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/insertion/package.html (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/insertion/package.html 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,34 @@
+<html>
+<head>
+<!--
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<title></title>
+</head>
+<body bgcolor="white">
+
+Provides the tree insertion mechanism.
+
+<!-- Put @see and @since tags down here. -->
+ at see pointcutMatcher.tree.insertion.InsertionKey
+
+</body>
+</html>
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/package.html
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/package.html (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/package.html 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,58 @@
+<html>
+<head>
+<!--
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<title></title>
+</head>
+<body bgcolor="white">
+
+Provides a search tree.
+
+<h2>Package Specification</h2>
+<p>
+This tree stores objects identified by a key, composed of expressions separated
+by the '.' character, and allows the search with expressions containing
+wildcards ('*').
+</p>
+<p>
+The key stored in the tree may contain any valid java name character, which
+includes a bundle of special characters, like the chinese ones, for example.
+</p>
+
+<h2>Internal Tree Structure</h2>
+<p>
+Every key inserted in the tree is broken into parts according to the common
+prefixes of the keys contained in the tree. This way, each internal node
+contains a <i>key part</i>, that represents the prefix common to all keys
+inserted in the internal node subtree. Each leaf contains the part of a key
+that is uncommon to all other keys and identifies this key as unique in
+the tree (this uncommon part is the result of subtracting from the key the
+longest prefix that is common to another key in the tree). Henceforth, a leaf
+represents a key, whose value can be retrieved by concatenating the contents of
+the nodes in the path from the root to the leaf.
+</p>
+
+<!-- Put @see and @since tags down here. -->
+ at see pointcutMatcher.tree.Tree
+
+</body>
+</html>
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/Flags.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/Flags.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/Flags.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,27 @@
+package org.jboss.aop.joinpoint.graph.tree.search;
+
+/**
+ * Defines characters with special meanings that can be returned from the
+ * <code>SearchKey.matches</code> method.
+ *
+ * @author Flavia Rainone
+ * @see SearchKey#matches(org.jboss.aop.joinpoint.graph.tree.KeyPart)
+ */
+public class Flags
+{
+ /**
+ * Indicates that no character identifies a possible positive matching, i.e.,
+ * any character could take the matching to a positive result.
+ */
+ public static final char ALL = '*';
+
+ /**
+ * Indicates that the search is finished with a positive result.
+ */
+ public static final char POSITIVE = '+';
+
+ /**
+ * Indicates that the search is finished with a negative result.
+ */
+ public static final char NEGATIVE = '-';
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/SearchKey.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/SearchKey.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/SearchKey.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,208 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search;
+
+import org.jboss.aop.joinpoint.graph.tree.KeyPart;
+import org.jboss.aop.joinpoint.graph.tree.search.match.Matcher;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatcherFactory;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatchingResult;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatchingState;
+import org.jboss.aop.joinpoint.graph.tree.search.part.ComparableKeyPartFactory;
+import org.jboss.aop.joinpoint.graph.tree.search.part.KeyPartIndex;
+
+
+/**
+ * A search key is meant to execute a macthing against a {@link
+ * org.jboss.aop.joinpoint.graph.tree.KeyPart key part}.
+ * <p>
+ * This matching process can be executed until {@link Flags#ALL} is returned. In
+ * this case, to continue the process against the subsequent key parts (in order
+ * to continue the search process throughout a tree) it is necessary to ask
+ * for the wildcard search key instance ({@link #getWildcardInstance()}).
+ *
+ * @author Flavia Rainone
+ */
+public class SearchKey
+{
+ /**
+ * The search key part matchers.
+ */
+ private Matcher[] partMatchers;
+
+ /**
+ * Points to the current matcher (the one responsible for matching the
+ * next key part).
+ */
+ private int index;
+
+ /**
+ * Contains the comparableIndex of the current matcher.
+ */
+ private KeyPartIndex comparableIndex;
+
+ /**
+ * Contains the index of the next target.
+ */
+ private KeyPartIndex targetIndex;
+
+ /**
+ * The state of the matching process.
+ */
+ private MatchingState state;
+
+ /**
+ * The wildcard instance associated with this search key.
+ */
+ private SearchKey wildcardSearchKey;
+
+ /**
+ * Constructor.
+ *
+ * @param searchExpression a search element. This element is allowed to
+ * contain wildcards (<code>'*'</code>) besides any
+ * character contained in a valid java class name.
+ */
+ public SearchKey (String searchExpression)
+ {
+ ComparableKeyPartFactory factory = ComparableKeyPartFactory.getInstance();
+ this.partMatchers = MatcherFactory.createSequence(searchExpression,
+ factory, factory.getMatcherSequenceProfile());
+ index = 0;
+ comparableIndex = new KeyPartIndex();
+ targetIndex = new KeyPartIndex();
+ state = new MatchingState(new MatchingState());
+ }
+
+ /**
+ * Private constructor.
+ * <p>
+ * Creates an empty search key.
+ */
+ private SearchKey()
+ {
+ this.comparableIndex = new KeyPartIndex();
+ this.targetIndex = new KeyPartIndex();
+ this.state = new MatchingState(new MatchingState());
+ }
+
+ /**
+ * Matches this <code>SearchKey</code> content against <code>keyPart</code>.
+ * <p>
+ * In order to know exactly what will be matched it is necessary to notice
+ * that this <code>SearchKey</code> is resultant of previous comparisons made
+ * before, i.e., the matching will start at the exact search key expression
+ * point where the last matching process stopped in the previous matching.
+ * <p>
+ *
+ * @param keyPart the <code>KeyPart</code> whose content will be compared to
+ * the search key. It is the content of a tree node.
+ * @return <code>Flags.NEGATIVE</code> if the matching is negative. If the
+ * matching is partially positive, returns the next character needed
+ * by a successful search. The return value may be <code>
+ * Flags.ALL</code> if there is no character that specifies a
+ * possible positive match (in this case, this matcher cannot execute
+ * the next matching, the {@link #getWildcardInstance() wildcard
+ * search key} should do so). And returns <code>Flags.POSITIVE
+ * </code> if the matching process finished succesfuly with a
+ * positive result.
+ * @see Flags
+ */
+ public char matches(KeyPart keyPart)
+ {
+ // the initial index of key part
+ MatchingResult result = partMatchers[index].matches(keyPart,
+ keyPart.getLengthRange(), targetIndex, comparableIndex, state);
+ while (result == MatchingResult.POSITIVE_MATCH &&
+ ++ index < partMatchers.length)
+ {
+ comparableIndex.reset();
+ result = partMatchers[index].matches(keyPart, keyPart.getLengthRange(),
+ targetIndex, comparableIndex, state);
+ }
+ if (result == MatchingResult.NEGATIVE_MATCH)
+ {
+ return Flags.NEGATIVE;
+ }
+ if (index == partMatchers.length &&
+ result == MatchingResult.POSITIVE_MATCH)
+ {
+ if (keyPart.getLengthRange().getSuffixMaxLength() == 0)
+ {
+ return Flags.POSITIVE;
+ }
+ index--;
+ }
+ char nextChar = partMatchers[index].getNextCharacter(comparableIndex,
+ keyPart, keyPart.getLengthRange(), state);
+ //this.createNextSearchKey = (nextChar == '*');
+ targetIndex.update(keyPart.getLengthRange());
+ return nextChar;
+ }
+
+ /**
+ * Returns the wildcard instance.
+ * <p>
+ * This method should be called when {@link #matches(KeyPart)} returns {@link
+ * Flags#ALL}. Once all subnodes of the current node will need to be
+ * searched, this instance is no longer appropriate. Instead, the client
+ * should search the subnodes using the wildcard instance.
+ *
+ * @return the wildcard instance. This search key must be {@link
+ * #prepareWildcardInstance prepared} before each time it is used
+ * to search in a subnode. And it must not perform the searches
+ * concurrently.
+ */
+ public SearchKey getWildcardInstance()
+ {
+ if (this.wildcardSearchKey == null)
+ {
+ this.wildcardSearchKey = new SearchKey();
+ }
+ return this.wildcardSearchKey;
+ }
+
+ /**
+ * Prepares the wildcard instance for doing a search.
+ * This method must be invoked before searching in each subnode of the last
+ * searched node (the one with a <code>Flags.ALL</code> result).
+ *
+ * @param wildcardInstance the wildcard instance, must be the same returned
+ * by <code>getWildcardInstance</cocde>
+ * @see #getWildcardInstance()
+ */
+ public void prepareWildcardInstance(SearchKey wildcardInstance)
+ {
+ wildcardInstance.partMatchers = this.partMatchers;
+ wildcardInstance.index = this.index;
+ //wildcardInstance.comparableIndex = new KeyPartIndex(this.comparableIndex);
+ //wildcardInstance.targetIndex = new KeyPartIndex(this.targetIndex);
+ wildcardInstance.comparableIndex.copy(this.comparableIndex);
+ wildcardInstance.comparableIndex.getElementIndex().copy(this.comparableIndex.getElementIndex());
+ wildcardInstance.targetIndex.copy(this.targetIndex);
+ wildcardInstance.targetIndex.getElementIndex().copy(this.targetIndex.getElementIndex());
+ //wildcardInstance.state = new MatchingState(this.state);
+ //wildcardInstance.state.setComparisonState(new MatchingState(
+ // (MatchingState) this.state.getComparisonState()));
+ wildcardInstance.state.copy(state);
+ }
+
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/PrefixFunctionImpl.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/PrefixFunctionImpl.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/PrefixFunctionImpl.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,334 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.common;
+
+import org.jboss.aop.joinpoint.graph.tree.search.match.Index;
+import org.jboss.aop.joinpoint.graph.tree.search.match.PrefixFunction;
+import org.jboss.aop.joinpoint.graph.tree.search.part.KeyPartIndex;
+
+
+/**
+ * Provides the prefix function to be used by <code>ComparableKeyPart</code>
+ * and <code>ComparableElement</code>.
+ * <p>
+ * This prefix function is calculated based on a key part pattern, which is
+ * composed by one or more elements. So, the function maps a {@link KeyPartIndex
+ * key part index}, which is formed by two values, the key part index value
+ * itself (part index for short) and the element index value, to an array
+ * containing two values: the new part index value, and the new element index
+ * value. When only the element index is provided, the part index is assumed to
+ * be equal to <code>0</code> and only the element index value of the prefix
+ * function is applied.
+ *
+ * @author Flavia Rainone
+ * @see org.jboss.aop.joinpoint.graph.tree.search.element.ComparableElement
+ * @see org.jboss.aop.joinpoint.graph.tree.search.part.ComparableKeyPart
+ */
+class PrefixFunctionImpl implements PrefixFunction
+{
+ /**
+ * An array that represents the prefix function zero value.
+ * <p>
+ * Avoids the recurrent allocation of the same array value.
+ */
+ private static final int[] ZERO_VALUE = new int[]{0, 0};
+
+ /**
+ * The index of the prefix function part value.
+ */
+ private static final int PART_VALUE = 0;
+
+ /**
+ * The index of the prefix function element value.
+ */
+ private static final int ELEMENT_VALUE = 1;
+
+ /**
+ * The pattern used for the calculation of the prefix function values.
+ */
+ private String[] pattern;
+
+ /**
+ * The prefix function values.
+ */
+ private int[][][] prefixFunction;
+
+ /**
+ * The part index from which the function has not been calculated (lazy
+ * initialization).
+ */
+ private int part;
+
+ /**
+ * The element index from which the function has not been calculated (lazy
+ * initialization).
+ */
+ private int element;
+
+ /**
+ * The current prefix function part value, utilized by the prefix calculation
+ * algorithm (lazy initialization).
+ */
+ private int i;
+
+ /**
+ * The current prefix function element value, utilized by the prefix
+ * calculation algorithm (lazy initialization).
+ */
+ private int j;
+
+ /**
+ * Assigns the prefix function value of the pattern end.
+ */
+ private PatternEnd patternEnd;
+
+ /**
+ * Package protected constructor. Creates a prefix function whose values
+ * will be calculated based on a pattern not yet loaded. When such a pattern
+ * is loaded, the created prefix function must be {@link #initialize
+ * initialized} with it.
+ *
+ * @see PrefixFunctionLoader#getLoadedFunction()
+ */
+ PrefixFunctionImpl()
+ { }
+
+ /**
+ * Initializes the prefix function with <code>pattern</code> data.
+ *
+ * @param pattern the pattern that will be used in the prefix
+ * function calculation
+ * @param lastElementComplete indicates whether the last <code>pattern</code>
+ * element is complete or not
+ */
+ final void initialize(String[] pattern, boolean lastElementComplete)
+ {
+ this.patternEnd = PatternEnd.getInstance(lastElementComplete);
+ this.pattern = pattern;
+ prefixFunction = new int[pattern.length + 1][][];
+ prefixFunction[0] = new int[pattern[0].length() + 1][];
+ prefixFunction[0][0] = ZERO_VALUE;
+ if (pattern[0].length() > 0)
+ {
+ prefixFunction[0][1] = ZERO_VALUE;
+ element = 1;
+ }
+ else
+ {
+ element = 0;
+ }
+ part = 0;
+ i = 0;
+ j = 0;
+ }
+
+ /**
+ * Applies the prefix function to <code>index</code>, changing its value to
+ * the correspondent prefix function value.
+ *
+ * @param index the index whose prefix function value will be applied. Notice
+ * the matching framework may call this method for <code>
+ * KeyPartIndex</code>es and for common <code>Index</code>es, as
+ * long as this prefix function is provided as the prefix
+ * function of both <code>ComparableKeyPart</code>s and <code>
+ * ComparableElements</code>.
+ */
+ public final void applyTo(Index index)
+ {
+ if (index instanceof KeyPartIndex)
+ {
+ KeyPartIndex keyPartIndex = (KeyPartIndex) index;
+ Index elementIndex = keyPartIndex.getElementIndex();
+ int[] value = getValue(index.getValue(), elementIndex.getValue());
+ keyPartIndex.applyPrefixFunction(value[PART_VALUE]);
+ elementIndex.applyPrefixFunction(value[ELEMENT_VALUE]);
+ }
+ else
+ {
+ int[] value = getValue(0, index.getValue());
+ index.applyPrefixFunction(value[ELEMENT_VALUE]);
+ }
+ }
+
+ /**
+ * Returns the prefix function value for the queried index.
+ *
+ * @param qPart the queried index part value
+ * @param qElement the queried index element value
+ * @return the prefix function value
+ */
+ private final int[] getValue(int qPart, int qElement)
+ {
+ // if the value is not calculated, calculate it!
+ if (prefixFunction[qPart] == null ||
+ prefixFunction[qPart][qElement] == null)
+ {
+ while(part < qPart || (part == qPart && element < qElement))
+ {
+ if (part < pattern.length)
+ {
+ while(element < pattern[part].length())
+ {
+ // while i,j indicates a '.' char
+ while ((i != 0 || j != 0) && j == pattern[i].length())
+ {
+ // steps backward
+ stepBackward();
+ }
+ // while the ZERO_VALUE is not reached nor a match is found
+ while ((i != 0 || j != 0) &&
+ pattern[i].charAt(j) != pattern[part].charAt(element))
+ {
+ // steps backward
+ stepBackward();
+ // while i,j indiates a '.', steps backward since
+ // pattern[part][element] doesn't contain a '.'
+ while ((i != 0 || j != 0) && j == pattern[i].length())
+ {
+ stepBackward();
+ }
+ }
+ // if previous while loop terminated because a match was found...
+ if (j < pattern[i].length() &&
+ pattern[i].charAt(j) == pattern[part].charAt(element))
+ {
+ j++; // increment current index value
+ }
+ // prefix function value calculated for part,element
+ prefixFunction[part][++element] = new int[]{i, j};
+ }
+ }
+ // if there is a '.' after this element...
+ if (++ part < pattern.length)
+ {
+ this.createPartElementFunction(pattern[part].length());
+ }
+ else
+ {
+ this.patternEnd.fillPatternEndValue(this);
+ }
+ }
+ }
+ return prefixFunction[qPart][qElement];
+ }
+
+ /**
+ * Creates the prefix function of the part element identified by the <code>
+ * part</code> index.
+ *
+ * @param length the length of the element
+ */
+ private final void createPartElementFunction(int length)
+ {
+ // while ZERO_VALUE is not reached and the '.' char is not found
+ while ((i != 0 || j != 0) && j != pattern[i].length())
+ {
+ // steps backward...
+ stepBackward();
+ }
+ // if previous while loop terminated because the '.' was found
+ if ((i < (part - 1) || j != 0) && j == pattern[i].length())
+ {
+ // increment index value
+ i++;
+ j = 0;
+ }
+ // function value calculated for part,0
+ element = 0;
+ prefixFunction[part] = new int[length + 1][];
+ prefixFunction[part][element] = new int[]{i, j};
+ }
+
+ /**
+ * Steps backward the calculation of a prefix function value, applying the
+ * prefix function itself to the current value.
+ * <p>
+ * Called everytime a mismatch is found in the prefix function calculation.
+ */
+ private final void stepBackward()
+ {
+ int oldI = i;
+ // steps backward
+ i = prefixFunction[oldI][j][PART_VALUE];
+ j = prefixFunction[oldI][j][ELEMENT_VALUE];
+
+ }
+
+ /**
+ * Defines the prefix function value to be assigned to the pattern end.
+ *
+ * @author Flavia Rainone
+ */
+ private static abstract class PatternEnd
+ {
+ /**
+ * This pattern end assigns the appropriate prefix function value to the
+ * end of a pattern whose last element is complete.
+ */
+ public static final PatternEnd LAST_ELEMENT_COMPLETE = new PatternEnd()
+ {
+ public void fillPatternEndValue(PrefixFunctionImpl pfi)
+ {
+ pfi.createPartElementFunction(0);
+ }
+ };
+
+ /**
+ * This pattern end assigns the appropriate prefix function value to the
+ * end of a pattern whose last element is incomplete.
+ */
+ public static final PatternEnd LAST_ELEMENT_INCOMPLETE = new PatternEnd()
+ {
+ public void fillPatternEndValue(PrefixFunctionImpl pfi)
+ {
+ pfi.prefixFunction[pfi.part] = new int[1][];
+ pfi.prefixFunction[pfi.part][0] = pfi.prefixFunction
+ [pfi.part - 1][pfi.pattern[pfi.part - 1].length()];
+ }
+ };
+
+ /**
+ * Fills the pattern end prefix function value.
+ *
+ * @param pfi the prefix function whose pattern end value will be
+ * filled
+ */
+ public abstract void fillPatternEndValue(PrefixFunctionImpl pfi);
+
+ /**
+ * Returns the appropriate pattern end instance, according to <code>
+ * lastElementComplete</code> value.
+ *
+ * @param lastElementComplete indicates whether the last pattern element
+ * is complete or not
+ * @return the appropriate pattern end instance
+ */
+ public static final PatternEnd getInstance(boolean lastElementComplete)
+ {
+ if (lastElementComplete)
+ {
+ return PatternEnd.LAST_ELEMENT_COMPLETE;
+ }
+ return PatternEnd.LAST_ELEMENT_INCOMPLETE;
+ }
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/PrefixFunctionLoader.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/PrefixFunctionLoader.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/PrefixFunctionLoader.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,234 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.common;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.aop.joinpoint.graph.tree.search.element.ComparableElement;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatcherProfile;
+import org.jboss.aop.joinpoint.graph.tree.search.match.PrefixFunction;
+import org.jboss.aop.joinpoint.graph.tree.search.part.ComparableKeyPart;
+
+
+/**
+ * Loads a prefix function for {@link ComparableKeyPart}s and for {@link
+ * ComparableElement}s.
+ *
+ * @author Flavia Rainone
+ */
+public class PrefixFunctionLoader
+{
+ /**
+ * Dummy loader, doesn't create a prefix function.
+ */
+ private static final PrefixFunctionLoader DUMMY_LOADER =
+ new PrefixFunctionLoader(false)
+ {
+ public PrefixFunctionImpl createPrefixFunction()
+ {
+ return null;
+ }
+ };
+
+ /**
+ * Pattern loader, loads the prefix function for a key part pattern.
+ */
+ private static final PrefixFunctionLoader PATTERN_LOADER =
+ new PrefixFunctionLoader(false);
+
+ /**
+ * Suffix loader, loads the prefix function for a key part suffix.
+ */
+ private static final PrefixFunctionLoader SUFFIX_LOADER =
+ new PrefixFunctionLoader(true);
+
+ /**
+ * Contains all prefix function loader instances.
+ */
+ private static final PrefixFunctionLoader[] instances;
+
+ /**
+ * The current prefix function loader, is the loader returned by the last
+ * invocation of {@link #getLoaderForProfile(MatcherProfile)}.
+ */
+ private static int currentLoader;
+
+ static
+ {
+ instances = new PrefixFunctionLoader[MatcherProfile.getNumberOfInstances()];
+ instances[MatcherProfile.SIMPLE.getId()] = DUMMY_LOADER;
+ instances[MatcherProfile.PREFIX.getId()] = DUMMY_LOADER;
+ instances[MatcherProfile.PATTERN.getId()] = PATTERN_LOADER;
+ instances[MatcherProfile.SUFFIX.getId()] = SUFFIX_LOADER;
+ }
+
+ /**
+ * Returns the prefix function loader appropriate for the <code>
+ * compKeyPartProfile</code>.
+ * <p>
+ * The loader returned by this method will become the current loader.
+ *
+ * @param compKeyPartProfile the matcher profile associated with the
+ * comparable key part whose prefix function will
+ * be loaded
+ * @return the appropriate prefix function loader
+ */
+ public static PrefixFunctionLoader getLoaderForProfile(
+ MatcherProfile compKeyPartProfile)
+ {
+ currentLoader = compKeyPartProfile.getId();
+ return instances[currentLoader];
+ }
+
+ /**
+ * Returns the current loader, which is the same loader returned by the
+ * last invocation of <code>getLoaderForProfile</code>.
+ *
+ * @return the current loader
+ * @see #getLoaderForProfile(MatcherProfile)
+ */
+ public static PrefixFunctionLoader getCurrentLoader()
+ {
+ return instances[currentLoader];
+ }
+
+ /**
+ * Contains the elements of the pattern being loaded.
+ */
+ protected final List elements = new ArrayList();
+
+
+ /**
+ * The instance whose pattern is being loaded. After the loading process
+ * finishes, this instance will be initialized with the loaded pattern.
+ */
+ protected PrefixFunctionImpl prefixFunction;
+
+ /**
+ * Indicates whether the last element of the pattern to be loaded is complete
+ * or not (such an element is complete only when the loaded elements are part
+ * of a comparable key part suffix).
+ */
+ protected boolean lastElementComplete;
+
+ /**
+ * Private constructor.
+ *
+ * @param lastElementComplete indicates whether the last element of the
+ * pattern whose prefix function to be loaded
+ * is complete or not
+ */
+ private PrefixFunctionLoader(boolean lastElementComplete)
+ {
+ this.lastElementComplete = lastElementComplete;
+ }
+
+ /**
+ * Prepares a prefix function instance for loading a pattern. Once
+ * this pattern is loaded, the created instance will be initialized with
+ * it.
+ *
+ * @see #loadElement(String)
+ * @see #loaded()
+ * @see #getLoadedFunction()
+ */
+ public final void prepareForLoading()
+ {
+ elements.clear();
+ prefixFunction = createPrefixFunction();
+ }
+
+ /**
+ * Creates a prefix function.
+ *
+ * @return the created prefix function
+ */
+ protected PrefixFunctionImpl createPrefixFunction()
+ {
+ return new PrefixFunctionImpl();
+ }
+
+ /**
+ * Notifies that the complete pattern has been loaded and, consequently,
+ * that the pattern prefix function created in <code>prepareForLoadingPattern
+ * </code> can be initialized with the loaded data.
+ * <p>
+ * If the <code>prepareForLoading</code> method wasn't invoked before this
+ * one, an error will occur.
+ *
+ * @see #prepareForLoading()
+ * @see #loadElement(String)
+ * @see #getLoadedFunction()
+ */
+ public void loaded()
+ {
+ if (this.prefixFunction != null)
+ {
+ String[] elementArray = new String[elements.size()];
+ elementArray = (String[]) elements.toArray(elementArray);
+ elements.clear();
+ prefixFunction.initialize(elementArray, lastElementComplete);
+ }
+ }
+
+ /**
+ * Loads an element of the pattern.
+ * <p>
+ * This method should be called in the order the elements occur in the
+ * pattern.
+ *
+ * @param element an element of the pattern
+ * @return the prefix function that will be initialized with the loaded
+ * pattern when the pattern loading process finishes. If the method
+ * <code>prepareForLoading</code> wasn't invoked, returns <code>null
+ * </code>.
+ * @see #prepareForLoading()
+ * @see #loaded()
+ * @see #getLoadedFunction()
+ */
+ public PrefixFunction loadElement(String element)
+ {
+ elements.add(element);
+ return prefixFunction;
+ }
+
+ /**
+ * Returns the prefix function whose values are calculated based on the
+ * previously loaded pattern.
+ * <p>
+ * The same prefix function cannot be retrieved more than once, or <code>
+ * null</code> will be returned.
+ *
+ * @return the prefix function whose values are calculated based on the
+ * previously loaded pattern. Returns <code>null</code> if the prefix
+ * function has already been retrieved or if the <code>
+ * prepareForLoading</code> method was not called before the pattern
+ * being loaded.
+ */
+ public PrefixFunction getLoadedFunction()
+ {
+ PrefixFunction function = prefixFunction;
+ prefixFunction = null;
+ return function;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/package.html
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/package.html (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/common/package.html 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,37 @@
+<html>
+<head>
+<!--
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<title></title>
+</head>
+<body bgcolor="white">
+
+Contains classes common to both <code>tree.search.element</code>
+and <code>tree.search.part</code> packages.
+
+
+<!-- Put @see and @since tags down here. -->
+ at see pointcutMatcher.tree.search.element
+ at see pointcutMatcher.tree.search.part
+
+</body>
+</html>
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/ComparableElement.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/ComparableElement.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/ComparableElement.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,124 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.element;
+
+import org.jboss.aop.joinpoint.graph.tree.KeyPart;
+import org.jboss.aop.joinpoint.graph.tree.search.Flags;
+import org.jboss.aop.joinpoint.graph.tree.search.common.PrefixFunctionLoader;
+import org.jboss.aop.joinpoint.graph.tree.search.match.Comparable;
+import org.jboss.aop.joinpoint.graph.tree.search.match.ComparisonResult;
+import org.jboss.aop.joinpoint.graph.tree.search.match.Index;
+import org.jboss.aop.joinpoint.graph.tree.search.match.LengthRange;
+import org.jboss.aop.joinpoint.graph.tree.search.match.PrefixFunction;
+import org.jboss.aop.joinpoint.graph.tree.search.match.State;
+import org.jboss.aop.joinpoint.graph.tree.search.part.ComparableKeyPart;
+
+
+/**
+ * Implements the <code>Comparable</code> interface having characters as
+ * components.
+ *
+ * @author Flavia Rainone
+ */
+public class ComparableElement implements Comparable
+{
+ /**
+ * The element expression.
+ */
+ private String expression;
+
+ /**
+ * The prefix function associated with this element.
+ */
+ private PrefixFunction prefixFunction;
+
+ /**
+ * Constructor.
+ *
+ * @param expression the element expression, that will be compared
+ * against a target in the {@link #compare
+ * compare} method
+ * @param prefixFunctionLoader the loader responsible for loading the prefix
+ * function of the {@link ComparableKeyPart} that
+ * contains this element.
+ */
+ ComparableElement (String expression,
+ PrefixFunctionLoader prefixFunctionLoader)
+ {
+ this.expression = expression;
+ this.prefixFunction = prefixFunctionLoader.loadElement(expression);
+ }
+
+ public final int getPostPrefixLength()
+ {
+ return expression.length();
+ }
+
+ public char getNextCharacter(Index comparableIndex, Object comparisonState)
+ {
+ if (expression.length() == 0)
+ {
+ return Flags.ALL;
+ }
+ if (comparableIndex.getValue() >= expression.length())
+ {
+ return KeyPart.KEY_ELEMENT_END;
+ }
+ return expression.charAt(comparableIndex.getValue());
+ }
+
+ public char getNextCharacter(Index comparableIndex, Object target,
+ LengthRange targetLengthRange, Object comparisonState)
+ {
+ return getNextCharacter(comparableIndex, comparisonState);
+ }
+
+ public PrefixFunction getPrefixFunction()
+ {
+ return prefixFunction;
+ }
+
+ public ComparisonResult compare(Object target, Index targetIndex,
+ Index comparableIndex, State comparisonState)
+ {
+ String targetExpression = (String) target;
+ while(comparableIndex.getValue() < expression.length() &&
+ targetIndex.getValue() < targetExpression.length())
+ {
+ if (targetExpression.charAt(targetIndex.getValue()) !=
+ expression.charAt(comparableIndex.getValue()))
+ {
+ return ComparisonResult.MISMATCH_FOUND;
+ }
+ targetIndex.increment();
+ comparableIndex.increment();
+ }
+ boolean expressionEnd = comparableIndex.getValue() >= expression.length();
+ boolean targetEnd = targetIndex.getValue() >= targetExpression.length();
+ return ComparisonResult.getInstance(expressionEnd, targetEnd);
+ }
+
+ public String toString()
+ {
+ return "\"" + expression + "\"";
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/ComparableElementFactory.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/ComparableElementFactory.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/ComparableElementFactory.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,145 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.element;
+
+import org.jboss.aop.joinpoint.graph.tree.search.common.PrefixFunctionLoader;
+import org.jboss.aop.joinpoint.graph.tree.search.match.Comparable;
+import org.jboss.aop.joinpoint.graph.tree.search.match.ComparableFactory;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatcherProfile;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatcherSequenceProfile;
+
+
+/**
+ * Creates <code>ComparableElement</code> instances.
+ *
+ * @author Flavia Rainone
+ * @see ComparableElement
+ */
+public class ComparableElementFactory implements ComparableFactory
+{
+ /**
+ * Singleton instance.
+ */
+ private static final ComparableElementFactory instance =
+ new ComparableElementFactory();
+
+ /**
+ * Returns the singleton factory instance.
+ *
+ * @return the singleton factory instance
+ */
+ public static final ComparableElementFactory getInstance()
+ {
+ return instance;
+ }
+
+ /**
+ * Map of <code>MatcherProfile</code> to <code>MatcherSequenceProfile</code>,
+ * indicates the profile of the element matcher sequence to be created
+ * according to the key part matcher profile.
+ */
+ private MatcherSequenceProfile[] profiles;
+
+ /**
+ * The responsible for loading the prefix function of the comparable key part
+ * that contains the comparable elements to be created.
+ */
+ private PrefixFunctionLoader loader;
+
+ /**
+ * Private constructor (singleton class).
+ */
+ private ComparableElementFactory()
+ {
+ this.profiles =
+ new MatcherSequenceProfile[MatcherProfile.getNumberOfInstances()];
+ // sequence for simple part
+ this.profiles[MatcherProfile.SIMPLE.getId()] = new MatcherSequenceProfile(
+ MatcherProfile.SIMPLE, MatcherProfile.SIMPLE,
+ MatcherProfile.SIMPLE, MatcherProfile.SIMPLE);
+ // sequence for prefix part
+ this.profiles[MatcherProfile.PREFIX.getId()] = new MatcherSequenceProfile(
+ MatcherProfile.SIMPLE, MatcherProfile.SIMPLE,
+ MatcherProfile.PREFIX, MatcherProfile.PREFIX);
+ // sequence for pattern part
+ this.profiles[MatcherProfile.PATTERN.getId()] = new MatcherSequenceProfile(
+ MatcherProfile.SUFFIX, MatcherProfile.SIMPLE,
+ MatcherProfile.PREFIX, MatcherProfile.PATTERN);
+ // sequence for suffix part
+ this.profiles[MatcherProfile.SUFFIX.getId()] = new MatcherSequenceProfile(
+ MatcherProfile.SUFFIX, MatcherProfile.SIMPLE,
+ MatcherProfile.SIMPLE, MatcherProfile.SUFFIX);
+ }
+
+ /**
+ * Notifies this factory to which key part matcher profile the comparable
+ * elements will be created.
+ * <p>
+ * This method must always be called before the <code>
+ * MatcherFactory.createSequence</code> method.
+ *
+ * @param profile the matcher profile of the comparale key part whose
+ * elements will be created by this factory
+ *
+ * @return the profile of the element matcher sequence to be created. Should
+ * be used as a parameter to the <code>MatcherFactory.createSequence
+ * </code> method.
+ */
+ public MatcherSequenceProfile performCreationForProfile(
+ MatcherProfile profile)
+ {
+ this.loader = PrefixFunctionLoader.getLoaderForProfile(profile);
+ return profiles[profile.getId()];
+ }
+
+
+ public char getSeparator()
+ {
+ return '.';
+ }
+
+ /**
+ * Prepares a prefix function for loading a pattern when needed.
+ *
+ * @see #stopCreation()
+ */
+ public void startCreation()
+ {
+ loader.prepareForLoading();
+ }
+
+ /**
+ * Stops the process of loading a pattern for a prefix function.
+ *
+ * @see #startCreation()
+ */
+ public void stopCreation()
+ {
+ loader.loaded();
+ }
+
+ public Comparable create(String comparableExpression,
+ MatcherProfile matcherProfile)
+ {
+ return new ComparableElement(comparableExpression, loader);
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/package.html
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/package.html (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/element/package.html 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,48 @@
+<html>
+<head>
+<!--
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<title></title>
+</head>
+<body bgcolor="white">
+
+Implements the <code>search.match</code> package.
+
+
+
+<h2>Package Specification</h2>
+<p>
+In this package, the <code>Comparable</code> interface is implemented by the
+<code>ComparableElement</code> class, whose components are simple characters.
+</p>
+<p>
+This package contains the <code>ComparableFactory</code> implementation
+associated with <code>ComparableElement</code>, but not the <code>
+PrefixFunction</code> one, which is located in the <code>search.common</code>
+package.
+</p>
+
+<!-- Put @see and @since tags down here. -->
+ at see pointcutMatcher.tree.search.element.ComparableElement
+
+</body>
+</html>
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/Comparable.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/Comparable.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/Comparable.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,118 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * Represents a <i>matchable expression</i> part. Capable of comparing itself
+ * against a target, is utilized by the <code>Matcher</code> to execute the
+ * matching algorithm.
+ *
+ * @author Flavia Rainone
+ * @see Matcher
+ * @see org.jboss.aop.joinpoint.graph.tree.search.match
+ */
+public interface Comparable
+{
+ /**
+ * Returns the number of components contained in the post-prefix of this
+ * comparable.
+ *
+ * @return the number of components contained in the post-prefix of this
+ * comparable
+ */
+ int getPostPrefixLength();
+
+ /**
+ * Returns the character that identifies the next comparable component that
+ * will be compared.
+ *
+ * @param comparableIndex indicates the next comparable component to be
+ * compared
+ * @return the identifier of the next comparable component that will be
+ * compared. May be <code>Flags.ALL</code> if this information
+ * can not be asserted.
+ */
+ char getNextCharacter(Index comparableIndex, Object comparisonState);
+
+ /**
+ * Returns the character that identifies the next comparable component that
+ * will be compared.
+ * <p>
+ * The extra information provided by this method allows the comparable to
+ * return a more accurate result.
+ *
+ * @param comparableIndex indicates the next comparable component to be
+ * compared
+ * @param target the target of the last comparison executed
+ * (with a <code>ComparisonResult.TARGET_END</code>
+ * or <code>ComparisonResult.BOTH_ENDS</code>
+ * result)
+ * @param targetLengthRange the length range of <code>target</code>
+ * @return the identifier of the next comparable component that will be
+ * compared. May be <code>Flags.ALL</code> if this information
+ * can not be asserted.
+ */
+ char getNextCharacter(Index comparableIndex, Object target,
+ LengthRange targetLengthRange, Object comparisonState);
+
+ /**
+ * Returns the prefix function associated with this comparable.
+ * <p>
+ * Is involked only when the matcher associated with this comparable has the
+ * {@link MatcherProfile#PATTERN PATTERN} or the {@link MatcherProfile#SUFFIX
+ * SUFFIX} profile.
+ *
+ * @return the prefix function associated with this comparable
+ * @see PrefixFunction
+ */
+ PrefixFunction getPrefixFunction();
+
+ /**
+ * Compares the <i>matchable expression</i> part components with the target
+ * components one by one, until a mismatch is found or the end of components
+ * is reached.
+ *
+ * @param target the target of the comparison. Should be of a type
+ * compatible with this comparable
+ * @param targetIndex indicates from which target component the
+ * comparison should start
+ * @param comparableIndex indicates from which comparable component the
+ * comparison should start
+ * @param comparisonState the state of the comparison, stores data relevant
+ * about previous comparisons. The same state is
+ * passed to each <code>compare</code> call made by
+ * the matcher sequence. The comparable is
+ * responsible for storing, updating and retrieving
+ * the data contained in this state, according to its
+ * need. The comparison state is passed by the client
+ * as an argument to the {@link
+ * MatchingState#MatchingState(State)} constructor. If
+ * the client doesn't provide a comparison state,
+ * the value contained in this parameter could be
+ * anything, including <code>null</code>.
+ * @return a comparison result, indicating whether a mismatch was found, or
+ * if the comparison finished by reaching the comparable end,
+ * target end or both ends.
+ */
+ ComparisonResult compare(Object target, Index targetIndex,
+ Index comparableIndex, State comparisonState);
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparableFactory.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparableFactory.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparableFactory.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,72 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * Creates a comparable instance.
+ * <p>
+ * Is invoked by the <code>MatcherFactory.createSequence</code> method.
+ *
+ * @author Flavia Rainone
+ * @see MatcherFactory
+ */
+public interface ComparableFactory
+{
+ /**
+ * Returns the separator that will be used by the <code>MatcherFactory
+ * </code> class, to break the <code>matchableExpression</code> into the
+ * parts that will be attributed to comparables.
+ *
+ * @return the separator that will be used to break the <code>
+ * matchableExpression</code> into parts
+ */
+ char getSeparator();
+
+ /**
+ * Callback method. Notifies this factory that the <code>MatcherFactory
+ * </code> will start the creation of comparables.
+ */
+ void startCreation();
+
+ /**
+ * Callback method. Notifies this factory that the <code>MatcherFactory
+ * </code> will stop the creation of comparables.
+ */
+ void stopCreation();
+
+ /**
+ * Creates a comparable, able of comparing <code>comparableExpression</code>
+ * against a target.
+ * <p>
+ * Is invoked by <code>MatcherFactory.createSequence</code> method.
+ *
+ * @param comparableExpression a part of the <i>matchable expression</i>
+ * passed to the <code>createSequence</code>
+ * method.
+ * @param matcherProfile the profile of the matcher that will be
+ * associated with the comparable to be created
+ * @return the created comparable, able of comparing <code>
+ * comparableExpression</code> against a target.
+ */
+ Comparable create(String comparableExpression,
+ MatcherProfile matcherProfile);
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonAlgorithm.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonAlgorithm.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonAlgorithm.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,285 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+
+/**
+ * One of the components of <code>MatcherProfile</code>.
+ * <p>
+ * Determines how the <code>Comparable</code> functionality is used
+ * by the <code>Matcher</code> methods.
+ *
+ * @author Flavia Rainone
+ * @see Comparable
+ * @see Matcher
+ */
+abstract class ComparisonAlgorithm
+{
+ /**
+ * Algorithm that just compares the comparable with the target.
+ */
+ public static final ComparisonAlgorithm SIMPLE = new ComparisonAlgorithm(
+ "Simple Algorithm")
+ {
+
+ public ComparisonResult execute(Comparable comparable,
+ Index comparableIndex, Object target, Index targetIndex,
+ int targetLength, LengthRestriction restriction,
+ State comparisonState)
+ {
+ return comparable.compare(target, targetIndex, comparableIndex,
+ comparisonState);
+ }
+
+ public ComparisonResult execute(Comparable comparable,
+ Index comparableIndex, Object target, Index targetIndex,
+ LengthRange targetLengthRange, LengthRestriction restriction,
+ State comparisonState)
+ {
+ return comparable.compare(target, targetIndex, comparableIndex,
+ comparisonState);
+ }
+
+ public char getNextCharacter(Comparable comparable, Index comparableIndex,
+ Object target, LengthRange targetLengthRange,
+ MatchingState matchingState)
+ {
+ return comparable.getNextCharacter(comparableIndex, target,
+ targetLengthRange, matchingState.comparisonState);
+ }
+
+ public char getNextCharacter(Comparable comparable, Index comparableIndex,
+ MatchingState matchingState)
+ {
+ return comparable.getNextCharacter(comparableIndex,
+ matchingState.comparisonState);
+ }
+ };
+
+ /**
+ * KMP pattern matching algorithm, executes the comparison one or more times,
+ * updating the index values until a mismatch is not found and the comparison
+ * succeeds, or until the length restriction cannot be applied anymore. TODO bom?
+ */
+ public static final ComparisonAlgorithm KMP = new ComparisonAlgorithm(
+ "KMP Algorithm")
+ {
+
+ public ComparisonResult execute(Comparable comparable,
+ Index comparableIndex, Object target, Index targetIndex,
+ int targetLength, LengthRestriction restriction,
+ State comparisonState)
+ {
+ comparisonState.save();
+ ComparisonResult result = comparable.compare(target, targetIndex,
+ comparableIndex, comparisonState);
+ PrefixFunction prefixFunction = comparable.getPrefixFunction();
+
+ while (result == ComparisonResult.MISMATCH_FOUND)
+ {
+ if (comparableIndex.isInitialState())
+ {
+ targetIndex.increment();
+ }
+ else
+ {
+ prefixFunction.applyTo(comparableIndex);
+ }
+ if (! restriction.appliesTo(comparable, comparableIndex,
+ targetLength, targetIndex))
+ {
+ return ComparisonResult.MISMATCH_FOUND;
+ }
+ comparisonState.rollback();
+ result = comparable.compare(target, targetIndex, comparableIndex,
+ comparisonState);
+ }
+ return result;
+ }
+
+ public ComparisonResult execute(Comparable comparable,
+ Index comparableIndex, Object target, Index targetIndex,
+ LengthRange targetLengthRange, LengthRestriction restriction,
+ State comparisonState)
+ {
+ comparisonState.save();
+ ComparisonResult result = comparable.compare(target, targetIndex,
+ comparableIndex, comparisonState);
+ PrefixFunction prefixFunction = comparable.getPrefixFunction();
+ while (result == ComparisonResult.MISMATCH_FOUND)
+ {
+ if (comparableIndex.isInitialState())
+ {
+ targetIndex.increment();
+ }
+ else
+ {
+ prefixFunction.applyTo(comparableIndex);
+ }
+ if (! restriction.appliesTo(comparable, comparableIndex,
+ targetLengthRange, targetIndex))
+ {
+ return ComparisonResult.MISMATCH_FOUND;
+ }
+ comparisonState.rollback();
+ result = comparable.compare(target, targetIndex, comparableIndex,
+ comparisonState);
+ }
+ return result;
+ }
+
+ public char getNextCharacter(Comparable comparable, Index comparableIndex,
+ Object target, LengthRange targetLengthRange, MatchingState state)
+ {
+ return state.getNextCharacter(comparable, comparableIndex, target,
+ targetLengthRange);
+ }
+
+ public char getNextCharacter(Comparable comparable, Index comparableIndex,
+ MatchingState state)
+ {
+ return state.getNextCharacter(comparable, comparableIndex);
+ }
+ };
+
+
+ /**
+ * A string that describes this algorithm.
+ */
+ private String description;
+
+ /**
+ * Private constructor.
+ */
+ private ComparisonAlgorithm(String description)
+ {
+ this.description = description;
+ }
+
+ /**
+ * Executes the algorithm, making use of the <code>comparable</code>
+ * functionality to compare it against the target.
+ * <p>
+ * Is invoked when <code>target</code> has no suffixes.
+ *
+ * @param comparable object that will be compared with <code>target
+ * </code>
+ * @param comparableIndex indicates from which <code>comparable</code>
+ * component the comparison will start
+ * @param target the target of the comparison
+ * @param targetIndex indicates from which target component the
+ * comparison will start
+ * @param targetLength the number of components contained in <code>
+ * target</code>
+ * @param restriction the length restriction that applies to this
+ * scenario. Every time the indexes values are
+ * changed outside of a comparison, this
+ * restriction must be applied again.
+ * @param comparisonState the state of comparison, is passed along to
+ * <code>comparable</code> on every comparison
+ * performed by it.
+ * @return the result of the comparison
+ */
+ public abstract ComparisonResult execute(Comparable comparable,
+ Index comparableIndex, Object target, Index targetIndex,
+ int targetLength, LengthRestriction restriction,
+ State comparisonState);
+
+ /**
+ * Executes the algorithm, making use of the <code>comparable</code>
+ * functionality to compare it against the target.
+ * <p>
+ * Is invoked when <code>target</code> has one or more suffixes.
+ *
+ * @param comparable object that will be compared with <code>target
+ * </code>
+ * @param comparableIndex indicates from which <code>comparable</code>
+ * component the comparison will start
+ * @param target the target of the comparison
+ * @param targetIndex indicates from which target component the
+ * comparison will start
+ * @param targetLengthRange the minimum-maximum range of the
+ * <code>target</code> suffixes and pos-prefixes
+ * length
+ * @param restriction the length restriction that applies to this
+ * scenario. Every time the indexes values are
+ * changed outside of a comparison, this
+ * restriction must be applied again.
+ * @param comparisonState the state of comparison, is passed along to
+ * <code>comparable</code> on every comparison
+ * performed by it.
+ * @return the result of the comparison
+ */
+ public abstract ComparisonResult execute(Comparable comparable,
+ Index comparableIndex, Object target, Index targetIndex,
+ LengthRange targetLengthRange, LengthRestriction restriction,
+ State comparisonState);
+
+ /**
+ * Returns the character that identifies the next target to be compared by
+ * this algorithm with a successful result. If a target not identified by
+ * this character is compared, the result will be certainly <code>
+ * ComparisonResult.MISMATCH_FOUND</code>.
+ * <p>
+ * Is invoked when the <code>target</code> and its length range are known.
+ *
+ * @param comparable object that will perform the next comparison
+ * @param comparableIndex indicates from which <code>comparable</code>
+ * component the comparison will start
+ * @param target the target of the last algorithm execution
+ * (with a <code>ComparisonResult.TARGET_END</code>
+ * or <code>ComparisonResult.BOTH_ENDS</code>
+ * result)
+ * @param targetLengthRange the length range of <code>target</code>
+ * @param matchingState the state of the matching process
+ * @return the character that identifies the next target to be compared by
+ * this algorithm with a successful result. May be <code>Flags.ALL
+ * </code> to indicate that any target may have a successful result.
+ */
+ public abstract char getNextCharacter(Comparable comparable,
+ Index comparableIndex, Object target, LengthRange targetLengthRange,
+ MatchingState matchingState);
+
+ /**
+ * Returns the character that identifies the next target to be compared by
+ * this algorithm with a successful result. If a target not identified by
+ * this character is compared, the result will be certainly <code>
+ * ComparisonResult.MISMATCH_FOUND</code>.
+ * <p>
+ * Is invoked when the last compared target and its length range are unknown.
+ *
+ * @param comparable object that will perform the next comparison
+ * @param comparableIndex indicates from which <code>comparable</code>
+ * component the comparison will start
+ * @param matchingState the state of the matching process
+ * @return the character that identifies the next target to be compared by
+ * this algorithm with a successful result. May be <code>Flags.ALL
+ * </code> to indicate that any target may have a successful result.
+ */
+ public abstract char getNextCharacter(Comparable comparable,
+ Index comparableIndex, MatchingState matchingState);
+
+ public String toString()
+ {
+ return this.description;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonEndState.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonEndState.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonEndState.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,242 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+import org.jboss.aop.joinpoint.graph.tree.search.Flags;
+
+/**
+ * This state indicates the relationship between the number of available
+ * comparable components and the maximum number of available target components
+ * (available components are those that still need to be compared and matched).
+ * In other words, it indicates how close to the end of the longest complete
+ * target the current comparison will finish, in case of a positive comparison
+ * result.
+ *
+ * @author Flavia Rainone
+ */
+public abstract class ComparisonEndState
+{
+ /**
+ * Loose state, indicates that the number of available comparable components
+ * is less than the maximum number of available target components.
+ */
+ public static final ComparisonEndState LOOSE =
+ new ComparisonEndState("Loose")
+ {
+ public void update(MatchingState state, Comparable comparable,
+ Index comparableIndex, int targetPostPrefixMaxLength,
+ Index targetIndex)
+ {
+ if ((targetPostPrefixMaxLength - targetIndex.getValue()) <=
+ (comparable.getPostPrefixLength() - comparableIndex.getValue()))
+ {
+ state.comparisonEndState= TIGHT;
+ }
+ }
+
+ public void tightenComparison(MatchingState state, Comparable comparable,
+ Index comparableIndex, int targetPostPrefixMinLength,
+ Index targetIndex)
+ {
+ int difference = comparable.getPostPrefixLength() -
+ targetPostPrefixMinLength + targetIndex.getValue();
+ if (difference < 0)
+ {
+ targetIndex.increment(- difference);
+ comparableIndex.reset();
+ }
+ PrefixFunction prefixFunction = comparable.getPrefixFunction();
+ while (comparableIndex.getValue() != 0 &&
+ comparableIndex.getValue() > difference)
+ {
+ prefixFunction.applyTo(comparableIndex);
+ }
+ }
+
+ public char getNextCharacter(MatchingState state, Comparable comparable,
+ Index comparableIndex, Object target,
+ LengthRange targetLengthRange)
+ {
+ if (targetLengthRange.getSuffixMaxLength() <=
+ (comparable.getPostPrefixLength() - comparableIndex.getValue()))
+ {
+ state.comparisonEndState = TIGHT;
+ return comparable.getNextCharacter(comparableIndex, target,
+ targetLengthRange, state.comparisonState);
+ }
+ return Flags.ALL;
+ }
+
+ public char getNextCharacter(MatchingState state, Comparable comparable,
+ Index comparableIndex)
+ {
+ return Flags.ALL;
+ }
+ };
+
+ /**
+ * Tight state, indicates that the number of available comparable components
+ * is equal to the maximum number of available target components.
+ */
+ public static final ComparisonEndState TIGHT =
+ new ComparisonEndState("Tight")
+ {
+ public void update(MatchingState state, Comparable comparable,
+ Index comparableIndex, int targetPostPrefixMaxLength,
+ Index targetIndex)
+ {}
+
+ public void tightenComparison(MatchingState state, Comparable comparable,
+ Index comparableIndex, int targetPostPrefixMinLength,
+ Index targetIndex)
+ {}
+
+ public char getNextCharacter(MatchingState state, Comparable comparable,
+ Index comparableIndex, Object target,
+ LengthRange targetLengthRange)
+ {
+ return comparable.getNextCharacter(comparableIndex, target,
+ targetLengthRange, state.comparisonState);
+ }
+
+ public char getNextCharacter(MatchingState state, Comparable comparable,
+ Index comparableIndex)
+ {
+ return comparable.getNextCharacter(comparableIndex,
+ state.comparisonState);
+ }
+ };
+
+ /**
+ * A string that describes this comparison end state.
+ */
+ private String description;
+
+ /**
+ * Private constructor.
+ */
+ private ComparisonEndState(String description)
+ {
+ this.description = description;
+ }
+
+ /**
+ * Updates the current comparison end state.
+ *
+ * @param state the matching state, that contains the
+ * current comparison end state
+ * @param comparable the comparable that will perform the next
+ * comparison
+ * @param comparableIndex indicates from which <code>comparable
+ * </code> component the next comparison
+ * will start
+ * @param targetPostPrefixMaxLength the length of the biggest target
+ * post-prefix
+ * @param targetIndex indicates from which target component
+ * the next comparison will start
+ *
+ */
+ public abstract void update(MatchingState state, Comparable comparable,
+ Index comparableIndex, int targetPostPrefixMaxLength,
+ Index targetIndex);
+
+ /**
+ * Tightens the comparison, incrementing <code>targetIndex</code> until
+ * the minimum number of available target components becomes the same as
+ * the number of the availble <code>comparable</code> components.
+ *
+ * @param state the matching state, contains the current
+ * comparison end state
+ * @param comparable the comparable that will perform the next
+ * comparison
+ * @param comparableIndex indicates from which <code>comparable
+ * </code> component the next comparison
+ * will start. This index value may be
+ * changed accordingly to the changes made
+ * to <code>targetIndex</code> value.
+ * @param targetPostPrefixMinLength the length of the smallest target
+ * post-prefix
+ * @param targetIndex indicates from which target component the
+ * next comparison will start. The value of
+ * this index may be changed by this method,
+ * in order to tighten comparison.
+ */
+ public abstract void tightenComparison(MatchingState state,
+ Comparable comparable, Index comparableIndex,
+ int targetPostPrefixMinLength, Index targetIndex);
+
+ /**
+ * Returns the character that identifies the next target to be compared
+ * with a positive result (i.e., with no mismatches found). If a target not
+ * identified by this character is compared, the result will be certainly
+ * a {@link ComparisonResult#MISMATCH_FOUND mismatch}.
+ * <p>
+ * Is invoked when the last target compared and/or its length range are
+ * unknown.
+ *
+ * @param state the matching state, stores the current comparison
+ * end state
+ * @param comparable the comparable that will perform the next
+ * comparison
+ * @param comparableIndex indicates from which <code>comparable</code>
+ * component the next comparison will start
+ * @return the character that identifies the next target to
+ * be compared with a positive result. May return
+ * {@link Flags#ALL} to indicate that any target may
+ * have a positive result.
+ */
+ public abstract char getNextCharacter(MatchingState state,
+ Comparable comparable, Index comparableIndex);
+
+ /**
+ * Returns the character that identifies the next target to be compared
+ * with a positive result (i.e., with no mismatches found). If a target not
+ * identified by this character is compared, the result will be certainly
+ * a {@link ComparisonResult#MISMATCH_FOUND mismatch}.
+ * <p>
+ * Is invoked when <code>target</code> and <code>targetLengthRange</code>
+ * are known.
+ *
+ * @param state the matching state, stores the current comparison
+ * end state
+ * @param comparable the comparable that will perform the next
+ * comparison
+ * @param comparableIndex indicates from which <code>comparable</code>
+ * component the next comparison will start
+ * @param target the object that will be compared to <code>
+ * comparable</code>
+ * @param targetLengthRange the minimum-maximum length range of the target
+ * suffixes and post-prefixes
+ * @return the character that identifies the next target to
+ * be compared with a positive result. May return
+ * {@link Flags#ALL} to indicate that any target may
+ * have a positive result.
+ */
+ public abstract char getNextCharacter(MatchingState state,
+ Comparable comparable, Index comparableIndex, Object target,
+ LengthRange targetLengthRange);
+
+ public String toString()
+ {
+ return description;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonResult.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonResult.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonResult.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,119 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * This class is a singleton whose instances represent the result of a
+ * comparison (type enum pattern, of Joshua Block).
+ *
+ * @author Flavia Rainone
+ * @see Comparable#compare
+ */
+public class ComparisonResult
+{
+ /**
+ * Indicates that only the comparable's end was reached during the
+ * comparison.
+ */
+ public static final ComparisonResult COMPARABLE_END =
+ new ComparisonResult("Comparable Expression End");
+
+ /**
+ * Indicates that both the comparable and the target reached their ends
+ * during the comparison.
+ */
+ public static final ComparisonResult BOTH_ENDS =
+ new ComparisonResult("End of Both Expressions");
+
+ /**
+ * Indicates that none of the parts involved reached their ends during the
+ * comparison, because a mismatch was found.
+ */
+ public static final ComparisonResult MISMATCH_FOUND =
+ new ComparisonResult("Mismatch Found");
+
+ /**
+ * Indicates that only the target's end was reached during the comparison.
+ */
+ public static final ComparisonResult TARGET_END =
+ new ComparisonResult("Target Expression End");
+
+ /**
+ * Returns the instance of <code>ComparisonResult</code> that represents
+ * the comparison outcome contained in the <code>compEnd</code> and <code>
+ * targetEnd</code> parameters.
+ *
+ * @param compEnd <code>true</code> if the comparable's end was reached
+ * during comparison
+ * @param targetEnd <code>true</code> if the target's end was reached during
+ * comparison
+ * @return the appropriate comparison result
+ */
+ public static ComparisonResult getInstance(boolean compEnd,
+ boolean targetEnd)
+ {
+ int id = 2 + (compEnd? -2: 0) + (targetEnd? + 1: 0);
+ return INSTANCES[id];
+ }
+
+ /**
+ * Returns the number of <code>ComparisonResult</code> instances.
+ *
+ * @return the number of <code>ComparisonResult</code> instances
+ */
+ public static final int getNumberOfInstances()
+ {
+ return INSTANCES.length;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ /** Contains all instances. */
+ private static ComparisonResult[] INSTANCES = new ComparisonResult[] {
+ COMPARABLE_END, BOTH_ENDS, MISMATCH_FOUND, TARGET_END};
+
+ /** Used to generate ids for the instances.*/
+ private static int ID_COUNTER = 0;
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ /** Identifier of this comparison result. */
+ private int id;
+
+ /** String that describes this comparison result. */
+ private String description;
+
+ /**
+ * Private constructor.
+ *
+ * @param description the description of the comparison result to be created.
+ */
+ private ComparisonResult(String description)
+ {
+ this.description = description;
+ id = ID_COUNTER++;
+ }
+
+ /**
+ * Returns the id of the <code>ComparisonResult</code> instance.
+ *
+ * @return an id. Notice that all <code>ComparisonResult</code> instances
+ * have an id, which is different for each instance. The smallest id
+ * is <code>0</code>, and for each existent id <code>i</code> there
+ * is also an id <code>i - 1</code> if <code>i</code> > <code>1
+ * </code>.
+ */
+ public int getId()
+ {
+ return id;
+ }
+
+ public String toString(){
+ return this.description;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonStart.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonStart.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonStart.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,130 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * One of the components of <code>MatcherProfile</code>.
+ * <p>
+ * Tunes the comparable and target indexes before a comparison is executed.
+ *
+ * @author Flavia Rainone
+ * @see MatcherProfile
+ */
+abstract class ComparisonStart
+{
+ /**
+ * Loose comparison start, keeps the indexes unchanged.
+ */
+ public static final ComparisonStart LOOSE = new ComparisonStart(
+ "Loose Comparison Start")
+ {
+ public void tuneIndex(Comparable comparable, Index comparableIndex,
+ int targetLength, Index targetIndex, MatchingState state)
+ {}
+ public boolean tuneIndex(Comparable comparable, Index comparableIndex,
+ LengthRange targetLengthRange, Index targetIndex,
+ MatchingState state)
+ {
+ return false;
+ }
+ };
+
+ /**
+ * Tight comparison start, increments the indexes until the number of
+ * available comparable components and the minimum number of available target
+ * components become the same (the number of available components it the
+ * number of components that still need to be compared and matched).
+ *
+ * @see MatchingState#tightenComparison(Comparable, Index, int, Index)
+ * @see MatchingState#tightenComparison(Comparable, Index, LengthRange, Index)
+ */
+ public static final ComparisonStart TIGHT = new ComparisonStart(
+ "Tight Comparison Start")
+ {
+ public void tuneIndex(Comparable comparable, Index comparableIndex,
+ int targetLength, Index targetIndex, MatchingState state)
+ {
+ state.tightenComparison(comparable, comparableIndex, targetLength,
+ targetIndex);
+ }
+
+ public boolean tuneIndex(Comparable comparable, Index comparableIndex,
+ LengthRange targetLengthRange, Index targetIndex,
+ MatchingState state)
+ {
+ return state.tightenComparison(comparable, comparableIndex,
+ targetLengthRange, targetIndex);
+ }
+ };
+
+
+ /**
+ * String that describes this comparison start.
+ */
+ private String description;
+
+ /**
+ * Private constructor.
+ */
+ private ComparisonStart(String description)
+ {
+ this.description = description;
+ }
+
+ /**
+ * Tunes the indexes to indicate from which <code>comparable</code> and
+ * target components comparison should start.
+ * <p>
+ * Is called when the target of the comparison has no suffixes.
+ *
+ * @param comparable object that will perform the comparison
+ * @param comparableIndex the comparable index before being tuned
+ * @param targetLength the length of the comparison target
+ * @param targetIndex the index of the target before being tuned
+ * @param state the state of the matching process
+ */
+ public abstract void tuneIndex(Comparable comparable, Index comparableIndex,
+ int targetLength, Index targetIndex, MatchingState state);
+
+ /**
+ * Tunes the indexes to indicate from which <code>comparable</code> and
+ * target components comparison should start.
+ * <p>
+ * Is called when the target of the comparison has one or more suffixes.
+ *
+ * @param comparable object that will perform the comparison
+ * @param comparableIndex the comparable index before being tuned
+ * @param targetLengthRange the length range of the comparison target
+ * @param targetIndex the index of the target before being tuned
+ * @param state the state of the matching process
+ * @return <code>true</code> if the comparison start is postponed to be
+ * performed on the target suffixes; <code>false</code> otherwise.
+ */
+ public abstract boolean tuneIndex(Comparable comparable,
+ Index comparableIndex,
+ LengthRange targetLengthRange, Index targetIndex, MatchingState state);
+
+ public String toString()
+ {
+ return this.description;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonStartState.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonStartState.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/ComparisonStartState.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,261 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+import org.jboss.aop.joinpoint.graph.tree.search.Flags;
+
+/**
+ * This state indicates whether comparison will start with the current target or
+ * with one of its suffixes.
+ *
+ * @author Flavia Rainone
+ */
+public abstract class ComparisonStartState
+{
+ /**
+ * Indicates the next comparison will start executing with the current
+ * target.
+ */
+ public static final ComparisonStartState CURRENT_TARGET =
+ new ComparisonStartState("Current Target")
+ {
+ public void update(MatchingState state, Index targetIndex,
+ LengthRange targetLengthRange)
+ {
+ if (targetLengthRange.getPostPrefixMaxLength() == 0)
+ {
+ return;
+ }
+ if (targetIndex.getValue() > targetLengthRange.getLength())
+ {
+ state.comparisonStartState = ComparisonStartState.NEXT_SUFFIXES;
+ }
+ else if (targetIndex.getValue() == targetLengthRange.getLength() &&
+ targetIndex.getValue() ==
+ targetLengthRange.getPostPrefix_SuffixDiff())
+ {
+ state.comparisonStartState =
+ ComparisonStartState.NEXT_SUFFIX_FIRST_COMPONENT;
+ }
+ else
+ {
+ return;
+ }
+ targetIndex.comparisonPostponed();
+ }
+
+ public char getNextCharacter(MatchingState state, Comparable comparable,
+ Index comparableIndex, Object target, LengthRange targetLengthRange)
+ {
+ return state.comparisonEndState.getNextCharacter(state, comparable,
+ comparableIndex, target, targetLengthRange);
+ }
+
+ public char getNextCharacter(MatchingState state, Comparable comparable,
+ Index comparableIndex)
+ {
+ return state.comparisonEndState.getNextCharacter(state, comparable,
+ comparableIndex);
+ }
+
+ public boolean isComparisonPostponed()
+ {
+ return false;
+ }
+ };
+
+ /**
+ * Indicates the next comparison will start executing with the first
+ * component of the next target suffixes.
+ */
+ public static final ComparisonStartState NEXT_SUFFIX_FIRST_COMPONENT =
+ new ComparisonStartState("First Component of Next Suffix")
+ {
+ public void update(MatchingState state, Index targetIndex,
+ LengthRange targetLengthRange)
+ {
+ if (targetLengthRange.getPostPrefixMaxLength() == 0 ||
+ targetIndex.getValue() < targetLengthRange.getLength())
+ {
+ state.comparisonStartState = ComparisonStartState.CURRENT_TARGET;
+ targetIndex.comparisonReady();
+ }
+ else if (targetIndex.getValue() !=
+ targetLengthRange.getPostPrefix_SuffixDiff())
+ {
+ state.comparisonStartState = ComparisonStartState.NEXT_SUFFIXES;
+ }
+ }
+
+ public char getNextCharacter(MatchingState state, Comparable comparable,
+ Index comparableIndex, Object target, LengthRange targetLengthRange)
+ {
+ return state.comparisonEndState.getNextCharacter(state, comparable,
+ comparableIndex, target, targetLengthRange);
+ }
+
+ public char getNextCharacter(MatchingState state, Comparable comparable,
+ Index comparableIndex)
+ {
+ return state.comparisonEndState.getNextCharacter(state, comparable,
+ comparableIndex);
+ }
+
+ public boolean isComparisonPostponed()
+ {
+ return true;
+ }
+ };
+
+ /**
+ * Indicates the next comparison will start executing with some component
+ * of the next target suffixes.
+ */
+ public static final ComparisonStartState NEXT_SUFFIXES =
+ new ComparisonStartState("Next Suffixes")
+ {
+ public void update(MatchingState state, Index targetIndex,
+ LengthRange targetLengthRange)
+ {
+ if (targetLengthRange.getPostPrefixMaxLength() == 0 ||
+ targetIndex.getValue() < targetLengthRange.getLength())
+ {
+ state.comparisonStartState = ComparisonStartState.CURRENT_TARGET;
+ targetIndex.comparisonReady();
+ }
+ else if (targetIndex.getValue() ==
+ targetLengthRange.getPostPrefix_SuffixDiff())
+ {
+ state.comparisonStartState =
+ ComparisonStartState.NEXT_SUFFIX_FIRST_COMPONENT;
+ }
+ }
+
+ public char getNextCharacter(MatchingState state, Comparable comparable,
+ Index comparableIndex, Object target, LengthRange targetLengthRange)
+ {
+ return Flags.ALL;
+ }
+
+ public char getNextCharacter(MatchingState state, Comparable comparable,
+ Index comparableIndex)
+ {
+ return Flags.ALL;
+ }
+
+ public boolean isComparisonPostponed()
+ {
+ return true;
+ }
+ };
+
+
+ /**
+ * A string that describes this comparison start state.
+ */
+ private String description;
+
+ /**
+ * Private constructor.
+ */
+ private ComparisonStartState(String description)
+ {
+ this.description = description;
+ }
+
+ /**
+ * Updates the current comparison start state.
+ *
+ * @param state the matching state, that contains the
+ * current comparison start state
+ * @param targetIndex indicates from which target component
+ * the next comparison will start
+ * @param targetLengthRange the minimum-maximum length range of the target
+ * suffixes and post-prefixes
+ */
+ public abstract void update(MatchingState state,
+ Index targetIndex, LengthRange targetLengthRange);
+
+ /**
+ * Returns the character that identifies the next target to be compared
+ * with a positive result (i.e., with no mismatches found). If a target not
+ * identified by this character is compared, the result will be certainly
+ * a {@link ComparisonResult#MISMATCH_FOUND mismatch}.
+ * <p>
+ * Is invoked when <code>target</code> and <code>targetLengthRange</code>
+ * are known.
+ *
+ * @param state the matching state, stores the current comparison
+ * start state
+ * @param comparable the comparable that will perform the next
+ * comparison
+ * @param comparableIndex indicates from which <code>comparable</code>
+ * component the next comparison will start
+ * @param target the object that will be compared to <code>
+ * comparable</code>
+ * @param targetLengthRange the minimum-maximum length range of the target
+ * suffixes and post-prefixes
+ * @return the character that identifies the next target to
+ * be compared with a positive result. May return
+ * {@link Flags#ALL} to indicate that any target may
+ * have a positive result.
+ */
+ public abstract char getNextCharacter(MatchingState state,
+ Comparable comparable, Index comparableIndex, Object target,
+ LengthRange targetLengthRange);
+
+ /**
+ * Returns the character that identifies the next target to be compared
+ * with a positive result (i.e., with no mismatches found). If a target not
+ * identified by this character is compared, the result will be certainly
+ * a {@link ComparisonResult#MISMATCH_FOUND mismatch}.
+ * <p>
+ * Is invoked when the last target compared and/or its length range are
+ * unknown.
+ *
+ * @param state the matching state, stores the current comparison
+ * start state
+ * @param comparable the comparable that will perform the next
+ * comparison
+ * @param comparableIndex indicates from which <code>comparable</code>
+ * component the next comparison will start
+ * @return the character that identifies the next target to
+ * be compared with a positive result. May return
+ * {@link Flags#ALL} to indicate that any target may
+ * have a positive result.
+ */
+ public abstract char getNextCharacter(MatchingState state,
+ Comparable comparable, Index comparableIndex);
+
+ /**
+ * Returns a boolean indicating whether this state indicates that the
+ * comparison is postponed to start with a target suffix.
+ * @return <code>true</code> if comparison is postponed to a target suffix;
+ * <code>false</code> otherwise.
+ */
+ public abstract boolean isComparisonPostponed();
+
+ public String toString()
+ {
+ return this.description;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/Index.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/Index.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/Index.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,217 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * Indicates from which target or comparable component a comparison will start.
+ * <p>
+ * Can be extended to store additional information about the comparable and
+ * target components.
+ *
+ * @author Flavia Rainone
+ */
+public class Index
+{
+ /**
+ * Indicates from which component comparison should start.
+ */
+ private int value;
+
+ /**
+ * Indicates comparison has been postponed to a target suffix.
+ * <p>
+ * When this field equals <code>true</code>, <code>value</code> is greater
+ * than the target length.
+ */
+ private boolean postponedComparison;
+
+ /**
+ * Constructor.
+ * <p>
+ * Creates an index with zero value.
+ */
+ public Index ()
+ {
+ this.value = 0;
+ }
+
+ /**
+ * Returns the value of the index.
+ *
+ * @return the index value, indicates from which component comparison should
+ * start
+ */
+ public final int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Indicates if this index is in its initial state, which means its
+ * value is zero.
+ * <p>
+ * Clients can overwrite this method when there is additional data that
+ * defines whether an index is in its initial state or not.
+ *
+ * @return <code>true</code> if this index is in its initial value; <code>
+ * false</code> otherwise.
+ */
+ public boolean isInitialState()
+ {
+ return this.value == 0;
+ }
+
+ /**
+ * This method should be called only by <code>PrefixFunction</code>
+ * implementations, to redefine the index as being its correspondent prefix
+ * function value.
+ *
+ * @param value the prefix function value of this index
+ * @see PrefixFunction
+ */
+ public void applyPrefixFunction(int value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Increments the index value by one.
+ */
+ public final void increment()
+ {
+ increment(1);
+ }
+
+ /**
+ * Increments the index value by <code>increment</code> units.
+ *
+ * @param increment the number of units by which the index value will be
+ * incremented
+ */
+ public final void increment(int increment)
+ {
+ this.value += increment;
+ this.valueChanged();
+ }
+
+ /**
+ * Increments the current index value by <code>increment</code> units,
+ * without triggering the {@link #valueChanged() valueChanged} callback
+ * method.
+ *
+ * @param increment the number of units by which the index value will be
+ * incremented
+ */
+ protected final void noCallBackIncrement(int increment)
+ {
+ this.value += increment;
+ }
+
+ /**
+ * Resets the index value to zero. After this method is executed, this <code>
+ * Index</code> will be the same as an index created by the default
+ * constructor.
+ * <p>
+ * This method provides a way of avoiding the cost of creating new instances.
+ */
+ public final void reset()
+ {
+ this.value = 0;
+ this.valueChanged();
+ }
+
+ /**
+ * Copies <code>indexToCopy</code>, so that this index becomes equivalent to
+ * <code>indexToCopy</code>.
+ *
+ * @param indexToCopy index whose values will be copied
+ */
+ public void copy(Index indexToCopy)
+ {
+ this.value = indexToCopy.value;
+ this.postponedComparison = indexToCopy.postponedComparison;
+ }
+
+ /**
+ * Notifies this index that comparison is postponed to a target suffix.
+ * <p>
+ * This method is invoked only for target indexes.
+ */
+ public final void comparisonPostponed()
+ {
+ this.postponedComparison = true;
+ }
+
+ /**
+ * Notifies this index that comparison is not postponed anymore. It is ready
+ * to start with the current target.
+ * <p>
+ * This method is always invoked after {@link #comparisonPostponed()}.
+ */
+ public final void comparisonReady()
+ {
+ this.postponedComparison = false;
+ }
+
+ /**
+ * Subtracts the apropriate number from this index value, so that this
+ * index becomes valid for matching the target suffixes.
+ * <p>
+ * For example, if this index value is 5, and the target length is 3, this
+ * index value could be updated to 2, to indicate comparison should start
+ * in the third target suffix component. Notice that not necessarily the
+ * target length is the number subtracted by this index value. This number
+ * is chosen according to whether the comparison is postponed. If it is not,
+ * the target length itself is subtracted. If it is postponed, the result of
+ * {@link LengthRange#getPostPrefix_SuffixDiff()
+ * targetLengthRange.getPostPrefix_SuffixDiff()} is the number subtracted.
+ * <p>
+ * This method is invoked only for target indexes.
+ *
+ * @param targetLengthRange the length range of the last matched target (with
+ * a {@link MatchingResult#PARTIAL_MATCH partial
+ * match} result)
+ */
+ public final void update(LengthRange targetLengthRange)
+ {
+ if (postponedComparison) // comparison was postponed to a target suffix
+ {
+ this.value -= targetLengthRange.getPostPrefix_SuffixDiff();
+ }
+ else // !comparisonPostponed means comparison took place
+ {
+ this.value = 0; // = value - targetLengthRange.getLength();
+ }
+ }
+
+ /**
+ * Callback method, called everytime the index value is changed by
+ * the <code>increment</code> or <code>reset</code> methods.
+ */
+ protected void valueChanged()
+ {}
+
+ public String toString()
+ {
+ return String.valueOf(this.value);
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/LengthRange.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/LengthRange.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/LengthRange.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,217 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * Provides information about the length of a target, its suffixes and
+ * post-prefixes.
+ * <p>
+ * This class assumes as default that a suffix length is equal to the length of
+ * the correspondent post-prefix length minus the target length. The client
+ * can change this by extending this class and overriding the
+ * {@link #getPostPrefix_SuffixDiff()} method.
+ *
+ * @author Flavia Rainone
+ *
+ */
+public class LengthRange
+{
+ /**
+ * The number of components contained in the target.
+ */
+ private byte length;
+
+ /**
+ * The number of components contained in the smallest target post-prefix.
+ */
+ private byte postPrefixMinLength;
+
+ /**
+ * The number of components contained in the biggest target post-prefix.
+ */
+ private byte postPrefixMaxLength;
+
+ /**
+ * Constructor, creates an object that provides information about the
+ * length of the suffix and post-prefix of a target.
+ * <p>
+ * Should be called when the target has only one suffix.
+ *
+ * @param length the number of components contained in the
+ * target
+ * @param postPrefixLength the number of components contained in the
+ * target post-prefix
+ */
+ public LengthRange(byte length, byte postPrefixLength)
+ {
+ this(length, postPrefixLength, postPrefixLength);
+ }
+
+ /**
+ * Constructor, creates an object that provides information about the
+ * length of the suffixes and post-prefixes of a target.
+ * <p>
+ * Should be called when the target has more than one suffix.
+ *
+ * @param length the number of components contained in the
+ * target
+ * @param postPrefixMinLength the number of components contained in the
+ * smallest target post-prefix
+ * @param postPrefixMaxLength the number of components contained in the
+ * biggest target post-prefix
+ */
+ public LengthRange(byte length, byte postPrefixMinLength,
+ byte postPrefixMaxLength)
+ {
+ this.length = length;
+ this.postPrefixMinLength = postPrefixMinLength;
+ this.postPrefixMaxLength = postPrefixMaxLength;
+ }
+
+ /**
+ * Resets the data contained in this intance.
+ * <p>
+ * This method avoids the cost of creating a new instance since, once this
+ * method is executed, this length range will be equal to the result of
+ * calling the constructor with the same parameters.
+ *
+ * @param length the number of components contained in the
+ * target
+ * @param postPrefixMinLength the number of components contained in the
+ * smallest target post-prefix
+ * @param postPrefixMaxLength the number of components contained in the
+ * biggest target post-prefix
+ */
+ public final void reset(byte length, byte postPrefixMinLength,
+ byte postPrefixMaxLength)
+ {
+ this.length = length;
+ this.postPrefixMinLength = postPrefixMinLength;
+ this.postPrefixMaxLength = postPrefixMaxLength;
+ }
+
+ /**
+ * Returns the number of components contained in the target.
+ *
+ * @return the number of components contained in the target
+ */
+ public final byte getLength()
+ {
+ return this.length;
+ }
+
+ /**
+ * Returns the number that must be subtracted from a post-prefix length
+ * to retrieve the correpondent suffix length.
+ * <p>
+ * This implementation returns the target length, but can be ovewritten by
+ * the client as needed.
+ *
+ * @return the length of the target
+ */
+ public byte getPostPrefix_SuffixDiff()
+ {
+ return this.length;
+ }
+
+ /**
+ * Returns the number of components contained in the smallest suffix.
+ *
+ * @return the number of components contained in the smallest suffix
+ */
+ public final byte getSuffixMinLength()
+ {
+ return (byte) (this.postPrefixMinLength -
+ this.getPostPrefix_SuffixDiff());
+ }
+
+ /**
+ * Returns the number of components contained in the biggest suffix.
+ *
+ * @return the number of components contained in the biggest suffix
+ */
+ public final byte getSuffixMaxLength()
+ {
+ return (byte) (this.postPrefixMaxLength -
+ this.getPostPrefix_SuffixDiff());
+ }
+
+ /**
+ * Returns the number of components contained in the smallest target
+ * post-prefix.
+ *
+ * @return the number of components contained in the smallest target
+ * post-prefix
+ */
+ public final byte getPostPrefixMinLength()
+ {
+ return this.postPrefixMinLength;
+ }
+
+ /**
+ * Returns the number of components contained in the biggest target
+ * post-prefix.
+ *
+ * @return the number of components contained in the biggest target
+ * post-prefix
+ */
+ public final byte getPostPrefixMaxLength()
+ {
+ return this.postPrefixMaxLength;
+ }
+
+ /**
+ * Updates the length range of a target.
+ * <p>
+ * Should be called when a new suffix is added to the target.
+ *
+ * @param newPostPrefixLength the number of components contained in the
+ * concatenation of the target and its new suffix
+ */
+ public final void update(byte newPostPrefixLength)
+ {
+ this.update(newPostPrefixLength, newPostPrefixLength);
+ }
+
+ /**
+ * Updates the length range of a target.
+ * <p>
+ * Should be called when a new suffix group is added to the target.
+ *
+ * @param ppMinLength the number of components contained in the concatenation
+ * of the target and the smallest suffix in the group
+ * @param ppMaxLength the number of components contained in the concatenation
+ * of the target and the biggest suffix in the group
+ */
+ public final void update(byte ppMinLength, byte ppMaxLength)
+ {
+ postPrefixMinLength = (byte) Math.min(postPrefixMinLength, ppMinLength);
+ postPrefixMaxLength = (byte) Math.max(postPrefixMaxLength, ppMaxLength);
+ }
+
+ public String toString()
+ {
+ return "[length=" + this.length + ", ppMinLength=" +
+ this.postPrefixMinLength + ", ppMaxLength=" + this.postPrefixMaxLength
+ + "]";
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/LengthRestriction.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/LengthRestriction.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/LengthRestriction.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,175 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+
+/**
+ * One of the components of <code>MatcherProfile</code>.
+ * <p>
+ * Defines a restriction between the number of available comparable components
+ * and the number of available target components (the number of available
+ * components is the number of components that need to be compared and
+ * matched).
+ * <p>
+ * This restriction must apply to a matching scenario before the matching
+ * execution proceeds.
+ *
+ * @author Flavia Rainone
+ * @see MatcherProfile
+ */
+abstract class LengthRestriction
+{
+ /**
+ * Restricts the number of available comparable components to be less than
+ * or equal to the number of available target components.
+ */
+ public static final LengthRestriction LESS_OR_EQUAL = new LengthRestriction(
+ "Less or Equal Restriction")
+ {
+ protected boolean appliesTo(int comparableLength, int targetLength)
+ {
+ return comparableLength <= targetLength;
+ }
+
+ protected boolean appliesTo(int comparableLength, int minimumTargetLength,
+ int maximumTargetLength)
+ {
+ return comparableLength <= maximumTargetLength;
+ }
+ };
+
+ /**
+ * Restricts the number of available comparable components to be equal to the
+ * number of available target components.
+ */
+ public static final LengthRestriction EQUAL = new LengthRestriction(
+ "Equal Restriction")
+ {
+ protected boolean appliesTo(int comparableLength, int targetLength)
+ {
+ return comparableLength == targetLength;
+ }
+
+ protected boolean appliesTo(int comparableLength, int minimumTargetLength,
+ int maximumTargetLength)
+ {
+ return comparableLength >= minimumTargetLength &&
+ comparableLength <= maximumTargetLength;
+ }
+ };
+
+ /**
+ * The string that describes this length restriction.
+ */
+ private String description;
+
+ /**
+ * Private constructor.
+ */
+ private LengthRestriction(String description)
+ {
+ this.description = description;
+ }
+
+
+ /**
+ * Checks if the restriction applies to the length of available comparable
+ * and target components.
+ * <p>
+ * This method is called when the target has no suffixes.
+ *
+ * @param comparable the comparable that will perform comparison
+ * @param comparableIndex the index of comparable, indicates from which
+ * component the comparison will start
+ * @param targetLength the length of the target, indicates how many
+ * components it is made of
+ * @param targetIndex the index of target, indicates from which target
+ * component the comparison will start
+ * @return <code>true</code> if the restriction applies to the scenario
+ * described in the parameters
+ */
+ public boolean appliesTo(Comparable comparable, Index comparableIndex,
+ int targetLength, Index targetIndex)
+ {
+ return appliesTo(comparable.getPostPrefixLength() -
+ comparableIndex.getValue(), targetLength - targetIndex.getValue());
+ }
+
+ /**
+ * Checks if the restriction applies to the length of available comparable
+ * and target components.
+ * <p>
+ * This method is called when the target has one or more suffixes.
+ *
+ * @param comparable the comparable that will perform comparison
+ * @param comparableIndex the index of comparable, indicates from which
+ * component the comparison will start
+ * @param targetLengthRange the length range of the target, indicates how
+ * many components its suffixes and post-prefixes
+ * contain
+ * @param targetIndex the index of target, indicates from which target
+ * component the comparison will start
+ * @return <code>true</code> if the restriction applies to the scenario
+ * described in the parameters
+ */
+ public boolean appliesTo(Comparable comparable, Index comparableIndex,
+ LengthRange targetLengthRange, Index targetIndex)
+ {
+ return appliesTo(
+ comparable.getPostPrefixLength() - comparableIndex.getValue(),
+ targetLengthRange.getPostPrefixMinLength() - targetIndex.getValue(),
+ targetLengthRange.getPostPrefixMaxLength() - targetIndex.getValue())
+ ;
+ }
+
+ /**
+ * Checks if the restriction applies to the comparable and target lengths.
+ *
+ * @param comparableLength the number of comparable elements available for
+ * comparison
+ * @param targetLength the number of target elements available for
+ * comparison
+ * @return <code>true</code> if the restriction applies to these lengths
+ */
+ protected abstract boolean appliesTo(int comparableLength, int targetLength);
+
+ /**
+ * Checks if the restriction applies to the comparable and target lengths.
+ * <p>
+ * Called when the target length is specified by an interval.
+ *
+ * @param comparableLength the number of comparable elements available for
+ * comparison
+ * @param minimumTargetLength the minimum number of target elements available
+ * for comparison
+ * @param maximumTargetLength the maximum number of target elements available
+ * for comparison
+ * @return <code>true</code> if the restriction applies to these lengths
+ */
+ protected abstract boolean appliesTo(int comparableLength,
+ int minimumTargetLength, int maximumTargetLength);
+
+ public String toString()
+ {
+ return this.description;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/Matcher.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/Matcher.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/Matcher.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,226 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * Matches a <i>matchable expression</i> part (represented by a <code>Comparable
+ * </code> instance) against a target. The matching algorithm executed by the
+ * matcher is defined by its profile.
+ * <p>
+ * A matcher is contained in a sequence of matchers, which can match a
+ * <i>matchable expression</i> against a complete target. To know how to use
+ * a matcher sequence, refer to {@link MatcherFactory} and to the {@link
+ * org.jboss.aop.joinpoint.graph.tree.search.match description of this package}.
+ *
+ * @author Flavia Rainone
+ * @see Comparable
+ * @see MatcherFactory
+ * @see MatcherProfile
+ */
+public class Matcher
+{
+ /**
+ * Defines the matching algorithm.
+ */
+ private MatcherProfile profile;
+
+ /**
+ * Performs comparisons with targets.
+ */
+ private Comparable comparable;
+
+ /**
+ * Constructor.
+ *
+ * @param profile defines the matching algorithm to be executed by the
+ * created matcher
+ * @param comparable the object to be compared against the target during the
+ * matching process. Represents a <i>matchable expression
+ * </i> part.
+ */
+ Matcher (MatcherProfile profile, Comparable comparable)
+ {
+ this.profile = profile;
+ this.comparable = comparable;
+ }
+
+ /**
+ * Executes the matching process against the target.
+ * <p>
+ * The indexes and <code>state</code> objects are changed during execution
+ * and, thus, are part of the method outcome.
+ * <p>
+ * This method should be called when the target has no suffixes at all, i.e.,
+ * when the target is the last component of the "complete target".
+ *
+ * @param target the matching target, that will be compared during
+ * the matching execution. Note that the comparison is
+ * performed by the <code>Comparable</code> associated
+ * with this matcher and, consequently, this target
+ * must be of a type compatible with the comparable.
+ * @param targetLength the number of components contained in <code>
+ * target</code>
+ * @param targetIndex indicates from which <code>target</code> component
+ * the matching should start. After this method runs,
+ * this index indicates in which <code>target</code>
+ * component the matching finished. This same index
+ * should be passed along with <code>target</code>
+ * to the next matcher in the sequence if the matching
+ * result is positive.
+ * @param comparableIndex indicates from which comparable component the
+ * matching should start.
+ * @param state contains data about the state of the matching
+ * process. This state must be the same state used in
+ * the previous matching executions associated with
+ * the same matchable expression and complete target.
+ * @return the result of the match
+ * @see MatchingResult
+ */
+ public MatchingResult matches(Object target, int targetLength, Index targetIndex,
+ Index comparableIndex, MatchingState state)
+ {
+ profile.comparisonStart.tuneIndex(comparable, comparableIndex,
+ targetLength, targetIndex, state);
+ if (!profile.restriction.appliesTo(comparable,
+ comparableIndex, targetLength, targetIndex))
+ {
+ return MatchingResult.NEGATIVE_MATCH;
+ }
+ ComparisonResult result = profile.algorithm.execute(comparable,
+ comparableIndex, target, targetIndex, targetLength,
+ profile.restriction, state.comparisonState);
+ return profile.resultMap[result.getId()];
+ }
+
+
+ /**
+ * Executes the matching process against the target.
+ * <p>
+ * The indexes and <code>state</code> objects are changed during execution
+ * and, thus, are part of the method outcome.
+ * <p>
+ * This method should be called when the target has no suffixes at all, i.e.,
+ * when the target is the last component of the "complete target".
+ *
+ * @param target the matching target, that will be compared during
+ * the matching execution. Note that the comparison
+ * is performed by the <code>Comparable</code>
+ * associated with this matcher and, consequently,
+ * this target must be of a type compatible with the
+ * comparable.
+ * @param targetLengthRange the maximum-minimum range of the number of
+ * components contained in the <code>target</code>
+ * suffixes and post-prefixes.
+ * @param targetIndex indicates from which <code>target</code>
+ * component the matching should start. After this
+ * method runs, this index indicates in which <code>
+ * target</code> component the matching finished.
+ * This same index should be passed along with
+ * <code>target</code> to the next matcher in the
+ * sequence if the matching result is positive.
+ * @param comparableIndex indicates from which comparable component the
+ * matching should start. After this method runs,
+ * this index indicates in which comparable
+ * component the matching finished. If the result of
+ * the matching is partial, the same index should
+ * be passed to this same matcher again, along with
+ * the next target and a reset target index.
+ * @param state contains data about the state of the matching
+ * process. This state must be the same state used
+ * in the previous matching executions associated
+ * with the same matchable expression and complete
+ * target.
+ * @return the result of the match
+ * @see MatchingResult
+ */
+ public MatchingResult matches(Object target, LengthRange targetLengthRange,
+ Index targetIndex, Index comparableIndex, MatchingState state)
+ {
+ if (profile.comparisonStart.tuneIndex(comparable, comparableIndex,
+ targetLengthRange, targetIndex, state))
+ {
+ return MatchingResult.PARTIAL_MATCH;
+ }
+ if (!profile.restriction.appliesTo(comparable,
+ comparableIndex, targetLengthRange, targetIndex))
+ {
+ return MatchingResult.NEGATIVE_MATCH;
+ }
+ ComparisonResult result = profile.algorithm.execute(comparable,
+ comparableIndex, target, targetIndex, targetLengthRange,
+ profile.restriction, state.comparisonState);
+ return profile.resultMap[result.getId()];
+ }
+
+ /**
+ * Returns the character that identifies the next target that can be matched
+ * with a non-negative result. If a target not identified by this character
+ * is matched, the result will be certainly negative.
+ * <p>
+ * Should be called whenever <code>target</code> and <code>targetLengthRange
+ * </code>are known, because this info allows a more accurate response.
+ *
+ * @param comparableIndex indicates from which comparable component the
+ * next matching will execute
+ * @param target the last matched target (with a positive result)
+ * @param targetLengthRange the maximum-minimum range of the length of the
+ * <code>target</code> suffixes and post-prefixes.
+ * @param state the state of the matching process
+ * @return the character that identifies the next target that can be matched
+ * with a non-negative result. May be <code>Flags.ALL</code> to
+ * indicate that this matcher cannot infer which targets will have a
+ * negative result.
+ */
+ public char getNextCharacter(Index comparableIndex, Object target,
+ LengthRange targetLengthRange, MatchingState state)
+ {
+ return profile.algorithm.getNextCharacter(comparable, comparableIndex,
+ target, targetLengthRange, state);
+ }
+
+ /**
+ * Returns the character that identifies the next target that can be matched
+ * with a non-negative result. If a target not identified by this character
+ * is matched, the result will be certainly negative.
+ * <p>
+ * Should be called if the last matched target and its length range are
+ * unknown.
+ *
+ * @param comparableIndex indicates from which comparable component the
+ * next matching will execute
+ * @param state the state of the matching process
+ * @return the character that identifies the next target that can be matched
+ * with a non-negative result. May be <code>Flags.ALL</code> to
+ * indicate that this matcher cannot infer which targets will have a
+ * negative result.
+ */
+ public char getNextCharacter(Index comparableIndex, MatchingState state)
+ {
+ return profile.algorithm.getNextCharacter(comparable, comparableIndex,
+ state);
+ }
+
+ public String toString()
+ {
+ return "MATCHER[" + profile + ", " + comparable + "]";
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatcherFactory.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatcherFactory.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatcherFactory.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,110 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Creates a sequence of matchers.<p>
+ * This sequence can be used to match a <i>matchable expression</i> against a
+ * complete target. To execute a matching process, the client must call each
+ * matcher of the sequence, in sequential order, and should consider the process
+ * as finished only when all matchers have stated a positive result, or when one
+ * of them returned a negative result. For more information on the generated
+ * matcher sequence, refer to {@link org.jboss.aop.joinpoint.graph.tree.search.match this
+ * package description}.
+ *
+ * @author Flavia Rainone
+ *
+ */
+public abstract class MatcherFactory
+{
+ /**
+ * Creates a sequence of matchers capable of matching <code>
+ * matchableExpression</code> against a complete target.
+ *
+ * @param matchableExpression the element that will be matched by the
+ * generated matcher sequence.
+ * @param comparableFactory a factory that will be used to create a <code>
+ * Comparable</code> for each part of <code>
+ * matchableExpression</code>. The comparable
+ * instances are created in the same order as the
+ * <code>matchableExpression</code> parts are
+ * found in the element.
+ * @param profile defines the profile of each matcher in the
+ * sequence
+ * @return a sequence of matchers that can match <code>
+ * matchableExpresion</code> against a complete target
+ * @see ComparableFactory
+ * @see MatcherSequenceProfile
+ */
+ public static final Matcher[] createSequence(String matchableExpression,
+ ComparableFactory comparableFactory,
+ MatcherSequenceProfile profile)
+ {
+ Collection matchers = new ArrayList();
+ char separator = comparableFactory.getSeparator();
+ int begin = 0;
+ int end = matchableExpression.indexOf(separator);
+ Comparable comparable;
+ String expression;
+ // invoke factory notification method
+ comparableFactory.startCreation();
+ if (end == -1)
+ {
+ // create unique matcher
+ comparable = comparableFactory.create(matchableExpression,
+ profile.uniqueMatcherProfile);
+ matchers.add(new Matcher(profile.uniqueMatcherProfile, comparable));
+ }
+ else {
+ // create first matcher
+ expression = matchableExpression.substring(begin, end);
+ comparable = comparableFactory.create(expression,
+ profile.firstMatcherProfile);
+ matchers.add(new Matcher(profile.firstMatcherProfile, comparable));
+ begin = end + 1;
+ end = matchableExpression.indexOf(separator, begin);
+ // create middle matchers
+ while (end > 0)
+ {
+ expression = matchableExpression.substring(begin, end);
+ comparable = comparableFactory.create(expression,
+ profile.middleMatchersProfile);
+ matchers.add(new Matcher(profile.middleMatchersProfile, comparable));
+ begin = end + 1;
+ end = matchableExpression.indexOf(separator, begin);
+ }
+ // create last matcher
+ expression = matchableExpression.substring(begin);
+ comparable = comparableFactory.create(expression,
+ profile.lastMatcherProfile);
+ matchers.add(new Matcher(profile.lastMatcherProfile, comparable));
+ }
+ // invoke factory notification method
+ comparableFactory.stopCreation();
+ // create and return sequence
+ Matcher[] matcherArray = new Matcher[matchers.size()];
+ return (Matcher[]) matchers.toArray(matcherArray);
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatcherProfile.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatcherProfile.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatcherProfile.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,198 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * Represents a property that must hold between the complete target and the
+ * comparable, so that the matching process ends with a positive result.
+ * Henceforth, this class defines the matching algorithm, that will be executed
+ * by the <code>Matcher.matches</code> methods to verify whether such property
+ * holds.
+ * <p>
+ * Every matcher has a profile.
+ *
+ * @author Flavia Rainone
+ * @see Matcher
+ * @see MatcherSequenceProfile
+ */
+public class MatcherProfile
+{
+ static
+ {
+ // SIMPLE profile creation
+ MatchingResult[] simpleMap =
+ new MatchingResult[ComparisonResult.getNumberOfInstances()];
+ simpleMap[ComparisonResult.MISMATCH_FOUND.getId()] =
+ MatchingResult.NEGATIVE_MATCH;
+ simpleMap[ComparisonResult.COMPARABLE_END.getId()] =
+ MatchingResult.NEGATIVE_MATCH;
+ simpleMap[ComparisonResult.TARGET_END.getId()] =
+ MatchingResult.PARTIAL_MATCH;
+ simpleMap[ComparisonResult.BOTH_ENDS.getId()] =
+ MatchingResult.POSITIVE_MATCH;
+ SIMPLE = new MatcherProfile("Simple Profile", ComparisonStart.LOOSE,
+ LengthRestriction.EQUAL, ComparisonAlgorithm.SIMPLE, simpleMap);
+
+ // PREFIX profile creation
+ MatchingResult[] prefixMap =
+ new MatchingResult[ComparisonResult.getNumberOfInstances()];
+ prefixMap[ComparisonResult.MISMATCH_FOUND.getId()] =
+ MatchingResult.NEGATIVE_MATCH;
+ prefixMap[ComparisonResult.COMPARABLE_END.getId()] =
+ MatchingResult.POSITIVE_MATCH;
+ prefixMap[ComparisonResult.TARGET_END.getId()] =
+ MatchingResult.PARTIAL_MATCH;
+ prefixMap[ComparisonResult.BOTH_ENDS.getId()] =
+ MatchingResult.POSITIVE_MATCH;
+ PREFIX = new MatcherProfile("Prefix Profile", ComparisonStart.LOOSE,
+ LengthRestriction.LESS_OR_EQUAL, ComparisonAlgorithm.SIMPLE,
+ prefixMap);
+
+ // PATTERN profile creation
+ PATTERN = new MatcherProfile("Pattern Profile", ComparisonStart.LOOSE,
+ LengthRestriction.LESS_OR_EQUAL, ComparisonAlgorithm.KMP,
+ prefixMap); // same map as PREFIX
+
+ // SUFFIX profile creation
+ SUFFIX = new MatcherProfile("Suffix Profile", ComparisonStart.TIGHT,
+ LengthRestriction.LESS_OR_EQUAL, ComparisonAlgorithm.KMP,
+ simpleMap); // same map as SIMPLE
+ }
+
+ /**
+ * Simple profile, defines the matching algorithm as verifying whether the
+ * the target is equal to the comparable.
+ */
+ public static final MatcherProfile SIMPLE;
+
+ /**
+ * Prefix profile, defines the matching algorithm as verifying whether the
+ * target starts with the comparable.
+ */
+ public static final MatcherProfile PREFIX;
+
+ /**
+ * Pattern profile, defines the matching algorithm as verifying whether the
+ * target contains the comparable.
+ */
+ public static final MatcherProfile PATTERN;
+
+ /**
+ * Suffix profile, defines the matching algorithm as verifying whether the
+ * target ends with the comparable.
+ */
+ public static final MatcherProfile SUFFIX;
+
+ /**
+ * Used to generate ids for the instances.
+ */
+ private static int ID_COUNTER = 0;
+
+ /**
+ * Returns the number of <code>MatcherProfile</code> instances.
+ *
+ * @return the number of <code>MatcherProfile</code> instances
+ */
+ public static int getNumberOfInstances()
+ {
+ return 4;
+ }
+
+ /**
+ * The identifier of a <code>MatcherProfile</code> instance.
+ */
+ private int id;
+
+ /**
+ * A string that describes this profile.
+ */
+ private String description;
+
+ /**
+ * Tunes the comparable and target indexes to define where the comparison
+ * should start.
+ */
+ ComparisonStart comparisonStart;
+
+ /**
+ * A restriction that must apply to the length of available comparable
+ * components and of available target components. If the restriction doesn't
+ * apply, the matching process terminates with a negative result.
+ */
+ LengthRestriction restriction;
+
+ /**
+ * The algorithm that defines how the functionality of a <code>Comparable
+ * </code> is used by the <code>Matcher</code>.
+ */
+ ComparisonAlgorithm algorithm;
+
+ /**
+ * Maps a <code>ComparisonResult</code> to the <code>MatchingResult</code>
+ * that should be returned by a <code>Matcher</code>.
+ */
+ MatchingResult[] resultMap;
+
+ /**
+ * Constructor.
+ *
+ * @param comparisonStart defines how the indexes should be tuned for
+ * comparison
+ * @param restriction defines a restriction that must apply to the length
+ * of comparable components and of target components
+ * available for comparison
+ * @param algorithm defines how <code>Comparable</code> functionality
+ * should be used in the matching process
+ * @param resultMap maps a <code>ComparisonResult</code> to a <code>
+ * MatchingResult</code>
+ */
+ private MatcherProfile(String description, ComparisonStart comparisonStart,
+ LengthRestriction restriction, ComparisonAlgorithm algorithm,
+ MatchingResult[] resultMap)
+ {
+ this.description = description;
+ this.comparisonStart = comparisonStart;
+ this.restriction = restriction;
+ this.algorithm = algorithm;
+ this.resultMap = resultMap;
+ this.id = ID_COUNTER++;
+ }
+
+ /**
+ * Returns the id of the <code>MatcherProfile</code> instance.
+ *
+ * @return an id. Notice that all <code>MatcherProfile</code> instances
+ * have an id, which is different for each instance. The smallest id
+ * is <code>0</code>, and for each existent id <code>i</code> there
+ * is also an id <code>i - 1</code> if <code>i</code> > <code>1
+ * </code>.
+ */
+ public int getId()
+ {
+ return this.id;
+ }
+
+ public String toString()
+ {
+ return this.description;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatcherSequenceProfile.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatcherSequenceProfile.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatcherSequenceProfile.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,88 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * The profile of a matcher sequence. Defines the profile of each matcher in the
+ * sequence.
+ *
+ * @author Flavia Rainone
+ * @see MatcherProfile
+ * @see MatcherFactory#createSequence(String, ComparableFactory, MatcherSequenceProfile)
+ */
+public class MatcherSequenceProfile
+{
+ /**
+ * The profile of the first matcher in the sequence.
+ */
+ MatcherProfile firstMatcherProfile;
+
+ /**
+ * The profile of all matchers in the sequence that not the first nor the
+ * last ones.
+ */
+ MatcherProfile middleMatchersProfile;
+
+ /**
+ * The profile of the last matcher in the sequence.
+ */
+ MatcherProfile lastMatcherProfile;
+
+ /**
+ * The profile of the unique matcher in the sequence, utilized by
+ * {@link MatcherFactory} when the sequence contains only one matcher.
+ */
+ MatcherProfile uniqueMatcherProfile;
+
+ /**
+ * Constructor. Creates the profile of an entire sequence of matchers.
+ *
+ * @param firstMatcherProfile the profile of the first matcher in the
+ * sequence
+ * @param middleMatchersProfile the profile of all matchers in the sequence
+ * that not the first nor the last ones
+ * @param lastMatcherProfile the profile of the last matcher in the
+ * sequence
+ * @param uniqueMatcherProfile the profile used in the unique matcher in the
+ * sequence, utilized by <code>MatcherFactory
+ * </code> when the sequence contains only one
+ * matcher
+ * @see MatcherFactory
+ */
+ public MatcherSequenceProfile(MatcherProfile firstMatcherProfile,
+ MatcherProfile middleMatchersProfile,
+ MatcherProfile lastMatcherProfile,
+ MatcherProfile uniqueMatcherProfile)
+ {
+ this.firstMatcherProfile = firstMatcherProfile;
+ this.middleMatchersProfile = middleMatchersProfile;
+ this.lastMatcherProfile = lastMatcherProfile;
+ this.uniqueMatcherProfile = uniqueMatcherProfile;
+ }
+
+ public String toString()
+ {
+ return "[first=" + firstMatcherProfile + ", middle=" +
+ middleMatchersProfile + ", last=" + lastMatcherProfile + ", unique=" +
+ uniqueMatcherProfile + "]";
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatchingResult.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatchingResult.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatchingResult.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,71 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * The result of a matching execution.
+ *
+ * @author Flavia Rainone
+ * @see Matcher#matches(Object, int, Index, Index, MatchingState)
+ * @see Matcher#matches(Object, LengthRange, Index, Index, MatchingState)
+ */
+public class MatchingResult
+{
+ /**
+ * Indicates that the matching is complete and has a positive result.
+ * <p>
+ * When this result is returned by a matcher, the client should pass the same
+ * target and the target index to the next matcher in the sequence. If this
+ * result is returned by the last matcher, the matching process is finished
+ * with a positive result.
+ */
+ public static final MatchingResult POSITIVE_MATCH =
+ new MatchingResult("Positive Match");
+
+ /**
+ * Indicates that matching is not complete, so its result cannot be inferred.
+ * <p>
+ * When this result is returned by a matcher, the client should pass the
+ * matched target suffix to the same matcher in the sequence, using the
+ * same comparable index and the {@link Index#update(LengthRange) updated}
+ * target index. If there are more than one suffix, the state and index must
+ * be copied for each suffix. If there are no suffixes, the matching process
+ * is finished and with a negative result, since the matcher is asking for a
+ * suffix that doesn't exist.
+ */
+ public static final MatchingResult PARTIAL_MATCH =
+ new MatchingResult("Partial Match");
+
+ /**
+ * Indicates that the matching is complete and has a negative result.
+ * <p>
+ * When this result is returned by a matcher, the client should consider the
+ * matching process as finished and with a negative result.
+ */
+ public static final MatchingResult NEGATIVE_MATCH =
+ new MatchingResult("Negative Match");
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ /** The string that describes this result. */
+ private String description;
+
+ /**
+ * Private constructor.
+ *
+ * @param description the description of the matching result to be created.
+ */
+ private MatchingResult(String description)
+ {
+ this.description = description;
+ }
+
+ public String toString(){
+ return this.description;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatchingState.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatchingState.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/MatchingState.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,315 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * The state of a matching process, is associated with a complete target and
+ * with a matcher sequence. If the client needs to pass more than one target
+ * suffix to the next matcher in the sequence, it needs to copy the matching
+ * state of the previous matching execution for each suffix matching, since each
+ * target suffix represents a different complete target.
+ * <p>
+ * The client can associate a comparison state with the matching
+ * state. This comparison state will be passed along to the comparable on every
+ * call to the {@link Comparable#compare Comparable.compare} method, so it can
+ * store data that might happen to be important in future comparisons. Notice
+ * that the same state object is passed along to every comparable in the matcher
+ * sequence, since this object is associated with the matching state. The
+ * comparable is completely responsible for managing this state data. To
+ * assigin a comparison state to the matching state, invoke the {@link
+ * #MatchingState(State)} constructor instead of the default one.
+ *
+ * @author Flavia Rainone
+ */
+public class MatchingState implements State
+{
+ /**
+ * Dummy state, is assigned to <code>comparisonState</code> when the client
+ * doesn't provide one.
+ */
+ private static final State DUMMY_STATE = new DummyState();
+
+ /**
+ * The state value, answers to all methods in this class, since their
+ * behaviour is dependent on this value.
+ */
+
+ /**
+ * The comparison state, stores data relevant to comparables.
+ */
+ State comparisonState;
+
+ /**
+ * Indicates whether the comparison is scheduled to start in the current
+ * target, in a target suffix, or in the firt component of the next target
+ * suffix.
+ */
+ ComparisonStartState comparisonStartState;
+
+ /**
+ * Indicates whether the comparison, in case the match outcomes a positive
+ * result, will finish exactly in the end of the longer complete target
+ * (tight comparison) or not (loose comparison).
+ */
+ ComparisonEndState comparisonEndState;
+
+ /**
+ * Saved comparison state, is the backup of {@link #comparisonState}.
+ * <p>
+ * Is assigned by the {@link #copy} method and read by the {@link
+ * #rollback()} method.
+ */
+ State savedComparisonState;
+
+ /**
+ * Saved comparison start state, is the backup of {@link
+ * #comparisonStartState }.
+ * <p>
+ * Is assigned by the {@link #copy} method and read by the {@link
+ * #rollback()} method.
+ */
+ ComparisonStartState savedComparisonStartState;
+
+ /**
+ * Saved comparison end state, is the backup of {@link #comparisonEndState}.
+ * <p>
+ * Is assigned by the {@link #copy} method and read by the {@link
+ * #rollback()} method.
+ */
+ ComparisonEndState savedComparisonEndState;
+
+
+ /**
+ * Constructor. Creates a initial state of a matching process, and should be
+ * passed to the first matcher in the sequence.
+ * <p>
+ * Invoke this constructor when there is no need of a comparison state.
+ */
+ public MatchingState()
+ {
+ comparisonStartState = ComparisonStartState.CURRENT_TARGET;
+ comparisonEndState = ComparisonEndState.LOOSE;
+ this.comparisonState = DUMMY_STATE;
+ }
+
+ /**
+ * Constructor. Creates a initial state of a matching process, and should be
+ * passed to the first matcher in the sequence.
+ * <p>
+ * Invoke this constructor when the comparables associated with the matcher
+ * sequence will need a comparison state to store comparison relevant data.
+ *
+ * @param comparisonState the comparison state that will be passed along to
+ * the comparables on every call to their {@link
+ * Comparable#compare compare} method
+ */
+ public MatchingState(State comparisonState)
+ {
+ comparisonStartState = ComparisonStartState.CURRENT_TARGET;
+ comparisonEndState = ComparisonEndState.LOOSE;
+ this.comparisonState = comparisonState;
+ }
+
+ /**
+ * Resets this state and the comparison state associated with it, if there is
+ * one.
+ *
+ * @see org.jboss.aop.joinpoint.graph.tree.search.match.State#reset()
+ */
+ public void reset()
+ {
+ comparisonStartState = ComparisonStartState.CURRENT_TARGET;
+ comparisonEndState = ComparisonEndState.LOOSE;
+ this.comparisonState.reset();
+ }
+
+ /**
+ * Saves the data contained in this state and in the comparison state
+ * associated with it, if there is one.
+ *
+ * @see org.jboss.aop.joinpoint.graph.tree.search.match.State#save()
+ */
+ public void save()
+ {
+ this.savedComparisonState = this.comparisonState;
+ this.savedComparisonStartState = this.comparisonStartState;
+ this.savedComparisonEndState = this.comparisonEndState;
+ }
+
+ /**
+ * Rollbacks the data contained in this state and in the comparison state
+ * associated with it, if there is one.
+ *
+ * @see org.jboss.aop.joinpoint.graph.tree.search.match.State#rollback()
+ */
+ public void rollback()
+ {
+ this.comparisonState = this.savedComparisonState;
+ this.comparisonStartState = this.savedComparisonStartState;
+ this.comparisonEndState = this.savedComparisonEndState;
+ }
+
+ /**
+ * Copies all data stored in <code>stateToCopy</code> to this state,
+ * including its comparison state data, if there is one.
+ * <p>
+ * This method should be called by the client everytime it will pass to the
+ * next match execution more than one suffixes of the previous matched
+ * target. The client needs to pass a diferent state instance to
+ * match each suffix.
+ *
+ * @param stateToCopy the <code>MatchingState</code> to be copied
+ * @throws ClassCastException if <code>state</code> is not an instance of
+ * <code>MatchingState</code>
+ */
+ public final void copy(State stateToCopy)
+ {
+ MatchingState matchingState = (MatchingState) stateToCopy;
+ comparisonStartState = matchingState.comparisonStartState;
+ comparisonEndState = matchingState.comparisonEndState;
+ comparisonState.copy(matchingState.comparisonState);
+ }
+
+ /**
+ * Increments the <code>targetIndex</code> in a way that the number of
+ * comparable components available for comparison become the same as the
+ * minimum number of available target components. The <code>comparableIndex
+ * </code> value is changed accordingly.
+ * <p>
+ * Is called when the comparison target has no suffixes.
+ *
+ * @param comparable the comparable that will perform comparison
+ * @param comparableIndex indicates from which comparable component
+ * comparison will start
+ * @param targetLength the length of the comparison target
+ * @param targetIndex indicates from which target component comparison
+ * will start
+ */
+ void tightenComparison(Comparable comparable, Index comparableIndex,
+ int targetLength, Index targetIndex)
+ {
+ // updates value
+ this.comparisonEndState.update(this, comparable, comparableIndex,
+ targetLength, targetIndex);
+ // tightens comparison
+ this.comparisonEndState.tightenComparison(this, comparable,
+ comparableIndex, targetLength, targetIndex);
+ // don't waste time updating comparisonStartState, a next character will
+ // not be retrieved, since this target doesn't has suffixes
+ }
+
+ /**
+ * Increments the <code>targetIndex</code> in a way that the number of
+ * comparable components available for comparison become the same as the
+ * minimum number of available target components. The <code>comparableIndex
+ * </code> value is changed accordingly.
+ * <p>
+ * Is called when the comparison target has one or more suffixes.
+ *
+ * @param comparable the comparable that will perform comparison
+ * @param comparableIndex indicates from which comparable component
+ * comparison will start
+ * @param targetLengthRange the length range of the comparison target
+ * @param targetIndex indicates from which target component comparison
+ * will start
+ * @return <code>true</code> if the comparison start is postponed to be
+ * performed on the target suffixes; <code>false</code> otherwise.
+ */
+ boolean tightenComparison(Comparable comparable, Index comparableIndex,
+ LengthRange targetLengthRange, Index targetIndex)
+ {
+ // updates value
+ this.comparisonEndState.update(this, comparable, comparableIndex,
+ targetLengthRange.getPostPrefixMaxLength(), targetIndex);
+ // tightens comparison
+ this.comparisonEndState.tightenComparison(this, comparable,
+ comparableIndex, targetLengthRange.getPostPrefixMinLength(),
+ targetIndex);
+ this.comparisonStartState.update(this, targetIndex, targetLengthRange);
+ return this.comparisonStartState.isComparisonPostponed();
+ }
+
+ /**
+ * Returns the character that identifies the next targets that may result
+ * in a positive result. If a target not identified by this character is
+ * matched next, certainly the result will be negative.
+ * <p>
+ * Is called when the <code>target</code> and its length range are known.
+ *
+ * @param comparable responsible for performing comparison
+ * @param comparableIndex indicates from which comparable component
+ * comparison will start
+ * @param target the previously matched target (with a positive
+ * result)
+ * @param targetLengthRange the length range of <code>target</code>.
+ * @return the character that identifies the next targets that may result
+ * in a positive result. May be <code>Flags.ALL</code> to indicate that
+ * any target can have a positive result in the next matching execution
+ */
+ char getNextCharacter(Comparable comparable, Index comparableIndex,
+ Object target, LengthRange targetLengthRange)
+ {
+ return this.comparisonStartState.getNextCharacter(this, comparable,
+ comparableIndex, target, targetLengthRange);
+ }
+
+ /**
+ * Returns the character that identifies the next targets that may result
+ * in a positive result. If a target not identified by this character is
+ * matched next, certainly the result will be negative.
+ * <p>
+ * Is called when the <code>target</code> or its length range are unknown.
+ *
+ * @param comparable responsible for performing comparison
+ * @param comparableIndex indicates from which comparable component
+ * comparison will start
+ * @return the character that identifies the next targets that may result
+ * in a positive result. May be <code>Flags.ALL</code> to indicate that
+ * any target can have a positive result in the next matching execution
+ */
+ char getNextCharacter(Comparable comparable, Index comparableIndex)
+ {
+ return this.comparisonStartState.getNextCharacter(this, comparable,
+ comparableIndex);
+ }
+
+ public String toString()
+ {
+ return "(comparisonStart=" + this.comparisonStartState +
+ ", comparisonEnd=" + this.comparisonEndState + ", comparisonState=" +
+ comparisonState + ")";
+ }
+
+ /**
+ * Empty implementation of <code>State</code>, provides a dummy comparison
+ * state to <code>MatchingState</code> when it doesn't have one.
+ *
+ * @author Flavia Rainone
+ */
+ private static class DummyState implements State
+ {
+ public void reset() {}
+ public void save() {}
+ public void rollback() {}
+ public final void copy(State State) {}
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/PrefixFunction.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/PrefixFunction.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/PrefixFunction.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * Provides the prefix function as defined in KMP pattern matching algorithm.
+ * <p>
+ * A prefix function is associated with a comparable and is responsible for,
+ * once a mismatch is returned by the <code>Comparable</code>, indicating from
+ * which comparable component the comparison should restart. This function is
+ * utilized in pattern and suffix matchings.
+ *
+ * @author Flavia Rainone
+ * @see Comparable
+ */
+public interface PrefixFunction
+{
+ /**
+ * Applies the prefix function value to <code>index</code>.
+ *
+ * @param index indicates in which comparable component the mismatch occured.
+ * After the function is applied to <code>index</code>, it will
+ * contain the prefix function value correspondent to it.
+ * This new index value is utilized to restart the comparison
+ * in pattern and suffix matchings.
+ * @see Index#applyPrefixFunction(int)
+ */
+ void applyTo(Index index);
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/State.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/State.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/State.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.match;
+
+/**
+ * Defines basic operations every state class needs to provide.
+ *
+ * @author Flavia Rainone
+ */
+public interface State
+{
+ /**
+ * Resets this state to its initial value. After this method is executed,
+ * this state should be equal to a newly created state of the same class.
+ */
+ public abstract void reset();
+
+ /**
+ * Saves this state data so it can be restored by the {@link #rollback}
+ * method.
+ * @see #rollback()
+ */
+ public abstract void save();
+
+ /**
+ * Overwrites the current state data by the last saved data. Notice that,
+ * after this method is executed, the previous state data will be lost,
+ * completely overwriten.
+ * <p>
+ * This method is called only after the {@link #save} method.
+ * @see #save()
+ */
+ public abstract void rollback();
+
+ /**
+ * Overwrites the current state data by the <code>stateToCopy</code> data.
+ * <p>
+ * The data saved by <code>stateToCopy.save()</code> executions is the only
+ * data that doesn't need to be copied.
+ *
+ * @param stateToCopy the state whose data will be copied
+ */
+ public void copy(State stateToCopy);
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/package.html
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/package.html (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/match/package.html 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,178 @@
+<html>
+<head>
+<!--
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<title></title>
+</head>
+<body bgcolor="white">
+
+Provides a framework for matching comparable objects using four different
+algorithms. All of these algorithms are based on functionality delivered by the
+{@link pointcutMatcher.tree.search.match.Comparable} interface, whose
+implementation must be provided by the client.
+
+
+<h2>Package Specification</h2>
+<p>
+This package is responsible for matching an expression, called <i>matchable
+expression</i>, against a <i>complete target</i>.</p>
+<p>
+In order for the matching process to take place, the matchable expression is
+scattered into smaller parts. Each part is associated with a {@link
+pointcutMatcher.tree.search.match.Matcher matcher}, responsible for matching its
+part against a complete target part, which we will call, for simplicity, just
+<i>target</i> (so, we can state that a complete target is the result of the
+concatenation of sequential targets). This means that the first step of a
+matching process is to break the matchable expression into smaller parts,
+transforming it into a sequence of matchers. This is done by invoking {@link
+pointcutMatcher.tree.search.match.MatcherFactory#createSequence
+MatcherFactory.createSequence} method. Once this sequence is generated, each
+matcher must be invoked, in order, to match its part against a target, and the
+matching process should be considered finished when one of them states a
+negative result or when all of them have done the matching and resulted in a
+positive match.</p>
+<p>
+The matching performed by a matcher consists of verifying wheter a relationship
+between the complete target and its matchable expression part exists or not.
+Which relationship is checked by the matcher is defined by its profile (
+{@link pointcutMatcher.tree.search.match.MatcherProfile}). The available
+profiles and the relationship they enforce are:
+</p>
+<ul>
+ <li><code>SIMPLE</code>: equality;</li>
+ <li><code>PREFIX</code>: starts with;</li>
+ <li><code>SUFFIX</code>: ends with;</li>
+ <li><code>PATTERN</code>: contains.</li>
+</ul>
+<p>
+The client is responsible for specifying the profile of the matchers contained
+in the sequence. It can specify the profile of: the first matcher, the last
+matcher, the middle ones, and the unique matcher (this one is generated when the
+matchers sequence contains only one element).
+</p>
+<p>
+The extensibility in this package is on the {@link
+pointcutMatcher.tree.search.match.Comparable} interface. Differently from what
+one may have thought, the matchers are not responsible for comparing its
+matchable expression part with a target. For this task, it delegates execution
+to a comparable instance, provided by the client. So, the matchers are not
+dependent on how a comparison is performed, nor what is the target type. They
+don't even manipulate the matchable expression part associated with them,
+because this is responsability of the comparable. So, a matcher is not actually
+associated with its part, but with its comparable. This one needs to provide the
+comparison functionality and information about its matchable expression part; in
+fact, it represents the expression part along with the comparison functionality.
+</p>
+<p>
+Before we state the responsabilities of the comparable, lets at first define the
+terms:
+</p>
+<ul>
+ <li>Comparable Prefix: is the concatenation of all comparables contained
+ in the matchers previous to the current matcher in the sequence.
+ </li>
+ <li>Comparable Suffix: is the concatenation of all comparables contained in
+ matchers that follow the current matcher in the sequence.
+ </li>
+ <li>
+ Comparable Post-Prefix: is the concatenation of the comparable with its
+ suffix.
+ </li>
+</ul>
+<p>
+In the same way comparables can be concatenated to form a matchable expression,
+the targets can be concatenated to form a complete target. So, we also have a
+target prefix, suffix and post-prefix. The only difference between a target and
+a comparable is that the first one can have more than one suffix, which means
+it can be part of more than one complete target. Henceforth the client can match
+more than one complete target with common prefixes in an economical way,
+matching a target that is the prefix common to all complete targets: if the
+matching result is negative, it means that none of the complete targets are
+positively matched by the matcher sequence; otherwise, the matching process
+should continue, this time with each suffix of the matched target.
+</p>
+<p>
+The comparable provided by the client must conform to the following rules:
+</p>
+<ul>
+ <li>
+ it is made up by components, as is the target. The comparable compares
+ each one of its components with a component of the target, in sequence.
+ What is the component is up to the client, but the most typical component
+ is a character;
+ </li>
+ <li>
+ it must provide the length of its post-prefix (how many components the
+ post-prefix contains);
+ </li>
+ <li>
+ it must also provide a prefix function, the one specified in the pattern
+ matching KMP algorithm. Such a function can say from which index the
+ comparison must proceed once a mismatch is found, and is used to improve
+ efficiency in patterns matching.
+ </li>
+ <li>
+ the comparable should provide a character that identifies the current
+ component being compared. This information can be used by the matcher to
+ provide an interesting functionality, capable of improving performance:
+ indicating to the client which target suffixes should be used in the next
+ matching execution. This way, some suffixes should not be processed
+ because certainly the matching result will be negative. Even though, there
+ are cases in which no suffix can be excluded from the matching process.
+ </li>
+</ul>
+<p>
+Besides this, the client is responsible for providing the target and its data,
+according to these rules:
+</p>
+<ul>
+ <li>
+ the target must be compatible with the comparable implementation the
+ client is providing;
+ </li>
+ <li>
+ the client must provide the target length when the target has no suffixes,
+ or the {@link pointcutMatcher.tree.search.match.LengthRange target length
+ range} (contains the length of minimum and maximum post-prefixes and of
+ the target itself) otherwise.
+ </li>
+</ul>
+<p>
+Notice that the length range is also responsbible for calculating the length of
+the minimum and maximum target suffixes. However, it is not assumed that the
+suffix length equals the post-prefix length minus the target length. The suffix
+length is just calculated this way as a default implementation, which can be
+overriden by the client. The reason for this is that the target is made of
+components which are known only to the client, so it cannot be assumed how the
+concatanation of target components is performed nor the length of its result. In
+the same way, the length of a comparable plus the length of its suffix is not
+assumed to be the same as the length of the comparable post-prefix.
+</p>
+
+<!-- Put @see and @since tags down here. -->
+ at see pointcutMatcher.tree.search.match.MatcherFactory
+ at see pointcutMatcher.tree.search.match.Matcher
+ at see pointcutMatcher.tree.search.match.ComparableFactory
+ at see pointcutMatcher.tree.search.match.Comparable
+
+</body>
+</html>
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/package.html
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/package.html (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/package.html 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,34 @@
+<html>
+<head>
+<!--
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<title></title>
+</head>
+<body bgcolor="white">
+
+Provides the search mechanism for the tree.
+
+<!-- Put @see and @since tags down here. -->
+ at see pointcutMatcher.tree.search.SearchKey
+
+</body>
+</html>
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/ComparableKeyPart.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/ComparableKeyPart.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/ComparableKeyPart.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,267 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.part;
+
+import org.jboss.aop.joinpoint.graph.tree.ExtendedLengthRange;
+import org.jboss.aop.joinpoint.graph.tree.KeyPart;
+import org.jboss.aop.joinpoint.graph.tree.search.common.PrefixFunctionLoader;
+import org.jboss.aop.joinpoint.graph.tree.search.element.ComparableElementFactory;
+import org.jboss.aop.joinpoint.graph.tree.search.match.Comparable;
+import org.jboss.aop.joinpoint.graph.tree.search.match.ComparisonResult;
+import org.jboss.aop.joinpoint.graph.tree.search.match.Index;
+import org.jboss.aop.joinpoint.graph.tree.search.match.LengthRange;
+import org.jboss.aop.joinpoint.graph.tree.search.match.Matcher;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatcherFactory;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatcherProfile;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatcherSequenceProfile;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatchingResult;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatchingState;
+import org.jboss.aop.joinpoint.graph.tree.search.match.PrefixFunction;
+import org.jboss.aop.joinpoint.graph.tree.search.match.State;
+
+
+/**
+ * Implements the <code>Comparable</code> interface having {@link
+ * org.jboss.aop.joinpoint.graph.tree.search.element.ComparableElement} matchers as
+ * components.
+ *
+ * @author Flavia Rainone
+ */
+public class ComparableKeyPart implements Comparable
+{
+ /**
+ * The components of this comparable.
+ */
+ private Matcher[] elementMatchers;
+
+ /**
+ * Indicates the index of the matcher element that doesn't specify the
+ * target end, it accepts any target suffix.
+ */
+ private int anySuffixMatcher;
+
+ /**
+ * The prefix function of this comparable key part.
+ */
+ private PrefixFunction prefixFunction;
+
+ /**
+ * The post prefix length.
+ */
+ protected int postPrefixLength;
+
+ /**
+ * Constructor.
+ *
+ * @param keyPartExpression the element that will be compared by the
+ * <code>ComparableKeyPart</code> to be created
+ * @param matcherProfile the profile of the matcher that will contain the
+ * <code>ComparableKeyPart</code> to be created
+ */
+ ComparableKeyPart(String keyPartExpression, MatcherProfile matcherProfile)
+ {
+ // creates element matchers
+ ComparableElementFactory factory = ComparableElementFactory.getInstance();
+ MatcherSequenceProfile seqProfile = factory.performCreationForProfile(
+ matcherProfile);
+ elementMatchers = MatcherFactory.createSequence(keyPartExpression,
+ factory, seqProfile);
+ // retrieves prefix function calculated (or null, if this part is not
+ // a pattern nor a suffix
+ PrefixFunctionLoader prefixFunctionLoader = PrefixFunctionLoader.
+ getCurrentLoader();
+ this.prefixFunction = prefixFunctionLoader.getLoadedFunction();
+ // last matcher is anySuffixMatcher if it doesn't specify the
+ // target end, as is the case of prefix and pattern
+ if (matcherProfile == MatcherProfile.PREFIX ||
+ matcherProfile == MatcherProfile.PATTERN)
+ {
+ this.anySuffixMatcher = elementMatchers.length - 1;
+ }
+ else
+ {
+ // there isn't a anySuffixMatcher
+ this.anySuffixMatcher = elementMatchers.length;
+ }
+ // the post prefix length is initialy the key part length
+ // this value is updated as new key parts are created
+ // by ComparableKeyPartFactory
+ this.postPrefixLength = elementMatchers.length;
+ }
+
+ /**
+ * Returns the number of element matchers contained in this comparable key
+ * part.
+ *
+ * @return the number of element matchers contained in this comparable key
+ * part
+ */
+ int getLength()
+ {
+ return this.elementMatchers.length;
+ }
+
+ public int getPostPrefixLength()
+ {
+ return this.postPrefixLength;
+ }
+
+ public char getNextCharacter(Index comparableIndex, Object comparisonState)
+ {
+ // the target and its length range should always be known when dealing
+ // with comparable key parts
+ throw new RuntimeException ("Unexpected call");
+ }
+
+ public char getNextCharacter(Index comparableIndex, Object target,
+ LengthRange targetLengthRange, Object comparisonState)
+ {
+ if (comparableIndex.getValue() >= elementMatchers.length)
+ {
+ return KeyPart.KEY_ELEMENT_END;
+ }
+ KeyPart keyPart = (KeyPart) target;
+ KeyPartIndex mIndex = (KeyPartIndex) comparableIndex; // matchers index
+ if (! keyPart.isLastElementComplete())
+ {
+ // pass length range information
+ LengthRange elementLengthRange = ((ExtendedLengthRange)
+ targetLengthRange).getElementLengthRange();
+ return elementMatchers[mIndex.getValue()].getNextCharacter(
+ // don't waste time getting the target because this value
+ // will not be used
+ mIndex.getElementIndex(), null, elementLengthRange,
+ (MatchingState) comparisonState);
+ }
+ // length range unknown
+ return elementMatchers[mIndex.getValue()].getNextCharacter(
+ mIndex.getElementIndex(), (MatchingState) comparisonState);
+ }
+
+ public PrefixFunction getPrefixFunction()
+ {
+ return prefixFunction;
+ }
+
+ /**
+ * @throws ClassCastException if <code>targetIndex</code> and/or <code>
+ * comparableIndex</code> are not instances of
+ * <code>KeyPartIndex</code>. The same exception
+ * is thrown if <code>target</code> isn't a <code>
+ * KeyPart</code>.
+ * @see KeyPartIndex
+ */
+ public ComparisonResult compare(Object target, Index targetIndex,
+ Index comparableIndex, State comparisonState)
+ {
+ // retrive important data from parameters
+ KeyPartIndex tIndex = (KeyPartIndex) targetIndex; // target index
+ KeyPartIndex mIndex = (KeyPartIndex) comparableIndex; // matchers index
+ MatchingState state = (MatchingState) comparisonState;
+ KeyPart keyPart = (KeyPart) target;
+ String[] elements = keyPart.getKeyElements();
+ int tEnd = keyPart.isLastElementComplete()? elements.length:
+ elements.length - 1;
+ MatchingResult result = MatchingResult.POSITIVE_MATCH;
+ Matcher matcher;
+ String element;
+
+ // complete targets comparison
+ while(mIndex.getValue() < anySuffixMatcher && tIndex.getValue() < tEnd)
+ {
+ matcher = elementMatchers[mIndex.getValue()];
+ element = elements[tIndex.getValue()];
+ result = matcher.matches(element, element.length(),
+ tIndex.getElementIndex(), mIndex.getElementIndex(), state);
+ if (result != MatchingResult.POSITIVE_MATCH)
+ {
+ break;
+ }
+ tIndex.increment();
+ mIndex.increment();
+ state.reset();
+ }
+
+ // compare incomplete target and/or suffixless element matcher
+ if (result == MatchingResult.POSITIVE_MATCH &&
+ mIndex.getValue() < elementMatchers.length &&
+ tIndex.getValue() < elements.length)
+ {
+ LengthRange elementLengthRange = null;
+ // if next target it a incomplete target
+ if (!keyPart.isLastElementComplete() && tIndex.getValue() == tEnd)
+ {
+ matcher = elementMatchers[mIndex.getValue()];
+ element = elements[tEnd];
+ elementLengthRange = ((ExtendedLengthRange)
+ keyPart.getLengthRange()).getElementLengthRange();
+ result = matcher.matches(element, elementLengthRange,
+ tIndex.getElementIndex(), mIndex.getElementIndex(), state);
+ }
+ else // mIndex.getValue() == anySuffixMatcher
+ {
+ matcher = elementMatchers[mIndex.getValue()];
+ element = elements[tIndex.getValue()];
+ result = matcher.matches(element, element.length(),
+ tIndex.getElementIndex(), mIndex.getElementIndex(), state);
+ }
+ // result is positive...
+ if (result == MatchingResult.POSITIVE_MATCH)
+ {
+ // and matcher doesn't specify the target end...
+ if (mIndex.getValue() == anySuffixMatcher)
+ {
+ // increments only matcher index
+ mIndex.increment();
+ }
+ // if compared target is an incomplete target
+ else//!keyPart.isLastElementComplete() && tIndex.getValue() == tEnd
+ {
+ // certainly last element was compared until
+ // the end and mIndex should not be incremented since
+ // the element end is not present
+ tIndex.increment(elementLengthRange);
+ }
+ }
+ else if (result == MatchingResult.PARTIAL_MATCH &&
+ // if target has suffixes...
+ (!keyPart.isLastElementComplete() && tIndex.getValue() == tEnd))
+ {
+ tIndex.increment(elementLengthRange);
+ }
+ }
+ boolean targetEnd = tIndex.getValue() >= elements.length;
+ boolean matchersEnd = mIndex.getValue() >= elementMatchers.length;
+ return ComparisonResult.getInstance(matchersEnd, targetEnd);
+ }
+
+ public String toString()
+ {
+ String result = "KeyPart:\n";
+ for (int i = 0; i < elementMatchers.length; i++)
+ {
+ result += "\t - " + elementMatchers[i] + "\n";
+ }
+ result += "-----------------------------------------";
+ return result;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/ComparableKeyPartFactory.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/ComparableKeyPartFactory.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/ComparableKeyPartFactory.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,115 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.part;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.jboss.aop.joinpoint.graph.tree.search.match.Comparable;
+import org.jboss.aop.joinpoint.graph.tree.search.match.ComparableFactory;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatcherProfile;
+import org.jboss.aop.joinpoint.graph.tree.search.match.MatcherSequenceProfile;
+
+
+/**
+ * Creates <code>ComparableKeyPart</code> instances.
+ *
+ * @author Flavia Rainone
+ * @see ComparableKeyPart
+ */
+public class ComparableKeyPartFactory implements ComparableFactory
+{
+ /**
+ * Singleton instance.
+ */
+ private static ComparableKeyPartFactory instance =
+ new ComparableKeyPartFactory();
+
+ /**
+ * Returns the singleton instance.
+ * @return the singleton instance
+ */
+ public static ComparableKeyPartFactory getInstance() {
+ return instance;
+
+ }
+
+ /**
+ * The profile of a key part matcher sequence.
+ */
+ private final MatcherSequenceProfile matcherSeqProfile;
+
+ /**
+ * Contains created <code>ComparableKeyPart</code> instances.
+ */
+ private Collection parts;
+
+ /**
+ * Private constructor (singleton class).
+ */
+ private ComparableKeyPartFactory()
+ {
+ parts = new ArrayList();
+ matcherSeqProfile = new MatcherSequenceProfile(MatcherProfile.PREFIX,
+ MatcherProfile.PATTERN, MatcherProfile.SUFFIX,
+ MatcherProfile.SIMPLE);
+ }
+
+ /**
+ * Returns the key part matcher sequence profile.
+ * @return the key part matcher sequence profile
+ */
+ public final MatcherSequenceProfile getMatcherSequenceProfile()
+ {
+ return this.matcherSeqProfile;
+ }
+
+ public char getSeparator()
+ {
+ return '*';
+ }
+
+ public void startCreation() {}
+
+ public void stopCreation()
+ {
+ parts.clear();
+ }
+
+ public Comparable create(String comparableExpression,
+ MatcherProfile matcherProfile)
+ {
+ // creates instance
+ ComparableKeyPart part = new ComparableKeyPart(
+ comparableExpression, matcherProfile);
+ // updates post-prefix information of previously created instances
+ for (Iterator i = parts.iterator(); i.hasNext(); )
+ {
+ ComparableKeyPart registeredPart = (ComparableKeyPart) i.next();
+ registeredPart.postPrefixLength += part.getLength() - 1;
+ }
+ // adds this part to the created parts collection
+ parts.add(part);
+ return part;
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/KeyPartIndex.java
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/KeyPartIndex.java (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/KeyPartIndex.java 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,97 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.joinpoint.graph.tree.search.part;
+
+import org.jboss.aop.joinpoint.graph.tree.search.match.Index;
+import org.jboss.aop.joinpoint.graph.tree.search.match.LengthRange;
+
+/**
+ * Extended index class with added information about the element index.
+ * <p>
+ * This extra information is necessary because it is not enough to state from
+ * which key part element the comparison should start, it is also important
+ * to know from which element character.
+ *
+ * @author Flavia Rainone
+ * @see Index
+ */
+public class KeyPartIndex extends Index
+{
+ /**
+ * Element index, contains the element char number from which comparison
+ * should start.
+ */
+ private Index elementIndex;
+
+ /**
+ * Default constructor, creates an index with zero value.
+ *
+ */
+ public KeyPartIndex()
+ {
+ super();
+ this.elementIndex = new Index();
+ }
+
+ /**
+ * Overwrites the method in the super class, redefining the initial
+ * state as that in which: this index value is 0 and <code>element index
+ * </code> is also in its initial state
+ */
+ public boolean isInitialState()
+ {
+ return super.isInitialState() && this.elementIndex.isInitialState();
+ }
+
+ /**
+ * Returns the element index.
+ *
+ * @return the element index, that indicates from which element char
+ * comparison should start
+ */
+ public final Index getElementIndex()
+ {
+ return elementIndex;
+ }
+
+ /**
+ * Increments this index value by <code>1</code> and updates the element
+ * index so it can be valid for matching the target suffix.
+ * <p>
+ * Should be called only when the target is incomplete.
+ */
+ final void increment(LengthRange elementLengthRange)
+ {
+ super.noCallBackIncrement(1);
+ this.elementIndex.update(elementLengthRange);
+ }
+
+ public void valueChanged()
+ {
+ this.elementIndex.reset();
+ }
+
+ public String toString()
+ {
+ return "[" + super.toString() + ", " + this.elementIndex + "]";
+ }
+}
\ No newline at end of file
Added: projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/package.html
===================================================================
--- projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/package.html (rev 0)
+++ projects/aop/branches/joinpoint_graph/aop/src/main/org/jboss/aop/joinpoint/graph/tree/search/part/package.html 2008-01-03 19:07:18 UTC (rev 68604)
@@ -0,0 +1,53 @@
+<html>
+<head>
+<!--
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<title></title>
+</head>
+<body bgcolor="white">
+
+Implements the <code>search.match</code> package.
+
+
+
+<h2>Package Specification</h2>
+<p>
+In this package, the <code>Comparable</code> interface is implemented by the
+<code>ComparableKeyPart</code> class, whose components are comparable elements
+(<code>search.element.ComparableElement</code>) matchers.
+</p>
+<p>
+As is with <code>search.element</code>, this package contains the <code>
+ComparableFactory</code> implementation associated with <code>ComparableKeyPart
+</code>, but not the <code>PrefixFunction</code> one, which is located in the
+<code>search.common</code> package.
+</p>
+<p>
+This package also extends <code>search.match.Index</code> to add information
+about the element index.
+</p>
+
+<!-- Put @see and @since tags down here. -->
+ at see pointcutMatcher.tree.search.part.ComparableKeyPart
+
+</body>
+</html>
\ No newline at end of file
More information about the jboss-cvs-commits
mailing list