You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metamodel.apache.org by ka...@apache.org on 2013/07/22 10:10:54 UTC

[41/64] [partial] Hard rename of all 'org/eobjects' folders to 'org/apache'.

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/schema/MutableTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/MutableTable.java b/core/src/main/java/org/apache/metamodel/schema/MutableTable.java
new file mode 100644
index 0000000..fb54377
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/schema/MutableTable.java
@@ -0,0 +1,202 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.schema;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Represents the metadata about a table. Tables reside within a schema and
+ * contains columns and relationships to other tables.
+ * 
+ * @see Schema
+ * @see Column
+ * @see Relationship
+ */
+public class MutableTable extends AbstractTable implements Serializable {
+
+    private static final long serialVersionUID = -5094888465714027354L;
+    protected String _name;
+    protected TableType _type;
+    protected String _remarks;
+    protected Schema _schema;
+    protected final List<Column> _columns;
+    protected final List<Relationship> _relationships;
+    protected String _quoteString = null;
+
+    public MutableTable() {
+        super();
+        _columns = new ArrayList<Column>();
+        _relationships = new ArrayList<Relationship>();
+    }
+
+    public MutableTable(String name) {
+        this();
+        setName(name);
+    }
+
+    public MutableTable(String name, TableType type) {
+        this(name);
+        _type = type;
+    }
+
+    public MutableTable(String name, TableType type, Schema schema) {
+        this(name, type);
+        _schema = schema;
+    }
+
+    public MutableTable(String name, TableType type, Schema schema, Column... columns) {
+        this(name, type, schema);
+        setColumns(columns);
+    }
+
+    @Override
+    public String getName() {
+        return _name;
+    }
+
+    public MutableTable setName(String name) {
+        _name = name;
+        return this;
+    }
+
+    /**
+     * Internal getter for the columns of the table. Overwrite this method to
+     * implement column lookup, column lazy-loading or similar.
+     */
+    protected List<Column> getColumnsInternal() {
+        return _columns;
+    }
+
+    /**
+     * Internal getter for the relationships of the table. Overwrite this method
+     * to implement relationship lookup, relationship lazy-loading or similar.
+     */
+    protected List<Relationship> getRelationshipsInternal() {
+        return _relationships;
+    }
+
+    @Override
+    public Column[] getColumns() {
+        List<Column> columns = getColumnsInternal();
+        return columns.toArray(new Column[columns.size()]);
+    }
+
+    public MutableTable setColumns(Column... columns) {
+        _columns.clear();
+        for (Column column : columns) {
+            _columns.add(column);
+        }
+        return this;
+    }
+
+    public MutableTable setColumns(Collection<Column> columns) {
+        _columns.clear();
+        for (Column column : columns) {
+            _columns.add(column);
+        }
+        return this;
+    }
+
+    public MutableTable addColumn(Column column) {
+        _columns.add(column);
+        return this;
+    }
+
+    public MutableTable addColumn(int index, Column column) {
+        _columns.add(index, column);
+        return this;
+    }
+
+    public MutableTable removeColumn(Column column) {
+        _columns.remove(column);
+        return this;
+    }
+
+    @Override
+    public Schema getSchema() {
+        return _schema;
+    }
+
+    public MutableTable setSchema(Schema schema) {
+        _schema = schema;
+        return this;
+    }
+
+    @Override
+    public TableType getType() {
+        return _type;
+    }
+
+    public MutableTable setType(TableType type) {
+        _type = type;
+        return this;
+    }
+
+    @Override
+    public Relationship[] getRelationships() {
+        List<Relationship> relationships = getRelationshipsInternal();
+        return relationships.toArray(new Relationship[relationships.size()]);
+    }
+
+    /**
+     * Protected method for adding a relationship to this table. Should not be
+     * used. Use Relationship.createRelationship(Column[], Column[]) instead.
+     */
+    protected void addRelationship(Relationship relation) {
+        for (Relationship existingRelationship : _relationships) {
+            if (existingRelationship.equals(relation)) {
+                // avoid duplicate relationships
+                return;
+            }
+        }
+        _relationships.add(relation);
+    }
+
+    /**
+     * Protected method for removing a relationship from this table. Should not
+     * be used. Use Relationship.remove() instead.
+     */
+    protected MutableTable removeRelationship(Relationship relation) {
+        _relationships.remove(relation);
+        return this;
+    }
+
+    @Override
+    public String getRemarks() {
+        return _remarks;
+    }
+
+    public MutableTable setRemarks(String remarks) {
+        _remarks = remarks;
+        return this;
+    }
+
+    @Override
+    public String getQuote() {
+        return _quoteString;
+    }
+
+    public MutableTable setQuote(String quoteString) {
+        _quoteString = quoteString;
+        return this;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/schema/NamedStructure.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/NamedStructure.java b/core/src/main/java/org/apache/metamodel/schema/NamedStructure.java
new file mode 100644
index 0000000..a5027d6
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/schema/NamedStructure.java
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.schema;
+
+import org.eobjects.metamodel.util.HasName;
+
+/**
+ * Super-interface for named structural types in a DataContext.
+ * 
+ * @author Kasper Sørensen
+ */
+public interface NamedStructure extends HasName {
+
+	/**
+	 * Gets the name of this structure.
+	 * 
+	 * @return The name of the structure
+	 */
+	public String getName();
+
+	/**
+	 * Gets an optional quote string that is used to enclose the name of this
+	 * structure.
+	 * 
+	 * @return A quote string used to enclose the name or null if none exists.
+	 */
+	public String getQuote();
+
+	/**
+	 * Gets the name, including optional quotes, of this structure.
+	 * 
+	 * @return The name of the structure with added quote strings.
+	 */
+	public String getQuotedName();
+
+	/**
+	 * Gets a qualified label for later lookup. Typically this qualified label
+	 * is formatted with a simple dot separator. For example, for a column a
+	 * typical qualified label would be: "MY_SCHEMA.MY_TABLE.MY_COLUMN".
+	 * 
+	 * The qualified label can be used as a unique identifier for the structure
+	 * but is not necessarily directly transferable to SQL syntax.
+	 * 
+	 * @return a qualified label
+	 */
+	public String getQualifiedLabel();
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/schema/Relationship.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/Relationship.java b/core/src/main/java/org/apache/metamodel/schema/Relationship.java
new file mode 100644
index 0000000..00a63d9
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/schema/Relationship.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.schema;
+
+import java.io.Serializable;
+
+/**
+ * Represents a relationship between two tables where one set of columns is the
+ * primary key, and another set is the foreign key.
+ * 
+ * @see Table
+ * @see Column
+ * 
+ * @author Kasper Sørensen
+ */
+public interface Relationship extends Serializable, Comparable<Relationship> {
+
+	/**
+	 * Gets the table of the primary key column(s).
+	 * 
+	 * @return the table of the primary key column(s).
+	 */
+	public Table getPrimaryTable();
+
+	/**
+	 * Gets the primary key columns of this relationship.
+	 * 
+	 * @return an array of primary key columns.
+	 */
+	public Column[] getPrimaryColumns();
+
+	/**
+	 * Gets the table of the foreign key column(s).
+	 * 
+	 * @return the table of the foreign key column(s).
+	 */
+	public Table getForeignTable();
+
+	/**
+	 * Gets the foreign key columns of this relationship.
+	 * 
+	 * @return an array of foreign key columns.
+	 */
+	public Column[] getForeignColumns();
+
+	/**
+	 * Determines whether this relationship contains a specific pair of columns
+	 * 
+	 * @param pkColumn
+	 *            primary key column
+	 * @param fkColumn
+	 *            foreign key column
+	 * @return true if this relation contains the specified primary and foreign
+	 *         columns as a part of the relation
+	 */
+	public boolean containsColumnPair(Column pkColumn, Column fkColumn);
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/schema/Schema.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/Schema.java b/core/src/main/java/org/apache/metamodel/schema/Schema.java
new file mode 100644
index 0000000..6aa7183
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/schema/Schema.java
@@ -0,0 +1,121 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.schema;
+
+import java.io.Serializable;
+
+import org.eobjects.metamodel.DataContext;
+
+/**
+ * Represents a schema and it's metadata description. Schemas represent a
+ * collection of tables.
+ * 
+ * @see DataContext
+ * @see Table
+ * 
+ * @author Kasper Sørensen
+ */
+public interface Schema extends Comparable<Schema>, Serializable, NamedStructure {
+
+	/**
+	 * Gets the name of this Schema
+	 * 
+	 * @return the name of this Schema
+	 */
+	@Override
+	public String getName();
+
+	/**
+	 * Gets the number of tables that reside in this schema.
+	 * 
+	 * @return the number of tables that reside in this schema.
+	 */
+	public int getTableCount();
+
+	/**
+	 * Gets the number of tables in this Schema that comply to a given
+	 * TableType.
+	 * 
+	 * @param type
+	 *            the TableType to use for searching and matching.
+	 * @return the count of tables that match the provided TableType.
+	 */
+	public int getTableCount(TableType type);
+
+	/**
+	 * Gets the names of the tables that reside in this Schema.
+	 * 
+	 * @return an array of table names.
+	 */
+	public String[] getTableNames();
+
+	/**
+	 * Gets all tables in this Schema.
+	 * 
+	 * @return the tables that reside in the schema
+	 */
+	public Table[] getTables();
+
+	/**
+	 * Gets all tables in this Schema of a particular type.
+	 * 
+	 * @param type
+	 *            the TableType to use for searching and matching.
+	 * @return an array of tables in this schema that matches the specified
+	 *         type.
+	 */
+	public Table[] getTables(TableType type);
+
+	/**
+	 * Gets a table by index. Use {@link #getTableCount()} to get the (0-based)
+	 * index range
+	 * 
+	 * @param index
+	 *            the index of the table
+	 * @return the column with the specified index
+	 * 
+	 * @throws IndexOutOfBoundsException
+	 *             if the index is out of bounds (index >= table count)
+	 */
+	public Table getTable(int index) throws IndexOutOfBoundsException;
+
+	/**
+	 * Convenience method for retrieving a table by it's name.
+	 * 
+	 * @param tableName
+	 *            the name of the table to retrieve
+	 * @return the table with the given name. Returns null if no such table is
+	 *         found.
+	 */
+	public Table getTableByName(String tableName);
+
+	/**
+	 * Gets all relationships to and from this Schema.
+	 * 
+	 * @return an array of relationships.
+	 */
+	public Relationship[] getRelationships();
+
+	/**
+	 * Gets the number of relationships to and from this Schema.
+	 * 
+	 * @return the number of relationships to and from this Schema
+	 */
+	public int getRelationshipCount();
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/schema/SuperColumnType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/SuperColumnType.java b/core/src/main/java/org/apache/metamodel/schema/SuperColumnType.java
new file mode 100644
index 0000000..d6545bc
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/schema/SuperColumnType.java
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.schema;
+
+import java.util.Date;
+
+/**
+ * Represents an abstract, generalized type of column
+ */
+public enum SuperColumnType {
+
+	BOOLEAN_TYPE(Boolean.class),
+
+	LITERAL_TYPE(String.class),
+
+	NUMBER_TYPE(Number.class),
+
+	TIME_TYPE(Date.class),
+
+	BINARY_TYPE(byte[].class),
+
+	OTHER_TYPE(Object.class);
+
+	private Class<?> _javaEquivalentClass;
+
+	private SuperColumnType(Class<?> javaEquivalentClass) {
+		_javaEquivalentClass = javaEquivalentClass;
+	}
+
+	/**
+	 * @return a java class that is appropriate for handling column values of
+	 *         this column super type
+	 */
+	public Class<?> getJavaEquivalentClass() {
+		return _javaEquivalentClass;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/schema/Table.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/Table.java b/core/src/main/java/org/apache/metamodel/schema/Table.java
new file mode 100644
index 0000000..bc9043c
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/schema/Table.java
@@ -0,0 +1,215 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.schema;
+
+import java.io.Serializable;
+
+/**
+ * Represents a table and it's metadata description. Tables reside within a
+ * schema and contains columns and relationships to other tables.
+ * 
+ * @see Schema
+ * @see Column
+ * 
+ * @author Kasper Sørensen
+ */
+public interface Table extends Comparable<Table>, Serializable, NamedStructure {
+
+    /**
+     * Gets the name of this Table
+     * 
+     * @return the name of this Table
+     */
+    @Override
+    public String getName();
+
+    /**
+     * Gets the number of columns in this table.
+     * 
+     * @return the number of columns in this table.
+     */
+    public int getColumnCount();
+
+    /**
+     * Gets the columns of this table.
+     * 
+     * @return the columns of this table.
+     */
+    public Column[] getColumns();
+
+    /**
+     * Convenience method for retrieving a column by it's name.
+     * 
+     * @param columnName
+     *            the name of the column to retrieve
+     * @return the column with the given name. Returns null if no such column is
+     *         found.
+     */
+    public Column getColumnByName(String columnName);
+
+    /**
+     * Gets a column by index. Use {@link #getColumnCount()} to get the
+     * (0-based) index range.
+     * 
+     * @param index
+     *            the index of the column
+     * @return the column with the specified index
+     * @throws IndexOutOfBoundsException
+     *             if the index is out of bounds (index >= column count)
+     */
+    public Column getColumn(int index) throws IndexOutOfBoundsException;
+
+    /**
+     * Gets the schema that this table resides in.
+     * 
+     * @return the schema that the table resides in.
+     */
+    public Schema getSchema();
+
+    /**
+     * Gets the table type of this table.
+     * 
+     * @return the type of table
+     */
+    public TableType getType();
+
+    /**
+     * Gets all relationships for this table.
+     * 
+     * @return all relationsips for this table. To add relations use
+     *         TableRelation.createRelation();
+     */
+    public Relationship[] getRelationships();
+
+    /**
+     * Gets relationships between this table and another table.
+     * 
+     * @param otherTable
+     *            another table for which to find relationships to and from.
+     * @return an array of relationsips between this and the other table.
+     */
+    public Relationship[] getRelationships(Table otherTable);
+
+    /**
+     * Gets a count of relationships to and from this table.
+     * 
+     * @return a count of relationships to and from this table.
+     */
+    public int getRelationshipCount();
+
+    /**
+     * Gets remarks/comments to this table.
+     * 
+     * @return remarks/comments to this table or null if none exist.
+     */
+    public String getRemarks();
+
+    /**
+     * Gets all of this table's columns that are of number type.
+     * 
+     * @return an array of columns.
+     * @see ColumnType
+     */
+    public Column[] getNumberColumns();
+
+    /**
+     * Gets all of this table's columns that are of literal (String/text) type.
+     * 
+     * @return an array of columns.
+     * @see ColumnType
+     */
+    public Column[] getLiteralColumns();
+
+    /**
+     * Gets all of this table's columns that are time and/or date based.
+     * 
+     * @return an array of columns.
+     * @see ColumnType
+     */
+    public Column[] getTimeBasedColumns();
+
+    /**
+     * Gets all of this table's columns that are of boolean type.
+     * 
+     * @return an array of columns.
+     * @see ColumnType
+     */
+    public Column[] getBooleanColumns();
+
+    /**
+     * Gets all of this table's columns that are indexed.
+     * 
+     * @return an array of columns.
+     */
+    public Column[] getIndexedColumns();
+
+    /**
+     * @return the relationships where this table is the foreign table
+     */
+    public Relationship[] getForeignKeyRelationships();
+
+    /**
+     * @return the relationships where this table is the primary table
+     */
+    public Relationship[] getPrimaryKeyRelationships();
+
+    /**
+     * Gets the columns of this table that are known to be foreign keys (ie.
+     * references primary keys in other tables).
+     * 
+     * @return an array of columns that are known to be foreign keys.
+     */
+    public Column[] getForeignKeys();
+
+    /**
+     * Gets the columns of this table that are known to be primary keys. See
+     * {@link Column#isPrimaryKey()}.
+     * 
+     * @return an array of columns that are known to be primary keys.
+     */
+    public Column[] getPrimaryKeys();
+
+    /**
+     * Gets the names of this table's columns.
+     * 
+     * @return an array of column names.
+     */
+    public String[] getColumnNames();
+
+    /**
+     * Gets the columns of this table that conforms to a specified
+     * {@link ColumnType}.
+     * 
+     * @param columnType
+     *            the column type to search for.
+     * @return an array of columns that match the specified ColumnType.
+     */
+    public Column[] getColumnsOfType(ColumnType columnType);
+
+    /**
+     * Gets the columns of this table that conforms to a specified
+     * {@link SuperColumnType}.
+     * 
+     * @param superColumnType
+     *            the super type of the column
+     * @return an array of columns that match the specified SuperColumnType.
+     */
+    public Column[] getColumnsOfSuperType(SuperColumnType superColumnType);
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/schema/TableType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/TableType.java b/core/src/main/java/org/apache/metamodel/schema/TableType.java
new file mode 100644
index 0000000..51b7361
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/schema/TableType.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.schema;
+
+/**
+ * Represents the various types of tables
+ */
+public enum TableType {
+
+	TABLE, VIEW, SYSTEM_TABLE, GLOBAL_TEMPORARY, LOCAL_TEMPORARY, ALIAS, SYNONYM, OTHER;
+
+	public static final TableType[] DEFAULT_TABLE_TYPES = new TableType[] {
+			TableType.TABLE, TableType.VIEW };
+
+	public boolean isMaterialized() {
+		switch (this) {
+		case TABLE:
+		case SYSTEM_TABLE:
+			return true;
+		default:
+			return false;
+		}
+	}
+
+	/**
+	 * Tries to resolve a TableType based on an incoming string/literal. If no
+	 * fitting TableType is found, OTHER will be returned.
+	 */
+	public static TableType getTableType(String literalType) {
+		literalType = literalType.toUpperCase();
+		if ("TABLE".equals(literalType)) {
+			return TABLE;
+		}
+		if ("VIEW".equals(literalType)) {
+			return VIEW;
+		}
+		if ("SYSTEM_TABLE".equals(literalType)) {
+			return SYSTEM_TABLE;
+		}
+		if ("GLOBAL_TEMPORARY".equals(literalType)) {
+			return GLOBAL_TEMPORARY;
+		}
+		if ("LOCAL_TEMPORARY".equals(literalType)) {
+			return LOCAL_TEMPORARY;
+		}
+		if ("ALIAS".equals(literalType)) {
+			return ALIAS;
+		}
+		if ("SYNONYM".equals(literalType)) {
+			return SYNONYM;
+		}
+		return OTHER;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/schema/package-info.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/package-info.java b/core/src/main/java/org/apache/metamodel/schema/package-info.java
new file mode 100644
index 0000000..87d991f
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/schema/package-info.java
@@ -0,0 +1,23 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/**
+ * API for schema structure
+ */
+package org.eobjects.metamodel.schema;
+

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/update/AbstractRowUpdationBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/update/AbstractRowUpdationBuilder.java b/core/src/main/java/org/apache/metamodel/update/AbstractRowUpdationBuilder.java
new file mode 100644
index 0000000..fd4341c
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/update/AbstractRowUpdationBuilder.java
@@ -0,0 +1,122 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.update;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eobjects.metamodel.data.AbstractRowBuilder;
+import org.eobjects.metamodel.query.FilterClause;
+import org.eobjects.metamodel.query.FilterItem;
+import org.eobjects.metamodel.query.SelectItem;
+import org.eobjects.metamodel.query.builder.AbstractFilterBuilder;
+import org.eobjects.metamodel.query.builder.FilterBuilder;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.Table;
+
+/**
+ * Abstract {@link RowUpdationBuilder} implementation.
+ */
+public abstract class AbstractRowUpdationBuilder extends AbstractRowBuilder<RowUpdationBuilder> implements
+        RowUpdationBuilder {
+
+    private final Table _table;
+    private final List<FilterItem> _whereItems;
+
+    public AbstractRowUpdationBuilder(Table table) {
+        super(table);
+        _table = table;
+        _whereItems = new ArrayList<FilterItem>();
+    }
+
+    protected List<FilterItem> getWhereItems() {
+        return _whereItems;
+    }
+
+    @Override
+    public FilterBuilder<RowUpdationBuilder> where(Column column) {
+        SelectItem selectItem = new SelectItem(column);
+        return new AbstractFilterBuilder<RowUpdationBuilder>(selectItem) {
+            @Override
+            protected RowUpdationBuilder applyFilter(FilterItem filter) {
+                return where(filter);
+            }
+        };
+    }
+
+    @Override
+    public FilterBuilder<RowUpdationBuilder> where(String columnName) {
+        Column column = _table.getColumnByName(columnName);
+        if (column == null) {
+            throw new IllegalArgumentException("No such column: " + columnName);
+        }
+        return where(column);
+    }
+
+    @Override
+    public RowUpdationBuilder where(FilterItem... filterItems) {
+        for (FilterItem filterItem : filterItems) {
+            _whereItems.add(filterItem);
+        }
+        return this;
+    }
+
+    @Override
+    public RowUpdationBuilder where(Iterable<FilterItem> filterItems) {
+        for (FilterItem filterItem : filterItems) {
+            _whereItems.add(filterItem);
+        }
+        return this;
+    }
+
+    @Override
+    public Table getTable() {
+        return _table;
+    }
+
+    @Override
+    public String toSql() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("UPDATE ");
+        sb.append(_table.getQualifiedLabel());
+        sb.append(" SET ");
+        Column[] columns = getColumns();
+        Object[] values = getValues();
+
+        for (int i = 0; i < columns.length; i++) {
+            if (i != 0) {
+                sb.append(',');
+            }
+            sb.append(columns[i].getName());
+            sb.append('=');
+            sb.append(values[i] == null ? "NULL" : values[i].toString());
+        }
+
+        List<FilterItem> whereItems = getWhereItems();
+        String whereClause = new FilterClause(null, " WHERE ").addItems(whereItems).toSql();
+        sb.append(whereClause);
+        return sb.toString();
+    }
+
+    @Override
+    public String toString() {
+        return toSql();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/update/RowUpdateable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/update/RowUpdateable.java b/core/src/main/java/org/apache/metamodel/update/RowUpdateable.java
new file mode 100644
index 0000000..8e42517
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/update/RowUpdateable.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.update;
+
+import org.eobjects.metamodel.schema.Table;
+
+public interface RowUpdateable {
+
+    /**
+     * Determines whether row update is supported
+     * 
+     * @return true if row update is supported
+     */
+    public boolean isUpdateSupported();
+
+    /**
+     * Initiates a row updation builder.
+     * 
+     * @param table
+     * @return
+     * @throws IllegalArgumentException
+     * @throws IllegalStateException
+     * @throws UnsupportedOperationException
+     */
+    public RowUpdationBuilder update(Table table) throws IllegalArgumentException, IllegalStateException,
+            UnsupportedOperationException;
+
+    /**
+     * Initiates a row updation builder.
+     * 
+     * @param tableName
+     * @return
+     * @throws IllegalArgumentException
+     * @throws IllegalStateException
+     * @throws UnsupportedOperationException
+     */
+    public RowUpdationBuilder update(String tableName) throws IllegalArgumentException, IllegalStateException,
+            UnsupportedOperationException;
+
+    /**
+     * Initiates a row updation builder.
+     * 
+     * @param schemaName
+     * @param tableName
+     * @return
+     * @throws IllegalArgumentException
+     * @throws IllegalStateException
+     * @throws UnsupportedOperationException
+     */
+    public RowUpdationBuilder update(String schemaName, String tableName) throws IllegalArgumentException,
+            IllegalStateException, UnsupportedOperationException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/update/RowUpdationBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/update/RowUpdationBuilder.java b/core/src/main/java/org/apache/metamodel/update/RowUpdationBuilder.java
new file mode 100644
index 0000000..500d066
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/update/RowUpdationBuilder.java
@@ -0,0 +1,59 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.update;
+
+import org.eobjects.metamodel.DataContext;
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.data.RowBuilder;
+import org.eobjects.metamodel.data.WhereClauseBuilder;
+import org.eobjects.metamodel.schema.Table;
+
+/**
+ * Builder object for row update on a {@link Table}.
+ * 
+ * @author Kasper Sørensen
+ */
+public interface RowUpdationBuilder extends RowBuilder<RowUpdationBuilder>, WhereClauseBuilder<RowUpdationBuilder> {
+
+    /**
+     * Gets the table that this update pertains to.
+     * 
+     * @return the table that this update pertains to.
+     */
+    @Override
+    public Table getTable();
+
+    /**
+     * Gets a SQL representation of this update operation. Note that the
+     * generated SQL is dialect agnostic, so it is not accurately the same as
+     * what will be passed to a potential backing database.
+     * 
+     * @return a SQL representation of this update operation.
+     */
+    public String toSql();
+
+    /**
+     * Commits the row updation operation. This operation will overwrite rows in
+     * the {@link DataContext}.
+     * 
+     * @throws MetaModelException
+     *             if the operation was rejected
+     */
+    public void execute() throws MetaModelException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/update/Update.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/update/Update.java b/core/src/main/java/org/apache/metamodel/update/Update.java
new file mode 100644
index 0000000..540dc3c
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/update/Update.java
@@ -0,0 +1,122 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.update;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eobjects.metamodel.DataContext;
+import org.eobjects.metamodel.UpdateCallback;
+import org.eobjects.metamodel.UpdateScript;
+import org.eobjects.metamodel.UpdateableDataContext;
+import org.eobjects.metamodel.data.AbstractRowBuilder;
+import org.eobjects.metamodel.data.Style;
+import org.eobjects.metamodel.data.WhereClauseBuilder;
+import org.eobjects.metamodel.query.FilterItem;
+import org.eobjects.metamodel.query.SelectItem;
+import org.eobjects.metamodel.query.builder.AbstractFilterBuilder;
+import org.eobjects.metamodel.query.builder.FilterBuilder;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.Table;
+
+/**
+ * Represents a single UPDATE operation to be applied to a
+ * {@link UpdateableDataContext}. Instead of providing a custom implementation
+ * of the {@link UpdateScript} interface, one can use this pre-built update
+ * implementation. Some {@link DataContext}s may even optimize specifically
+ * based on the knowledge that there will only be a single update statement
+ * executed.
+ */
+public final class Update extends AbstractRowBuilder<Update> implements UpdateScript, WhereClauseBuilder<Update> {
+
+    private final Table _table;
+    private final List<FilterItem> _whereItems;
+
+    public Update(Table table) {
+        super(table);
+        _table = table;
+        _whereItems = new ArrayList<FilterItem>();
+    }
+
+    @Override
+    public Table getTable() {
+        return _table;
+    }
+
+    @Override
+    public void run(UpdateCallback callback) {
+        RowUpdationBuilder updateBuilder = callback.update(_table).where(_whereItems);
+
+        final Column[] columns = getColumns();
+        final Object[] values = getValues();
+        final Style[] styles = getStyles();
+        final boolean[] explicitNulls = getExplicitNulls();
+
+        for (int i = 0; i < columns.length; i++) {
+            Object value = values[i];
+            Column column = columns[i];
+            Style style = styles[i];
+            if (value == null) {
+                if (explicitNulls[i]) {
+                    updateBuilder = updateBuilder.value(column, value, style);
+                }
+            } else {
+                updateBuilder = updateBuilder.value(column, value, style);
+            }
+        }
+
+        updateBuilder.execute();
+    }
+
+    @Override
+    public FilterBuilder<Update> where(Column column) {
+        SelectItem selectItem = new SelectItem(column);
+        return new AbstractFilterBuilder<Update>(selectItem) {
+            @Override
+            protected Update applyFilter(FilterItem filter) {
+                return where(filter);
+            }
+        };
+    }
+
+    @Override
+    public FilterBuilder<Update> where(String columnName) {
+        Column column = _table.getColumnByName(columnName);
+        if (column == null) {
+            throw new IllegalArgumentException("No such column: " + columnName);
+        }
+        return where(column);
+    }
+
+    @Override
+    public Update where(FilterItem... filterItems) {
+        for (FilterItem filterItem : filterItems) {
+            _whereItems.add(filterItem);
+        }
+        return this;
+    }
+
+    @Override
+    public Update where(Iterable<FilterItem> filterItems) {
+        for (FilterItem filterItem : filterItems) {
+            _whereItems.add(filterItem);
+        }
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/update/package-info.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/update/package-info.java b/core/src/main/java/org/apache/metamodel/update/package-info.java
new file mode 100644
index 0000000..4b03ca5
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/update/package-info.java
@@ -0,0 +1,23 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/**
+ * API for updating rows
+ */
+package org.eobjects.metamodel.update;
+

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/util/Action.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/Action.java b/core/src/main/java/org/apache/metamodel/util/Action.java
new file mode 100644
index 0000000..2d79054
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/util/Action.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.util;
+
+/**
+ * Represents an abstract action, which is an executable piece of functionality
+ * that takes an argument. An {@link Action} has no return type, unlike a
+ * {@link Func}.
+ * 
+ * @author Kasper Sørensen
+ * 
+ * @param <E>
+ *            the argument type of the action
+ */
+public interface Action<E> {
+
+	public void run(E arg) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/util/AggregateBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/AggregateBuilder.java b/core/src/main/java/org/apache/metamodel/util/AggregateBuilder.java
new file mode 100644
index 0000000..3663959
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/util/AggregateBuilder.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.util;
+
+/**
+ * Interface for aggregate builders which allows for an iterative approach to
+ * evaluating aggregates.
+ * 
+ * @author Kasper Sørensen
+ * 
+ * @param <E>
+ *            the aggregate result type
+ */
+public interface AggregateBuilder<E> {
+
+	public void add(Object o);
+
+	public E getAggregate();
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/util/AlphabeticSequence.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/AlphabeticSequence.java b/core/src/main/java/org/apache/metamodel/util/AlphabeticSequence.java
new file mode 100644
index 0000000..5f578f6
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/util/AlphabeticSequence.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.util;
+
+/**
+ * A sequence based on alphabetic representations. Typically a sequence begin
+ * with "A", "B", "C" etc. and go from "Z" to "AA", from "AZ" to "BA" etc.
+ * 
+ * This sequence is practical for generating column names that correspond to
+ * column identifiers in spreadsheets and the like.
+ * 
+ * @author Kasper Sørensen
+ */
+public class AlphabeticSequence {
+
+	private StringBuilder _stringBuilder;
+
+	/**
+	 * Creates an alphabetic sequence that will have "A" as it's first value, if
+	 * iterated using next().
+	 */
+	public AlphabeticSequence() {
+		this(Character.toString((char) ('A' - 1)));
+	}
+
+	/**
+	 * Creates an alphabetic sequence based on a value
+	 * 
+	 * @param value
+	 */
+	public AlphabeticSequence(String value) {
+		_stringBuilder = new StringBuilder(value.toUpperCase());
+	}
+
+	/**
+	 * Gets the current value (ie. doesn't iterate).
+	 * 
+	 * @return a string identifier, eg. "A", "B", "AA" etc.
+	 */
+	public String current() {
+		return _stringBuilder.toString();
+	}
+
+	/**
+	 * Iterates to the next value and returns it.
+	 * 
+	 * @return a string identifier, eg. "A", "B", "AA" etc.
+	 */
+	public String next() {
+		boolean updated = false;
+		int length = _stringBuilder.length();
+		for (int i = length - 1; i >= 0; i--) {
+			char c = _stringBuilder.charAt(i);
+			if (c != 'Z') {
+				c = (char) (c + 1);
+				_stringBuilder.setCharAt(i, c);
+				updated = true;
+				break;
+			} else {
+				_stringBuilder.setCharAt(i, 'A');
+			}
+		}
+
+		if (!updated) {
+			// need to add another char
+			_stringBuilder.append('A');
+		}
+		return current();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/util/BaseObject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/BaseObject.java b/core/src/main/java/org/apache/metamodel/util/BaseObject.java
new file mode 100644
index 0000000..dde30da
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/util/BaseObject.java
@@ -0,0 +1,166 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.util;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A base object type with conveniently implemented base methods like hashCode()
+ * and equals(). Subclasses should implement the {@link #decorateIdentity(List)}
+ * method to have {@link #equals(Object)} and {@link #hashCode()} automatically
+ * implemented.
+ * 
+ * @author Kasper Sørensen
+ */
+public abstract class BaseObject {
+
+	private static final Logger logger = LoggerFactory
+			.getLogger(BaseObject.class);
+
+	@Override
+	public String toString() {
+		// overridden version of toString() method that uses identity hash code
+		// (to prevent hashCode() recursion due to logging!)
+		return getClass().getName() + "@"
+				+ Integer.toHexString(System.identityHashCode(this));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public final int hashCode() {
+		logger.debug("{}.hashCode()", this);
+		int hashCode = -1;
+		List<Object> list = new ArrayList<Object>();
+		decorateIdentity(list);
+		if (list.isEmpty()) {
+			list.add(toString());
+		}
+		hashCode -= list.size();
+		for (Object obj : list) {
+			hashCode += hashCode(obj);
+		}
+		return hashCode;
+	}
+
+	private static final int hashCode(Object obj) {
+		if (obj == null) {
+			logger.debug("obj is null, returning constant");
+			return -17;
+		}
+		if (obj.getClass().isArray()) {
+			logger.debug("obj is an array, returning a sum");
+			int length = Array.getLength(obj);
+			int hashCode = 4324;
+			for (int i = 0; i < length; i++) {
+				Object o = Array.get(obj, i);
+				hashCode += hashCode(o);
+			}
+			return hashCode;
+		}
+		logger.debug("obj is a regular object, returning hashCode");
+		return obj.hashCode();
+	}
+
+	/**
+	 * Override this method if the equals method should support different
+	 * subtypes. For example, if different subtypes of Number should be
+	 * supported, implement this method with:
+	 * 
+	 * <code>
+	 * obj instanceof Number
+	 * </code>
+	 * 
+	 * and make sure that the decorateIdentity(...) method will always return a
+	 * comparable list of identity-objects.
+	 * 
+	 * @param obj
+	 * @return true if the provided object's class is accepted for equals
+	 *         comparison
+	 */
+	protected boolean classEquals(BaseObject obj) {
+		return getClass() == obj.getClass();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public final boolean equals(Object obj) {
+		if (obj == null) {
+			return false;
+		}
+		if (obj == this) {
+			return true;
+		}
+		if (obj instanceof BaseObject) {
+			BaseObject that = (BaseObject) obj;
+			if (classEquals(that)) {
+				List<Object> list1 = new ArrayList<Object>();
+				List<Object> list2 = new ArrayList<Object>();
+
+				decorateIdentity(list1);
+				that.decorateIdentity(list2);
+
+				if (list1.size() != list2.size()) {
+					throw new IllegalStateException(
+							"Two instances of the same class ("
+									+ getClass().getName()
+									+ ") returned different size decorated identity lists");
+				}
+
+				if (list1.isEmpty()) {
+					assert list2.isEmpty();
+					list1.add(toString());
+					list2.add(that.toString());
+				}
+
+				EqualsBuilder eb = new EqualsBuilder();
+
+				Iterator<Object> it1 = list1.iterator();
+				Iterator<Object> it2 = list2.iterator();
+				while (it1.hasNext()) {
+					assert it2.hasNext();
+					Object next1 = it1.next();
+					Object next2 = it2.next();
+					eb.append(next1, next2);
+				}
+				assert !it2.hasNext();
+
+				return eb.isEquals();
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Subclasses should implement this method and add all fields to the list
+	 * that are to be included in equals(...) and hashCode() evaluation
+	 * 
+	 * @param identifiers
+	 */
+	protected abstract void decorateIdentity(List<Object> identifiers);
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/util/BooleanComparator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/BooleanComparator.java b/core/src/main/java/org/apache/metamodel/util/BooleanComparator.java
new file mode 100644
index 0000000..22bc9f1
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/util/BooleanComparator.java
@@ -0,0 +1,162 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.util;
+
+import java.util.Comparator;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Comparator of booleans
+ * 
+ * @author Kasper Sørensen
+ */
+public final class BooleanComparator implements Comparator<Object> {
+
+	private static final Logger logger = LoggerFactory
+			.getLogger(BooleanComparator.class);
+
+	private static BooleanComparator _instance = new BooleanComparator();
+
+	private BooleanComparator() {
+	}
+
+	public static Comparator<Object> getComparator() {
+		return _instance;
+	}
+
+	public static Comparable<Object> getComparable(Object object) {
+		final Boolean b = toBoolean(object);
+		return new Comparable<Object>() {
+
+			@Override
+			public boolean equals(Object obj) {
+				return _instance.equals(obj);
+			}
+
+			public int compareTo(Object o) {
+				return _instance.compare(b, o);
+			}
+
+			@Override
+			public String toString() {
+				return "BooleanComparable[boolean=" + b + "]";
+			}
+		};
+	}
+
+	public int compare(Object o1, Object o2) {
+		if (o1 == null && o2 == null) {
+			return 0;
+		}
+		if (o1 == null) {
+			return -1;
+		}
+		if (o2 == null) {
+			return 1;
+		}
+		Boolean b1 = toBoolean(o1);
+		Boolean b2 = toBoolean(o2);
+		return b1.compareTo(b2);
+	}
+
+	public static Boolean toBoolean(Object o) {
+		if (o == null) {
+			return null;
+		}
+
+		if (o instanceof Boolean) {
+			return (Boolean) o;
+		}
+		if (o instanceof String) {
+			try {
+				return parseBoolean((String) o);
+			} catch (IllegalArgumentException e) {
+				logger.warn(
+						"Could not convert String '{}' to boolean, returning false", o);
+				return false;
+			}
+		}
+		if (o instanceof Number) {
+			int i = ((Number) o).intValue();
+			return i >= 1;
+		}
+		
+		logger.warn(
+				"Could not convert '{}' to boolean, returning false",
+				o);
+		return false;
+	}
+
+	/**
+	 * Parses a string and returns a boolean representation of it. To parse the
+	 * string the following values will be accepted, irrespective of case.
+	 * <ul>
+	 * <li>true</li>
+	 * <li>false</li>
+	 * <li>1</li>
+	 * <li>0</li>
+	 * <li>yes</li>
+	 * <li>no</li>
+	 * <li>y</li>
+	 * <li>n</li>
+	 * </ul>
+	 * 
+	 * @param string
+	 *            the string to parse
+	 * @return a boolean
+	 * @throws IllegalArgumentException
+	 *             if the string provided is null or cannot be parsed as a
+	 *             boolean
+	 */
+	public static boolean parseBoolean(String string)
+			throws IllegalArgumentException {
+		if (string == null) {
+			throw new IllegalArgumentException("string cannot be null");
+		}
+		string = string.trim();
+		if ("true".equalsIgnoreCase(string) || "1".equals(string)
+				|| "y".equalsIgnoreCase(string)
+				|| "yes".equalsIgnoreCase(string)) {
+			return true;
+		} else if ("false".equalsIgnoreCase(string) || "0".equals(string)
+				|| "n".equalsIgnoreCase(string)
+				|| "no".equalsIgnoreCase(string)) {
+			return false;
+		} else {
+			throw new IllegalArgumentException(
+					"Could not get boolean value of string: " + string);
+		}
+	}
+
+	public static boolean isBoolean(Object o) {
+		if (o instanceof Boolean) {
+			return true;
+		}
+		if (o instanceof String) {
+			if ("true".equalsIgnoreCase((String) o)
+					|| "false".equalsIgnoreCase((String) o)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/util/ClasspathResource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/ClasspathResource.java b/core/src/main/java/org/apache/metamodel/util/ClasspathResource.java
new file mode 100644
index 0000000..e38b372
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/util/ClasspathResource.java
@@ -0,0 +1,145 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.util;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.net.URL;
+
+/**
+ * A {@link Resource} based on a classpath entry
+ */
+public class ClasspathResource implements Resource, Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String _resourcePath;
+
+    public ClasspathResource(String resourcePath) {
+        if (resourcePath == null) {
+            throw new IllegalArgumentException("Classpath resource path cannot be null");
+        }
+        _resourcePath = resourcePath;
+    }
+    
+    @Override
+    public String toString() {
+        return "ClasspathResource[" + _resourcePath + "]";
+    }
+    
+    /**
+     * Gets the name of the classpath entry
+     * @return
+     */
+    public String getResourcePath() {
+        return _resourcePath;
+    }
+
+    @Override
+    public String getName() {
+        String name = _resourcePath;
+        final int lastSlash = name.lastIndexOf('/');
+        final int lastBackSlash = name.lastIndexOf('\\');
+        final int lastIndex = Math.max(lastSlash, lastBackSlash);
+        if (lastIndex != -1) {
+            final String lastPart = name.substring(lastIndex + 1);
+            if (!"".equals(lastPart)) {
+                return lastPart;
+            }
+        }
+        return name;
+    }
+
+    protected ClassLoader getClassLoader() {
+        return ClassLoader.getSystemClassLoader();
+    }
+
+    private UrlResource getUrlResourceDelegate() {
+        ClassLoader classLoader = getClassLoader();
+
+        URL url = classLoader.getResource(_resourcePath);
+        if (url == null && _resourcePath.startsWith("/")) {
+            url = classLoader.getResource(_resourcePath.substring(1));
+        }
+
+        if (url == null) {
+            return null;
+        }
+        return new UrlResource(url);
+    }
+
+    @Override
+    public boolean isReadOnly() {
+        return true;
+    }
+
+    @Override
+    public boolean isExists() {
+        UrlResource delegate = getUrlResourceDelegate();
+        if (delegate == null) {
+            return false;
+        }
+        return delegate.isExists();
+    }
+
+    @Override
+    public long getSize() {
+        UrlResource delegate = getUrlResourceDelegate();
+        if (delegate == null) {
+            return -1;
+        }
+        return delegate.getSize();
+    }
+
+    @Override
+    public long getLastModified() {
+        UrlResource delegate = getUrlResourceDelegate();
+        if (delegate == null) {
+            return -1;
+        }
+        return delegate.getLastModified();
+    }
+
+    @Override
+    public void write(Action<OutputStream> writeCallback) throws ResourceException {
+        getUrlResourceDelegate().write(writeCallback);
+    }
+
+    @Override
+    public void append(Action<OutputStream> appendCallback) throws ResourceException {
+        getUrlResourceDelegate().append(appendCallback);
+    }
+
+    @Override
+    public InputStream read() throws ResourceException {
+        return getUrlResourceDelegate().read();
+    }
+
+    @Override
+    public void read(Action<InputStream> readCallback) throws ResourceException {
+        getUrlResourceDelegate().read(readCallback);
+    }
+
+    @Override
+    public <E> E read(Func<InputStream, E> readCallback) throws ResourceException {
+        return getUrlResourceDelegate().read(readCallback);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/util/CollectionUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/CollectionUtils.java b/core/src/main/java/org/apache/metamodel/util/CollectionUtils.java
new file mode 100644
index 0000000..52cff9a
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/util/CollectionUtils.java
@@ -0,0 +1,240 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.util;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Various utility methods for handling of collections and arrays.
+ * 
+ * @author Kasper Sørensen
+ */
+public final class CollectionUtils {
+
+	private CollectionUtils() {
+		// prevent instantiation
+	}
+
+	/**
+	 * Concatenates two arrays
+	 * 
+	 * @param existingArray an existing array
+	 * @param elements the elements to add to the end of it
+	 * @return
+	 */
+	@SuppressWarnings("unchecked")
+	public static <E> E[] array(final E[] existingArray, final E... elements) {
+		if (existingArray == null) {
+			return elements;
+		}
+		Object result = Array.newInstance(existingArray.getClass()
+				.getComponentType(), existingArray.length + elements.length);
+		System.arraycopy(existingArray, 0, result, 0, existingArray.length);
+		System.arraycopy(elements, 0, result, existingArray.length,
+				elements.length);
+		return (E[]) result;
+	}
+
+	public static <E> List<E> concat(boolean removeDuplicates,
+			Collection<? extends E> firstCollection,
+			Collection<?>... collections) {
+		final List<E> result;
+		if (removeDuplicates) {
+			result = new ArrayList<E>();
+			addElements(removeDuplicates, result, firstCollection);
+		} else {
+			result = new ArrayList<E>(firstCollection);
+		}
+		for (Collection<?> collection : collections) {
+			@SuppressWarnings("unchecked")
+			Collection<? extends E> elems = (Collection<? extends E>) collection;
+			addElements(removeDuplicates, result, elems);
+		}
+		return result;
+	}
+
+	private static <E> void addElements(boolean removeDuplicates,
+			final List<E> result, Collection<? extends E> elements) {
+		for (E item : elements) {
+			if (removeDuplicates) {
+				if (!result.contains(item)) {
+					result.add(item);
+				}
+			} else {
+				result.add(item);
+			}
+		}
+	}
+
+	public static <E> E[] arrayRemove(E[] array, E elementToRemove) {
+		@SuppressWarnings("unchecked")
+		E[] result = (E[]) arrayRemoveInternal(array, elementToRemove);
+		return result;
+	}
+
+	public static Object arrayRemove(Object array, Object elementToRemove) {
+		return arrayRemoveInternal(array, elementToRemove);
+	}
+
+	private static Object arrayRemoveInternal(Object array,
+			Object elementToRemove) {
+		boolean found = false;
+		final int oldLength = Array.getLength(array);
+		if (oldLength == 0) {
+			return array;
+		}
+		final int newLength = oldLength - 1;
+		final Object result = Array.newInstance(array.getClass()
+				.getComponentType(), newLength);
+		int nextIndex = 0;
+		for (int i = 0; i < oldLength; i++) {
+			final Object e = Array.get(array, i);
+			if (e.equals(elementToRemove)) {
+				found = true;
+			} else {
+				if (nextIndex == newLength) {
+					break;
+				}
+				Array.set(result, nextIndex, e);
+				nextIndex++;
+			}
+		}
+		if (!found) {
+			return array;
+		}
+		return result;
+	}
+
+	@SuppressWarnings("unchecked")
+	public static <E> E[] arrayOf(Class<E> elementClass, Object arrayOrElement) {
+		if (arrayOrElement == null) {
+			return null;
+		}
+		if (arrayOrElement.getClass().isArray()) {
+			return (E[]) arrayOrElement;
+		}
+		Object result = Array.newInstance(elementClass, 1);
+		Array.set(result, 0, arrayOrElement);
+		return (E[]) result;
+	}
+
+	public static <E> List<E> filter(E[] items, Predicate<? super E> predicate) {
+		return filter(Arrays.asList(items), predicate);
+	}
+
+	public static <E> List<E> filter(Iterable<E> items,
+			Predicate<? super E> predicate) {
+		List<E> result = new ArrayList<E>();
+		for (E e : items) {
+			if (predicate.eval(e).booleanValue()) {
+				result.add(e);
+			}
+		}
+		return result;
+	}
+
+	public static <I, O> List<O> map(I[] items, Func<? super I, O> func) {
+		return map(Arrays.asList(items), func);
+	}
+
+	public static <I, O> List<O> map(Iterable<I> items, Func<? super I, O> func) {
+		List<O> result = new ArrayList<O>();
+		for (I item : items) {
+			O output = func.eval(item);
+			result.add(output);
+		}
+		return result;
+	}
+
+	public static <E> void forEach(E[] items, Action<? super E> action) {
+		forEach(Arrays.asList(items), action);
+	}
+
+	public static <E> void forEach(Iterable<E> items, Action<? super E> action) {
+		for (E item : items) {
+			try {
+				action.run(item);
+			} catch (Exception e) {
+				if (e instanceof RuntimeException) {
+					throw (RuntimeException) e;
+				}
+				throw new IllegalStateException("Action threw exception", e);
+			}
+		}
+	}
+
+	public static <E> boolean isNullOrEmpty(E[] arr) {
+		return arr == null || arr.length == 0;
+	}
+
+	public static boolean isNullOrEmpty(Collection<?> col) {
+		return col == null || col.isEmpty();
+	}
+
+	/**
+	 * General purpose list converter method. Will convert arrays, collections,
+	 * iterables etc. into lists.
+	 * 
+	 * If the argument is a single object (such as a String or a POJO) it will
+	 * be wrapped in a single-element list.
+	 * 
+	 * Null will be converted to the empty list.
+	 * 
+	 * @param obj
+	 *            any object
+	 * @return a list representation of the object
+	 */
+	public static List<?> toList(Object obj) {
+		final List<Object> result;
+		if (obj == null) {
+			result = Collections.emptyList();
+		} else if (obj instanceof List) {
+			@SuppressWarnings("unchecked")
+			List<Object> list = (List<Object>) obj;
+			result = list;
+		} else if (obj.getClass().isArray()) {
+			int length = Array.getLength(obj);
+			result = new ArrayList<Object>(length);
+			for (int i = 0; i < length; i++) {
+				result.add(Array.get(obj, i));
+			}
+		} else if (obj instanceof Iterable) {
+			result = new ArrayList<Object>();
+			for (Object item : (Iterable<?>) obj) {
+				result.add(item);
+			}
+		} else if (obj instanceof Iterator) {
+			result = new ArrayList<Object>();
+			Iterator<?> it = (Iterator<?>) obj;
+			while (it.hasNext()) {
+				result.add(it.next());
+			}
+		} else {
+			result = new ArrayList<Object>(1);
+			result.add(obj);
+		}
+		return result;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/util/ConstantFunc.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/ConstantFunc.java b/core/src/main/java/org/apache/metamodel/util/ConstantFunc.java
new file mode 100644
index 0000000..0f071e5
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/util/ConstantFunc.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.util;
+
+/**
+ * A function that always returns the same constant response.
+ * 
+ * @param <I>
+ * @param <O>
+ */
+public final class ConstantFunc<I, O> implements Func<I, O> {
+
+    private final O _response;
+
+    public ConstantFunc(O response) {
+        _response = response;
+    }
+
+    @Override
+    public O eval(I arg) {
+        return _response;
+    }
+
+    @Override
+    public int hashCode() {
+        if (_response == null) {
+            return -1;
+        }
+        return _response.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (obj instanceof ConstantFunc) {
+            Object otherResponse = ((ConstantFunc<?, ?>) obj)._response;
+            if (otherResponse == null && _response == null) {
+                return true;
+            } else if (_response == null) {
+                return false;
+            } else {
+                return _response.equals(otherResponse);
+            }
+        }
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/util/DateUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/DateUtils.java b/core/src/main/java/org/apache/metamodel/util/DateUtils.java
new file mode 100644
index 0000000..b146523
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/util/DateUtils.java
@@ -0,0 +1,112 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.util;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * Various utility methods pertaining to date handling
+ * 
+ * @author Kasper Sørensen
+ */
+public final class DateUtils {
+
+	public static final long MILLISECONDS_PER_SECOND = 1000;
+	public static final long MILLISECONDS_PER_MINUTE = MILLISECONDS_PER_SECOND * 60;
+	public static final long MILLISECONDS_PER_HOUR = MILLISECONDS_PER_MINUTE * 60;
+	public static final long MILLISECONDS_PER_DAY = MILLISECONDS_PER_HOUR * 24;
+
+	private DateUtils() {
+		// prevent instantiation
+	}
+
+	public static Date get(int year, Month month, int dayOfMonth) {
+		Calendar c = createCalendar();
+		c.set(Calendar.YEAR, year);
+		c.set(Calendar.MONTH, month.getCalendarConstant());
+		c.set(Calendar.DAY_OF_MONTH, dayOfMonth);
+		c.set(Calendar.HOUR, 0);
+		c.set(Calendar.MINUTE, 0);
+		c.set(Calendar.SECOND, 0);
+		c.set(Calendar.MILLISECOND, 0);
+		return c.getTime();
+	}
+
+	public static Date get(Date date) {
+		Calendar c = Calendar.getInstance();
+		c.setTime(date);
+		c.set(Calendar.HOUR, 0);
+		c.set(Calendar.MINUTE, 0);
+		c.set(Calendar.SECOND, 0);
+		c.set(Calendar.MILLISECOND, 0);
+
+		return c.getTime();
+	}
+
+	public static Date get(Date originalDate, int daysDiff) {
+		long millis = originalDate.getTime();
+		long diff = daysDiff * MILLISECONDS_PER_DAY;
+		millis = millis + diff;
+		return new Date(millis);
+	}
+
+	public static int getYear(Date date) {
+		Calendar cal = createCalendar();
+		cal.setTime(date);
+		return cal.get(Calendar.YEAR);
+	}
+
+	public static Month getMonth(Date date) {
+		Calendar cal = createCalendar();
+		cal.setTime(date);
+		int monthConstant = cal.get(Calendar.MONTH);
+		return Month.getByCalendarConstant(monthConstant);
+	}
+
+	public static Weekday getWeekday(Date date) {
+		Calendar cal = createCalendar();
+		cal.setTime(date);
+		int weekdayConstant = cal.get(Calendar.DAY_OF_WEEK);
+		return Weekday.getByCalendarConstant(weekdayConstant);
+	}
+
+	public static int getDayOfMonth(Date date) {
+		Calendar cal = createCalendar();
+		cal.setTime(date);
+		return cal.get(Calendar.DAY_OF_MONTH);
+	}
+
+	public static Calendar createCalendar() {
+		Calendar c = Calendar.getInstance();
+		c.setTimeInMillis(0l);
+		return c;
+	}
+
+	public static DateFormat createDateFormat() {
+		return createDateFormat("yyyy-MM-dd HH:mm:ss");
+	}
+
+	public static DateFormat createDateFormat(String datePattern) {
+		SimpleDateFormat dateFormat = new SimpleDateFormat(datePattern);
+		return dateFormat;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/util/EqualsBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/EqualsBuilder.java b/core/src/main/java/org/apache/metamodel/util/EqualsBuilder.java
new file mode 100644
index 0000000..b02b6df
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/util/EqualsBuilder.java
@@ -0,0 +1,99 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.util;
+
+import java.lang.reflect.Array;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A helper class for implementing equals(...) methods.
+ * 
+ * @author Kasper Sørensen
+ */
+public final class EqualsBuilder {
+
+	private static final Logger logger = LoggerFactory
+			.getLogger(EqualsBuilder.class);
+	private boolean equals = true;
+
+	public EqualsBuilder append(boolean b) {
+		logger.debug("append({})", b);
+		if (equals) {
+			equals = b;
+		}
+		return this;
+	}
+
+	public EqualsBuilder append(Object o1, Object o2) {
+		if (equals) {
+			equals = equals(o1, o2);
+		}
+		return this;
+	}
+
+	public static boolean equals(final Object obj1, final Object obj2) {
+		if (obj1 == obj2) {
+			return true;
+		}
+		
+		if (obj1 == null || obj2 == null) {
+			return false;
+		}
+		
+		Class<? extends Object> class1 = obj1.getClass();
+		Class<? extends Object> class2 = obj2.getClass();
+		if (class1.isArray()) {
+			if (!class2.isArray()) {
+				return false;
+			} else {
+				Class<?> componentType1 = class1.getComponentType();
+				Class<?> componentType2 = class2.getComponentType();
+				if (!componentType1.equals(componentType2)) {
+					return false;
+				}
+
+				int length1 = Array.getLength(obj1);
+				int length2 = Array.getLength(obj2);
+				if (length1 != length2) {
+					return false;
+				}
+				for (int i = 0; i < length1; i++) {
+					Object elem1 = Array.get(obj1, i);
+					Object elem2 = Array.get(obj2, i);
+					if (!equals(elem1, elem2)) {
+						return false;
+					}
+				}
+				return true;
+			}
+		} else {
+			if (class2.isArray()) {
+				return false;
+			}
+		}
+
+		return obj1.equals(obj2);
+	}
+
+	public boolean isEquals() {
+		return equals;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/util/ExclusionPredicate.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/ExclusionPredicate.java b/core/src/main/java/org/apache/metamodel/util/ExclusionPredicate.java
new file mode 100644
index 0000000..78744bc
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/util/ExclusionPredicate.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.util;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A predicate that uses an exclusion list ("black list") of elements to
+ * determine whether to evaluate true or false.
+ * 
+ * @param <E>
+ */
+public class ExclusionPredicate<E> implements Predicate<E> {
+
+    private final Collection<E> _exclusionList;
+
+    public ExclusionPredicate(Collection<E> exclusionList) {
+        _exclusionList = exclusionList;
+    }
+
+    @Override
+    public Boolean eval(E arg) {
+        if (_exclusionList.contains(arg)) {
+            return false;
+        }
+        return true;
+    }
+
+    public Collection<E> getExclusionList() {
+        return Collections.unmodifiableCollection(_exclusionList);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/util/FalsePredicate.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/FalsePredicate.java b/core/src/main/java/org/apache/metamodel/util/FalsePredicate.java
new file mode 100644
index 0000000..01be8eb
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/util/FalsePredicate.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.util;
+
+import java.io.Serializable;
+
+/**
+ * A predicate that is always false
+ * 
+ * @param <E>
+ */
+public final class FalsePredicate<E> implements Predicate<E>, Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public Boolean eval(E arg) {
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Boolean.FALSE.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return obj != null && obj.getClass() == FalsePredicate.class;
+    }
+}