/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.thesett.aima.attribute.time;

import java.nio.ByteBuffer;

/**
 * ByteBufferUtils provides helper methods for working with ByteBuffers.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Grows a buffer if needed.
 *
 Write common types as ASCII strings into a byte buffer.
 *

 *
 * @author Rupert Smith
 */
public class ByteBufferUtils
{
    /** The minus sign in ASCII. */
    private static final byte MINUS_ASCII = (byte) '-';

    /** Zero in ASCII. */
    private static final byte ZERO_ASCII = (byte) '0';

    /**
     * Writes the specified integer value as an ASCII string into the specified byte buffer. If the integer value is
     * shorted than the specified length, the number will be padded with leading zeros, so that it fills the required
     * length. If there is insufficient space in the buffer to write the value into, then the buffer size is increased
     * using the supplied byte buffer pool.
     *
     * @param  buffer The byte buffer to write to.
     * @param  value  The value to write.
     * @param  length The length to pad the number to with leading zeros.
     *
     * @return The byte buffer with the value written to it. This may be a different buffer to the one passed in if the
     *         buffer had to be copied in order to increase its size.
     */
    public static ByteBuffer putPaddedInt32AsString(ByteBuffer buffer, int value, int length)
    {
        // Ensure there is sufficient space in the buffer to hold the result.
        int charsRequired = BitHackUtils.getCharacterCountInt32(value);
        length = (charsRequired < length) ? length : charsRequired;

        // Take an explicit index into the buffer to start writing to, as the numbers will be written backwards.
        int index = buffer.position() + length - 1;

        // Record the start position, to remember if a minus sign was written or not, so that it does not get
        // overwritten by the zero padding.
        int start = buffer.position();

        // Advance the buffer position manually, as the characters will be written to specific indexes backwards.
        buffer.position(buffer.position() + length);

        // Take care of the minus sign for negative numbers.
        if (value < 0)
        {
            buffer.put(MINUS_ASCII);
            start++; // Stop padding code overwriting minus sign.
        }
        else
        {
            value = -value;
        }

        // Write the digits least significant to most significant into the buffer. As the number was converted to be
        // negative the remainders will be negative too.
        do
        {
            int remainder = value % 10;
            value = value / 10;

            buffer.put(index--, ((byte) (ZERO_ASCII - remainder)));
        }
        while (value != 0);

        // Write out the padding zeros.
        while (index >= start)
        {
            buffer.put(index--, ZERO_ASCII);
        }

        return buffer;
    }

    /**
     * Writes a single byte as raw characer data into the specified buffer. The buffer is increased in size using the
     * supplied buffer pool, if needed.
     *
     * @param  buffer The byte buffer to write to.
     * @param  value  The value to write.
     *
     * @return The byte buffer with the value written to it. This may be a different buffer to the one passed in if the
     *         buffer had to be copied in order to increase its size.
     */
    public static ByteBuffer putByteAsString(ByteBuffer buffer, byte value)
    {
        buffer.put(value);

        return buffer;
    }

    /**
     * Returns the contents of a buffer as a string, converting ASCII characters in the buffer, into unicode string
     * characters.
     *
     * @param  buffer The buffer.
     * @param  length The length of the string to get from the buffer.
     *
     * @return The buffer as a string.
     */
    public static String asString(ByteBuffer buffer, int length)
    {
        char[] chars = new char[length];

        for (int i = 0; i < length; i++)
        {
            chars[i] = (char) buffer.get(i);
        }

        return String.valueOf(chars);
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.thesett.aima.attribute.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.thesett.aima.state.BaseType;
import com.thesett.aima.state.InfiniteValuesException;
import com.thesett.aima.state.OrdinalAttribute;
import com.thesett.aima.state.ReferencableAttribute;
import com.thesett.aima.state.Type;
import com.thesett.aima.state.TypeVisitor;
import com.thesett.aima.state.restriction.TypeRestriction;
import com.thesett.aima.state.restriction.ValidEnumRestriction;
import com.thesett.common.error.NotImplementedException;

/**
 * EnumeratedStringAttributes are used to represent properties that are symbols described by strings. The number of
 * possible values that an EnumeratedStringAttribute can take on is expected to be small. Typically less than ten. The
 * number of supported data points using this attribute that can be held in memory at one time is to be as large as
 * possible. Data sets in the hundreds of megabytes should be possible.
 *
 *
Working with string comparisons is time consuming and this attribute class provides facilities for working quickly
 * with strings when it is known in advance that only a limited set of string will be used to describe a given
 * attribute.
 *
 *
Storing strings can require a large amount of space. For example, if we know that a given attribute will only take
 * on the values 'Red', 'Green' and 'Blue' and the data for this attribute is to be loaded from a large text data file
 * it would not be efficient to create new String objects for every value. The strings are interned using
 * {@link java.lang.String#intern} to store them efficiently.
 *
 *
The number of supported data points using this attribute that can be held in memory at one time is to be as large
 * as possible. A string attribute is described using a single byte and there are methods to convert between a byte and
 * an EnumeratedStringAttribute and back again so that algorithms using StringAttributes can work with arrays of bytes
 * to eliminate the overhead of using an object representation. Typically, an object is 8 bytes, on 8 byte alignments,
 * so storing the object representation takes 13 (8 for object, 1 for the byte, 4 for the ref to the attribute class)
 * rounded up to 16 bytes, whereas the byte representation takes just 1.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Represent a single string from a set of strings.
 *
 Convert string to compact byte representation.
 *
 Restore string from compact representation.
 *
 Provide factory for creating string attributes.
 *
 Close string set into finite set from extensible open set.
 *
 Provide fast equality on strings.
 *

 *
 * @author Rupert Smith
 */
public class EnumeratedStringAttribute implements OrdinalAttribute, ReferencableAttribute, Serializable
{
    /** Used to hold all the different named attribute classes. */
    private static final Map<String, EnumeratedStringClassImpl> attributeClasses =
        new HashMap<String, EnumeratedStringClassImpl>();

    /** Used to hold the byte offset into the string array. */
    byte value;

    /** Holds a reference to the class of string attribute that this one belongs to. */
    EnumeratedStringClassImpl attributeClass;

    /**
     * Private constructor for an attribute. Attributes can only be created with a factory for an attribute class.
     *
     * @param value          The compact byte index that is used to lookup the actual string value in the creating
     *                       factory instance.
     * @param attributeClass The factory implentation used to create this class of string attribute.
     */
    private EnumeratedStringAttribute(byte value, EnumeratedStringClassImpl attributeClass)
    {
        // Keep the byte representation and the class.
        this.value = value;
        this.attributeClass = attributeClass;
    }

    /**
     * Generates a factory for building string attributes of the named class.
     *
     * @param  name The name of the string attribute class to get a factory for.
     *
     * @return The string attribute factory for the named string attribute class.
     */
    public static EnumeratedStringAttributeFactory getFactoryForClass(String name)
    {
        return EnumeratedStringClassImpl.getInstance(name);
    }

    /**
     * Returns the attribute type of this attribute.
     *
     * @return The attribute type of this attribute.
     */
    public Type<EnumeratedStringAttribute> getType()
    {
        return attributeClass;
    }

    /**
     * Converts the object representation into a compact byte representation.
     *
     * @return The compact byte representation of this attribute.
     */
    public byte getByteFromAttribute()
    {
        // Just return the byte representation that has already been found.
        return value;
    }

    /**
     * Returns the integer id of the attribute.
     *
     * @return The integer id of the attribute.
     */
    public long getId()
    {
        // Check if the attribute class has been finalized yet.
        if (attributeClass.finalized)
        {
            // Fetch the string value from the attribute class array of finalized values.
            return attributeClass.lookupValue[value].id;
        }

        // The attribute class has not been finalized yet.
        else
        {
            // Fetch the string value from the attribute class list of unfinalized values.
            return attributeClass.lookupValueList.get(value).id;
        }
    }

    /**
     * Sets the integer id of the attribute. If the attribute class is finalized this will change the value of this
     * attribute to that of the matched id, or raise an exception if no matching id exists. If the attribute class is
     * unfinalized this will change the id value of this attribute within the attribute class to the new id, provided
     * that the id has not already been assigned to another attribute value. If it has been assigned to another
     * attribute value then an exception is raised.
     *
     * @param  id The new id value.
     *
     * @throws IllegalArgumentException If the type is finalized but the id does not exist. Or if the type is
     *                                  unfinalized if the id has already been assigned to another instance of the type.
     */
    public void setId(long id)
    {
        // Find the enumeration node for this enumeration value.
        EnumerationNode node = null;

        // Check if the attribute class has been finalized yet.
        if (attributeClass.finalized)
        {
            // Fetch the string value from the attribute class array of finalized values.
            node = attributeClass.lookupValue[value];
        }
        else
        {
            // The attribute class has not been finalized yet.
            // Fetch the string value from the attribute class list of unfinalized values.
            node = attributeClass.lookupValueList.get(value);
        }

        // Extract the id from it.
        long existingId = node.id;

        // Do nothing if the new id matches the existing one.
        if (id == existingId)
        {
            return;
        }

        // Check if the type is finalized.
        if (attributeClass.finalized)
        {
            // Raise an illegal argument exception if the id is not known.
            EnumeratedStringAttribute newValue = attributeClass.getAttributeFromId(id);

            // Otherwise, change the value of this attribute to that of the new id.
            this.value = newValue.value;
        }
        else
        {
            // The type is un-finalized.
            // Check if another instance of the type already has the id and raise an exception if so.
            EnumerationNode existingNode = attributeClass.idMap.get(id);

            if (existingNode != null)
            {
                throw new IllegalArgumentException("The id value, " + id +
                    ", cannot be set because another instance of this type with that " + "id already exists.");
            }

            // Assign it to this instance if the type is unfinalized. Also removing the old id mapping from the id
            // map and replacing it with the new one.
            node.id = id;
            attributeClass.idMap.remove(existingId);
            attributeClass.idMap.put(id, node);
        }
    }

    /**
     * Gets the string value of a string attribute.
     *
     * @return The underlying string value of this attribute.
     */
    public String getStringValue()
    {
        // Check if the attribute class has been finalized yet.
        if (attributeClass.finalized)
        {
            // Fetch the string value from the attribute class.
            return attributeClass.lookupValue[value].label;
        }
        else
        {
            return attributeClass.lookupValueList.get(value).label;
        }
    }

    /**
     * Sets the specified string as the value of this attribute. The value to set must be a legitimate member of this
     * attributes type, when the type has been finalized. If the type has yet to be finalized then the new value is
     * added to the set of possible values for the type.
     *
     * @param  value The new value to set.
     *
     * @throws IllegalArgumentException If the type has been finalized and the new value is not a member of the type.
     */
    public void setStringValue(String value) throws IllegalArgumentException
    {
        Byte b = attributeClass.lookupByte.get(value);

        // Check if the value is not already a memeber of the attribute class.
        if (b == null)
        {
            // Check if the attribute class has been finalized yet.
            if (attributeClass.finalized)
            {
                throw new IllegalArgumentException("The value to set, " + value +
                    ", is not already a member of the finalized EnumeratedStringType, " +
                    attributeClass.attributeClassName + ".");
            }
            else
            {
                // Add the new value to the attribute class. Delegate to the factory to do this so that strings are
                // interned and so on.
                EnumeratedStringAttribute newAttribute = attributeClass.createStringAttribute(value);
                b = newAttribute.value;
            }
        }

        // Set the new value as the value of this attribute.
        this.value = b;
    }

    /**
     * Generates hashCodes unique to the value of the string value.
     *
     * @return A hashcode which is the java.lang.String hashcode for the string value of this atttributes value.
     */
    public int hashCode()
    {
        return getStringValue().hashCode();
    }

    /**
     * Tests if two string attributes are equal. They are equal if they have the same string value. They do no have to
     * be of the same string attribute class although the comparator must be a string attribute.
     *
     * @param  o The object to compare to.
     *
     * @return True if the comparator is a string attribute and has the same value as this one.
     */
    public boolean equals(Object o)
    {
        // return getValue().equals(((EnumeratedStringAttribute)o).getValue());
        // The == operator can safely be used because the strings were interned.
        return (o instanceof EnumeratedStringAttribute) &&
            (getStringValue() == ((EnumeratedStringAttribute) o).getStringValue()) &&
            ((EnumeratedStringAttribute) o).attributeClass.attributeClassName.equals(attributeClass.attributeClassName);
    }

    /**
     * Should return an integer index for the current value of this attribute from 0 to num possible values where the
     * number of possible values is finite.
     *
     * @return An integer index for the current value of this attribute from 0 to num possible values of this string
     *         attribute class.
     */
    public int ordinal()
    {
        return (int) value;
    }

    /**
     * Returns the string value.
     *
     * @return The string value.
     */
    public String toString()
    {
        return getStringValue();
    }

    /**
     * Defines the type interface for string attributes.
     */
    public static interface EnumeratedStringType extends Type<EnumeratedStringAttribute>
    {
        /**
         * Returns all the different values that an OrdinalAttribute of this type can take on as an iterator over these
         * values. The hierarchy forms a tree the leaves of which are values that it can take on. The iterator returns
         * the leaves 'in-order'.
         *
         * @param  failOnNonFinalized <tt>true</tt> if this should throw an infinite values exception when the type is
         *                            not finalized, <tt>false</tt> if it should list all values defined so far anyway.
         *
         * @return An iterator over the set of attributes defining the possible value set for this attribute.
         */
        public Iterator<EnumeratedStringAttribute> getAllPossibleValuesIterator(boolean failOnNonFinalized);

        /**
         * Returns all the different values that an OrdinalAttribute of this type can take on.
         *
         * @param  failOnNonFinalized <tt>true</tt> if this should throw an infinite values exception when the type is
         *                            not finalized, <tt>false</tt> if it should list all values defined so far anyway.
         *
         * @return A set of attributes defining the possible value set for this attribute.
         */
        public Set<EnumeratedStringAttribute> getAllPossibleValuesSet(boolean failOnNonFinalized);

        /**
         * Provides a map of all possible values, keyed by their string values.
         *
         * @param  failOnNonFinalized <tt>true</tt> if this should throw an infinite values exception when the type is
         *                            not finalized, <tt>false</tt> if it should list all values defined so far anyway.
         *
         * @return A map of all possible values, keyed by their string values.
         */
        public Map<String, EnumeratedStringAttribute> getAllPossibleValuesMap(boolean failOnNonFinalized);
    }

    /**
     * Defines a factory for creating string attributes of a given class.
     */
    public static interface EnumeratedStringAttributeFactory
    {
        /**
         * Gets the type for this factory.
         *
         * @return The type for this factory.
         */
        public EnumeratedStringType getType();

        /**
         * Creates a string attribute of the class that this is a factory for. If the attribute class has been finalized
         * and the requested string value is not in the class then this should raise an exception.
         *
         * @param  value The value that the string attribute should have.
         *
         * @return A new string attribute with the specified value.
         */
        public EnumeratedStringAttribute createStringAttribute(String value);

        /**
         * Converts a compact byte representation of a string attribute into its object representation. If the byte is
         * not valid then this should raise an exception.
         *
         * @param  b The compact byte index that a string attribute should be created from.
         *
         * @return A string attribute looked up by its byte index.
         */
        public EnumeratedStringAttribute getAttributeFromByte(byte b);

        /**
         * Looks up an attribute by its id.
         *
         * @param  id The id of the attribute to look up.
         *
         * @return A string attribute looked up by its id.
         */
        public EnumeratedStringAttribute getAttributeFromId(long id);

        /** Finalizes an attribute class. This prevents any new attribute value from being added to the class. */
        public void finalizeAttribute();

        /** Drops an attribute class. The attribute class is explicitly deleted. */
        public void dropAttributeClass();
    }

    /**
     * Defines the class of enumerated string attributes. Class = Type + Factory.
     */
    public static interface EnumeratedStringClass extends EnumeratedStringType, EnumeratedStringAttributeFactory
    {
    }

    /**
     * Used to hold the lookup String values and the number of possible values for a string attribute class.
     */
    private static class EnumeratedStringClassImpl extends BaseType<EnumeratedStringAttribute>
        implements EnumeratedStringClass
    {
        /** The number of possible values this attribute can take on. Defaults to infinity. */
        int numValues = -1;

        /** The String lookup array for converting bytes back into Strings for this class. */
        EnumerationNode[] lookupValue;

        /**
         * A map from Strings to bytes for use when creating new attributes with strings that already exist. It is safe
         * to use an IdentityHashMap here because all the String keys will have been interned.
         */
        Map<String, Byte> lookupByte = new IdentityHashMap<String, Byte>();

        /** Used to hold a collection of values for this attribute until the attribute is finalized. */
        List<EnumerationNode> lookupValueList = new ArrayList<EnumerationNode>();

        /**
         * Holds a map from referencable ids to enumeration nodes. This is used to resolve ids into instances of the
         * attribute type. It is a map rather than an array because the ids do not have to be sequentially assigned from
         * 0 but could be a scattered range of values.
         */
        Map<Long, EnumerationNode> idMap = new HashMap<Long, EnumerationNode>();

        /** Used to indicate whether the class has been finalized yet. */
        boolean finalized;

        /** Used to hold the name of the attribute class that this is a factory for. */
        String attributeClassName;

        /**
         * Builds a new factory for a given class.
         *
         * @param name The name that identifies this class of string attributes.
         */
        private EnumeratedStringClassImpl(String name)
        {
            // Keep a reference to the attribute class and name.
            this.attributeClassName = name;

            restrictions = new LinkedList<TypeRestriction>();
            restrictions.add(new ValidEnumRestriction(name));
        }

        /**
         * Gets an instance of this factory implementation for specified class of sting attribute. If the attribute
         * class is a new one, then a new factory instance is created, otherwise an existing factory for the class is
         * used.
         *
         * @param  name The name that identifies this class of string attributes.
         *
         * @return A factory implementation for the named string attribute class.
         */
        public static EnumeratedStringAttributeFactory getInstance(String name)
        {
            // Try to get the attribute class from the map of those that have already been created.
            EnumeratedStringClassImpl attributeClass = attributeClasses.get(name);

            // Check if this is a new class and create it if so.
            if (attributeClass == null)
            {
                attributeClass = new EnumeratedStringClassImpl(name);
                attributeClasses.put(name, attributeClass);
            }

            return attributeClass;
        }

        /**
         * Gets a new default instance of the type. The types value will be set to its default uninitialized value.
         *
         * @return A new default instance of the type. Always <tt>false</tt>.
         */
        public EnumeratedStringAttribute getDefaultInstance()
        {
            throw new NotImplementedException();
        }

        /** {@inheritDoc} */
        public EnumeratedStringType getType()
        {
            return this;
        }

        /**
         * Creates a string attribute of the class that this is a factory for.
         *
         * @param  value The string value to create an attribute instance for.
         *
         * @return A new string attribute with the specified value.
         *
         * @throws IllegalArgumentException If the type has been finalized but the value to create an attribute for if
         *                                  not a member of the type.
         */
        public EnumeratedStringAttribute createStringAttribute(String value) throws IllegalArgumentException
        {
            // Intern the string to ensure memory is not wasted on duplicate strings and that fast string equality can
            // be used safely.
            String internValue = value.intern();

            // Check if the value is already in the attribute class.
            Byte b = lookupByte.get(internValue);

            if (b != null)
            {
                return new EnumeratedStringAttribute(b, this);
            }

            // Check if the attribute class has been finalized yet.
            if (finalized)
            {
                // The value is not already in the attribute class and it is finalized so an attribute cannot be
                // created.
                // return null;
                throw new IllegalArgumentException("The value, " + value +
                    ", is not a member of the finalized EnumeratedStringAttribute class, " + attributeClassName + ".");
            }
            else
            {
                // The attribute class is not finalized yet so work with the list.
                // Work out what position in the list the new value will be at.
                int position = lookupValueList.size();

                // Create a new enumeration node to insert.
                EnumerationNode node = new EnumerationNode();
                node.label = internValue;
                node.value = (byte) position;
                //node.id = node.value;

                // Add the new value at the end of the list.
                lookupValueList.add(node);

                // Also add the new value to the map of values.
                lookupByte.put(internValue, (byte) position);

                // Also add the new value to the id map.
                //idMap.put(node.id, node);

                // Create a new string attribute from a byte representation of the position.
                return new EnumeratedStringAttribute((byte) position, this);
            }
        }

        /**
         * Converts a compact byte representation of a string attribute into its object representation. If the byte is
         * not valid then this returns null.
         *
         * @param  b The compact byte index that a string attribute should be created from.
         *
         * @return A string attribute looked up by its byte index.
         */
        public EnumeratedStringAttribute getAttributeFromByte(byte b)
        {
            // Check if the attribute class has already been finalized in which case the byte is only valid if it is
            // less than num possible values.
            if (finalized && (b >= numValues))
            {
                throw new IllegalArgumentException("The specified enum element cannot be generated from the " +
                    "compact representation, " + b + ", because that does not represent an existing value.");
            }

            // If the attribute is not finalized the byte is only valid if it is less than the attribute list size.
            else if (b >= lookupValueList.size())
            {
                throw new IllegalArgumentException("The specified enum element cannot be generated from the " +
                    "compact representation, " + b + ", because that does not represent an existing value.");
            }

            return new EnumeratedStringAttribute(b, this);
        }

        /**
         * Converts an id representation of an enumerated attribute into its object representation. If the id is not
         * valid then this will raise an exception.
         *
         * @param  id The id of the enumerated attribute value to fetch.
         *
         * @return An enumerated attribute looked up by its id.
         */
        public EnumeratedStringAttribute getAttributeFromId(long id)
        {
            // The id is only valid if it is in the id map.
            EnumerationNode matchedNode = idMap.get(id);

            // Check that the value exists.
            if (matchedNode == null)
            {
                throw new IllegalArgumentException("The enumerated attribute cannot be generated from the id, " + id +
                    ", because that does not represent an existing value.");
            }

            return new EnumeratedStringAttribute(matchedNode.value, this);
        }

        /** Finalizes an attribute class. This prevents any new attribute value from being added to the class. */
        public void finalizeAttribute()
        {
            // Check if the attribute class has already been finalized.
            if (finalized)
            {
                // Its already been finalized. Do nothing.
                return;
            }

            // Count how many values there are and set this as the possible value count.
            int count = lookupValueList.size();

            numValues = count;

            // Convert the List of values into an array and set the List reference to null.
            lookupValue = lookupValueList.toArray(new EnumerationNode[count]);
            lookupValueList = null;

            // Set the finalized flag.
            finalized = true;
        }

        /** Drops an attribute class. The attribute class is explicitly deleted. */
        public void dropAttributeClass()
        {
            attributeClasses.remove(attributeClassName);
        }

        /**
         * Returns the name of this string attribute class.
         *
         * @return The name of this string attribute class.
         */
        public String getName()
        {
            return attributeClassName;
        }

        /**
         * Gets the underlying Java class that implements the type.
         *
         * @return The underlying Java class that implements the type.
         */
        public Class<EnumeratedStringAttribute> getBaseClass()
        {
            return EnumeratedStringAttribute.class;
        }

        /** {@inheritDoc} */
        public String getBaseClassName()
        {
            return getBaseClass().getName();
        }

        /**
         * Gets the number of possible values that attributes of this string class can take on.
         *
         * @return the number of possible values that an instance of this attribute can take on. If the value is -1 then
         *         this is to be interpreted as infinity.
         */
        public int getNumPossibleValues()
        {
            // Fetch the number of possible values that this attribute class can take.
            return numValues;
        }

        /**
         * Returns all the different values that an OrdinalAttribute of this type can take on.
         *
         * @return A set of attributes defining the possible value set for this attribute.
         */
        public Set<EnumeratedStringAttribute> getAllPossibleValuesSet()
        {
            return getAllPossibleValuesSet(true);
        }

        /**
         * Returns all the different values that a string attribute of this class can take on. If the class is finalized
         * this will list all the possible strings in the class. If the class is not yet finalized the set of strings is
         * still open and potentially infinite and this will throw an infinite values exception if the fail flag is set.
         * Clearing the fail flag allows all non-finalized values to be listed.
         *
         * @param  failOnNonFinalized <tt>true</tt> to fail if the type is not yet finalized, and therefore potentially
         *                            infinite.
         *
         * @return All the string that this class of string attribute can take on.
         *
         * @throws InfiniteValuesException If the set of values cannot be listed because the string attribute class is
         *                                 unfinalized.
         */
        public Set<EnumeratedStringAttribute> getAllPossibleValuesSet(boolean failOnNonFinalized)
        {
            // Check if the attribute class is not yet finalized so an infinte values exception must be thrown.
            if (!finalized && failOnNonFinalized)
            {
                throw new InfiniteValuesException("The string attribute class is not finalized yet, " +
                    "so can have infinite values.", null);
            }

            // The attribute class is finalized so return the array of possible values as a set.
            else
            {
                Set<EnumeratedStringAttribute> result = new HashSet<EnumeratedStringAttribute>();

                if (finalized)
                {
                    for (EnumerationNode node : lookupValue)
                    {
                        result.add(createStringAttribute(node.label));
                    }
                }
                else
                {
                    for (EnumerationNode node : lookupValueList)
                    {
                        result.add(createStringAttribute(node.label));
                    }
                }

                return result;
            }
        }

        /** {@inheritDoc} */
        public Map<String, EnumeratedStringAttribute> getAllPossibleValuesMap(boolean failOnNonFinalized)
        {
            // Get the set of already existing values, so that they will not be created again.
            Iterator<EnumeratedStringAttribute> allPossibleValuesIterator = getAllPossibleValuesIterator(false);
            Map<String, EnumeratedStringAttribute> existingValues = new HashMap<String, EnumeratedStringAttribute>();

            for (; allPossibleValuesIterator.hasNext();)
            {
                EnumeratedStringAttribute existingAttribute = allPossibleValuesIterator.next();
                existingValues.put(existingAttribute.getStringValue(), existingAttribute);
            }

            return Collections.unmodifiableMap(existingValues);
        }

        /**
         * Returns an iterator over all the different values that a string attribute of this class can take on. If the
         * class is finalized this will list all the possible strings in the class. If the class is not yet finalized
         * the set of strings is still open and potentially infinite so this will throw an infinite values exception.
         *
         * @return An iterator over all the string that this class of string attribute can take on.
         *
         * @throws InfiniteValuesException If the set of values cannot be listed because the string attribute class is
         *                                 unfinalized.
         */
        public Iterator<EnumeratedStringAttribute> getAllPossibleValuesIterator() throws InfiniteValuesException
        {
            return getAllPossibleValuesSet().iterator();
        }

        /** {@inheritDoc} */
        public Iterator<EnumeratedStringAttribute> getAllPossibleValuesIterator(boolean failOnNonFinalized)
        {
            return getAllPossibleValuesSet(failOnNonFinalized).iterator();
        }

        /** {@inheritDoc} */
        public void acceptVisitor(TypeVisitor visitor)
        {
            if (visitor instanceof EnumeratedStringTypeVisitor)
            {
                ((EnumeratedStringTypeVisitor) visitor).visit(this);
            }
            else
            {
                super.acceptVisitor(visitor);
            }
        }
    }

    /**
     * An EnumerationNode captures all the relevant information about a label within an enumeration; its label, its
     * enumerated compact byte representation, its referenceable id value.
     */
    private static class EnumerationNode implements Serializable
    {
        /** The label of the node. */
        public String label;

        /** The compact byte value of the node. */
        public byte value;

        /** The referencable id of the value. */
        public long id = -1L;

        /**
         * Outputs all values as a string for debugging.
         *
         * @return All values as a string for debugging.
         */
        public String toString()
        {
            return "label = " + label + ": value = " + value + ", id = " + id;
        }
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.thesett.aima.logic.fol.isoprologparser;

import com.thesett.aima.logic.fol.Sentence;
import com.thesett.aima.logic.fol.SentenceImpl;
import com.thesett.aima.logic.fol.Term;
import com.thesett.aima.logic.fol.VariableAndFunctorInterner;
import com.thesett.common.parsing.SourceCodeException;

/**
 * Parses first order logic terms from strings using Prolog syntax. The term parsed may be any valid first order logic
 * term; variables, atoms, functors, literals, clauses all included. The term will be parsed as a 'sentence' which means
 * that it will be parsed in a fresh variable context, so that variables are scoped over the term only.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Parse a string as a logical term relative to a variable and functor interner.
 *      {@link Term}, {@link VariableAndFunctorInterner}.
 *

 *
 * @author Rupert Smith
 */
public class TermParser extends BasePrologParser<Term>
{
    /**
     * Creates a term parser over an interner.
     *
     * @param interner The interner to use to intern all functor and variable names.
     */
    public TermParser(VariableAndFunctorInterner interner)
    {
        super(interner);
    }

    /**
     * Parses the next sentence from the current token source.
     *
     * @return The fully parsed syntax tree for the next sentence.
     *
     * @throws SourceCodeException If the source being parsed does not match the grammar.
     */
    public Sentence<Term> parse() throws SourceCodeException
    {
        try
        {
            return new SentenceImpl<Term>(parser.termSentence());
        }
        catch (SourceCodeException e)
        {
            throw new IllegalStateException(e);
        }
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.thesett.aima.logic.fol.jpc.salt;

import org.jpc.salt.TermContentHandler;
import org.jpc.salt.TermReader;

import com.thesett.aima.logic.fol.FloatLiteral;
import com.thesett.aima.logic.fol.Functor;
import com.thesett.aima.logic.fol.IntLiteral;
import com.thesett.aima.logic.fol.NumericType;
import com.thesett.aima.logic.fol.Term;
import com.thesett.aima.logic.fol.Variable;
import com.thesett.aima.logic.fol.VariableAndFunctorInterner;

/**
 * LojixTermReader is a {@link TermReader} for Lojix terms. It reads a Lojix term and describes its contents and
 * structure to a {@link TermContentHandler}.
 *
 *

CRC Card

 *
 Responsibilities 	 Collaborations
 *
 Read Lojix terms and describe their structure/content to a content handler.
 *      {@link TermContentHandler}

 *

 */
public class LojixTermReader extends TermReader
{
    /** The interner used to de-intern all names. */
    private final VariableAndFunctorInterner interner;

    /** The Lojix term to be translated to a JPC term. */
    private Term readTerm;

    /**
     * Creates a Lojix term read.
     *
     * @param readTerm       The Lojix term to read.
     * @param contentHandler The content handler to visit the term with.
     * @param interner       The Lojix name interner to de-intern names with.
     */
    public LojixTermReader(Term readTerm, TermContentHandler contentHandler, VariableAndFunctorInterner interner)
    {
        super(contentHandler);
        this.readTerm = readTerm;
        this.interner = interner;
    }

    /** {@inheritDoc} */
    public void read()
    {
        read(readTerm);
    }

    /**
     * Reads a Lojix term and invoked appropriate methods on the content handler to describe its structure and contents
     * to it.
     *
     * @param term The Lojix term to read.
     */
    private void read(Term term)
    {
        if (term.isNumber())
        {
            NumericType numericType = (NumericType) term;

            if (numericType.isInteger())
            {
                IntLiteral jplInteger = (IntLiteral) term;
                getContentHandler().startIntegerTerm(jplInteger.longValue());
            }
            else if (numericType.isFloat())
            {
                FloatLiteral jplFloat = (FloatLiteral) term;
                getContentHandler().startFloatTerm(jplFloat.doubleValue());
            }
        }
        else if (term.isVar())
        {
            Variable var = (Variable) term;
            getContentHandler().startVariable(interner.getVariableName(var.getName()));
        }
        else if (term.isAtom())
        {
            Functor atom = (Functor) term;
            getContentHandler().startAtom(interner.getFunctorName(atom.getName()));
        }
        else if (term.isCompound())
        {
            Functor functor = (Functor) term;
            getContentHandler().startCompound();
            getContentHandler().startAtom(interner.getFunctorName(functor.getName()));

            for (com.thesett.aima.logic.fol.Term child : functor.getArguments())
            {
                read(child);
            }

            getContentHandler().endCompound();
        }
        else
        {
            throw new IllegalStateException("Unrecognized Lojix term: " + term);
        }
    }
}


/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.hobsoft.microbrowser.spi;

import java.util.List;

import org.hobsoft.microbrowser.MicrodataDocument;
import org.hobsoft.microbrowser.MicrodataItem;
import org.hobsoft.microbrowser.MicrodataItemNotFoundException;

import static org.hobsoft.microbrowser.spi.Urls.newUrl;

/**
 * Base {@code MicrodataDocument} implementation.
 */
public abstract class AbstractMicrodataDocument extends AbstractHypermedia implements MicrodataDocument
{
	// ----------------------------------------------------------------------------------------------------------------
	// MicrodataDocument methods
	// ----------------------------------------------------------------------------------------------------------------

	public final MicrodataItem getItem(String type)
	{
		List<MicrodataItem> items = getItems(type);

		if (items.isEmpty())
		{
			throw new MicrodataItemNotFoundException(newUrl(type));
		}

		return items.get(0);
	}
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.thesett.common.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;

/**
 * Provides helper methods for operating on classes and methods using reflection. Reflection methods tend to return a
 * lot of checked exception so writing code to use them can be tedious and harder to read, especially when such errors
 * are not expected to occur. This class always works with {@link ReflectionUtilsException}, which is a runtime
 * exception, to wrap the checked exceptions raised by the standard Java reflection methods. Code using it does not
 * normally expect these errors to occur, usually does not have a recovery mechanism for them when they do, but is
 * cleaner, quicker to write and easier to read in the majority of cases.
 *
 *

CRC Card

 *
ResponsibilitiesCollaborations
 *
Look up Classes by name.
 *
Instantiate Classes by no-arg constructor.
 *

 *
 * @author Rupert Smith
 */
public class ReflectionUtils
{
    /* private static final Logger log = Logger.getLogger(ReflectionUtils.class.getName()); */
    /**
     * Checks if the named class exists and is loadable.
     *
     * @param  className The class to check for.
     *
     * @return <tt>true</tt> if the named class exists and is loadable.
     */
    public static boolean classExistsAndIsLoadable(String className)
    {
        try
        {
            Class.forName(className);

            return true;
        }
        catch (ClassNotFoundException e)
        {
            // Exception noted and ignored.
            e = null;

            return false;
        }
    }

    /**
     * Checks if the named class exists and is loadable and is a sub-type of the specified class.
     *
     * @param  parent    The class to check that the named class is a sub-type of.
     * @param  className The class to check for.
     *
     * @return <tt>true</tt> if the named class exists and is loadable and is a sub-type of the specified class.
     */
    public static boolean isSubTypeOf(Class parent, String className)
    {
        try
        {
            Class cls = Class.forName(className);

            return parent.isAssignableFrom(cls);
        }
        catch (ClassNotFoundException e)
        {
            // Exception noted and ignored.
            e = null;

            return false;
        }
    }

    /**
     * Checks that the named child class is the same type or a sub-type of the named parent class.
     *
     * @param  parent The parent class name.
     * @param  child  The child class name.
     *
     * @return <tt>true</tt> if the named child class is the same type or a sub-type of the named parent class, <tt>
     *         false</tt> otherwise.
     */
    public static boolean isSubTypeOf(String parent, String child)
    {
        try
        {
            return isSubTypeOf(Class.forName(parent), Class.forName(child));
        }
        catch (ClassNotFoundException e)
        {
            // Exception noted so can be ignored.
            e = null;

            return false;
        }
    }

    /**
     * Checks that the child class is the same type or a sub-type of the parent class.
     *
     * @param  parentClass The parent class.
     * @param  childClass  The child class.
     *
     * @return <tt>true</tt> if the child class is the same type or a sub-type of the parent class, <tt>false</tt>
     *         otherwise.
     */
    public static boolean isSubTypeOf(Class parentClass, Class childClass)
    {
        try
        {
            // Check that the child class can be cast as a sub-type of the parent.
            childClass.asSubclass(parentClass);

            return true;
        }
        catch (ClassCastException e)
        {
            // Exception noted so can be ignored.
            e = null;

            return false;
        }
    }

    /**
     * Gets the Class object for a named class.
     *
     * @param  className The class to get the Class object for.
     *
     * @return The Class object for the named class.
     */
    public static Class<?> forName(String className)
    {
        try
        {
            return Class.forName(className);
        }
        catch (ClassNotFoundException e)
        {
            throw new ReflectionUtilsException("ClassNotFoundException whilst finding class: " + className + ".", e);
        }
    }

    /**
     * Creates an instance of a Class, instantiated through its no-args constructor.
     *
     * @param  cls The Class to instantiate.
     * @param  <T> The Class type.
     *
     * @return An instance of the class.
     */
    public static <T> T newInstance(Class<T> cls)
    {
        try
        {
            return cls.newInstance();
        }
        catch (InstantiationException e)
        {
            throw new ReflectionUtilsException("InstantiationException whilst instantiating class.", e);
        }
        catch (IllegalAccessException e)
        {
            throw new ReflectionUtilsException("IllegalAccessException whilst instantiating class.", e);
        }
    }

    /**
     * Calls a constuctor with the specified arguments.
     *
     * @param  constructor The constructor.
     * @param  args        The arguments.
     * @param  <T>         The Class type.
     *
     * @return An instance of the class that the constructor is for.
     */
    public static <T> T newInstance(Constructor<T> constructor, Object[] args)
    {
        try
        {
            return constructor.newInstance(args);
        }
        catch (InstantiationException e)
        {
            throw new IllegalStateException(e);
        }
        catch (IllegalAccessException e)
        {
            throw new IllegalStateException(e);
        }
        catch (InvocationTargetException e)
        {
            throw new IllegalStateException(e);
        }
    }

    /**
     * Calls a named method on an object with a specified set of parameters, any Java access modifier are overridden.
     *
     * @param  o            The object to call.
     * @param  method       The method name to call.
     * @param  params       The parameters to pass.
     * @param  paramClasses The argument types.
     *
     * @return The return value from the method call.
     */
    public static Object callMethodOverridingIllegalAccess(Object o, String method, Object[] params,
        Class[] paramClasses)
    {
        // Get the objects class.
        Class cls = o.getClass();

        // Get the classes of the parameters.
        /*Class[] paramClasses = new Class[params.length];

        for (int i = 0; i < params.length; i++)
        {
            paramClasses[i] = params[i].getClass();
        }*/

        try
        {
            // Try to find the matching method on the class.

            Method m = cls.getDeclaredMethod(method, paramClasses);

            // Make it accessible.
            m.setAccessible(true);

            // Invoke it with the parameters.
            return m.invoke(o, params);
        }
        catch (NoSuchMethodException e)
        {
            throw new IllegalStateException(e);
        }
        catch (IllegalAccessException e)
        {
            throw new IllegalStateException(e);
        }
        catch (InvocationTargetException e)
        {
            throw new IllegalStateException(e);
        }
    }

    /**
     * Calls a named method on an object with a specified set of parameters.
     *
     * @param  o      The object to call.
     * @param  method The method name to call.
     * @param  params The parameters to pass.
     *
     * @return The return value from the method call.
     */
    public static Object callMethod(Object o, String method, Object[] params)
    {
        // Get the objects class.
        Class cls = o.getClass();

        // Get the classes of the parameters.
        Class[] paramClasses = new Class[params.length];

        for (int i = 0; i < params.length; i++)
        {
            paramClasses[i] = params[i].getClass();
        }

        try
        {
            // Try to find the matching method on the class.
            Method m = cls.getMethod(method, paramClasses);

            // Invoke it with the parameters.
            return m.invoke(o, params);
        }
        catch (NoSuchMethodException e)
        {
            throw new IllegalStateException(e);
        }
        catch (IllegalAccessException e)
        {
            throw new IllegalStateException(e);
        }
        catch (InvocationTargetException e)
        {
            throw new IllegalStateException(e);
        }
    }

    /**
     * Calls a named static method on a class with a specified set of parameters.
     *
     * @param  method The method name to call.
     * @param  params The parameters to pass.
     *
     * @return The return value from the method call.
     */
    public static Object callStaticMethod(Method method, Object[] params)
    {
        try
        {
            return method.invoke(null, params);
        }
        catch (IllegalAccessException e)
        {
            throw new IllegalStateException(e);
        }
        catch (InvocationTargetException e)
        {
            throw new IllegalStateException(e);
        }
    }

    /**
     * Gets the constructor of a class that takes the specified set of arguments if any matches. If no matching
     * constructor is found then a runtime exception is raised.
     *
     * @param  cls  The class to get a constructor from.
     * @param  args The arguments to match.
     * @param  <T>  The class type.
     *
     * @return The constructor.
     */
    public static <T> Constructor<T> getConstructor(Class<T> cls, Class[] args)
    {
        try
        {
            return cls.getConstructor(args);
        }
        catch (NoSuchMethodException e)
        {
            throw new IllegalStateException(e);
        }
    }

    /**
     * Finds the argument types of all setter methods on a bean for a given property name. For a method to be a setter
     * method it must have a void return type, be public and accept only a single argument. Its name must be 'set'
     * followed by the property name.
     *
     * @param  obClass      The class to find all setter methods matching a given property for.
     * @param  propertyName The property name to find all matching setter methods for.
     *
     * @return An array of the types (as classes) of all the possible types that the setter method can be called with.
     */
    public static Set<Class> findMatchingSetters(Class obClass, String propertyName)
    {
        /*log.fine("private Set<Class> findMatchingSetters(Object ob, String propertyName): called");*/
        Set<Class> types = new HashSet<Class>();

        // Convert the first letter of the property name to upper case to match against the upper case version of
        // it that will be in the setter method name. For example the property test will have a setter method called
        // setTest.
        String upperPropertyName = Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);

        // Scan through all the objects methods.
        Method[] methods = obClass.getMethods();

        for (Method nextMethod : methods)
        {
            // Get the next method.
            /*log.fine("nextMethod = " + nextMethod.getName());*/
            // Check if a method has the correct name, accessibility and the correct number of arguments to be a setter
            // method for the property.
            String methodName = nextMethod.getName();

            if (methodName.equals("set" + upperPropertyName) && Modifier.isPublic(nextMethod.getModifiers()) &&
                    (nextMethod.getParameterTypes().length == 1))
            {
                /*log.fine(methodName + " is a valid setter method for the property " + propertyName +
                        " with argument of type " + nextMethod.getParameterTypes()[0]);*/

                // Add its argument type to the array of setter types.
                types.add(nextMethod.getParameterTypes()[0]);
            }
        }

        return types;
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.thesett.text.impl.model;

import com.thesett.text.api.model.TextGridModel;
import com.thesett.text.api.model.TextTableModel;

/**
 * Renders the contents of a {@link TextTableModel} into a {@link TextGridModel}.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Render a text table into a grid model. 	 {@link TextTableModel}, {@link TextGridModel}
 *

 *
 * @author Rupert Smith
 */
public class TextTableGridRenderer
{
    /** The table model to render. */
    private final TextTableModel tableModel;

    /** The grid to render into. */
    private final TextGridModel gridModel;

    /**
     * Creates a text table renderer.
     *
     * @param tableModel The table model to render.
     * @param gridModel  The grid to render into.
     */
    public TextTableGridRenderer(TextTableModel tableModel, TextGridModel gridModel)
    {
        this.tableModel = tableModel;
        this.gridModel = gridModel;
    }

    /** Renders the table. */
    public void renderTable()
    {
        for (int i = 0; i < tableModel.getRowCount(); i++)
        {
            int colOffset = 0;

            for (int j = 0; j < tableModel.getColumnCount(); j++)
            {
                // Print the contents of the table cell.
                String valueToPrint = tableModel.get(j, i);
                valueToPrint = (valueToPrint == null) ? "" : valueToPrint;
                gridModel.insert(valueToPrint, colOffset, i);

                // Pad spaces up to the column width if the contents are shorted.
                Integer maxColumnSize = tableModel.getMaxColumnSize(j);
                int spaces = maxColumnSize - valueToPrint.length();

                while (spaces > 0)
                {
                    gridModel.insert(" ", colOffset + valueToPrint.length() + spaces-- - 1, i);
                }

                // Shift to the next column.
                colOffset += maxColumnSize;
            }
        }
    }
}


/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.hobsoft.microbrowser.selenium;

import java.net.URL;
import java.util.List;

import org.hobsoft.microbrowser.Control;
import org.hobsoft.microbrowser.ControlGroup;
import org.hobsoft.microbrowser.ControlNotFoundException;
import org.hobsoft.microbrowser.MicrodataDocument;
import org.hobsoft.microbrowser.spi.AbstractForm;
import org.hobsoft.microbrowser.spi.DefaultControlGroup;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import com.google.common.base.Function;
import com.google.common.collect.Lists;

import static org.hobsoft.microbrowser.spi.Urls.newUrlOrNull;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

/**
 * {@code Form} adapter to a Selenium {@code WebElement}.
 */
class SeleniumForm extends AbstractForm
{
	// ----------------------------------------------------------------------------------------------------------------
	// fields
	// ----------------------------------------------------------------------------------------------------------------

	private final WebDriver driver;

	private final WebElement element;

	// ----------------------------------------------------------------------------------------------------------------
	// constructors
	// ----------------------------------------------------------------------------------------------------------------

	SeleniumForm(WebDriver driver, WebElement element)
	{
		this.driver = checkNotNull(driver, "driver");
		this.element = checkNotNull(element, "element");
	}

	// ----------------------------------------------------------------------------------------------------------------
	// Form methods
	// ----------------------------------------------------------------------------------------------------------------

	public String getName()
	{
		return element.getAttribute("name");
	}

	public ControlGroup getControlGroup(String name)
	{
		List<WebElement> elements = element.findElements(byControl(name));

		if (elements.isEmpty())
		{
			throw new ControlNotFoundException(name);
		}

		return newControlGroup(elements);
	}

	public MicrodataDocument submit()
	{
		WebElement submit = getSubmit();
		checkArgument(getAction() != null, "Invalid action: " + element.getAttribute("action"));

		submit.click();

		return new SeleniumMicrodataDocument(driver);
	}

	// ----------------------------------------------------------------------------------------------------------------
	// Unwrappable methods
	// ----------------------------------------------------------------------------------------------------------------

	public <T> T unwrap(Class<T> type)
	{
		checkArgument(WebElement.class.equals(type), "Cannot unwrap to: %s", type);

		return type.cast(element);
	}

	// ----------------------------------------------------------------------------------------------------------------
	// private methods
	// ----------------------------------------------------------------------------------------------------------------

	private URL getAction()
	{
		String action = element.getAttribute("action");

		if (action.isEmpty())
		{
			action = driver.getCurrentUrl();
		}

		return newUrlOrNull(action);
	}

	private static By byControl(String name)
	{
		return By.cssSelector(String.format("input[name='%1$s'], textarea[name='%1$s']", name));
	}

	private static ControlGroup newControlGroup(List<WebElement> elements)
	{
		List<Control> controls = Lists.transform(elements, new Function<WebElement, Control>()
		{
			public Control apply(WebElement element)
			{
				return newControl(element);
			}
		});

		return new DefaultControlGroup(controls);
	}

	private static Control newControl(WebElement element)
	{
		Control control;
		String type = element.getAttribute("type");

		if ("hidden".equals(type))
		{
			control = new SeleniumHiddenControl(element);
		}
		else if ("checkbox".equals(type))
		{
			control = new SeleniumCheckboxControl(element);
		}
		else if ("radio".equals(type))
		{
			control = new SeleniumRadioControl(element);
		}
		else
		{
			control = new SeleniumTextControl(element);
		}

		return control;
	}

	private WebElement getSubmit()
	{
		List<WebElement> elements = element.findElements(bySubmit());
		checkState(!elements.isEmpty(), "Missing form submit button");

		return elements.get(0);
	}

	private static By bySubmit()
	{
		return By.cssSelector("input[type='submit'], button[type='submit'], button:not([type])");
	}
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.thesett.common.util.queues;

import java.util.Collection;
import java.util.LinkedList;

import com.thesett.common.error.NotImplementedException;
import com.thesett.common.util.Queue;
import com.thesett.common.util.Sizeable;
import com.thesett.common.util.SizeableQueue;
import com.thesett.common.util.SizeableReQueue;
import com.thesett.common.util.concurrent.BlockingQueue;
import com.thesett.common.util.concurrent.SizeableBlockingQueue;

/**
 * Queues is a utility class for providing specialized queue implementations on top of underlying queue types. It is
 * similar in its conception to the java.util.Collections class, that provides collection specializations.
 *
 *

CRC Card

 *
ResponsibilitiesCollaborations
 *
Make queues sizable.
 *
Make queues atomically counted.
 *
Make queues synchronized.
 *
Make queues transactional.
 *
Provide fake transactional queues for transactional code running in a non-transactonal context.
 *

 *
 * @author Rupert Smith
 */
public class Queues
{
    /**
     * Wraps a java.util.concurrent.BlockingQueue as a {@link com.thesett.common.util.concurrent.BlockingQueue}
     * implementation.
     *
     * @param  queue The blocking queue to wrap.
     * @param  <E>   The type of queue element.
     *
     * @return The queue as a {@link com.thesett.common.util.concurrent.BlockingQueue} implementation.
     */
    public static <E> BlockingQueue<E> getBlockingQueue(java.util.concurrent.BlockingQueue<E> queue)
    {
        return new WrapperQueue<E>(queue, new LinkedList<E>(), false, false, false);
    }

    /**
     * Wraps a java.util.concurrent.BlockingQueue as a {@link com.thesett.common.util.concurrent.BlockingQueue}
     * implementation.
     *
     * @param  queue The blocking queue to wrap.
     * @param  <E>   The type of queue element.
     *
     * @return The queue as a {@link com.thesett.common.util.concurrent.BlockingQueue} implementation.
     */
    public static <E> SizeableBlockingQueue<E> getSizeableBlockingQueue(java.util.concurrent.BlockingQueue<E> queue)
    {
        return new WrapperQueue<E>(queue, new LinkedList<E>(), false, false, false);
    }

    /**
     * Wraps a queue with a sizeable implementation, that keeps track of the size of the queue, provided that the
     * elements being inserted into the queue are {@link com.thesett.common.util.Sizeable}. As elements are
     * added/removed on a queue, the queues size is incremented/decrements accordingly.
     *
     * @param  queue The queue to make sizeable.
     * @param  <E>   The type of queue element.
     *
     * @return A sizeable queue from an ordinary queue.
     */
    public static <E extends Sizeable> SizeableQueue<E> getSizeableQueue(java.util.Queue<E> queue)
    {
        return new WrapperQueue<E>(queue, new LinkedList<E>(), false, true, false);
    }

    /**
     * Wraps a queue with a queue that counts the number of elements in it atomically, as elements are inserted/removed
     * on the queue. This is usefull for non-locking queue implementations, that can only estimate their size, at the
     * momemnt the 'size' operation is called, because many threads may be in the process of altering the queue at once.
     *
     * @param  queue The queue to provide atomic counting of.
     * @param  <E>   The type of queue element.
     *
     * @return An atomicically counted queue.
     */
    public static <E> Queue<E> getAtomicCountedQueue(java.util.Queue<E> queue)
    {
        return new WrapperQueue<E>(queue, new LinkedList<E>(), false, false, true);
    }

    /**
     * Wraps queue as a sizeable, atomically counted queue, as per the {@link #getSizeableQueue} and
     * {@link #getAtomicCountedQueue} methods.
     *
     * @param  queue The queue to provide atomic counting and sizing of.
     * @param  <E>   The type of queue element.
     *
     * @return An atomicically counted, sizeable queue.
     */
    public static <E extends Sizeable> SizeableQueue<E> getAtomicCountedSizeableQueue(java.util.Queue<E> queue)
    {
        return new WrapperQueue<E>(queue, new LinkedList<E>(), false, true, true);
    }

    /**
     * Turns non-synched queue into a synched queue for concurrent use. The resulting queue uses blocking
     * synchronization on its methods to ensure that only one thread at a time can access the queue. The resulting queue
     * may not provide the best performance, especially on multi-processor machines. A non-locking implementation may be
     * consideredd instead.
     *
     * @param  queue The queue to synchronize for concurrent use.
     * @param  <E>   The type of queue element.
     *
     * @return A synchronized queue.
     */
    public static <E> Queue<E> synchronizeQueue(java.util.Queue<E> queue)
    {
        throw new NotImplementedException();
    }

    /**
     * Provides a transactional queue, that delays all queue manipulation operations until the transaction is committed,
     * or erases them if it is rolled back.
     *
     * @param  queue The queue to make transactional.
     * @param  <E>   The type of queue element.
     *
     * @return A transactional queue.
     */
    public static <E> Queue<E> getTransactionalQueue(java.util.Queue<E> queue)
    {
        return new WrapperQueue<E>(queue, new LinkedList<E>(), true, false, false);
    }

    /**
     * Provides a transactional requeue, that delays all queue manipulation operations until the transaction is
     * committed, or erases them if it is rolled back. As this is a requeue, the requeue buffer may be examined directly
     * and the queue fully supports browsing with iterators.
     *
     * @param  queue   The queue to use as the underlying queue implementation for the requeue.
     * @param  requeue The collection to use for the requeue buffer.
     * @param  <E>     The type of queue element.
     *
     * @return A transactional requeue.
     */
    public static <E> Queue<E> getTransactionalReQueue(java.util.Queue<E> queue, Collection<E> requeue)
    {
        return new WrapperQueue<E>(queue, requeue, true, false, false);
    }

    /**
     * Wraps queue as a sizeable, transactional requeue, as per the {@link #getSizeableQueue} and
     * {@link #getTransactionalReQueue} methods.
     *
     * @param  queue   The queue to provide sizing and transactional operations on.
     * @param  requeue The requeue buffer implementation to use.
     * @param  <E>     The type of queue element.
     *
     * @return An atomicically counted, sizeable queue.
     */
    public static <E extends Sizeable> SizeableQueue<E> getSizeableTransactionalReQueue(java.util.Queue<E> queue,
        Collection<E> requeue)
    {
        return new WrapperQueue<E>(queue, requeue, true, true, false);
    }

    /**
     * Wraps queue as a sizeable, atomically counted queue, transactional requeue, as per the {@link #getSizeableQueue},
     * {@link #getAtomicCountedQueue}, and {@link #getTransactionalReQueue} methods.
     *
     * @param  queue   The queue to provide atomic counting, sizing and transactional operations on.
     * @param  requeue The requeue buffer implementation to use.
     * @param  <E>     The type of queue element.
     *
     * @return An atomicically counted, sizeable queue.
     */
    public static <E extends Sizeable> Queue<E> getAtomicCountedSizeableTransactionalReQueue(
        java.util.Queue<E> queue, Collection<E> requeue)
    {
        return new WrapperQueue<E>(queue, requeue, true, true, true);
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.thesett.aima.state.impl;

import com.thesett.aima.state.Attribute;
import com.thesett.aima.state.Type;

/**
 * TypeHelper provides some helper methods for deriving the {@link Type}s of objects.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Get the type of an object.
 *

 *
 * @author Rupert Smith
 */
public class TypeHelper
{
    /**
     * Gets the type of a specified object.
     *
     * @param  o The object to get the type of.
     *
     * @return The type of the object.
     */
    public static Type getTypeFromObject(Object o)
    {
        // Check if the object is null, in which case its type cannot be derived.
        if (o == null)
        {
            return new UnknownType();
        }

        // Check if the object is an attribute a and get its type that way if possible.
        if (o instanceof Attribute)
        {
            return ((Attribute) o).getType();
        }

        // Return an approproate Type for the java primitive, wrapper or class type of the argument.
        return new JavaType(o);
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.thesett.aima.search.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Queue;

import com.thesett.aima.search.QueueBasedSearchMethod;
import com.thesett.aima.search.RepeatedStateFilter;
import com.thesett.aima.search.SearchNode;
import com.thesett.aima.search.SearchNotExhaustiveException;
import com.thesett.aima.search.Traversable;
import com.thesett.aima.search.spi.QueueSearchAlgorithm;
import com.thesett.aima.search.spi.QueueSearchState;
import com.thesett.common.util.logic.UnaryPredicate;

/**
 * BaseQueueSearch provides a base implementation for deriving new searches from by providing different queue
 * implementations. For example using a LIFO queue generates depth first search and a FIFO queue generates breadth
 * first. Heuristic searches can easily be implemented by using priority queues with ordering based on a heuristic
 * evaluation. Uniform cost search can be implement by using a priority queue with an ordering based on the path cost.
 *
 *
The actual search algorithm is factored out of this class and provided by classes that implement the
 * {@link QueueSearchAlgorithm} interface. Roughly speaking all queue search algorithms are quite similar; they procede
 * by extracting the head item from the queue buffer and testing to see if it is a goal state, if it is then the search
 * terminates on that {@link SearchNode}, otherwise the accessible states from the present search node are expanded into
 * the queue and the search continues with the next element. See the search algorithm implementations for the finer
 * details of each. This class uses the {@link MaxStepsAlgorithm} by default.
 *
 *
Depending on the queue implementation the search nodes will be extracted from it in different orders and this is
 * what determines the order in which elements are examined by the search algorithms. The queue implementation must be
 * provided by concrete sub-classes of this base class.
 *
 *
Different kinds of search node can be used to capture different information about the states being searched over
 * and this in turn can be used by the queue implementations and ordering functions to control the way in which the
 * search proceeds. The most obvious example is to extend the basic search node with a heuristic one that computes
 * heuristics for the states and then to provide an ordering over heuristics (Greedy, or A-Star for example) to control
 * the search.
 *
 *
As specified in the {@link QueueBasedSearchMethod} interface this class provides a way to plug in a repeated state
 * filter.
 *
 *
These four aspects of the search routine, the basic algorithm, the search node type, the queue and the rejected
 * state pool can all be combined independently of one another to provide an array of different queue based search
 * techniques in a very flexible manner. It is necessary though to understand each of the components separately in order
 * to be able to combine them together successfully. Implementations of many standard search routines are provided in
 * this package by the combination of plug-in elements, consult the implementations for the details.
 *
 *
Generally speaking if the queue should become empty without a goal state being found then the search algorithm
 * should return null and terminate. However, it should only do this if the search space is known to have been searched
 * completely. Searches that terminate prematurely and know that there are still unsearched states to work with should
 * terminate by throwing a {@link SearchNotExhaustiveException} or a specific sub-class of it. Returning with null must
 * be reserved for the case where it is known that no solutions exist so there is no point in searching any further.
 *
 *
This class implements {@link QueueSearchState} interface. This is a call-back interface that provides a limited
 * view onto this class to the {@link QueueSearchAlgorithm} implementations so that they can call its
 * {@link #enqueueStartStates} method to initialize the queue ready for searching. This was done for the sake of hiding
 * the full implementation of this class from the search algorithms.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Combine implementations of queue, search node, repeated state filter and basic algorithm into a search.
 *      {@link SearchNode}, {@link RepeatedStateFilter}, {@link QueueSearchAlgorithm}, {@link QueueSearchState}
 *
 Set up the start states for a search.
 *
 Set a maximum number of search steps allowable.
 *
 Reset a search algorithm.
 *

 *
 * @author Rupert Smith
 */
public abstract class BaseQueueSearch<O, T extends Traversable<O>> implements QueueBasedSearchMethod<O, T>,
    QueueSearchState<O, T>
{
    /** The queue used to control the search order. */
    protected Queue<SearchNode<O, T>> queue;

    /** Used to hold the start states. */
    protected Collection<T> startStates;

    /** Holds a reference to the repeated state filtering strategy. */
    protected RepeatedStateFilter<O, T> repeatedStateFilter;

    /** Holds the goal predicate for evaluating potential goal states with. */
    protected UnaryPredicate<T> goalPredicate;

    /**
     * Used to hold the maximum number of search steps to perform before quitting with no solution. If this is zero or
     * less then this is taken to mean that no maximum limit is in effect.
     */
    protected int maxSteps;

    /** Used to hold the number of search steps taken so far in a search. */
    protected int searchSteps;

    /** Holds the queue search algorithm to run. */
    protected QueueSearchAlgorithm<O, T> searchAlgorithm;

    /** Flag used to monitor whether or not the start states have already been enqueued. */
    protected boolean enqueuedOnce;

    /**
     * Constructor takes an initial search node, and a search queue. Specific searches can be instantiated by choosing
     * specific queues in the constructor.
     */
    public BaseQueueSearch()
    {
        // Create an empty collection of start states.
        startStates = new ArrayList<T>();

        // Set up the max steps algorithm as the default.
        searchAlgorithm = new MaxStepsAlgorithm<O, T>();
    }

    /**
     * This abstract method should be overriden to turn states into search nodes. Different implementation of queue
     * based algorithms can control the way they search by using different search node implementations. This method
     * allows the type of search node to be abstracted out of this search method to be supplied by concrete
     * implementations.
     *
     * @param  state The state to create a {@link SearchNode} from.
     *
     * @return The {@link SearchNode} for the specified state.
     */
    public abstract SearchNode<O, T> createSearchNode(T state);

    /**
     * This abstract method should be overriden to return an empty queue of search nodes. Different implementations of
     * queue search algorithms can control the way the search proceeds by using different queue implementations. This
     * method allows the type of queue to be abstracted out of this search method to be supplied by concrete
     * implementations.
     *
     * @return An empty queue of search nodes.
     */
    public abstract Queue<SearchNode<O, T>> createQueue();

    /**
     * Attaches the specified repeated state filtering strategy to the search algorithm. This should be called prior to
     * starting a search for the filter to take effect.
     *
     * @param filter The repeated state filter to prune the search space with.
     */
    public void setRepeatedStateFilter(RepeatedStateFilter filter)
    {
        // Keep the reference to the filter.
        this.repeatedStateFilter = filter;
    }

    /**
     * Sets the maximum number of goal tests that this search will perform before quiting without a solution. If the max
     * is 0 or negative then the maximum step limit is lifted.
     *
     * @param max The number of search states to examine before stopping the search without a solution.
     */
    public void setMaxSteps(int max)
    {
        maxSteps = max;
    }

    /**
     * Adds a start state to the search. Many search algorithms will only accept a single start state in which case the
     * most recent call to this method is taken as the definition of the single start state to use. Some search
     * algorithms may take multiple start states in which case successive calls to this method should be used to
     * establish all the start states.
     *
     * @param startState The start state to add to the collection of start states to begin the search with.
     */
    public void addStartState(T startState)
    {
        // Add the new start state to the collection of start states
        startStates.add(startState);
    }

    /**
     * Some search algorithms may accept definitions of the goal state in which case the most recent call to this method
     * is taken as the definition of the goal state. In some searches the goal state is not known in advance, in others
     * the purpose of the search is to find a path from the start to the goal. If the search algorithm does not accept a
     * goal state it should throw an exception indicating that this method is not supported by that algorithm.
     *
     *
Note that the {@link com.thesett.aima.search.GoalState} interface itself defines the method
     * {@link com.thesett.aima.search.GoalState#isGoal} which tests if a state is a goal state. It is therefore not
     * necessary to call this method to set goal states where the goal definition is defined already in the states.
     * Setting goal states through this method, when it is supported by an algorithm overrides the goal definition in
     * the states themselves.
     *
     * @param  goalPredicate The predicate that evaluates search states to check if they are goals.
     *
     * @throws UnsupportedOperationException If the search algorithm does not accept goal predicates.
     */
    public void setGoalPredicate(UnaryPredicate<T> goalPredicate) throws UnsupportedOperationException
    {
        this.goalPredicate = goalPredicate;
    }

    /**
     * Provides the goal predicate for the search.
     *
     * @return The goal predicate for the search.
     */
    public UnaryPredicate<T> getGoalPredicate()
    {
        return goalPredicate;
    }

    /** Resets the search, clearing out the queue and setting it to contain just the start state node. */
    public void reset()
    {
        // Clear out the start states.
        startStates.clear();
        enqueuedOnce = false;

        // Reset the queue to a fresh empty queue.
        queue = createQueue();

        // Clear the goal predicate.
        goalPredicate = null;

        // Reset the maximum steps limit
        maxSteps = 0;

        // Reset the number of steps taken
        searchSteps = 0;

        // Reset the repeated state filter if there is one.
        if (repeatedStateFilter != null)
        {
            repeatedStateFilter.reset();
        }

        // Reset the search alogorithm if it requires resettting.
        searchAlgorithm.reset();
    }

    /**
     * This logic enqueues all the start states, calling the {@link #createSearchNode} method that concrete sub-classes
     * implement to specify the search node type. If there is a repeated state filter set up then this is attached to
     * the search nodes. This is called at the start of the search method to set up the queue into a state which is
     * ready for the search algorithm.
     *
     * @param  startStates The set of start states to being the search at.
     *
     * @return The queue of search nodes for each of the start states.
     *
     * @throws IllegalStateException if no start states have been set for the search.
     */
    public Queue<SearchNode<O, T>> enqueueStartStates(Collection<T> startStates)
    {
        // Check that there are some start states
        if (!startStates.isEmpty())
        {
            // Only enqueue the start states if they have not already been enqueued.
            if (!enqueuedOnce)
            {
                // Enqueue all the start states
                for (T nextStartState : startStates)
                {
                    // If the goal predicate has not been defined, try to set up the default from the initial search
                    // states.
                    if (goalPredicate == null)
                    {
                        goalPredicate = nextStartState.getDefaultGoalPredicate();
                    }

                    // Make search nodes out of the start states using the abstract search node creation method,
                    // subclasses override this to create different kinds of search node.
                    SearchNode newStartNode = createSearchNode(nextStartState);

                    // Check if a repeated state filter has been applied and attach it to the start node if so.
                    if (repeatedStateFilter != null)
                    {
                        // Attach it to the start node.
                        newStartNode.setRepeatedStateFilter(repeatedStateFilter);
                    }

                    // Insert the new start search node onto the queue.
                    queue.offer(newStartNode);
                }
            }
        }
        else
        {
            // There are no start states so raise an exception because the search cannot be run without a start state.
            throw new IllegalStateException("Cannot start the search because there are no start states defined. " +
                "Queue searches require some start states.", null);
        }

        // Check that a goal predicate is set up.
        if (goalPredicate == null)
        {
            throw new IllegalStateException("Cannot start the search because there is no goal predicate.", null);
        }

        // Set the enqueuedOnce flag to indicate that the start states have already been enqueued.
        enqueuedOnce = true;

        return queue;
    }

    /**
     * Indicates whether or not the start states have already been enqueued.
     *
     * @return <tt>true</tt> if the start states have already been enqueued, <tt>false</tt> otherwise.
     */
    public boolean isEnqueuedOnce()
    {
        return enqueuedOnce;
    }

    /**
     * Resets the flag that indicates whether or not start states have already been enqueued. Iterative algorithms will
     * use this, for example, to allow their search to be reset to the begining before searching to a higher search
     * bound.
     */
    public void resetEnqueuedOnceFlag()
    {
        enqueuedOnce = false;
    }

    /**
     * This provides a call back that search algorithms use to update the number of search steps taken. They can do this
     * at the end of the search, so that it is only updated once to save on the number of calls, or as the search is
     * running, which will be slower but provide runtime statistics.
     *
     * @param steps The number of search states seen so far.
     */
    public void setStepsTaken(int steps)
    {
        searchSteps = steps;
    }

    /**
     * This provides a call back that search algorithms use to get the number of search steps taken so far.
     *
     * @return The number of search states seen so far.
     */
    public int getStepsTaken()
    {
        return searchSteps;
    }

    /**
     * Implementation of the general queue search. The basic algorithm is simple: take the next element from the queue
     * and goal test it. If it is a goal then return it and stop the search. If it is not a goal then expand its
     * successor states and enqueue them and then repeat the procedure.
     *
     * @return The first {@link SearchNode} corresponding to a goal state that is found or null if none can be found
     *         after exhaustive searching. A return value of null should really mean that exhaustive searching has been
     *         completed rather than some premature termination condition being reached. See the comment below about the
     *         SearchNotExhaustiveException.
     *
     * @throws SearchNotExhaustiveException If the search stops before finding a solution or exhausting the search
     *                                      space. Different search algorithms may fail for different reasons but in
     *                                      particular it it is worth noting that if the maximum number of steps is
     *                                      reached without exhausting the search space this will cause an exception to
     *                                      be thrown rather than for this method to return null.
     */
    public SearchNode<O, T> findGoalPath() throws SearchNotExhaustiveException
    {
        // Delegate the search to the pluggable search algorithm.
        return searchAlgorithm.search(this, startStates, maxSteps, searchSteps);
    }

    /**
     * Perform the search. This can be called multiple times to get successive results where more than one goal can be
     * found, if the algorithm supports this. In this case it should return null once no more goals can be found.
     *
     * @return The first state corresponding to a goal state that is found or null if none can be found after exhaustive
     *         searching. A return value of null should really mean that exhaustive searching has been completed rather
     *         than some premature termination condition being reached. See the comment below about the
     *         SearchNotExhaustiveException.
     *
     * @throws SearchNotExhaustiveException If the search stops before finding a solution or exhausting the search
     *                                      space. Different search algorithms may fail for different reasons but in
     *                                      particular it it is worth noting that if the maximum number of steps is
     *                                      reached without exhausting the search space this will cause an exception to
     *                                      be thrown rather than for this method to return null.
     */
    public T search() throws SearchNotExhaustiveException
    {
        SearchNode<O, T> path = findGoalPath();

        if (path != null)
        {
            return path.getState();
        }
        else
        {
            return null;
        }
    }

    /**
     * Allows different queue search algorithms to replace the default one.
     *
     * @param algorithm The search algorithm to use.
     */
    protected void setQueueSearchAlgorithm(QueueSearchAlgorithm<O, T> algorithm)
    {
        this.searchAlgorithm = algorithm;
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.thesett.aima.logic.fol.prolog.builtins;

import java.util.LinkedList;
import java.util.List;

import com.thesett.aima.logic.fol.Functor;
import com.thesett.aima.logic.fol.Term;
import com.thesett.aima.logic.fol.Variable;

/**
 * Is implements the arithmetic evaluation operator in Prolog. The right hand side of the operator is evaluated and must
 * produce a numeric result. The result is then unified against the left hand side to determine whether the 'is'
 * predicate is proveable.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Evaluate an arithemtic expression and unify it with another term.
 *      {@link ResolutionState}, {@link PrologUnifier}, {@link Term},
 *          {@link com.thesett.aima.logic.fol.NumericType}.
 *

 *
 * @author Rupert Smith
 */
public class Is extends BaseBuiltIn
{
    /** Used for debugging purposes. */
    public static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(Is.class.getName());

    /**
     * Creates an is built-in to implement the specified functor.
     *
     * @param functor The functor to implement as a built in.
     */
    public Is(Functor functor)
    {
        super(functor);
    }

    /** {@inheritDoc} */
    public boolean proofStep(ResolutionState state)
    {
        Functor isOp = state.getGoalStack().poll().getFunctor();

        // Evaluate the second argument as a fully instantiated numeric value.
        Term expressionValue = BuiltInUtils.evaluateAsNumeric(isOp.getArgument(1));

        // This is used to record variables bound during the unification, so that they may be undone if the resolution
        // state is backtracked over.
        List<Variable> boundVariables = new LinkedList<Variable>();

        // Unify against the LHS.
        boolean matched =
            state.getUnifier().unifyInternal(isOp.getArgument(0), expressionValue, boundVariables, boundVariables);

        for (Variable binding : boundVariables)
        {
            state.getVariableBindings().offer(binding);
        }

        return matched;
    }
}