diff options
author | Marcin Chrzanowski <marcin.j.chrzanowski@gmail.com> | 2019-10-21 19:31:52 +0200 |
---|---|---|
committer | Marcin Chrzanowski <marcin.j.chrzanowski@gmail.com> | 2019-10-21 19:31:52 +0200 |
commit | c2ccf4e675c68d8b1cca6f662dbfbf800449247a (patch) | |
tree | e441d0dd420b11542523bb7238ec6273a9d4dd73 /src/pl |
Intial commit - import scenario 2
Diffstat (limited to 'src/pl')
22 files changed, 3096 insertions, 0 deletions
diff --git a/src/pl/edu/mimuw/cloudatlas/model/Attribute.java b/src/pl/edu/mimuw/cloudatlas/model/Attribute.java new file mode 100644 index 0000000..d0af5bb --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/Attribute.java @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +/** + * Represents an attribute (without value, name only). + * <p> + * A valid attribute name is an identifier starting with a letter and containing only letters and digits. It can + * additionally start with an ampersand - such names are reserved for queries. + * <p> + * This class is immutable. + */ +public class Attribute { + private final String name; + + /** + * Creates a new <code>Attribute</code> object with the specified <code>name</code>. + * + * @param name the name of the attribute + * @throws IllegalArgumentException if the <code>name</code> does not meet the rules + */ + public Attribute(String name) { + if(!name.matches("^&?[a-zA-Z]{1}[a-zA-z0-9_]*$")) + throw new IllegalArgumentException("Invalid name: may contain only letters, digits, underscores, " + + "must start with a letter and may optionally have an ampersand at the beginning."); + this.name = name; + } + + /** + * Indicates whether an <code>attribute</code> represents a query. This is true if and only if attribute name starts with an + * ampersand. + * + * @param attribute the attribute to check + * @return whether the <code>attribute</code> represents a query + */ + public static boolean isQuery(Attribute attribute) { + return attribute.getName().startsWith("&"); + } + + /** + * Gets the name of this attribute. + * + * @return string representing name + */ + public String getName() { + return name; + } + + /** + * Returns a hash code value for this attribute. For a proper behavior when using <code>Attribute</code> objects in + * <code>HashMap</code>, <code>HashSet</code> etc. this is the hash code of a string representing attribute name. + * + * @return hash code for this attribute + */ + @Override + public int hashCode() { + return name.hashCode(); + } + + /** + * Indicates whether another object is equal to this attribute. + * + * @param object the object to check + * @return true if and only if the <code>object</code> is an instance of <code>Attribute</code> class and has + * identical name + */ + @Override + public boolean equals(Object object) { + if(object == null) + return false; + if(getClass() != object.getClass()) + return false; + return name.equals(((Attribute)object).name); + } + + /** + * Returns a textual representation of this attribute. + * + * @return the name of this attribute + */ + @Override + public String toString() { + return name; + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/AttributesMap.java b/src/pl/edu/mimuw/cloudatlas/model/AttributesMap.java new file mode 100644 index 0000000..86f8969 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/AttributesMap.java @@ -0,0 +1,282 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +/** + * Represents a map from <code>Attribute</code> to <code>Value</code>. It cannot contain duplicate keys. + */ +public class AttributesMap implements Iterable<Entry<Attribute, Value>>, Cloneable { + private Map<Attribute, Value> map = new HashMap<Attribute, Value>(); + + private void checkNulls(Attribute attribute, Value value) { + if(attribute == null) + throw new NullPointerException("The attribute cannot be null."); + if(value == null) + throw new NullPointerException( + "The value cannot be null. You may want create a Value object that contains null."); + } + + /** + * Adds to this map a new <code>attribute</code> mapping to the specified <code>value</code>. The + * <code>attribute</code> cannot already exist in the map. To overwrite an existing attribute, use method + * {@link #addOrChange(Attribute, Value)} instead. + * + * @param attribute the attribute to add + * @param value the value for the <code>attribute</code> + * @throws IllegalArgumentException if the <code>attribute</code> already exists in this map + * @throws NullPointerException if either the <code>attribute</code> or the <code>value</code> is <code>null</code>; + * for null value, create a <code>Value</code> object containing <code>null</code> + * @see #addOrChange(Attribute, Value) + * @see #add(String, Value) + * @see #add(Entry) + * @see #add(AttributesMap) + */ + public void add(Attribute attribute, Value value) { + if(getOrNull(attribute) != null) + throw new IllegalArgumentException("Attribute \"" + attribute.getName() + + "\" already exists. Use method addOrChange(Attribute, Value) instead."); + checkNulls(attribute, value); + map.put(attribute, value); + } + + /** + * Adds a new attribute mapping to the specified <code>value</code>. Convenient version of + * {@link #add(Attribute, Value)}. + * + * @param name the attribute name + * @param value the attribute value + * @see #add(Attribute, Value) + * @see #addOrChange(String, Value) + */ + public void add(String name, Value value) { + add(new Attribute(name), value); + } + + /** + * Adds a new mapping to this map. Convenient version of {@link #add(Attribute, Value)}. + * + * @param entry a pair containing both an attribute and a value + * @see #add(Attribute, Value) + * @see #addOrChange(Entry) + */ + public void add(Entry<Attribute, Value> entry) { + add(entry.getKey(), entry.getValue()); + } + + /** + * Adds all entries from another map to this map. This method uses {@link #add(Attribute, Value)}, so it throws an + * exception when trying to overwrite an existing attribute. + * + * @param attributes the map to add + * @see #add(Attribute, Value) + * @see #addOrChange(AttributesMap) + */ + public void add(AttributesMap attributes) { + for(Entry<Attribute, Value> entry : attributes.map.entrySet()) + add(entry); + } + + /** + * Adds to this map a new <code>attribute</code> mapping to the specified <code>value</code>. Unlike + * {@link #add(Attribute, Value)}, this method overwrites an existing attribute with the same name. + * + * @param attribute the attribute to add or overwrite + * @param value the value for the <code>attribute</code> + * @throws NullPointerException if either the <code>attribute</code> or the <code>value</code> is <code>null</code>; + * for null value create a <code>Value</code> object containing <code>null</code> + * @see #add(Attribute, Value) + * @see #addOrChange(String, Value) + * @see #addOrChange(Entry) + * @see #addOrChange(AttributesMap) + */ + public void addOrChange(Attribute attribute, Value value) { + map.put(attribute, value); + checkNulls(attribute, value); + } + + /** + * Adds a new attribute< mapping to the specified <code>value</code> or overwrites an existing one. Convenient + * version of {@link #addOrChange(Attribute, Value)}. + * + * @param name the attribute name + * @param value the attribute value + * @see #addOrChange(Attribute, Value) + * @see #add(String, Value) + */ + public void addOrChange(String name, Value value) { + addOrChange(new Attribute(name), value); + } + + /** + * Adds a new mapping to this map or overwrites an existing one with the same attribute name. Convenient version of + * {@link #addOrChange(Attribute, Value)}. + * + * @param entry a pair containing both an attribute and a value + * @see #addOrChange(Attribute, Value) + * @see #add(Entry) + */ + public void addOrChange(Entry<Attribute, Value> entry) { + addOrChange(entry.getKey(), entry.getValue()); + } + + /** + * Adds all entries from another map to this map. If any attribute with the same name exists in this map, it will be + * overwritten. + * + * @param attributes the map to add + * @see #addOrChange(Attribute, Value) + * @see #add(AttributesMap) + */ + public void addOrChange(AttributesMap attributes) { + for(Entry<Attribute, Value> entry : attributes.map.entrySet()) + addOrChange(entry); + } + + private void checkAttribute(Attribute attribute) { + if(attribute == null) + throw new NullPointerException("The attribute cannot be null."); + } + + /** + * Gets the value mapped to the specified <code>attribute</code>. If such mapping does not exist, this method throws + * an exception. If this is not an expected behavior, use method {@link #getOrNull(Attribute)} instead. + * + * @param attribute the attribute to obtain + * @return the value mapped to the <code>attribute</code> + * @throws IllegalArgumentException if no value is mapped to the <code>attribute</code> + * @throws NullPointerException if the <code>attribute</code> is <code>null</code> + * @see #getOrNull(Attribute) + * @see #get(String) + */ + public Value get(Attribute attribute) { + Value value = getOrNull(attribute); + if(value == null) + throw new IllegalArgumentException("Attribute " + attribute.getName() + + " does not exist. Use method getOrNull(Attribute) instead."); + return value; + } + + /** + * Gets the value mapped to the specified attribute. Convenient version of {@link #get(Attribute)}. + * + * @param name name of the attribute + * @return the value mapped to the specified attribute + * @see #get(Attribute) + * @see #getOrNull(String) + */ + public Value get(String name) { + return get(new Attribute(name)); + } + + /** + * Gets the value mapped to the specified <code>attribute</code>. Unlike {@link #get(Attribute)}, this method + * returns <code>null</code> if the requested mapping does not exist. + * + * @param attribute the attribute to obtain + * @return the value mapped to the <code>attribute</code> or <code>null</code> if it does not exist + * @throws NullPointerException if the <code>attribute</code> is <code>null</code> + * @see #get(Attribute) + * @see #getOrNull(String) + */ + public Value getOrNull(Attribute attribute) { + checkAttribute(attribute); + return map.get(attribute); + } + + /** + * Gets the value mapped to the specified attribute. Convenient version of {@link #getOrNull(Attribute)}. + * + * @param name name of the attribute + * @return the value mapped to specified attribute or <code>null</code> if it does not exist + * @see #getOrNull(Attribute) + * @see #getOr(String) + */ + public Value getOrNull(String name) { + return getOrNull(new Attribute(name)); + } + + /** + * Removes the specified <code>attribute</code> and its value from this map. If the <code>attribute</code> does not + * exist, this method performs nothing. + * + * @param attribute the attribute to remove + * @throws NullPointerException if the <code>attribute</code> is <code>null</code> + * @see #remove(String) + */ + public void remove(Attribute attribute) { + checkAttribute(attribute); + map.remove(attribute); + } + + /** + * Removes the specified attribute and its value from this map. Convenient version of {@link #remove(Attribute)}. + * + * @param name the name of the attribute to remove + * @see #remove(Attribute) + */ + public void remove(String name) { + map.remove(new Attribute(name)); + } + + /** + * Returns an iterator over all entries stored in this map. + * + * @return an iterator for this map + * @see java.util.Iterator + * @see java.lang.Iterable + */ + @Override + public Iterator<Entry<Attribute, Value>> iterator() { + return map.entrySet().iterator(); + } + + /** + * Creates a copy of this map. Since <code>Value</code> and <code>Attribute</code> are immutable classes, this + * method does not clone them. + * + * @return a copy of this map containing identical entries + */ + @Override + public AttributesMap clone() { + AttributesMap result = new AttributesMap(); + result.add(this); + return result; + } + + /** + * Returns a string representation of this map listing all key-value pairs stored in it. + * + * @return a string representation of this object + */ + @Override + public String toString() { + return map.toString(); + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/IncompatibleTypesException.java b/src/pl/edu/mimuw/cloudatlas/model/IncompatibleTypesException.java new file mode 100644 index 0000000..e8a962d --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/IncompatibleTypesException.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import pl.edu.mimuw.cloudatlas.model.Value.Operation; + +/** + * An exception thrown when an unsupported binary operation on values is requested. + * + * @see UnsupportedValueOperationException + * @see UnsupportedConversionException + */ +@SuppressWarnings("serial") +public class IncompatibleTypesException extends UnsupportedOperationException { + private final Type left; + private final Type right; + private final Operation operation; + + /** + * Creates a new object representing this exception. + * + * @param left type of a left operand + * @param right type of a right operand + * @param operation an operation that caused this exception + */ + protected IncompatibleTypesException(Type left, Type right, Operation operation) { + super("Incompatible types: " + left + " and " + right + " in operation " + operation + "."); + this.left = left; + this.right = right; + this.operation = operation; + } + + /** + * Gets a type of a left operand in an operation that caused this exception. + * + * @return the type of the left operand + */ + public Type getLeft() { + return left; + } + + /** + * Gets a type of a right operand in an operation that caused this exception. + * + * @return the type of the right operand + */ + public Type getRight() { + return right; + } + + /** + * Gets an object representing an operation that caused this exception. + * + * @return an operation that caused this exception + */ + public Operation getOperation() { + return operation; + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/PathName.java b/src/pl/edu/mimuw/cloudatlas/model/PathName.java new file mode 100644 index 0000000..c5ef4e8 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/PathName.java @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * Represent a fully qualified name of a zone, also known as a global name or a path name. This class is immutable. + */ +public class PathName { + /** + * The object representing a name of the root zone (/). + */ + public static final PathName ROOT = new PathName("/"); + + private final List<String> components; + private final String name; + + /** + * Creates a <code>PathName</code> object representing the specified path. For the root zone, there are three + * accepted forms: <code>null</code> reference, empty string or slash. Any other zone is represented by a string + * starting with slash and containing names of zones at each level of hierarchy, separated by slashes. Zone name + * must contain only letters and digits. + * + * @param name path name of a zone, for instance: <code>/warsaw/uw/violet07</code> + * @throws IllegalArgumentException if the <code>name</code> is incorrect + */ + public PathName(String name) { + // we accept null and "/" as names of a root zone, however, we convert all of them to "" + name = name == null || name.equals("/")? "" : name.trim(); + if(!name.matches("(/\\w+)*")) + throw new IllegalArgumentException("Incorrect fully qualified name: " + name + "."); + this.name = name; + components = name.equals("")? new ArrayList<String>() : Arrays.asList(name.substring(1).split("/")); + } + + /** + * Creates a <code>PathName</code> object from a collection of zones names. Every zone name must contain only + * letters and digits. + * + * @param components a collection of zones names at subsequent levels of hierarchy (starting from root); empty + * collection represents the root zone + * @throws IllegalArgumentException if any zone name is incorrect + */ + public PathName(Collection<String> components) { + this.components = new ArrayList<String>(components); + if(components.isEmpty()) + this.name = ""; + else { + String currentName = ""; + for(String c : components) { + currentName += "/" + c; + if(!c.matches("\\w+")) + throw new IllegalArgumentException("Incorrect component " + c + "."); + } + this.name = currentName; + } + } + + /** + * Gets zones names at subsequent levels of hierarchy, starting from root. For the root zone, this method returns an + * empty collection. Modifying returned list will throw an exception. + * + * @return a collection of zones names + */ + public List<String> getComponents() { + return Collections.unmodifiableList(components); + } + + /** + * Gets a full path name. For the root zone, this method returns an empty string. + * + * @return a path name represented by this object + * @see #toString() + */ + public String getName() { + return name; + } + + /** + * Gets a name one level up in a hierarchy. For the root zone, this method returns a new instance of the same zone. + * + * @return a new <code>PathName</code> object representing a zone one level up in the hierarchy + */ + public PathName levelUp() { + List<String> componentsUp = new ArrayList<String>(components); + if(!componentsUp.isEmpty()) + componentsUp.remove(componentsUp.size() - 1); + return new PathName(componentsUp); + } + + /** + * Gets a name one level down in a hierarchy. + * + * @param son zone name at a lower level + * @return a new <code>PathName</code> object representing a zone one level down in the hierarchy + */ + public PathName levelDown(String son) { + return new PathName(name + "/" + son); + } + + /** + * Gets a zone name at the lowest level (highest number) in a hierarchy. + * + * @return a leaf zone + * @throws UnsupportedOperationException if this object represents the root zone + */ + public String getSingletonName() { + try { + return components.get(components.size() - 1); + } catch(IndexOutOfBoundsException exception) { + throw new UnsupportedOperationException("getSingletonName() is not supported for the root zone."); + } + } + + /** + * Returns a hash code value for this object. This method returns a hash code of a string representing full path + * name. + * + * @return a hash code for this object + */ + @Override + public int hashCode() { + return name.hashCode(); + } + + /** + * Indicates whether this object is equal to another. A <code>PathName</code> object is equal to other objects of + * the same class representing identical path name. + * + * @object the object to check + * @return whether the <code>object</code> is equal to this name + */ + @Override + public boolean equals(Object object) { + if(object == null) + return false; + if(getClass() != object.getClass()) + return false; + return name.equals(((PathName)object).name); + } + + /** + * Returns a textual representation for this <code>PathName</code>. For the root zone, unlike {@link #getName()}, + * this method returns slash. + * + * @return a path name for this object + * @see #getName() + */ + @Override + public String toString() { + return name.equals("")? "/" : getName(); + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/Type.java b/src/pl/edu/mimuw/cloudatlas/model/Type.java new file mode 100644 index 0000000..ba6cf62 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/Type.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +/** + * A type of a value that may be stored as an attribute. + */ +public abstract class Type { + /** + * A primary type. This is a characteristic that every type has. It can be extended: for instance a collection may + * be parameterized with a type of stored values. + */ + public static enum PrimaryType { + BOOLEAN, CONTACT, DOUBLE, DURATION, INT, LIST, NULL, SET, STRING, TIME, + } + + private final PrimaryType primaryType; + + /** + * Creates a <code>Type</code> object with a given primary type. + * + * @param primaryType a primary type for this type + */ + public Type(PrimaryType primaryType) { + this.primaryType = primaryType; + } + + /** + * Returns a primary type of this type. + * + * @return a primary type + */ + public PrimaryType getPrimaryType() { + return primaryType; + } + + /** + * Indicates whether this type can be implicitly "cast" to given one and vice verse. This is introduced to deal with + * null values. In practice, two types are compatible either if they are the same or if one them is a special + * "null type". + * + * @param type a type to check + * @return whether two types are compatible with each other + * @see TypePrimitive#NULL + * @see ValueNull + */ + public boolean isCompatible(Type type) { + return getPrimaryType() == PrimaryType.NULL || type.getPrimaryType() == PrimaryType.NULL; + } + + /** + * Indicates whether this type represents a collection. + * + * @return true for collections, false otherwise + */ + public boolean isCollection() { + return false; + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/TypeCollection.java b/src/pl/edu/mimuw/cloudatlas/model/TypeCollection.java new file mode 100644 index 0000000..9ace5c5 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/TypeCollection.java @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import java.util.Collection; + +import pl.edu.mimuw.cloudatlas.model.Type; +import pl.edu.mimuw.cloudatlas.model.TypePrimitive; +import pl.edu.mimuw.cloudatlas.model.Value; +import pl.edu.mimuw.cloudatlas.model.ValueNull; + +/** + * Represents a collection type with specified element type. + * + * @see TypePrimitve + */ +public class TypeCollection extends Type { + private final Type elementType; + + /** + * Creates a new collection type. + * + * @param primaryType a type of this collection (set, list etc.) + * @param elementType a type of an element of this collection; may be a complex type (for instance + * <code>TypeCollection</code>) + */ + public TypeCollection(PrimaryType primaryType, Type elementType) { + super(primaryType); + switch(primaryType) { + case LIST: + case SET: + break; + default: + throw new IllegalArgumentException("This class can represent a collection only (list, set etc.)."); + } + this.elementType = elementType; + } + + /** + * Gets a type of elements stored in this collection. + * + * @return type of element in this collection + */ + public Type getElementType() { + return elementType; + } + + /** + * Returns a friendly textual representation of this collection, for instance: "SET of (STRING)". + * + * @return a textual representation of this type + */ + @Override + public String toString() { + return getPrimaryType().toString() + " of (" + elementType.toString() + ")"; + } + + @Override + public boolean isCompatible(Type type) { + return super.isCompatible(type) + || (getPrimaryType() == type.getPrimaryType() && elementType + .isCompatible(((TypeCollection)type).elementType)); + } + + @Override + public boolean isCollection() { + return true; + } + + /** + * Returns a type of all elements in the specified collection. If the collection is empty, this method returns + * {@link TypePrimitive#NULL}. If the collection contains at least two elements of distinct types that are not nulls, + * an exception is thrown. + * + * @param collection a collection of values to check + * @return type of elements in this collection + * @throws IllegalArgumentException if the collection contains non-null elements of different types + */ + public static Type computeElementType(Collection<Value> collection) { + Type mainType = null; + + for(Value v : collection) { + if(v.isNull()) + v = ValueNull.getInstance(); + if(mainType == null) { + if(v.getType().getPrimaryType() != Type.PrimaryType.NULL) + mainType = v.getType(); + } else if(!mainType.isCompatible(v.getType())) + throw new IllegalArgumentException("Collection has non-null elements of different types."); + } + + return mainType == null? TypePrimitive.NULL : mainType; + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/TypePrimitive.java b/src/pl/edu/mimuw/cloudatlas/model/TypePrimitive.java new file mode 100644 index 0000000..4940a16 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/TypePrimitive.java @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +/** + * Convenient class for types that just wrap ordinary Java types. + * + * @see TypeCollection + */ +public class TypePrimitive extends Type { + /** + * Boolean type. + */ + public static final TypePrimitive BOOLEAN = new TypePrimitive(PrimaryType.BOOLEAN); + + /** + * Contact type. + */ + public static final TypePrimitive CONTACT = new TypePrimitive(PrimaryType.CONTACT); + + /** + * Double type. + */ + public static final TypePrimitive DOUBLE = new TypePrimitive(PrimaryType.DOUBLE); + + /** + * Duration type. + */ + public static final TypePrimitive DURATION = new TypePrimitive(PrimaryType.DURATION); + + /** + * Integer type. + */ + public static final TypePrimitive INTEGER = new TypePrimitive(PrimaryType.INT); + + /** + * A special "null type" that represents null value of an unknown type. It can be converted to any other type. + * + * @see Type#isCompatible(Type) + * @see ValueNull + */ + public static final TypePrimitive NULL = new TypePrimitive(PrimaryType.NULL); + + /** + * String type. + */ + public static final TypePrimitive STRING = new TypePrimitive(PrimaryType.STRING); + + /** + * Time type. + */ + public static final TypePrimitive TIME = new TypePrimitive(PrimaryType.TIME); + + private TypePrimitive(PrimaryType primaryType) { + super(primaryType); + switch(primaryType) { + case BOOLEAN: + case CONTACT: + case DOUBLE: + case DURATION: + case INT: + case NULL: + case STRING: + case TIME: + break; + default: + throw new IllegalArgumentException( + "This class can represent a primitive type only (boolean, int etc.)."); + } + } + + /** + * Gets a textual representation of this type. + * + * @return a string representing this type + */ + @Override + public String toString() { + return getPrimaryType().toString(); + } + + @Override + public boolean isCompatible(Type type) { + return super.isCompatible(type) || getPrimaryType() == type.getPrimaryType(); + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/UnsupportedConversionException.java b/src/pl/edu/mimuw/cloudatlas/model/UnsupportedConversionException.java new file mode 100644 index 0000000..024c89f --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/UnsupportedConversionException.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +/** + * An exception describing unsupported conversion of a value to another type. + * + * @see IncompatibleTypesException + * @see UnsupportedValueOperationException + */ +@SuppressWarnings("serial") +public class UnsupportedConversionException extends UnsupportedOperationException { + private final Type from; + private final Type to; + + /** + * Creates a new instance of this this exception. + * + * @param from source type of an unsupported conversion + * @param to destination type of an unsupported conversion + */ + protected UnsupportedConversionException(Type from, Type to) { + super("Type " + from + " cannot be converted to " + to + "."); + this.from = from; + this.to = to; + } + + /** + * Gets a source type of an unsupported conversion that caused this exception. + * + * @return source type + */ + public Type getFrom() { + return from; + } + + /** + * Gets a destination type of an unsupported conversion that caused this exception. + * + * @return destination type + */ + public Type getTo() { + return to; + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/UnsupportedValueOperationException.java b/src/pl/edu/mimuw/cloudatlas/model/UnsupportedValueOperationException.java new file mode 100644 index 0000000..e292265 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/UnsupportedValueOperationException.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import pl.edu.mimuw.cloudatlas.model.Value.Operation; + +/** + * An exception caused by calling an unsupported unary operation on value. + * + * @see IncompatibleTypesException + * @see UnsupportedConversionException + */ +@SuppressWarnings("serial") +public class UnsupportedValueOperationException extends UnsupportedOperationException { + private final Type left; + private final Operation operation; + + /** + * Creates a new object representing this exception. + * + * @param left type of a value that was an argument of an operation that caused this exception + * @param operation the operation that caused this exception + */ + protected UnsupportedValueOperationException(Type left, Operation operation) { + super("Type: " + left + " does not provide operation " + operation + "."); + this.left = left; + this.operation = operation; + } + + /** + * Gets a type of value that was an argument to an operation that caused this exception. + * + * @return first argument of the operation + */ + public Type getLeft() { + return left; + } + + /** + * Gets an operation that caused this exception. + * + * @return the operation + */ + public Operation getOperation() { + return operation; + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/Value.java b/src/pl/edu/mimuw/cloudatlas/model/Value.java new file mode 100644 index 0000000..ad1887d --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/Value.java @@ -0,0 +1,241 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import pl.edu.mimuw.cloudatlas.model.Value; + +/** + * A single value stored as an attribute. + */ +public abstract class Value { + /** + * An operation that may be performed on values. + */ + public enum Operation { + EQUAL, COMPARE, ADD, SUBTRACT, MULTIPLY, DIVIDE, MODULO, AND, OR, REG_EXPR, NEGATE, VALUE_SIZE, + } + + /** + * Gets type of this value. + * + * @return type of this value + */ + public abstract Type getType(); + + /** + * Indicates whether this value is null. Distinct from a <code>Value</code> reference that is <code>null</code> + * itself. + * + * @return true if and only if this value is null + */ + public abstract boolean isNull(); + + protected final void sameTypesOrThrow(Value value, Operation operation) { + if(!getType().isCompatible(value.getType())) + throw new IncompatibleTypesException(getType(), value.getType(), operation); + } + + /** + * Checks whether this value is equal to the specified one (operator ==). + * + * @param value the right side of the operator + * @return a <code>ValueBoolean</code> representing true if and only if both values are equal + * @throws UnsupportedValueOperationException if this operation is unsupported for these values + */ + public Value isEqual(Value value) { + throw new UnsupportedValueOperationException(getType(), Operation.EQUAL); + } + + /** + * Indicates whether this object is equal to another one. + * + * @param object the object to check + * @return whether two objects are equal + */ + @Override + public boolean equals(Object object) { + if(!(object instanceof Value)) + return false; + return ((ValueBoolean)isEqual((Value)object)).getValue(); + } + + /** + * Checks whether this value is lower than the specified one (operator <=). + * + * @param value the right side of the operator + * @return a <code>ValueBoolean</code> representing true if and only if this value is lower than the provided one + * @throws UnsupportedValueOperationException if this operator is unsupported for these values (for example + * incompatible or non-numeric types) + */ + public Value isLowerThan(Value value) { + throw new UnsupportedValueOperationException(getType(), Operation.COMPARE); + } + + /** + * Returns a new value created by adding argument to this value (operator +). + * + * @param the right side of the operator + * @return a sum of two values + * @throws UnsupportedValueOperationException if this operator is unsupported for these values (for example + * incompatible or non-numeric types) + */ + public Value addValue(Value value) { + // name clash with add from List interface + throw new UnsupportedValueOperationException(getType(), Operation.ADD); + } + + /** + * Returns a new value created by subtracting argument from this value (operator -). + * + * @param the right side of the operator + * @return a difference of two values + * @throws UnsupportedValueOperationException if this operator is unsupported for these values (for example + * incompatible or non-numeric types) + */ + public Value subtract(Value value) { + throw new UnsupportedValueOperationException(getType(), Operation.SUBTRACT); + } + + /** + * Returns a new value created by multiplying this value by an argument (operator *). + * + * @param the right side of the operator + * @return a product of two values + * @throws UnsupportedValueOperationException if this operator is unsupported for these values (for example + * incompatible or non-numeric types) + */ + public Value multiply(Value value) { + throw new UnsupportedValueOperationException(getType(), Operation.MULTIPLY); + } + + /** + * Returns a new value created by dividing this value by an argument (operator /). + * + * @param the right side of the operator + * @return a quotient of two values + * @throws UnsupportedValueOperationException if this operator is unsupported for these values (for example + * incompatible or non-numeric types) + */ + public Value divide(Value value) { + throw new UnsupportedValueOperationException(getType(), Operation.DIVIDE); + } + + /** + * Returns a remainder of a division of this value by an argument (operator %). + * + * @param the right side of the operator + * @return a remainder + * @throws UnsupportedValueOperationException if this operator is unsupported for these values (for example + * incompatible or non-numeric types) + */ + public Value modulo(Value value) { + throw new UnsupportedValueOperationException(getType(), Operation.MODULO); + } + + /** + * Returns a result of a logical and (operator &&). + * + * @param value the right side of the operator + * @return a conjunction of two values + * @throws UnsupportedValueOperationException if this operator is unsupported for these values (for example + * non-boolean types) + */ + public Value and(Value value) { + throw new UnsupportedValueOperationException(getType(), Operation.AND); + } + + /** + * Returns a result of a logical or (operator ||). + * + * @param value the right side of the operator + * @return an alternative of two values + * @throws UnsupportedValueOperationException if this operator is unsupported for these values (for example + * non-boolean types) + */ + public Value or(Value value) { + throw new UnsupportedValueOperationException(getType(), Operation.OR); + } + + /** + * Returns a result of applying to this value a regular expression specified as an argument.. + * + * @param value the regular expression + * @return a <code>ValueBoolean</code> representing true if and only if this value matches provided regular + * expression + * @throws UnsupportedValueOperationException if this operator is unsupported for these values + */ + public Value regExpr(Value value) { + throw new UnsupportedValueOperationException(getType(), Operation.REG_EXPR); + } + + /** + * Returns a negation (numeric or logical) of this value. This may refer to operator - or !, depending on type. + * + * @return a value that is negation of this value + * @throws UnsupportedValueOperationException if this operator is unsupported for this value + */ + public Value negate() { // !, - + throw new UnsupportedValueOperationException(getType(), Operation.NEGATE); + } + + /** + * Returns a size of this value. Semantic depends on type. + * + * @return a size of this value + * @throws UnsupportedValueOperationException if this operation is unsupported for this value + */ + public Value valueSize() { + // name clash with size from List interface + throw new UnsupportedValueOperationException(getType(), Operation.VALUE_SIZE); + } + + /** + * Returns this value converted to another type. + * + * @param to a desired type + * @return this value converted to the <code>type</code> + * @throws UnsupportedConversionException if a requested conversion is unsupported + */ + public abstract Value convertTo(Type to); + + /** + * Returns a textual representation of this value. This method uses conversion to <code>ValueString</code>. + * + * @return a textual representation of this value + * @see #convertTo(Type) + */ + @Override + public String toString() { + return ((ValueString)convertTo(TypePrimitive.STRING)).getValue(); + } + + /** + * Returns a default value (such as uninitialized variable). This may be <code>0</code> for integer types, + * <code>false</code> for boolean, <code>null</code> for complex types etc. + * + * @return a default value of this type + */ + public abstract Value getDefaultValue(); +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/ValueBoolean.java b/src/pl/edu/mimuw/cloudatlas/model/ValueBoolean.java new file mode 100644 index 0000000..1ca20fc --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/ValueBoolean.java @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import pl.edu.mimuw.cloudatlas.model.Value; +import pl.edu.mimuw.cloudatlas.model.ValueBoolean; + +/** + * A class that wraps a Java <code>Boolean</code> object. + */ +public class ValueBoolean extends ValueSimple<Boolean> { + /** + * Constructs a new <code>ValueBoolean</code> object wrapping the specified <code>value</code>. + * + * @param value the value to wrap + */ + public ValueBoolean(Boolean value) { + super(value); + } + + @Override + public Type getType() { + return TypePrimitive.BOOLEAN; + } + + @Override + public Value getDefaultValue() { + return new ValueBoolean(false); + } + + @Override + public ValueBoolean isLowerThan(Value value) { + sameTypesOrThrow(value, Operation.COMPARE); + if(isNull() || value.isNull()) + return new ValueBoolean(null); + return new ValueBoolean(!getValue() && ((ValueBoolean)value).getValue()); + } + + @Override + public ValueBoolean and(Value value) { + sameTypesOrThrow(value, Operation.AND); + if(isNull() || value.isNull()) + return new ValueBoolean(null); + return new ValueBoolean(getValue() && ((ValueBoolean)value).getValue()); + } + + @Override + public ValueBoolean or(Value value) { // - + sameTypesOrThrow(value, Operation.OR); + if(isNull() || value.isNull()) + return new ValueBoolean(null); + return new ValueBoolean(getValue() || ((ValueBoolean)value).getValue()); + } + + @Override + public ValueBoolean negate() { // ! + return new ValueBoolean(isNull()? null : !getValue()); + } + + @Override + public Value convertTo(Type type) { + switch(type.getPrimaryType()) { + case BOOLEAN: + return this; + case STRING: + return getValue() == null? ValueString.NULL_STRING : new ValueString(getValue().toString()); + default: + throw new UnsupportedConversionException(getType(), type); + } + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/ValueContact.java b/src/pl/edu/mimuw/cloudatlas/model/ValueContact.java new file mode 100644 index 0000000..5101d17 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/ValueContact.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import java.net.InetAddress; + +import pl.edu.mimuw.cloudatlas.model.Value; +import pl.edu.mimuw.cloudatlas.model.ValueContact; + +/** + * A class that represents a contact to a node. The contact consists of a full path name of this node and its IP + * address. + * <p> + * This class is immutable. + */ +public class ValueContact extends Value { + private final PathName name; + private final InetAddress address; + + /** + * Constructs a new <code>ValueContact</code> with the specified path name and IP address. + * + * @param name the full path name of a node + * @param address the IP address of the node + */ + public ValueContact(PathName name, InetAddress address) { + this.name = name; + this.address = address; + } + + @Override + public Value getDefaultValue() { + return new ValueContact(null, null); + } + + /** + * Returns a name stored in this object. + * + * @return the name of a node + */ + public PathName getName() { + return name; + } + + /** + * Returns an IP address stored in this object. + * + * @return the IP address of a node + */ + public InetAddress getAddress() { + return address; + } + + @Override + public Type getType() { + return TypePrimitive.CONTACT; + } + + @Override + public Value convertTo(Type type) { + switch(type.getPrimaryType()) { + case CONTACT: + return this; + case STRING: + if(isNull()) + return ValueString.NULL_STRING; + else + return new ValueString("(" + name.toString() + ", " + address.toString() + ")"); + default: + throw new UnsupportedConversionException(getType(), type); + } + } + + @Override + public boolean isNull() { + return name == null || address == null; + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/ValueDouble.java b/src/pl/edu/mimuw/cloudatlas/model/ValueDouble.java new file mode 100644 index 0000000..b979f5f --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/ValueDouble.java @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import pl.edu.mimuw.cloudatlas.model.Value; +import pl.edu.mimuw.cloudatlas.model.ValueDouble; + +/** + * A class that wraps a Java <code>Double</code> object. + */ +public class ValueDouble extends ValueSimple<Double> { + /** + * Constructs a new <code>ValueDouble</code> object wrapping the specified <code>value</code>. + * + * @param value the value to wrap + */ + public ValueDouble(Double value) { + super(value); + } + + @Override + public Type getType() { + return TypePrimitive.DOUBLE; + } + + @Override + public Value getDefaultValue() { + return new ValueDouble(0.0); + } + + @Override + public ValueBoolean isLowerThan(Value value) { + sameTypesOrThrow(value, Operation.COMPARE); + if(isNull() || value.isNull()) + return new ValueBoolean(null); + return new ValueBoolean(getValue() < ((ValueDouble)value).getValue()); + } + + @Override + public ValueDouble addValue(Value value) { + sameTypesOrThrow(value, Operation.ADD); + if(isNull() || value.isNull()) + return new ValueDouble(null); + return new ValueDouble(getValue() + ((ValueDouble)value).getValue()); + } + + @Override + public ValueDouble subtract(Value value) { + sameTypesOrThrow(value, Operation.SUBTRACT); + if(isNull() || value.isNull()) + return new ValueDouble(null); + return new ValueDouble(getValue() - ((ValueDouble)value).getValue()); + } + + @Override + public ValueDouble multiply(Value value) { + sameTypesOrThrow(value, Operation.MULTIPLY); + if(isNull() || value.isNull()) + return new ValueDouble(null); + return new ValueDouble(getValue() * ((ValueDouble)value).getValue()); + } + + @Override + public ValueDouble divide(Value value) { + sameTypesOrThrow(value, Operation.DIVIDE); + if(isNull() || value.isNull()) + return new ValueDouble(null); + return new ValueDouble(getValue() / ((ValueDouble)value).getValue()); + } + + @Override + public ValueDouble negate() { + return new ValueDouble(isNull()? null : -getValue()); + } + + @Override + public Value convertTo(Type type) { + switch(type.getPrimaryType()) { + case DOUBLE: + return this; + case INT: + return new ValueInt(getValue() == null? null : getValue().longValue()); + case STRING: + return getValue() == null? ValueString.NULL_STRING : new ValueString(getValue().toString()); + default: + throw new UnsupportedConversionException(getType(), type); + } + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/ValueDuration.java b/src/pl/edu/mimuw/cloudatlas/model/ValueDuration.java new file mode 100644 index 0000000..12c2c73 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/ValueDuration.java @@ -0,0 +1,173 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + + +/** + * A class representing duration in milliseconds. The duration can be negative. This is a simple wrapper of a Java + * <code>Long</code> object. + */ +public class ValueDuration extends ValueSimple<Long> { + /** + * Constructs a new <code>ValueDuration</code> object wrapping the specified <code>value</code>. + * + * @param value the value to wrap + */ + public ValueDuration(Long value) { + super(value); + } + + @Override + public Type getType() { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public Value getDefaultValue() { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + /** + * Constructs a new <code>ValueDuration</code> object from the specified amounts of different time units. + * + * @param seconds a number of full seconds + * @param milliseconds a number of milliseconds (an absolute value does not have to be lower than 1000) + */ + public ValueDuration(long seconds, long milliseconds) { + this(seconds * 1000l + milliseconds); + } + + /** + * Constructs a new <code>ValueDuration</code> object from the specified amounts of different time units. + * + * @param minutes a number of full minutes + * @param seconds a number of full seconds (an absolute value does not have to be lower than 60) + * @param milliseconds a number of milliseconds (an absolute value does not have to be lower than 1000) + */ + public ValueDuration(long minutes, long seconds, long milliseconds) { + this(minutes * 60l + seconds, milliseconds); + } + + /** + * Constructs a new <code>ValueDuration</code> object from the specified amounts of different time units. + * + * @param hours a number of full hours + * @param minutes a number of full minutes (an absolute value does not have to be lower than 60) + * @param seconds a number of full seconds (an absolute value does not have to be lower than 60) + * @param milliseconds a number of milliseconds (an absolute value does not have to be lower than 1000) + */ + public ValueDuration(long hours, long minutes, long seconds, long milliseconds) { + this(hours * 60l + minutes, seconds, milliseconds); + } + + /** + * Constructs a new <code>ValueDuration</code> object from the specified amounts of different time units. + * + * @param days a number of full days + * @param hours a number of full hours (an absolute value does not have to be lower than 24) + * @param minutes a number of full minutes (an absolute value does not have to be lower than 60) + * @param seconds a number of full seconds (an absolute value does not have to be lower than 60) + * @param milliseconds a number of milliseconds (an absolute value does not have to be lower than 1000) + */ + public ValueDuration(long days, long hours, long minutes, long seconds, long milliseconds) { + this(days * 24l + hours, minutes, seconds, milliseconds); + } + + /** + * Constructs a new <code>ValueDuration</code> object from its textual representation. The representation has + * format: <code>sd hh:mm:ss.lll</code> where: + * <ul> + * <li><code>s</code> is a sign (<code>+</code> or <code>-</code>),</li> + * <li><code>d</code> is a number of days,</li> + * <li><code>hh</code> is a number of hours (between <code>00</code> and <code>23</code>),</li> + * <li><code>mm</code> is a number of minutes (between <code>00</code> and <code>59</code>),</li> + * <li><code>ss</code> is a number of seconds (between <code>00</code> and <code>59</code>),</li> + * <li><code>lll</code> is a number of milliseconds (between <code>000</code> and <code>999</code>).</li> + * </ul> + * <p> + * All fields are obligatory. + * + * @param value a textual representation of a duration + * @throws IllegalArgumentException if <code>value</code> does not meet described rules + */ + public ValueDuration(String value) { + this(parseDuration(value)); + } + + private static long parseDuration(String value) { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public ValueBoolean isLowerThan(Value value) { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public ValueDuration addValue(Value value) { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public ValueDuration subtract(Value value) { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public ValueDuration multiply(Value value) { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public Value divide(Value value) { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public ValueDuration modulo(Value value) { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public ValueDuration negate() { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public Value convertTo(Type type) { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/ValueInt.java b/src/pl/edu/mimuw/cloudatlas/model/ValueInt.java new file mode 100644 index 0000000..d48532d --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/ValueInt.java @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import pl.edu.mimuw.cloudatlas.model.Type.PrimaryType; +import pl.edu.mimuw.cloudatlas.model.Value; +import pl.edu.mimuw.cloudatlas.model.ValueInt; + +/** + * A class that wraps a Java <code>Long</code> object. + */ +public class ValueInt extends ValueSimple<Long> { + /** + * Constructs a new <code>ValueInt</code> object wrapping the specified <code>value</code>. + * + * @param value the value to wrap + */ + public ValueInt(Long value) { + super(value); + } + + @Override + public Type getType() { + return TypePrimitive.INTEGER; + } + + @Override + public Value getDefaultValue() { + return new ValueInt(0l); + } + + @Override + public ValueBoolean isLowerThan(Value value) { + sameTypesOrThrow(value, Operation.COMPARE); + if(isNull() || value.isNull()) + return new ValueBoolean(null); + return new ValueBoolean(getValue() < ((ValueInt)value).getValue()); + } + + @Override + public ValueInt addValue(Value value) { + sameTypesOrThrow(value, Operation.ADD); + if(isNull() || value.isNull()) + return new ValueInt(null); + return new ValueInt(getValue() + ((ValueInt)value).getValue()); + } + + @Override + public ValueInt subtract(Value value) { + sameTypesOrThrow(value, Operation.SUBTRACT); + if(isNull() || value.isNull()) + return new ValueInt(null); + return new ValueInt(getValue() - ((ValueInt)value).getValue()); + } + + @Override + public Value multiply(Value value) { + if(value.getType().getPrimaryType() == PrimaryType.DURATION) + return value.multiply(this); + sameTypesOrThrow(value, Operation.MULTIPLY); + if(isNull() || value.isNull()) + return new ValueInt(null); + return new ValueInt(getValue() * ((ValueInt)value).getValue()); + } + + @Override + public ValueDouble divide(Value value) { + sameTypesOrThrow(value, Operation.DIVIDE); + if(value.isNull()) + return new ValueDouble(null); + if(((ValueInt)value).getValue() == 0l) + throw new ArithmeticException("Division by zero."); + if(isNull()) + return new ValueDouble(null); + return new ValueDouble((double)getValue() / ((ValueInt)value).getValue()); + } + + @Override + public ValueInt modulo(Value value) { + sameTypesOrThrow(value, Operation.MODULO); + if(value.isNull()) + return new ValueInt(null); + if(((ValueInt)value).getValue() == 0l) + throw new ArithmeticException("Division by zero."); + if(isNull()) + return new ValueInt(null); + return new ValueInt(getValue() % ((ValueInt)value).getValue()); + } + + @Override + public ValueInt negate() { + return new ValueInt(isNull()? null : -getValue()); + } + + @Override + public Value convertTo(Type type) { + switch(type.getPrimaryType()) { + case DOUBLE: + return new ValueDouble(getValue() == null? null : getValue().doubleValue()); + case DURATION: + return new ValueDuration(getValue()); + case INT: + return this; + case STRING: + return getValue() == null? ValueString.NULL_STRING : new ValueString(Long.toString(getValue() + .longValue())); + default: + throw new UnsupportedConversionException(getType(), type); + } + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/ValueList.java b/src/pl/edu/mimuw/cloudatlas/model/ValueList.java new file mode 100644 index 0000000..d914736 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/ValueList.java @@ -0,0 +1,275 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Set; + +import pl.edu.mimuw.cloudatlas.model.TypeCollection; +import pl.edu.mimuw.cloudatlas.model.Value; +import pl.edu.mimuw.cloudatlas.model.ValueList; + +/** + * A value representing a list of values of the specified type. Implements <code>List</code> interface. + * <p> + * All constructors expect type of elements stored in this list. This type is checked when adding elements to the list + * and an <code>IllegalArgumentException</code> is thrown in case of error. + * + * @see java.util.List + */ +public class ValueList extends ValueSimple<List<Value>> implements List<Value> { + private TypeCollection type; + + /** + * Creates a new <code>ValueList</code> containing all the elements in the specified list. + * + * @param value a list which content will be copied to this value + * @param elementType type of elements stored in this list + */ + public ValueList(List<Value> value, Type elementType) { + this(elementType); + if(value != null) + setValue(value); + } + + /** + * Creates an empty list. + * + * @param elementType type of elements stored in this list + */ + public ValueList(Type elementType) { + super(new ArrayList<Value>()); + type = new TypeCollection(Type.PrimaryType.LIST, elementType); + } + + @Override + public Type getType() { + return type; + } + + @Override + public Value getDefaultValue() { + return new ValueList(((TypeCollection)this.getType()).getElementType()); + } + + /** + * Gets a <code>List</code> containing all the objects stored in this value. Modifying a return value will cause an + * exception. + */ + @Override + public List<Value> getValue() { + return getList() == null? null : Collections.unmodifiableList(getList()); + } + + @Override + public ValueList addValue(Value value) { + sameTypesOrThrow(value, Operation.ADD); + if(isNull() || value.isNull()) + return new ValueList(null, ((TypeCollection)getType()).getElementType()); + List<Value> result = new ArrayList<Value>(getValue()); + result.addAll(((ValueList)value).getValue()); + return new ValueList(result, ((TypeCollection)getType()).getElementType()); + } + + @Override + public Value convertTo(Type type) { + switch(type.getPrimaryType()) { + case LIST: + if(getType().isCompatible(type)) + return this; + throw new UnsupportedConversionException(getType(), type); + case SET: + if(this.type.getElementType().isCompatible(((TypeCollection)type).getElementType())) { + if(this.isNull()) + return new ValueSet(null, this.type.getElementType()); + Set<Value> l = new HashSet<Value>(); + l.addAll(this); + return new ValueSet(l, this.type.getElementType()); + } + throw new UnsupportedConversionException(getType(), type); + case STRING: + return getValue() == null? ValueString.NULL_STRING : new ValueString(getValue().toString()); + default: + throw new UnsupportedConversionException(getType(), type); + } + } + + @Override + public ValueInt valueSize() { + return new ValueInt((getList() == null? null : (long)getList().size())); + } + + @Override + public void setValue(List<Value> list) { + if(list == null) + super.setValue(null); + else { + super.setValue(new ArrayList<Value>()); + for(Value e : list) + add(e); + } + } + + private List<Value> getList() { + return super.getValue(); + } + + private void checkElement(Value element) { + if(element == null) + throw new IllegalArgumentException("If you want to use null, create an object containing null instead."); + if(!type.getElementType().isCompatible(element.getType())) + throw new IllegalArgumentException("This list contains elements of type " + + type.getElementType().toString() + " only. Not compatibile with elements of type: " + + element.getType().toString()); + } + + @Override + public boolean add(Value e) { + checkElement(e); + return getList().add(e); + } + + @Override + public void add(int index, Value element) { + checkElement(element); + getList().add(index, element); + } + + @Override + public boolean addAll(Collection<? extends Value> c) { + for(Value e : c) + checkElement(e); + return getList().addAll(c); + } + + @Override + public boolean addAll(int index, Collection<? extends Value> c) { + for(Value e : c) + checkElement(e); + return getList().addAll(index, c); + } + + @Override + public void clear() { + getList().clear(); + } + + @Override + public boolean contains(Object o) { + return getList().contains(o); + } + + @Override + public boolean containsAll(Collection<?> c) { + return getList().containsAll(c); + } + + @Override + public Value get(int index) { + return getList().get(index); + } + + @Override + public int indexOf(Object o) { + return getList().indexOf(o); + } + + @Override + public boolean isEmpty() { + return getList().isEmpty(); + } + + @Override + public Iterator<Value> iterator() { + return getList().iterator(); + } + + @Override + public int lastIndexOf(Object o) { + return getList().lastIndexOf(o); + } + + @Override + public ListIterator<Value> listIterator() { + return getList().listIterator(); + } + + @Override + public ListIterator<Value> listIterator(int index) { + return getList().listIterator(index); + } + + @Override + public boolean remove(Object o) { + return getList().remove(o); + } + + @Override + public Value remove(int index) { + return getList().remove(index); + } + + @Override + public boolean removeAll(Collection<?> c) { + return getList().removeAll(c); + } + + @Override + public boolean retainAll(Collection<?> c) { + return getList().retainAll(c); + } + + @Override + public Value set(int index, Value element) { + checkElement(element); + return getList().set(index, element); + } + + @Override + public int size() { + return getList().size(); + } + + @Override + public List<Value> subList(int fromIndex, int toIndex) { + return new ValueList(getList().subList(fromIndex, toIndex), type.getElementType()); + } + + @Override + public Object[] toArray() { + return getList().toArray(); + } + + @Override + public <Y> Y[] toArray(Y[] a) { + return getList().toArray(a); + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/ValueNull.java b/src/pl/edu/mimuw/cloudatlas/model/ValueNull.java new file mode 100644 index 0000000..e0c3f2a --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/ValueNull.java @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import pl.edu.mimuw.cloudatlas.model.Value; +import pl.edu.mimuw.cloudatlas.model.ValueNull; + +/** + * A special null value of an unknown type introduced to deal with nulls. This class is a singleton. + * + * @see TypePrimitve#NULL + * @see Type#isCompatible(Value) + */ +public class ValueNull extends Value { + private static ValueNull instance = null; + + private ValueNull() {} + + /** + * Gets a singleton instance of a <code>ValueNull</code> class. Every call to this method returns the same + * reference. + * + * @return an instance of <code>ValueNull</code> + */ + public static ValueNull getInstance() { + if(instance == null) + instance = new ValueNull(); + return instance; + } + + @Override + public Value getDefaultValue() { + return instance; + } + + @Override + public Value convertTo(Type type) { + switch(type.getPrimaryType()) { + case STRING: + return ValueString.NULL_STRING; + default: + return this; + } + } + + @Override + public Type getType() { + return TypePrimitive.NULL; + } + + @Override + public boolean isNull() { + return true; + } + + @Override + public Value isEqual(Value value) { + return new ValueBoolean(isNull() && value.isNull()); + } + + @Override + public Value isLowerThan(Value value) { + if(value == getInstance()) + return this; + return value.isLowerThan(this); + } + + @Override + public Value addValue(Value value) { + if(value == getInstance()) + return this; + return value.addValue(this); + } + + @Override + public Value subtract(Value value) { + if(value == getInstance()) + return this; + return value.subtract(this); + } + + @Override + public Value multiply(Value value) { + if(value == getInstance()) + return this; + return value.multiply(this); + } + + @Override + public Value divide(Value value) { + if(value == getInstance()) + return this; + return value.divide(this); + } + + @Override + public Value modulo(Value value) { + if(value == getInstance()) + return this; + return value.modulo(this); + } + + @Override + public Value and(Value value) { + if(value == getInstance()) + return this; + return value.and(this); + } + + @Override + public Value or(Value value) { + if(value == getInstance()) + return this; + return value.or(this); + } + + @Override + public Value regExpr(Value value) { + if(value == getInstance()) + return this; + return value.regExpr(this); + } + + @Override + public Value negate() { + return this; + } + + @Override + public Value valueSize() { + return this; + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/ValueSet.java b/src/pl/edu/mimuw/cloudatlas/model/ValueSet.java new file mode 100644 index 0000000..c91374d --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/ValueSet.java @@ -0,0 +1,232 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import pl.edu.mimuw.cloudatlas.model.TypeCollection; +import pl.edu.mimuw.cloudatlas.model.Value; +import pl.edu.mimuw.cloudatlas.model.ValueSet; + +/** + * A value representing a set of values of the specified type. Implements <code>Set</code> interface. + * <p> + * All constructors expect type of elements stored in this set. This type is checked when adding elements to the set and + * an <code>IllegalArgumentException</code> is thrown in case of error. + * + * @see java.util.Set + */ +public class ValueSet extends ValueSimple<Set<Value>> implements Set<Value> { + private TypeCollection type; + + /** + * Creates a new <code>ValueSet</code> containing all the elements in the specified set. + * + * @param value a set which content will be copied to this value + * @param elementType type of elements stored in this set + */ + public ValueSet(Set<Value> value, Type elementType) { + this(elementType); + if(value != null) + setValue(value); + } + + /** + * Creates an empty set. + * + * @param elementType type of elements stored in this set + */ + public ValueSet(Type elementType) { + super(new HashSet<Value>()); + type = new TypeCollection(Type.PrimaryType.SET, elementType); + } + + @Override + public Type getType() { + return type; + } + + @Override + public Value getDefaultValue() { + return new ValueSet(((TypeCollection)this.getType()).getElementType()); + } + + /** + * Gets a <code>Set</code> containing all the objects stored in this value. Modifying a return value will cause an + * exception. + */ + @Override + public Set<Value> getValue() { + return getSet() == null? null : Collections.unmodifiableSet(getSet()); + } + + @Override + public ValueSet addValue(Value value) { + sameTypesOrThrow(value, Operation.ADD); + if(isNull() || value.isNull()) + return new ValueSet(null, ((TypeCollection)getType()).getElementType()); + Set<Value> result = new HashSet<Value>(getValue()); + result.addAll(((ValueSet)value).getValue()); + return new ValueSet(result, ((TypeCollection)getType()).getElementType()); + } + + @Override + public ValueInt valueSize() { + return new ValueInt((getSet() == null? null : (long)getSet().size())); + } + + @Override + public void setValue(Set<Value> set) { + if(set == null) + super.setValue(null); + else { + super.setValue(new HashSet<Value>()); + for(Value e : set) + add(e); + } + } + + private Set<Value> getSet() { + return super.getValue(); + } + + private void checkElement(Value element) { + if(element == null) + throw new IllegalArgumentException("If you want to use null, create an object containing null instead."); + if(!type.getElementType().isCompatible(element.getType())) + throw new IllegalArgumentException("This set contains elements of type " + type.getElementType().toString() + + " only. Not compatibile with elements of type: " + element.getType().toString()); + } + + @Override + public boolean add(Value e) { + checkElement(e); + return getSet().add(e); + } + + @Override + public boolean addAll(Collection<? extends Value> c) { + for(Value e : c) + checkElement(e); + return getSet().addAll(c); + } + + @Override + public void clear() { + getSet().clear(); + } + + @Override + public boolean contains(Object o) { + return getSet().contains(o); + } + + @Override + public boolean containsAll(Collection<?> c) { + return getSet().containsAll(c); + } + + @Override + public boolean isEmpty() { + return getSet().isEmpty(); + } + + @Override + public Iterator<Value> iterator() { + return getSet().iterator(); + } + + @Override + public boolean remove(Object o) { + return getSet().remove(o); + } + + @Override + public boolean removeAll(Collection<?> c) { + return getSet().removeAll(c); + } + + @Override + public boolean retainAll(Collection<?> c) { + return getSet().retainAll(c); + } + + @Override + public int size() { + return getSet().size(); + } + + @Override + public Object[] toArray() { + return getSet().toArray(); + } + + @Override + public <U> U[] toArray(U[] a) { + return getSet().toArray(a); + } + + @Override + public Value convertTo(Type type) { + switch(type.getPrimaryType()) { + case SET: + if(getType().isCompatible(type)) + return this; + throw new UnsupportedConversionException(getType(), type); + case LIST: + if(this.type.getElementType().isCompatible(((TypeCollection)type).getElementType())) { + if(this.isNull()) + return new ValueList(null, this.type.getElementType()); + List<Value> l = new ArrayList<Value>(); + l.addAll(this); + return new ValueList(l, this.type.getElementType()); + } + throw new UnsupportedConversionException(getType(), type); + case STRING: + if(getValue() == null) + return ValueString.NULL_STRING; + StringBuilder sb = new StringBuilder(); + sb.append("{"); + boolean notFirst = false; + for(Value v : getValue()) { + if(notFirst) { + sb.append(", "); + } else + notFirst = true; + sb.append(v.toString()); + } + sb.append("}"); + return new ValueString(sb.toString()); + default: + throw new UnsupportedConversionException(getType(), type); + } + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/ValueSimple.java b/src/pl/edu/mimuw/cloudatlas/model/ValueSimple.java new file mode 100644 index 0000000..76d9062 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/ValueSimple.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +/** + * Convenient class for wrapping Java types into <code>Value</code> objects. + * <p> + * This class is immutable. + * + * @param <T> a wrapped type + */ +abstract class ValueSimple<T> extends Value { + private T value; + + /** + * Constructs a new <code>Value</code> wrapping the specified <code>value</code>. + * + * @param value the value to wrap + */ + public ValueSimple(T value) { + setValue(value); + } + + /** + * Returns a hash code value for this object. This is a hash code of underlying wrapped object. + * + * @return the hash code for this value + */ + @Override + public int hashCode() { + return getValue().hashCode(); + } + + /** + * Gets a wrapped object. + * + * @return the wrapped value + */ + public T getValue() { + return value; + } + + /** + * Sets a wrapped value. This method is not public to ensure that the underlying value cannot be changed. + * + * @param value the value to set + */ + void setValue(T value) { + this.value = value; + } + + @Override + public boolean isNull() { + return value == null; + } + + @SuppressWarnings("unchecked") + @Override + public Value isEqual(Value v) { + sameTypesOrThrow(v, Operation.EQUAL); + if(isNull() && v.isNull()) + return new ValueBoolean(true); + else if(isNull() || v.isNull()) + return new ValueBoolean(false); + return new ValueBoolean(value.equals(((ValueSimple<T>)v).getValue())); + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/ValueString.java b/src/pl/edu/mimuw/cloudatlas/model/ValueString.java new file mode 100644 index 0000000..34af8d1 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/ValueString.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import java.text.ParseException; + +import pl.edu.mimuw.cloudatlas.model.Value; +import pl.edu.mimuw.cloudatlas.model.ValueString; + +/** + * A class that wraps a Java <code>String</code> object. + */ +public class ValueString extends ValueSimple<String> { + /** + * A result of conversion values representing null to <code>ValueString</code>. + */ + protected static final ValueString NULL_STRING = new ValueString("NULL"); + + /** + * Constructs a new <code>ValueString</code> object wrapping the specified <code>value</code>. + * + * @param value the value to wrap + */ + public ValueString(String value) { + super(value); + } + + @Override + public Type getType() { + return TypePrimitive.STRING; + } + + @Override + public Value getDefaultValue() { + return new ValueString(""); + } + + @Override + public ValueBoolean isLowerThan(Value value) { + sameTypesOrThrow(value, Operation.COMPARE); + if(isNull() || value.isNull()) + return new ValueBoolean(null); + return new ValueBoolean(getValue().compareTo(((ValueString)value).getValue()) < 0); + } + + @Override + public ValueString addValue(Value value) { + sameTypesOrThrow(value, Operation.ADD); + if(isNull() || value.isNull()) + return new ValueString(null); + return new ValueString(getValue().concat(((ValueString)value).getValue())); + } + + @Override + public ValueBoolean regExpr(Value value) { + sameTypesOrThrow(value, Operation.REG_EXPR); + if(isNull() || value.isNull()) + return new ValueBoolean(null); + return new ValueBoolean(getValue().matches(((ValueString)value).getValue())); + } + + @Override + public Value convertTo(Type type) { + switch(type.getPrimaryType()) { + case BOOLEAN: + return new ValueBoolean(Boolean.parseBoolean(getValue())); + case DOUBLE: + try { + return new ValueDouble(Double.parseDouble(getValue())); + } catch(NumberFormatException exception) { + return new ValueDouble(null); + } + case DURATION: + return new ValueDuration(getValue()); + case INT: + try { + return new ValueInt(Long.parseLong(getValue())); + } catch(NumberFormatException exception) { + return new ValueInt(null); + } + case STRING: + return getValue() == null? ValueString.NULL_STRING : this; + case TIME: + try { + return new ValueTime(getValue()); + } catch(ParseException exception) { + return new ValueTime((Long)null); + } + default: + throw new UnsupportedConversionException(getType(), type); + } + } + + @Override + public ValueInt valueSize() { + return new ValueInt(getValue() == null? null : (long)getValue().length()); + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/ValueTime.java b/src/pl/edu/mimuw/cloudatlas/model/ValueTime.java new file mode 100644 index 0000000..f494757 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/ValueTime.java @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +import pl.edu.mimuw.cloudatlas.model.Value; +import pl.edu.mimuw.cloudatlas.model.ValueTime; + +/** + * A class representing the POSIX time in milliseconds. This is a simple wrapper of a Java <code>Long</code> object. + */ +public class ValueTime extends ValueSimple<Long> { + /** + * A format of string representing <code>ValueTime</code> when constructing from or converting to a + * <code>String</code> object. + */ + public static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS"); + + /** + * Constructs a new <code>ValueTime</code> object wrapping the specified value. + * + * @param value the POSIX time + */ + public ValueTime(Long value) { + super(value); + } + + @Override + public Type getType() { + return TypePrimitive.TIME; + } + + @Override + public Value getDefaultValue() { + return new ValueTime(0l); + } + + /** + * Constructs a new <code>ValueTime</code> object from its textual representation. + * + * @param time a time formatted according to {@link #TIME_FORMAT} + * @throws ParseException if the <code>time</code> is incorrect + * @see #TIME_FORMAT + */ + public ValueTime(String time) throws ParseException { + this(TIME_FORMAT.parse(time).getTime()); + } + + @Override + public ValueBoolean isLowerThan(Value value) { + sameTypesOrThrow(value, Operation.COMPARE); + if(isNull() || value.isNull()) + return new ValueBoolean(null); + return new ValueBoolean(getValue() < ((ValueTime)value).getValue()); + } + + @Override + public ValueTime addValue(Value value) { + if(!value.getType().isCompatible(TypePrimitive.DURATION)) + throw new IncompatibleTypesException(getType(), value.getType(), Operation.ADD); + if(isNull() || value.isNull()) + return new ValueTime((Long)null); + return new ValueTime(getValue() + ((ValueDuration)value).getValue()); + } + + @Override + public Value subtract(Value value) { + if(value.getType().isCompatible(TypePrimitive.DURATION)) { + if(isNull() || value.isNull()) + return new ValueTime((Long)null); + return new ValueTime(getValue() - ((ValueDuration)value).getValue()); + } else if(value.getType().isCompatible(TypePrimitive.TIME)) { + if(isNull() || value.isNull()) + return new ValueTime((Long)null); + return new ValueDuration(getValue() - ((ValueTime)value).getValue()); + } + throw new IncompatibleTypesException(getType(), value.getType(), Operation.SUBTRACT); + + } + + @Override + public Value convertTo(Type type) { + switch(type.getPrimaryType()) { + case STRING: + return getValue() == null? ValueString.NULL_STRING : new ValueString(TIME_FORMAT.format(getValue())); + case TIME: + return this; + default: + throw new UnsupportedConversionException(getType(), type); + } + } +} diff --git a/src/pl/edu/mimuw/cloudatlas/model/ZMI.java b/src/pl/edu/mimuw/cloudatlas/model/ZMI.java new file mode 100644 index 0000000..0e1c852 --- /dev/null +++ b/src/pl/edu/mimuw/cloudatlas/model/ZMI.java @@ -0,0 +1,166 @@ +/** + * Copyright (c) 2014, University of Warsaw + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package pl.edu.mimuw.cloudatlas.model; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map.Entry; + +/** + * A zone management information. This object is a single node in a zone hierarchy. It stores zone attributes as well as + * references to its father and sons in the tree. + */ +public class ZMI implements Cloneable { + private final AttributesMap attributes = new AttributesMap(); + + private final List<ZMI> sons = new ArrayList<ZMI>(); + private ZMI father; + + /** + * Creates a new ZMI with no father (the root zone) and empty sons list. + */ + public ZMI() { + this(null); + } + + /** + * Creates a new ZMI with the specified node as a father and empty sons list. This method does not perform any + * operation on the <code>father</code>. Especially, setting this object as a <code>father</code>'s son must be done + * separately. + * + * @param father a father of this ZMI + * @see #addSon(ZMI) + */ + public ZMI(ZMI father) { + this.father = father; + } + + /** + * Gets a father of this ZMI in a tree. + * + * @return a father of this ZMI or <code>null</code> if this is the root zone + */ + public ZMI getFather() { + return father; + } + + /** + * Sets or changes a father of this ZMI in a tree. This method does not perform any operation on the + * <code>father</code>. Especially, setting this object as a <code>father</code>'s son must be done separately. + * + * @param father a new father for this ZMI + * @see #addSon(ZMI) + */ + public void setFather(ZMI father) { + this.father = father; + } + + /** + * Gets a list of sons of this ZMI in a tree. Modifying a return value will cause an exception. + * + * @return + */ + public List<ZMI> getSons() { + return Collections.unmodifiableList(sons); + } + + /** + * Adds the specified ZMI to the list of sons of this ZMI. This method does not perform any operation on a + * <code>son</code>. Especially, setting this object as a <code>son</code>'s father must be done separately. + * + * @param son + * @see #ZMI(ZMI) + * @see #setFather(ZMI) + */ + public void addSon(ZMI son) { + sons.add(son); + } + + /** + * Removes the specified ZMI from the list of sons of this ZMI. This method does not perform any operation on a + * <code>son</code>. Especially, its father remains unchanged. + * + * @param son + * @see #setFather(ZMI) + */ + public void removeSon(ZMI son) { + sons.remove(son); + } + + /** + * Gets a map of all the attributes stored in this ZMI. + * + * @return map of attributes + */ + public AttributesMap getAttributes() { + return attributes; + } + + /** + * Prints recursively in a prefix order (starting from this ZMI) a whole tree with all the attributes. + * + * @param stream a destination stream + * @see #toString() + */ + public void printAttributes(PrintStream stream) { + for(Entry<Attribute, Value> entry : attributes) + stream.println(entry.getKey() + " : " + entry.getValue().getType() + " = " + entry.getValue()); + System.out.println(); + for(ZMI son : sons) + son.printAttributes(stream); + } + + /** + * Creates an independent copy of a whole hierarchy. A returned ZMI has the same reference as a father (but the + * father does not have a reference to it as a son). For the root zone, the copy is completely independent, since + * its father is <code>null</code>. + * + * @return a deep copy of this ZMI + */ + @Override + public ZMI clone() { + ZMI result = new ZMI(father); + result.attributes.add(attributes.clone()); + for(ZMI son : sons) { + ZMI sonClone = son.clone(); + result.sons.add(sonClone); + sonClone.father = result; + } + return result; + } + + /** + * Prints a textual representation of this ZMI. It contains only attributes of this node. + * + * @return a textual representation of this object + * @see #printAttributes(PrintStream) + */ + @Override + public String toString() { + return attributes.toString(); + } +} |