Commits

Danny van Bruggen committed 26e5d87

* Reorganize away from modules
* Implement some preliminary SQL support

  • Participants
  • Parent commits 1987f14

Comments (0)

Files changed (71)

hql-queryprutser/pom.xml

-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<groupId>com.laamella.queryprutser</groupId>
-		<artifactId>queryprutser</artifactId>
-		<version>1.0-SNAPSHOT</version>
-	</parent>
-	<groupId>com.laamella.queryprutser.hql</groupId>
-	<artifactId>hql-queryprutser</artifactId>
-	<dependencies>
-		<dependency>
-			<groupId>org.slf4j</groupId>
-			<artifactId>slf4j-api</artifactId>
-			<version>1.6.6</version>
-		</dependency>
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<version>4.10</version>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.mockito</groupId>
-			<artifactId>mockito-core</artifactId>
-			<version>1.9.5-rc1</version>
-		</dependency>
-		<dependency>
-			<groupId>org.hibernate</groupId>
-			<artifactId>hibernate-core</artifactId>
-			<version>4.1.7.Final</version>
-			<scope>compile</scope>
-		</dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <version>1.0.7</version>
-            <scope>test</scope>
-        </dependency>
-
-    </dependencies>
-
-</project>

hql-queryprutser/src/main/java/com/laamella/queryprutser/Assert.java

-package com.laamella.queryprutser;
-
-final class Assert {
-	private Assert() {
-		// Singleton.
-	}
-
-	static void notNull(final Object value) {
-		if (value == null) {
-			throw new AssertionError("Value was null");
-		}
-	}
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/ClauseWithRootEntity.java

-package com.laamella.queryprutser;
-
-public class ClauseWithRootEntity extends SeparatedStringBuilder {
-    ClauseWithRootEntity(final CharSequence prefix, final CharSequence infix, final CharSequence postfix, final Class<?> rootEntity, final CharSequence alias) {
-        super(prefix, infix, postfix);
-        add(createEntityString(rootEntity, alias));
-    }
-
-    private CharSequence createEntityString(Class<?> rootClass, CharSequence alias) {
-        Assert.notNull(rootClass);
-        StringBuilder stringBuilder = new StringBuilder(rootClass.getCanonicalName());
-        if (alias != null) {
-            stringBuilder.append(" ");
-            stringBuilder.append(alias);
-        }
-        stringBuilder.append(" ");
-        return stringBuilder;
-    }
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/ClauseWithSubselects.java

-package com.laamella.queryprutser;
-
-import java.util.*;
-
-public class ClauseWithSubselects extends SeparatedStringBuilder {
-	private final List<Subquery> subqueries = new ArrayList<Subquery>();
-
-	ClauseWithSubselects(final CharSequence prefix, final CharSequence infix, final CharSequence postfix) {
-		super(prefix, infix, postfix);
-	}
-
-	public Subquery subselect(final Class<?> rootClass, final CharSequence alias) {
-		final Subquery subquery = new Subquery(rootClass, alias);
-		subqueries.add(subquery);
-		return subquery;
-	}
-
-	public Subquery subselect(final Class<?> rootClass) {
-		return subselect(rootClass, null);
-	}
-
-	@Override
-	public String toString() {
-		final SeparatedStringBuilder locallCopy = new SeparatedStringBuilder(this);
-		for (final Subquery builder : subqueries) {
-			locallCopy.add(" " + builder.queryString() + " ");
-		}
-		return locallCopy.toString();
-	}
-
-	void putAllParametersInThisMap(final Map<String, Object> inHere) {
-		for (final Subquery subquery : subqueries) {
-			inHere.putAll(subquery.allParameters());
-		}
-	}
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/Delete.java

-package com.laamella.queryprutser;
-
-public class Delete extends Statement {
-    @Override
-    public CharSequence queryString() {
-        // TODO
-        return null;
-    }
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/FromClause.java

-package com.laamella.queryprutser;
-
-public class FromClause extends ClauseWithRootEntity {
-    FromClause(final Class<?> rootClass, final CharSequence alias) {
-        super("from ", " ", " ", rootClass, alias);
-    }
-
-    public FromClause joinFetch(final CharSequence relationship, final CharSequence alias) {
-        add("join fetch " + relationship + " " + alias);
-        return this;
-    }
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/GroupByClause.java

-package com.laamella.queryprutser;
-
-public class GroupByClause extends SeparatedStringBuilder {
-	GroupByClause() {
-		super("\ngroup by ", ", ", " ");
-	}
-
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/HavingClause.java

-package com.laamella.queryprutser;
-
-public class HavingClause extends WhereClause {
-	HavingClause() {
-		super("having");
-	}
-
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/Insert.java

-package com.laamella.queryprutser;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Map;
-
-/**
- * Simple helper for building dynamic HQL insert queries, as opposed to
- * Criteria, which are more helpful, complex, and contain many gotcha's, and to
- * plain HQL, which is not dynamic.
- */
-public class Insert extends Statement {
-    private final Logger log = LoggerFactory.getLogger(Insert.class);
-
-    private final InsertIntoClause insertEntityPart;
-    public final SeparatedStringBuilder insertInto = new SeparatedStringBuilder("(", ", ", ") ");
-    public final Select select;
-
-    public Insert(final Class<?> intoRootEntity, final CharSequence intoAlias, final Class<?> selectRootEntity, final CharSequence selectAlias) {
-        insertEntityPart = new InsertIntoClause(intoRootEntity, intoAlias);
-        select = new Select(selectRootEntity, selectAlias);
-    }
-
-    public Insert(final Class<?> intoRootEntity, final Class<?> selectRootEntity) {
-        this(intoRootEntity, null, selectRootEntity, null);
-    }
-
-    /**
-     * @return all parameters that occur in the query and its subqueries.
-     */
-    public Map<String, Object> allParameters() {
-        final Map<String, Object> allParameters = super.allParameters();
-        select.putAllParametersInThisMap(allParameters);
-        return allParameters;
-    }
-
-    /**
-     * @return the current HQL for the query.
-     */
-    public CharSequence queryString() {
-        final StringBuilder hql = new StringBuilder();
-        hql.append(insertEntityPart);
-        hql.append(insertInto);
-        hql.append(select);
-        return hql;
-    }
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/InsertIntoClause.java

-package com.laamella.queryprutser;
-
-public class InsertIntoClause extends ClauseWithRootEntity {
-    InsertIntoClause(final Class<?> rootClass, final CharSequence alias) {
-        super("insert into ", "", "", rootClass, alias);
-    }
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/OrderByClause.java

-package com.laamella.queryprutser;
-
-public class OrderByClause extends SeparatedStringBuilder {
-	OrderByClause() {
-		super("\norder by ", ", ", " ");
-	}
-
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/Select.java

-package com.laamella.queryprutser;
-
-import org.hibernate.Query;
-import org.hibernate.Session;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Map;
-
-/**
- * Simple helper for building dynamic HQL select queries, as opposed to
- * Criteria, which are more helpful, complex, and contain many gotcha's, and to
- * plain HQL, which is not dynamic.
- */
-public class Select extends Statement {
-    private final Logger log = LoggerFactory.getLogger(Select.class);
-
-    public final SelectClause select = new SelectClause();
-    public final FromClause from;
-    public final WhereClause where = new WhereClause();
-    private final GroupByClause groupBy = new GroupByClause();
-    public final HavingClause having = new HavingClause();
-    private final OrderByClause orderBy = new OrderByClause();
-
-    public Select(final Class<?> rootClass, final CharSequence alias) {
-        from = new FromClause(rootClass, alias);
-    }
-
-    public Select(final Class<?> rootClass) {
-        this(rootClass, null);
-    }
-
-    public Select orderBy(final CharSequence... fields) {
-        orderBy.add(fields);
-        return this;
-    }
-
-    public Select groupBy(final CharSequence... fields) {
-        groupBy.add(fields);
-        return this;
-    }
-
-    public Select select(final CharSequence... fields) {
-        select.add(fields);
-        return this;
-    }
-
-    /**
-     * @return all parameters that occur in the query and its subqueries.
-     */
-    public Map<String, Object> allParameters() {
-        final Map<String, Object> allParameters = super.allParameters();
-        where.putAllParametersInThisMap(allParameters);
-        select.putAllParametersInThisMap(allParameters);
-        having.putAllParametersInThisMap(allParameters);
-        return allParameters;
-    }
-
-    /**
-     * @return the current HQL for the query.
-     */
-    public CharSequence queryString() {
-        final StringBuilder hql = new StringBuilder();
-        hql.append(select);
-        hql.append(from);
-        hql.append(where);
-        hql.append(groupBy);
-        hql.append(having);
-        hql.append(orderBy);
-        return hql;
-    }
-
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/SelectClause.java

-package com.laamella.queryprutser;
-
-public class SelectClause extends ClauseWithSubselects {
-    SelectClause() {
-        super("select ", ", ", " ");
-    }
-
-    public void min(final CharSequence string) {
-        add("min(" + string + ")");
-    }
-
-    public void max(final CharSequence string) {
-        add("max(" + string + ")");
-    }
-
-    public void avg(final CharSequence string) {
-        add("avg(" + string + ")");
-    }
-
-    public void sum(final CharSequence string) {
-        add("sum(" + string + ")");
-    }
-
-    public void count(final CharSequence string) {
-        add("count(" + string + ")");
-    }
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/SeparatedStringBuilder.java

-package com.laamella.queryprutser;
-
-/**
- * Builds a string with the correct prefix, infix and postfix insertions.
- */
-public class SeparatedStringBuilder {
-    private final StringBuilder builder;
-    private final CharSequence infix;
-    private final CharSequence postfix;
-    private final CharSequence prefix;
-
-    private boolean firstAppend;
-
-    /**
-     * "Normal" constructor.
-     *
-     * @param prefix  a piece of text to put at the start of the eventual string.
-     * @param infix   a piece of text to put inbetween each piece of text added.
-     * @param postfix a piece of text to put at the end of the eventual string, but
-     *                only if the eventual string isn't empty.
-     */
-    SeparatedStringBuilder(final CharSequence prefix, final CharSequence infix, final CharSequence postfix) {
-        this(prefix, infix, postfix, true, new StringBuilder());
-    }
-
-    /**
-     * Makes this {@link SeparatedStringBuilder} a copy of source.
-     */
-    SeparatedStringBuilder(final SeparatedStringBuilder source) {
-        this(source.prefix, source.infix, source.postfix, source.firstAppend, new StringBuilder(source.builder));
-    }
-
-    private SeparatedStringBuilder(final CharSequence prefix, final CharSequence infix, final CharSequence postfix, final boolean firstAppend, final StringBuilder builder) {
-        Assert.notNull(prefix);
-        Assert.notNull(infix);
-        Assert.notNull(postfix);
-        Assert.notNull(builder);
-        this.prefix = prefix;
-        this.infix = infix;
-        this.postfix = postfix;
-        this.firstAppend = firstAppend;
-        this.builder = builder;
-    }
-
-    /**
-     * Adds one piece of text, taking care to insert pre, in, and postfixes.
-     *
-     * @return this
-     */
-    public SeparatedStringBuilder add(final CharSequence text) {
-        return addWithSpecialInfix(infix, text);
-    }
-
-    /**
-     * Calls add for each supplied text.
-     *
-     * @return this
-     */
-    public SeparatedStringBuilder add(final CharSequence... texts) {
-        return addWithSpecialInfix(infix, texts);
-    }
-
-    /**
-     * Adds one piece of text, taking care to insert pre, in, and postfixes,
-     * overriding the infix for just this once.
-     *
-     * @return this
-     */
-    public SeparatedStringBuilder addWithSpecialInfix(final CharSequence specialInfix, final CharSequence text) {
-        Assert.notNull(specialInfix);
-        Assert.notNull(text);
-        if (!firstAppend) {
-            builder.append(specialInfix);
-        } else {
-            builder.append(prefix);
-        }
-        builder.append(text);
-        firstAppend = false;
-        return this;
-    }
-
-    /**
-     * Calls addWithSpecialInfix for each supplied text.
-     *
-     * @return this
-     */
-    public SeparatedStringBuilder addWithSpecialInfix(final CharSequence specialInfix, final CharSequence... texts) {
-        for (final CharSequence text : texts) {
-            addWithSpecialInfix(specialInfix, text);
-        }
-        return this;
-    }
-
-    /**
-     * @return the string as it was built up to now, as a CharSequence.
-     */
-    public CharSequence toCharSequence(){
-        if (firstAppend) {
-            /* Don't even return the postfix */
-            return "";
-        }
-        return builder.append(postfix);
-    }
-
-    /**
-     * @return the string as it was built up to now.
-     */
-    @Override
-    public String toString() {
-        return toCharSequence().toString();
-    }
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/Statement.java

-package com.laamella.queryprutser;
-
-import org.hibernate.Query;
-import org.hibernate.Session;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public abstract class Statement {
-    private final Logger log = LoggerFactory.getLogger(Statement.class);
-
-    private final Map<String, Object> parameters = new HashMap<String, Object>();
-
-    /**
-     * Set a named parameter for this statement.
-     */
-    public final Statement parameter(final String name, final Object value) {
-        Assert.notNull(name);
-        parameters.put(name, value);
-        return this;
-    }
-
-    protected final Map<String, Object> localParameters() {
-        return parameters;
-    }
-
-    /**
-     * @return the current HQL for the query.
-     */
-    public abstract CharSequence queryString();
-
-    @Override
-    public final String toString() {
-        return queryString().toString();
-    }
-
-    /**
-     * @return all parameters that occur in the query and its subqueries.
-     */
-    public Map<String, Object> allParameters() {
-        final Map<String, Object> allParameters = new HashMap<String, Object>();
-        allParameters.putAll(localParameters());
-        return allParameters;
-    }
-
-    public final void putAllParametersInThisMap(Map<String, Object> allParameters) {
-        allParameters.putAll(allParameters());
-    }
-
-    /**
-     * @return create the final query.
-     */
-    public final Query query(final Session session) {
-        final String hql = queryString().toString();
-        log.debug(hql);
-        final Query query = session.createQuery(hql);
-        query.setProperties(allParameters());
-
-        if (log.isDebugEnabled()) {
-            for (final Map.Entry<String, Object> entry : allParameters().entrySet()) {
-                log.debug(entry.getKey() + "=" + entry.getValue());
-            }
-        }
-
-        return query;
-    }
-
-
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/Subquery.java

-package com.laamella.queryprutser;
-
-public class Subquery extends Select {
-	private CharSequence before = "";
-	private CharSequence after = "";
-
-	Subquery(final Class<?> rootClass, final CharSequence alias) {
-		super(rootClass, alias);
-	}
-
-	public Subquery before(final CharSequence before) {
-		Assert.notNull(before);
-		this.before = before;
-		return this;
-	}
-
-	public Subquery after(final CharSequence after) {
-		Assert.notNull(after);
-		this.after = after;
-		return this;
-	}
-
-	@Override
-	public CharSequence queryString() {
-		final StringBuilder hql = new StringBuilder();
-		hql.append(before);
-		hql.append("(");
-		hql.append(super.queryString());
-		hql.append(") ");
-		hql.append(after);
-		return hql;
-	}
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/Update.java

-package com.laamella.queryprutser;
-
-public class Update extends Statement {
-    @Override
-    public CharSequence queryString() {
-        // TODO
-        return null; 
-    }
-}

hql-queryprutser/src/main/java/com/laamella/queryprutser/WhereClause.java

-package com.laamella.queryprutser;
-
-public class WhereClause extends ClauseWithSubselects {
-	WhereClause() {
-		this("where");
-	}
-
-	protected WhereClause(final CharSequence keyword) {
-		super(" \n" + keyword + " ", "\n", " ");
-	}
-
-	public void and(final CharSequence... values) {
-		addWithSpecialInfix("\nand ", values);
-	}
-}

hql-queryprutser/src/test/java/com/laamella/queryprutser/AssertTest.java

-package com.laamella.queryprutser;
-
-import org.junit.Test;
-
-public class AssertTest {
-	@Test(expected = AssertionError.class)
-	public void whenAssertNotNullOnNullThenGetAnAssertionError() {
-		Assert.notNull(null);
-	}
-
-	@Test
-	public void whenAssertNotNullOnNotNullThenNothingHappens() {
-        Assert.notNull("");
-	}
-}

hql-queryprutser/src/test/java/com/laamella/queryprutser/Fuzzy.java

-package com.laamella.queryprutser;
-
-import org.mockito.ArgumentMatcher;
-
-import static org.junit.Assert.assertEquals;
-
-public class Fuzzy {
-    static void assertFuzzyString(final CharSequence expected, final CharSequence actual) {
-        assertEquals(cleanString(expected), cleanString(actual));
-    }
-
-    private static String cleanString(final CharSequence actual) {
-        final String[] split = actual.toString().split("\\s+");
-        final StringBuffer stringBuffer = new StringBuffer();
-        for (final String s : split) {
-            stringBuffer.append(s);
-            stringBuffer.append(" ");
-        }
-        return stringBuffer.toString().trim();
-    }
-
-    static ArgumentMatcher fuzzy(final String expected) {
-        return new ArgumentMatcher<String>() {
-            @Override
-            public boolean matches(Object argument) {
-                return cleanString(expected).equals(cleanString(argument.toString()));
-            }
-        };
-    }
-}

hql-queryprutser/src/test/java/com/laamella/queryprutser/InsertTest.java

-package com.laamella.queryprutser;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class InsertTest {
-    @Test
-    public void whenNothingIsDoneWithInsertThenItShowsUp() {
-        Insert insert = new Insert(String.class, "s", Object.class, "o");
-        assertEquals(0, insert.allParameters().size());
-        Fuzzy.assertFuzzyString("insert into java.lang.String s from java.lang.Object o", insert.queryString());
-    }
-    @Test
-    public void whenOneIntoPropertyIsSetThenItShowsUp() {
-        Insert insert = new Insert(String.class, "s", Object.class, "o");
-        insert.insertInto.add("x");
-        assertEquals(0, insert.allParameters().size());
-        Fuzzy.assertFuzzyString("insert into java.lang.String s (x) from java.lang.Object o", insert.queryString());
-    }
-    @Test
-    public void whenOneSelectPropertyIsSetThenItShowsUp() {
-        Insert insert = new Insert(String.class, "s", Object.class, "o");
-        insert.select.select("x");
-        assertEquals(0, insert.allParameters().size());
-        Fuzzy.assertFuzzyString("insert into java.lang.String s select x from java.lang.Object o", insert.queryString());
-    }
-
-}

hql-queryprutser/src/test/java/com/laamella/queryprutser/SelectTest.java

-package com.laamella.queryprutser;
-
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
-
-import java.util.Map;
-
-import org.hibernate.Query;
-import org.hibernate.Session;
-import org.junit.Test;
-
-public class SelectTest {
-	@Test
-	public void whenNothingIsDoneWithQueryBuilderThenWeGetASelectEverything() {
-		final Select queryBuilder = new Select(Object.class);
-		assertEquals(0, queryBuilder.allParameters().size());
-		Fuzzy.assertFuzzyString("from java.lang.Object", queryBuilder.queryString());
-	}
-
-	@Test
-	public void whenTheRootObjectIsAliasedThenItShowsInTheHql() {
-		final Select queryBuilder = new Select(Object.class, "o");
-        Fuzzy.assertFuzzyString("from java.lang.Object o", queryBuilder.queryString());
-	}
-
-	@Test
-	public void whenDoingAnAliasedJoinFetchThenWeGetThat() {
-		final Select queryBuilder = new Select(Object.class);
-		queryBuilder.from.joinFetch("relationship", "rel");
-        Fuzzy.assertFuzzyString("from java.lang.Object join fetch relationship rel", queryBuilder.queryString());
-	}
-
-	@Test
-	public void whenPuttingASubqueryIntoTheSelectClauseThenItIsThere() {
-		final Select builder = new Select(Object.class);
-		builder.select.subselect(String.class);
-        Fuzzy.assertFuzzyString("select (from java.lang.String ) from java.lang.Object", builder.queryString());
-	}
-
-	@Test
-	public void whenPuttingASubqueryIntoTheWhereClauseThenItIsThere() {
-		final Select builder = new Select(Object.class);
-		builder.where.subselect(String.class);
-        Fuzzy.assertFuzzyString("from java.lang.Object where (from java.lang.String )", builder.queryString());
-	}
-
-	@Test
-	public void whenGivingASubqueryABeforeAndAfterStringThenTheyAreThere() {
-		final Select builder = new Select(Object.class);
-		final Subquery subselect = builder.where.subselect(String.class);
-		subselect.before(">>>");
-		subselect.after("<<<");
-        Fuzzy.assertFuzzyString("from java.lang.Object where >>>(from java.lang.String ) <<<", builder.queryString());
-	}
-
-	@Test
-	public void whenUsingAllClausesThenTheyAreInTheRightOrder() {
-		final Select builder = new Select(Object.class);
-		builder.select.add("[select clause]");
-		builder.from.add("[from clause]");
-		builder.where.add("[where clause]");
-		builder.orderBy("[order by clause]");
-		builder.groupBy("[group by clause]");
-		builder.having.add("[having clause]");
-        Fuzzy.assertFuzzyString("select [select clause] from java.lang.Object [from clause] where [where clause] group by [group by clause] having [having clause] order by [order by clause]",
-                builder.queryString());
-	}
-
-	@Test
-	public void whenUsingMinMaxThenThoseAreAdded() {
-		final Select builder = new Select(Object.class);
-		builder.select.max("a");
-		builder.select.min("b");
-        Fuzzy.assertFuzzyString("select max(a), min(b) from java.lang.Object", builder.queryString());
-	}
-
-	@Test
-	public void whenSelectingMoreThanOneThingThenTheRightInfixesAreUsed() {
-		final Select builder = new Select(Object.class);
-		builder.select("abc", "def", "ghi");
-        Fuzzy.assertFuzzyString("select abc, def, ghi from java.lang.Object", builder.queryString());
-	}
-
-	@Test
-	public void whenWhereingMoreThanOneThingThenTheRightInfixesAreUsed() {
-		final Select builder = new Select(Object.class);
-		builder.where.and("abc", "def", "ghi");
-        Fuzzy.assertFuzzyString("from java.lang.Object where abc and def and ghi", builder.queryString());
-	}
-
-	@Test
-	public void whenSettingParametersAllOverThePlaceThenTheyAreAllCollected() {
-		final Select builder = new Select(Object.class);
-		builder.parameter("a", "a");
-		builder.select.subselect(String.class).parameter("b", "b");
-		builder.where.subselect(Integer.class).having.subselect(Float.class).parameter("c", "c");
-		final Map<String, Object> allParameters = builder.allParameters();
-
-		assertEquals(3, allParameters.size());
-		assertEquals("a", allParameters.get("a"));
-		assertEquals("b", allParameters.get("b"));
-		assertEquals("c", allParameters.get("c"));
-	}
-
-	@Test
-	public void whenCallingToStringThenTheHqlIsReturned() {
-		final Select builder = new Select(Object.class);
-        Fuzzy.assertFuzzyString("from java.lang.Object", builder.toString());
-	}
-
-	@Test
-	public void whenCreatingAHibernateQueryThenTheRightHqlAndAllParametersAreSet() {
-		final Select builder = new Select(Object.class);
-		builder.parameter("a", "a");
-		final Session sessionMock = mock(Session.class);
-		final Query queryMock = mock(Query.class);
-		when(sessionMock.createQuery((String) argThat(Fuzzy.fuzzy("from java.lang.Object ")))).thenReturn(queryMock);
-
-		final Query query = builder.query(sessionMock);
-		assertEquals(queryMock, query);
-		verify(queryMock).setProperties(anyMap());
-	}
-}

hql-queryprutser/src/test/java/com/laamella/queryprutser/SeparatedStringBuilderTest.java

-package com.laamella.queryprutser;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class SeparatedStringBuilderTest {
-
-	@Test
-	public void whenNotAppendingAnythingThenResultIsEmpty() {
-		final SeparatedStringBuilder string = new SeparatedStringBuilder("pre", "in", "post");
-		assertEquals("", string.toString());
-	}
-
-	@Test
-	public void whenAppendingOneThingThenPreAndPostfixAreAdded() {
-		final SeparatedStringBuilder string = new SeparatedStringBuilder("pre", "in", "post");
-		string.add("text");
-		assertEquals("pretextpost", string.toString());
-	}
-
-	@Test
-	public void whenAppendingSeveralThingsThenPreInAndPostfixAreAdded() {
-		final SeparatedStringBuilder string = new SeparatedStringBuilder("pre", "in", "post");
-		string.add("text1", "text2", "text3");
-		assertEquals("pretext1intext2intext3post", string.toString());
-	}
-
-}
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<groupId>com.laamella.queryprutser</groupId>
-	<artifactId>queryprutser</artifactId>
-	<version>1.0-SNAPSHOT</version>
-	<name>Laamella Gad's Query Prutser</name>
-	<packaging>pom</packaging>
-	<modules>
-		<module>hql-queryprutser</module>
-	</modules>
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.laamella.queryprutser</groupId>
+    <artifactId>queryprutser</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <name>Laamella Gad's Query Prutser</name>
+    <dependencies>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.6.6</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.10</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>1.9.5-rc1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-core</artifactId>
+            <version>3.6.10.Final</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javaee</groupId>
+            <artifactId>javaee-api</artifactId>
+            <version>5</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.0.7</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
 </project>

src/main/java/com/laamella/queryprutser/common/Assert.java

+package com.laamella.queryprutser.common;
+
+public final class Assert {
+    private Assert() {
+        // Singleton.
+    }
+
+    public static void notNull(final Object value) {
+        if (value == null) {
+            throw new AssertionError("Value was null");
+        }
+    }
+}

src/main/java/com/laamella/queryprutser/common/SeparatedStringBuilder.java

+package com.laamella.queryprutser.common;
+
+/**
+ * Builds a string with the correct prefix, infix and postfix insertions.
+ */
+public class SeparatedStringBuilder {
+    private final StringBuilder builder;
+    private final CharSequence infix;
+    private final CharSequence postfix;
+    private final CharSequence prefix;
+
+    private boolean firstAppend;
+
+    /**
+     * "Normal" constructor.
+     *
+     * @param prefix  a piece of text to put at the start of the eventual string.
+     * @param infix   a piece of text to put inbetween each piece of text added.
+     * @param postfix a piece of text to put at the end of the eventual string, but
+     *                only if the eventual string isn't empty.
+     */
+    public SeparatedStringBuilder(final CharSequence prefix, final CharSequence infix, final CharSequence postfix) {
+        this(prefix, infix, postfix, true, new StringBuilder());
+    }
+
+    /**
+     * Makes this {@link SeparatedStringBuilder} a copy of source.
+     */
+    public SeparatedStringBuilder(final SeparatedStringBuilder source) {
+        this(source.prefix, source.infix, source.postfix, source.firstAppend, new StringBuilder(source.builder));
+    }
+
+    private SeparatedStringBuilder(final CharSequence prefix, final CharSequence infix, final CharSequence postfix, final boolean firstAppend, final StringBuilder builder) {
+        Assert.notNull(prefix);
+        Assert.notNull(infix);
+        Assert.notNull(postfix);
+        Assert.notNull(builder);
+        this.prefix = prefix;
+        this.infix = infix;
+        this.postfix = postfix;
+        this.firstAppend = firstAppend;
+        this.builder = builder;
+    }
+
+    /**
+     * Adds one piece of text, taking care to insert pre, in, and postfixes.
+     *
+     * @return this
+     */
+    public SeparatedStringBuilder add(final CharSequence text) {
+        return addWithSpecialInfix(infix, text);
+    }
+
+    /**
+     * Calls add for each supplied text.
+     *
+     * @return this
+     */
+    public SeparatedStringBuilder add(final CharSequence... texts) {
+        return addWithSpecialInfix(infix, texts);
+    }
+
+    /**
+     * Adds one piece of text, taking care to insert pre, in, and postfixes,
+     * overriding the infix for just this once.
+     *
+     * @return this
+     */
+    public SeparatedStringBuilder addWithSpecialInfix(final CharSequence specialInfix, final CharSequence text) {
+        Assert.notNull(specialInfix);
+        Assert.notNull(text);
+        if (!firstAppend) {
+            builder.append(specialInfix);
+        } else {
+            builder.append(prefix);
+        }
+        builder.append(text);
+        firstAppend = false;
+        return this;
+    }
+
+    /**
+     * Calls addWithSpecialInfix for each supplied text.
+     *
+     * @return this
+     */
+    public SeparatedStringBuilder addWithSpecialInfix(final CharSequence specialInfix, final CharSequence... texts) {
+        for (final CharSequence text : texts) {
+            addWithSpecialInfix(specialInfix, text);
+        }
+        return this;
+    }
+
+    /**
+     * @return the string as it was built up to now, as a CharSequence.
+     */
+    public CharSequence toCharSequence(){
+        if (firstAppend) {
+            /* Don't even return the postfix */
+            return "";
+        }
+        return builder.append(postfix);
+    }
+
+    /**
+     * @return the string as it was built up to now.
+     */
+    @Override
+    public String toString() {
+        return toCharSequence().toString();
+    }
+}

src/main/java/com/laamella/queryprutser/common/Statement.java

+package com.laamella.queryprutser.common;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Select, insert, delete, update, etc.
+ */
+public abstract class Statement {
+    private final Map<String, Object> parameters = new HashMap<String, Object>();
+
+    /**
+     * Set a named parameter for this statement.
+     */
+    public final Statement parameter(final String name, final Object value) {
+        Assert.notNull(name);
+        parameters.put(name, value);
+        return this;
+    }
+
+    protected final Map<String, Object> localParameters() {
+        return parameters;
+    }
+
+    /**
+     * @return the current text of the query.
+     */
+    public abstract CharSequence queryText();
+
+    @Override
+    public final String toString() {
+        return queryText().toString();
+    }
+
+    /**
+     * @return all parameters that occur in the query and its subqueries.
+     */
+    public Map<String, Object> allParameters() {
+        final Map<String, Object> allParameters = new HashMap<String, Object>();
+        allParameters.putAll(localParameters());
+        return allParameters;
+    }
+
+    /**
+     * Chuck all parameters that this statement holds into the supplied Map.
+     */
+    public final void putAllParametersInThisMap(Map<String, Object> inHere) {
+        inHere.putAll(allParameters());
+    }
+
+}

src/main/java/com/laamella/queryprutser/common/package.html

+<body>
+Internal tools.
+</body>

src/main/java/com/laamella/queryprutser/hql/ClauseWithRootEntity.java

+package com.laamella.queryprutser.hql;
+
+import com.laamella.queryprutser.common.Assert;
+import com.laamella.queryprutser.common.SeparatedStringBuilder;
+
+public class ClauseWithRootEntity<T> extends SeparatedStringBuilder {
+    ClauseWithRootEntity(final CharSequence prefix, final CharSequence infix, final CharSequence postfix, final Class<T> rootEntity, final CharSequence alias) {
+        super(prefix, infix, postfix);
+        add(createEntityString(rootEntity, alias));
+    }
+
+    private CharSequence createEntityString(Class<T> rootClass, CharSequence alias) {
+        Assert.notNull(rootClass);
+        StringBuilder stringBuilder = new StringBuilder(rootClass.getCanonicalName());
+        if (alias != null) {
+            stringBuilder.append(" ");
+            stringBuilder.append(alias);
+        }
+        stringBuilder.append(" ");
+        return stringBuilder;
+    }
+}

src/main/java/com/laamella/queryprutser/hql/ClauseWithSubselects.java

+package com.laamella.queryprutser.hql;
+
+import com.laamella.queryprutser.common.SeparatedStringBuilder;
+
+import java.util.*;
+
+public class ClauseWithSubselects extends SeparatedStringBuilder {
+	private final List<Subquery<?>> subqueries = new ArrayList<Subquery<?>>();
+
+	ClauseWithSubselects(final CharSequence prefix, final CharSequence infix, final CharSequence postfix) {
+		super(prefix, infix, postfix);
+	}
+
+	public <T> Subquery<T> subselect(final Class<T> rootClass, final CharSequence alias) {
+		final Subquery<T> subquery = new Subquery<T>(rootClass, alias);
+		subqueries.add(subquery);
+		return subquery;
+	}
+
+	public <T> Subquery<T> subselect(final Class<T> rootClass) {
+		return subselect(rootClass, null);
+	}
+
+	@Override
+	public String toString() {
+		final SeparatedStringBuilder locallCopy = new SeparatedStringBuilder(this);
+		for (final Subquery<?> builder : subqueries) {
+			locallCopy.add(" " + builder.queryText() + " ");
+		}
+		return locallCopy.toString();
+	}
+
+	void putAllParametersInThisMap(final Map<String, Object> inHere) {
+		for (final Subquery<?> subquery : subqueries) {
+			inHere.putAll(subquery.allParameters());
+		}
+	}
+}

src/main/java/com/laamella/queryprutser/hql/Delete.java

+package com.laamella.queryprutser.hql;
+
+public class Delete extends HqlStatement {
+    @Override
+    public CharSequence queryText() {
+        // TODO
+        return null;
+    }
+}

src/main/java/com/laamella/queryprutser/hql/FromClause.java

+package com.laamella.queryprutser.hql;
+
+public class FromClause<T> extends ClauseWithRootEntity<T> {
+    FromClause(final Class<T> rootClass, final CharSequence alias) {
+        super("from ", " ", " ", rootClass, alias);
+    }
+
+    public FromClause<T> joinFetch(final CharSequence relationship, final CharSequence alias) {
+        add("join fetch " + relationship + " " + alias);
+        return this;
+    }
+}

src/main/java/com/laamella/queryprutser/hql/GroupByClause.java

+package com.laamella.queryprutser.hql;
+
+import com.laamella.queryprutser.common.SeparatedStringBuilder;
+
+// TODO isn't this just a SelectClause?
+public class GroupByClause extends SeparatedStringBuilder {
+	GroupByClause() {
+		super("\ngroup by ", ", ", " ");
+	}
+
+}

src/main/java/com/laamella/queryprutser/hql/HavingClause.java

+package com.laamella.queryprutser.hql;
+
+public class HavingClause extends WhereClause {
+	HavingClause() {
+		super("having");
+	}
+
+}

src/main/java/com/laamella/queryprutser/hql/HqlPrutser.java

+package com.laamella.queryprutser.hql;
+
+/**
+ * Main user entry point for the HQL functionality.
+ */
+public final class HqlPrutser {
+    public static <T> Select<T> select(final Class<T> rootClass, final CharSequence alias) {
+        return new Select<T>(rootClass, alias);
+    }
+
+    public static <T> Select<T> select(final Class<T> rootClass) {
+        return select(rootClass, null);
+    }
+
+    public static <T, U> Insert<T, U> insert(final Class<T> intoRootEntity, final CharSequence intoAlias, final Class<U> selectRootEntity, final CharSequence selectAlias) {
+        return new Insert<T, U>(intoRootEntity, intoAlias, selectRootEntity, selectAlias);
+    }
+
+    public static <T, U> Insert<T, U> insert(final Class<T> intoRootEntity, final Class<U> selectRootEntity) {
+        return insert(intoRootEntity, null, selectRootEntity, null);
+    }
+
+    public static Delete delete() {
+        return new Delete();
+    }
+
+    public static Update update() {
+        return new Update();
+    }
+}

src/main/java/com/laamella/queryprutser/hql/HqlStatement.java

+package com.laamella.queryprutser.hql;
+
+import java.util.Map;
+
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.laamella.queryprutser.common.Statement;
+
+public abstract class HqlStatement extends Statement {
+    private final Logger log = LoggerFactory.getLogger(HqlStatement.class);
+
+    /**
+     * @return create the final query.
+     */
+    public final Query query(final Session session) {
+        final String hql = queryText().toString();
+        log.debug(hql);
+        final Query query = session.createQuery(hql);
+        query.setProperties(allParameters());
+
+        if (log.isDebugEnabled()) {
+            for (final Map.Entry<String, Object> entry : allParameters().entrySet()) {
+                log.debug(entry.getKey() + "=" + entry.getValue());
+            }
+        }
+
+        return query;
+    }
+
+
+}

src/main/java/com/laamella/queryprutser/hql/Insert.java

+package com.laamella.queryprutser.hql;
+
+import java.util.Map;
+
+import com.laamella.queryprutser.common.SeparatedStringBuilder;
+
+/**
+ * Simple helper for building dynamic HQL insert queries, as opposed to
+ * Criteria, which are more helpful, complex, and contain many gotcha's, and to
+ * plain HQL, which is not dynamic.
+ */
+public class Insert<T, U> extends HqlStatement {
+    private final InsertIntoClause<T> insertEntityPart;
+    public final SeparatedStringBuilder insertInto = new SeparatedStringBuilder("(", ", ", ") ");
+    public final Select<U> select;
+
+     Insert(final Class<T> intoRootEntity, final CharSequence intoAlias, final Class<U> selectRootEntity, final CharSequence selectAlias) {
+        insertEntityPart = new InsertIntoClause<T>(intoRootEntity, intoAlias);
+        select = new Select<U>(selectRootEntity, selectAlias);
+    }
+
+    /**
+     * @return all parameters that occur in the query and its subqueries.
+     */
+    @Override
+	public Map<String, Object> allParameters() {
+        final Map<String, Object> allParameters = super.allParameters();
+        select.putAllParametersInThisMap(allParameters);
+        return allParameters;
+    }
+
+    /**
+     * @return the current HQL for the query.
+     */
+    @Override
+	public CharSequence queryText() {
+        final StringBuilder hql = new StringBuilder();
+        hql.append(insertEntityPart);
+        hql.append(insertInto);
+        hql.append(select);
+        return hql;
+    }
+}

src/main/java/com/laamella/queryprutser/hql/InsertIntoClause.java

+package com.laamella.queryprutser.hql;
+
+public class InsertIntoClause<T> extends ClauseWithRootEntity<T> {
+    InsertIntoClause(final Class<T> rootClass, final CharSequence alias) {
+        super("insert into ", "", "", rootClass, alias);
+    }
+}

src/main/java/com/laamella/queryprutser/hql/OrderByClause.java

+package com.laamella.queryprutser.hql;
+
+import com.laamella.queryprutser.common.SeparatedStringBuilder;
+
+public class OrderByClause extends SeparatedStringBuilder {
+	OrderByClause() {
+		super("\norder by ", ", ", " ");
+	}
+
+}

src/main/java/com/laamella/queryprutser/hql/Select.java

+package com.laamella.queryprutser.hql;
+
+import java.util.Map;
+
+/**
+ * Simple helper for building dynamic HQL select queries, as opposed to
+ * Criteria, which are more helpful, complex, and contain many gotcha's, and to
+ * plain HQL, which is not dynamic.
+ */
+public class Select<T> extends HqlStatement {
+    public final SelectClause select = new SelectClause();
+    public final FromClause<T> from;
+    public final WhereClause where = new WhereClause();
+    private final GroupByClause groupBy = new GroupByClause();
+    public final HavingClause having = new HavingClause();
+    private final OrderByClause orderBy = new OrderByClause();
+
+    Select(final Class<T> rootClass, final CharSequence alias) {
+        from = new FromClause<T>(rootClass, alias);
+    }
+
+    public Select<T> orderBy(final CharSequence... fields) {
+        orderBy.add(fields);
+        return this;
+    }
+
+    public Select<T> groupBy(final CharSequence... fields) {
+        groupBy.add(fields);
+        return this;
+    }
+
+    public Select<T> select(final CharSequence... fields) {
+        select.add(fields);
+        return this;
+    }
+
+    /**
+     * @return all parameters that occur in the query and its subqueries.
+     */
+    @Override
+	public Map<String, Object> allParameters() {
+        final Map<String, Object> allParameters = super.allParameters();
+        where.putAllParametersInThisMap(allParameters);
+        select.putAllParametersInThisMap(allParameters);
+        having.putAllParametersInThisMap(allParameters);
+        return allParameters;
+    }
+
+    /**
+     * @return the current HQL for the query.
+     */
+    @Override
+	public CharSequence queryText() {
+        final StringBuilder hql = new StringBuilder();
+        hql.append(select);
+        hql.append(from);
+        hql.append(where);
+        hql.append(groupBy);
+        hql.append(having);
+        hql.append(orderBy);
+        return hql;
+    }
+
+}

src/main/java/com/laamella/queryprutser/hql/SelectClause.java

+package com.laamella.queryprutser.hql;
+
+public class SelectClause extends ClauseWithSubselects {
+    SelectClause() {
+        super("select ", ", ", " ");
+    }
+
+    public void min(final CharSequence string) {
+        add("min(" + string + ")");
+    }
+
+    public void max(final CharSequence string) {
+        add("max(" + string + ")");
+    }
+
+    public void avg(final CharSequence string) {
+        add("avg(" + string + ")");
+    }
+
+    public void sum(final CharSequence string) {
+        add("sum(" + string + ")");
+    }
+
+    public void count(final CharSequence string) {
+        add("count(" + string + ")");
+    }
+}

src/main/java/com/laamella/queryprutser/hql/Subquery.java

+package com.laamella.queryprutser.hql;
+
+import com.laamella.queryprutser.common.Assert;
+
+public class Subquery<T> extends Select<T> {
+	private CharSequence before = "";
+	private CharSequence after = "";
+
+	Subquery(final Class<T> rootClass, final CharSequence alias) {
+		super(rootClass, alias);
+	}
+
+	public Subquery<T> before(final CharSequence before) {
+		Assert.notNull(before);
+		this.before = before;
+		return this;
+	}
+
+	public Subquery<T> after(final CharSequence after) {
+		Assert.notNull(after);
+		this.after = after;
+		return this;
+	}
+
+	@Override
+	public CharSequence queryText() {
+		final StringBuilder hql = new StringBuilder();
+		hql.append(before);
+		hql.append("(");
+		hql.append(super.queryText());
+		hql.append(") ");
+		hql.append(after);
+		return hql;
+	}
+}

src/main/java/com/laamella/queryprutser/hql/Update.java

+package com.laamella.queryprutser.hql;
+
+public class Update extends HqlStatement {
+    @Override
+    public CharSequence queryText() {
+        // TODO
+        return null; 
+    }
+}

src/main/java/com/laamella/queryprutser/hql/WhereClause.java

+package com.laamella.queryprutser.hql;
+
+public class WhereClause extends ClauseWithSubselects {
+	WhereClause() {
+		this("where");
+	}
+
+	protected WhereClause(final CharSequence keyword) {
+		super(" \n" + keyword + " ", "\n", " ");
+	}
+
+	public void and(final CharSequence... values) {
+		addWithSpecialInfix("\nand ", values);
+	}
+}

src/main/java/com/laamella/queryprutser/hql/package.html

+<body>
+Builds Hibernate HQL queries. Start with HqlPrutser.
+</body>

src/main/java/com/laamella/queryprutser/jpql/JpqlPrutser.java

+package com.laamella.queryprutser.jpql;
+
+public final class JpqlPrutser {
+    // TODO
+}

src/main/java/com/laamella/queryprutser/jpql/package.html

+<body>
+Builds Java Persistence Query Language queries. Start with JpqlPrutser.
+
+<p>No work on this has been done yet.</p>
+</body>

src/main/java/com/laamella/queryprutser/package.html

+<body>
+Simple helpers for dynamically building textual queries for various database types.
+</body>

src/main/java/com/laamella/queryprutser/sql/ClauseWithRootEntity.java

+package com.laamella.queryprutser.sql;
+
+import com.laamella.queryprutser.common.SeparatedStringBuilder;
+
+public class ClauseWithRootEntity extends SeparatedStringBuilder {
+    ClauseWithRootEntity(final CharSequence prefix, final CharSequence infix, final CharSequence postfix, final CharSequence  firstTable) {
+        super(prefix, infix, postfix);
+        add(firstTable);
+    }
+}

src/main/java/com/laamella/queryprutser/sql/ClauseWithSubselects.java

+package com.laamella.queryprutser.sql;
+
+import com.laamella.queryprutser.common.SeparatedStringBuilder;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class ClauseWithSubselects extends SeparatedStringBuilder {
+	private final List<Subquery> subqueries = new ArrayList<Subquery>(0);
+
+	ClauseWithSubselects(final CharSequence prefix, final CharSequence infix, final CharSequence postfix) {
+		super(prefix, infix, postfix);
+	}
+
+	public Subquery subselect(String firstTable) {
+		final Subquery subquery = new Subquery(firstTable);
+		subqueries.add(subquery);
+		return subquery;
+	}
+
+	@Override
+	public String toString() {
+		final SeparatedStringBuilder locallCopy = new SeparatedStringBuilder(this);
+		for (final Subquery builder : subqueries) {
+			locallCopy.add(" " + builder.queryText() + " ");
+		}
+		return locallCopy.toString();
+	}
+
+	void putAllParametersInThisMap(final Map<String, Object> inHere) {
+		for (final Subquery subquery : subqueries) {
+			inHere.putAll(subquery.allParameters());
+		}
+	}
+}

src/main/java/com/laamella/queryprutser/sql/Delete.java

+package com.laamella.queryprutser.sql;
+
+import java.util.Map;
+
+import com.laamella.queryprutser.common.SeparatedStringBuilder;
+
+public class Delete extends SqlStatement {
+	public SeparatedStringBuilder from = new SeparatedStringBuilder("DELETE FROM ", ", ", "");
+	public WhereClause where = new WhereClause();
+
+	public Delete(String firstTable) {
+		from.add(firstTable);
+	}
+
+	/**
+	 * @return all parameters that occur in the query and its subqueries.
+	 */
+	@Override
+	public Map<String, Object> allParameters() {
+		final Map<String, Object> allParameters = super.allParameters();
+		where.putAllParametersInThisMap(allParameters);
+		return allParameters;
+	}
+
+	/**
+	 * @return the current HQL for the query.
+	 */
+	@Override
+	public CharSequence queryText() {
+		final StringBuilder sql = new StringBuilder();
+		sql.append(from);
+		sql.append(where);
+		return sql;
+	}
+
+}

src/main/java/com/laamella/queryprutser/sql/FromClause.java

+package com.laamella.queryprutser.sql;
+
+import com.laamella.queryprutser.common.SeparatedStringBuilder;
+
+public class FromClause extends SeparatedStringBuilder {
+	FromClause() {
+		super("FROM ", " ", " ");
+	}
+
+	public FromClause innerJoin(final String table) {
+		add("INNER JOIN " + table);
+		return this;
+	}
+
+	public FromClause join(final String table) {
+		add("JOIN " + table);
+		return this;
+	}
+
+	public FromClause outerJoin(final String table) {
+		add("OUTER JOIN " + table);
+		return this;
+	}
+
+	public FromClause on(String joinOn) {
+		add("ON " + joinOn);
+		return this;
+	}
+}

src/main/java/com/laamella/queryprutser/sql/GroupByClause.java

+package com.laamella.queryprutser.sql;
+
+import com.laamella.queryprutser.common.SeparatedStringBuilder;
+
+// TODO isn't this just a SelectClause?
+public class GroupByClause extends SeparatedStringBuilder {
+	GroupByClause() {
+		super("\nGROUP BY ", ", ", " ");
+	}
+
+}

src/main/java/com/laamella/queryprutser/sql/HavingClause.java

+package com.laamella.queryprutser.sql;
+
+public class HavingClause extends WhereClause {
+	HavingClause() {
+		super("HAVING");
+	}
+
+}

src/main/java/com/laamella/queryprutser/sql/Insert.java

+package com.laamella.queryprutser.sql;
+
+import java.util.Map;
+
+import com.laamella.queryprutser.common.SeparatedStringBuilder;
+
+/**
+ * Build and SQL insert statement. Access through SqlPrutser.
+ */
+// FIXME
+public class Insert extends SqlStatement {
+	private final InsertIntoClause insertTablePart = new InsertIntoClause();
+	public final SeparatedStringBuilder into = new SeparatedStringBuilder("(", ", ", ") ");
+	public final Select select = new Select();