mirror of https://github.com/tasks/tasks
Moved stuff around into subfolders, started integrating databases.
parent
a01c3fa2af
commit
be57b599a9
File diff suppressed because one or more lines are too long
@ -0,0 +1,123 @@
|
|||||||
|
/**
|
||||||
|
* See the file "LICENSE" for the full license governing this code.
|
||||||
|
*/
|
||||||
|
package com.todoroo.astrid.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constants for interfacing with Astrid.
|
||||||
|
*
|
||||||
|
* @author Tim Su <tim@todoroo.com>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
public class AstridApiConstants {
|
||||||
|
|
||||||
|
// --- General Constants
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Astrid application package name
|
||||||
|
*/
|
||||||
|
public static final String PACKAGE = "com.todoroo.astrid";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permission for reading tasks and receiving to GET_FILTERS intent
|
||||||
|
*/
|
||||||
|
public static final String PERMISSION_READ = PACKAGE + ".READ";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permission for writing and creating tasks
|
||||||
|
*/
|
||||||
|
public static final String PERMISSION_WRITE = PACKAGE + ".WRITE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extras name for Task id
|
||||||
|
*/
|
||||||
|
public static final String EXTRAS_TASK_ID = "task";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extras name for an array of response items
|
||||||
|
*/
|
||||||
|
public static final String EXTRAS_ITEMS = "items";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extras name for your plug-in name, used for logging errors to LogCat
|
||||||
|
*/
|
||||||
|
public static final String EXTRAS_PLUGIN = "plugin";
|
||||||
|
|
||||||
|
// --- Filters API
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action name for broadcast intent requesting filters
|
||||||
|
*/
|
||||||
|
public static final String BROADCAST_REQUEST_FILTERS = PACKAGE + ".REQUEST_FILTERS";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action name for broadcast intent sending filters back to Astrid
|
||||||
|
*/
|
||||||
|
public static final String BROADCAST_SEND_FILTERS = PACKAGE + ".SEND_FILTERS";
|
||||||
|
|
||||||
|
// --- Edit Operations API
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action name for broadcast intent requesting task edit operations
|
||||||
|
*/
|
||||||
|
public static final String BROADCAST_REQUEST_EDIT_OPERATIONS = PACKAGE + ".REQUEST_EDIT_OPERATIONS";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action name for broadcast intent sending task edit operations back to Astrid
|
||||||
|
*/
|
||||||
|
public static final String BROADCAST_SEND_EDIT_OPERATIONS = PACKAGE + ".SEND_EDIT_OPERATIONS";
|
||||||
|
|
||||||
|
// --- Task List Details API
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action name for broadcast intent requesting task list details for a task
|
||||||
|
*/
|
||||||
|
public static final String BROADCAST_REQUEST_DETAILS = PACKAGE + ".REQUEST_DETAILS";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action name for broadcast intent sending details back to Astrid
|
||||||
|
*/
|
||||||
|
public static final String BROADCAST_SEND_DETAILS = PACKAGE + ".SEND_DETAILS";
|
||||||
|
|
||||||
|
// --- Actions API
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action name for intents to be displayed on task context menu
|
||||||
|
*/
|
||||||
|
public static final String ACTION_TASK_CONTEXT_MENU = PACKAGE + ".CONTEXT_MENU";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action name for intents to be displayed on Astrid's task list menu
|
||||||
|
*/
|
||||||
|
public static final String ACTION_TASK_LIST_MENU = PACKAGE + ".TASK_LIST_MENU";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action name for intents to be displayed in Astrid's settings
|
||||||
|
*/
|
||||||
|
public static final String ACTION_SETTINGS = PACKAGE + ".SETTINGS";
|
||||||
|
|
||||||
|
// --- Events API
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action name for broadcast intent notifying that task was completed
|
||||||
|
*/
|
||||||
|
public static final String BROADCAST_EVENT_TASK_COMPLETED = PACKAGE + ".TASK_COMPLETED";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action name for broadcast intent notifying that task was created
|
||||||
|
*/
|
||||||
|
public static final String BROADCAST_EVENT_TASK_CREATED = PACKAGE + ".TASK_CREATED";
|
||||||
|
|
||||||
|
// --- SQL Constants
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table name for tasks
|
||||||
|
*/
|
||||||
|
public static final String TASK_TABLE = "tasks";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table name for metadata
|
||||||
|
*/
|
||||||
|
public static final String METADATA_TABLE = "metadata";
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,194 @@
|
|||||||
|
/**
|
||||||
|
* See the file "LICENSE" for the full license governing this code.
|
||||||
|
*/
|
||||||
|
package com.todoroo.astrid.api;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constants for interfacing with Astrid's Content Providers.
|
||||||
|
*
|
||||||
|
* @author Tim Su <tim@todoroo.com>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
public class AstridContentProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content Provider
|
||||||
|
*/
|
||||||
|
public static final String PROVIDER = "com.todoroo.astrid.provider";
|
||||||
|
|
||||||
|
// --- methods for generating URI's for accessing Astrid data
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URI for:
|
||||||
|
* <ul>
|
||||||
|
* <li>Queries on multiple tasks
|
||||||
|
* <li>Inserting new tasks
|
||||||
|
* <li>Deleting multiple tasks at a time
|
||||||
|
* <li>Updating multiple tasks at a time
|
||||||
|
* </ul>
|
||||||
|
* If your selection clause contains metadata columns, you need to use
|
||||||
|
* <code>allItemsWithMetadataUri</code> instead of this one.
|
||||||
|
*/
|
||||||
|
public static Uri allItemsUri() {
|
||||||
|
return Uri.parse("content://" + PROVIDER + "/items");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URI for:
|
||||||
|
* <ul>
|
||||||
|
* <li>Querying on tasks with metadata columns in selection
|
||||||
|
* <li>Deleting multiple tasks with metadata columns in selection
|
||||||
|
* <li>Updating multiple tasks with metadata columns in selection
|
||||||
|
* </ul>
|
||||||
|
* If, for example, you have defined metadata key 'tag' and wish to delete
|
||||||
|
* all tasks where 'tag' = 'deleteme', you would use this URI. For querying
|
||||||
|
* or insertion, use <code>allItemsUri</code>.
|
||||||
|
* <p>
|
||||||
|
* For queries, <code>allItemsUri</code> will be more efficient, but will
|
||||||
|
* not work if your selection clause contains columns not mentioned in your
|
||||||
|
* projection
|
||||||
|
*
|
||||||
|
* @param metadata
|
||||||
|
* array of metadata columns you wish to select using
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static Uri allItemsWithMetadataUri(String[] metadata) {
|
||||||
|
if(metadata == null || metadata.length == 0)
|
||||||
|
throw new IllegalArgumentException("You must provide metadata");
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for(int i = 0; i < metadata.length; i++)
|
||||||
|
builder.append(escapeUriSubComponent(metadata[i])).append(
|
||||||
|
SUB_COMPONENT_SEPARATOR);
|
||||||
|
|
||||||
|
return Uri.parse("content://" + PROVIDER + "/itemsWith/" +
|
||||||
|
escapeUriComponent(builder.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URI for:
|
||||||
|
* <ul>
|
||||||
|
* <li>Queries on a single task
|
||||||
|
* <li>Updating fields for a single task
|
||||||
|
* <li>Deleting a single task
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* id of task to fetch
|
||||||
|
*/
|
||||||
|
public static Uri singleItemUri(long id) {
|
||||||
|
return Uri.parse("content://" + PROVIDER + "/" + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URI for:
|
||||||
|
* <ul>
|
||||||
|
* <li>Queries on multiple tasks, grouped by column
|
||||||
|
* </ul>
|
||||||
|
* @param groupBy
|
||||||
|
* column name to group by
|
||||||
|
*/
|
||||||
|
public static Uri groupByUri(String groupBy) {
|
||||||
|
groupBy = escapeUriComponent(groupBy);
|
||||||
|
return Uri.parse("content://" + PROVIDER + "/groupby/" + groupBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- task built-in columns and constnats
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task in Astrid represents a single item in a user's task list
|
||||||
|
*
|
||||||
|
* @author Tim Su <tim@todoroo.com>
|
||||||
|
*/
|
||||||
|
public static class AstridTask {
|
||||||
|
|
||||||
|
// --- columns
|
||||||
|
|
||||||
|
/** long: Task id */
|
||||||
|
public static final String ID = AstridApiConstants.TASK_TABLE + "._id";
|
||||||
|
|
||||||
|
/** String: name of Task */
|
||||||
|
public static final String TITLE = AstridApiConstants.TASK_TABLE
|
||||||
|
+ ".title";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* int: Task Urgency setting (see <code>Task.URGENCY_*</code> for
|
||||||
|
* possible values)
|
||||||
|
*/
|
||||||
|
public static final String URGENCY = AstridApiConstants.TASK_TABLE
|
||||||
|
+ ".urgency";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* int: Task Importance setting (see <code>Task.IMPORTANCE_*</code> for
|
||||||
|
* possible values)
|
||||||
|
*/
|
||||||
|
public static final String IMPORTANCE = AstridApiConstants.TASK_TABLE
|
||||||
|
+ ".importance";
|
||||||
|
|
||||||
|
/** int: unixtime Task is due, 0 if not set */
|
||||||
|
public static final String DUE_DATE = AstridApiConstants.TASK_TABLE
|
||||||
|
+ ".dueDate";
|
||||||
|
|
||||||
|
/** int: unixtime Task should be hidden until, 0 if not set */
|
||||||
|
public static final String HIDDEN_UNTIL = AstridApiConstants.TASK_TABLE
|
||||||
|
+ ".hiddenUntil";
|
||||||
|
|
||||||
|
/** int: unixtime Task was created */
|
||||||
|
public static final String CREATION_DATE = AstridApiConstants.TASK_TABLE
|
||||||
|
+ ".creationDate";
|
||||||
|
|
||||||
|
/** int: unixtime Task was completed, 0 if task not completed */
|
||||||
|
public static final String COMPLETION_DATE = AstridApiConstants.TASK_TABLE
|
||||||
|
+ ".completionDate";
|
||||||
|
|
||||||
|
/** int: unixtime Task was deleted, 0 if task not deleted */
|
||||||
|
public static final String DELETION_DATE = AstridApiConstants.TASK_TABLE
|
||||||
|
+ ".deletionDate";
|
||||||
|
|
||||||
|
// --- urgency settings
|
||||||
|
|
||||||
|
public static final int URGENCY_NONE = 0;
|
||||||
|
public static final int URGENCY_TODAY = 1;
|
||||||
|
public static final int URGENCY_THIS_WEEK = 2;
|
||||||
|
public static final int URGENCY_THIS_MONTH = 3;
|
||||||
|
public static final int URGENCY_WITHIN_THREE_MONTHS = 4;
|
||||||
|
public static final int URGENCY_WITHIN_SIX_MONTHS = 5;
|
||||||
|
public static final int URGENCY_WITHIN_A_YEAR = 6;
|
||||||
|
public static final int URGENCY_SPECIFIC_DAY = 7;
|
||||||
|
public static final int URGENCY_SPECIFIC_DAY_TIME = 8;
|
||||||
|
|
||||||
|
// --- importance settings
|
||||||
|
|
||||||
|
public static final int IMPORTANCE_DO_OR_DIE = 0;
|
||||||
|
public static final int IMPORTANCE_MUST_DO = 1;
|
||||||
|
public static final int IMPORTANCE_SHOULD_DO = 2;
|
||||||
|
public static final int IMPORTANCE_NONE = 3;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- internal methods
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escapes a string for use in a URI. Used internally to pass extra data
|
||||||
|
* to the content provider.
|
||||||
|
* @param component
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String escapeUriComponent(String component) {
|
||||||
|
return component.replace("%", "%o").replace("/", "%s");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String SUB_COMPONENT_SEPARATOR = "|";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escapes a string for use as part of a URI string. Used internally to pass extra data
|
||||||
|
* to the content provider.
|
||||||
|
* @param component
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String escapeUriSubComponent(String component) {
|
||||||
|
return component.replace("$", "$o").replace(SUB_COMPONENT_SEPARATOR, "$s");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* See the file "LICENSE" for the full license governing this code.
|
||||||
|
*/
|
||||||
|
package com.todoroo.astrid.api;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an intent that can be called on a task being edited
|
||||||
|
*
|
||||||
|
* @author Tim Su <tim@todoroo.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class EditOperation implements Parcelable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin Id
|
||||||
|
*/
|
||||||
|
public String plugin = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Label
|
||||||
|
*/
|
||||||
|
public String text = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intent to call when invoking this operation
|
||||||
|
*/
|
||||||
|
public Intent intent = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an EditOperation object
|
||||||
|
*
|
||||||
|
* @param text
|
||||||
|
* label to display
|
||||||
|
* @param intent
|
||||||
|
* intent to invoke. {@link EXTRAS_TASK_ID} will be passed
|
||||||
|
*/
|
||||||
|
public EditOperation(String text, Intent intent) {
|
||||||
|
super();
|
||||||
|
this.text = text;
|
||||||
|
this.intent = intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- parcelable helpers
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeString(text);
|
||||||
|
dest.writeParcelable(intent, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parcelable creator
|
||||||
|
*/
|
||||||
|
public static final Parcelable.Creator<EditOperation> CREATOR = new Parcelable.Creator<EditOperation>() {
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public EditOperation createFromParcel(Parcel source) {
|
||||||
|
return new EditOperation(source.readString(), (Intent)source.readParcelable(
|
||||||
|
Intent.class.getClassLoader()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public EditOperation[] newArray(int size) {
|
||||||
|
return new EditOperation[size];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,140 @@
|
|||||||
|
/**
|
||||||
|
* See the file "LICENSE" for the full license governing this code.
|
||||||
|
*/
|
||||||
|
package com.todoroo.astrid.api;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import com.todoroo.astrid.api.AstridContentProvider.AstridTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A <code>FilterListFilter</code> allows users to display tasks that have
|
||||||
|
* something in common.
|
||||||
|
* <p>
|
||||||
|
* A plug-in can expose new <code>FilterListFilter</code>s to the system by
|
||||||
|
* responding to the <code>com.todoroo.astrid.GET_FILTERS</code> broadcast
|
||||||
|
* intent.
|
||||||
|
*
|
||||||
|
* @author Tim Su <tim@todoroo.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Filter extends FilterListItem {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expanded title of this filter. This is displayed at the top
|
||||||
|
* of the screen when user is viewing this filter.
|
||||||
|
* <p>
|
||||||
|
* e.g "Tasks With Notes"
|
||||||
|
*/
|
||||||
|
public String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SQL query for this filter. The query will be appended to the select
|
||||||
|
* statement after "<code>SELECT fields FROM table %s</code>". Use
|
||||||
|
* {@link AstridApiConstants.TASK_TABLE} and
|
||||||
|
* {@link AstridApiConstants.METADATA_TABLE} as table names,
|
||||||
|
* {@link AstridTask} for field names.
|
||||||
|
* <p>
|
||||||
|
* Examples:
|
||||||
|
* <ul>
|
||||||
|
* <li><code>" WHERE completionDate = 0"</code>
|
||||||
|
* <li><code>" INNER JOIN " +
|
||||||
|
* Constants.TABLE_METADATA + " ON metadata.task = tasks.id WHERE
|
||||||
|
* metadata.namespace = " + NAMESPACE + " AND metadata.key = 'a' AND
|
||||||
|
* metadata.value = 'b' GROUP BY tasks.id ORDER BY tasks.title"</code>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public String sqlQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SQL query to execute on a task when quick-creating a new task while viewing
|
||||||
|
* this filter. For example, when a user views tasks tagged 'ABC', the
|
||||||
|
* tasks they create should also be tagged 'ABC'. If set to null, no
|
||||||
|
* query will be executed. In this string, $ID will be replaced with the
|
||||||
|
* task id.
|
||||||
|
* <p>
|
||||||
|
* Examples:
|
||||||
|
* <ul>
|
||||||
|
* <li><code>"INSERT INTO " + Constants.TABLE_METADATA + " (task,
|
||||||
|
* namespace, key, string) VALUES ($ID, " + ... + ")"</code>
|
||||||
|
* <li><code>"UPDATE " + Constants.TABLE_TASK + " SET urgency = 0
|
||||||
|
* WHERE _id = $ID"</code>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public String sqlForNewTasks = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility constructor for creating a TaskList object
|
||||||
|
*
|
||||||
|
* @param listingTitle
|
||||||
|
* Title of this item as displayed on the lists page, e.g. Inbox
|
||||||
|
* @param title
|
||||||
|
* Expanded title of this filter when user is viewing this
|
||||||
|
* filter, e.g. Inbox (20 tasks)
|
||||||
|
* @param sqlQuery
|
||||||
|
* SQL query for this list (see {@link sqlQuery} for examples).
|
||||||
|
* @param sqlForNewTasks
|
||||||
|
* see {@link sqlForNewTasks}
|
||||||
|
*/
|
||||||
|
public Filter(String listingTitle,
|
||||||
|
String title, String sqlQuery, String sqlForNewTasks) {
|
||||||
|
this.listingTitle = listingTitle;
|
||||||
|
this.title = title;
|
||||||
|
this.sqlQuery = sqlQuery;
|
||||||
|
this.sqlForNewTasks = sqlForNewTasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blank constructor
|
||||||
|
*/
|
||||||
|
public Filter() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- parcelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
super.writeToParcel(dest, flags);
|
||||||
|
dest.writeString(title);
|
||||||
|
dest.writeString(sqlQuery);
|
||||||
|
dest.writeString(sqlForNewTasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parcelable Creator Object
|
||||||
|
*/
|
||||||
|
public static final Parcelable.Creator<Filter> CREATOR = new Parcelable.Creator<Filter>() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public Filter createFromParcel(Parcel source) {
|
||||||
|
Filter item = new Filter();
|
||||||
|
item.readFromParcel(source);
|
||||||
|
item.title = source.readString();
|
||||||
|
item.sqlQuery = source.readString();
|
||||||
|
item.sqlForNewTasks = source.readString();
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public Filter[] newArray(int size) {
|
||||||
|
return new Filter[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
/**
|
||||||
|
* See the file "LICENSE" for the full license governing this code.
|
||||||
|
*/
|
||||||
|
package com.todoroo.astrid.api;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A <code>FilterCategory</code> groups common {@link Filter}s and allows
|
||||||
|
* a user to show/hide all of its children.
|
||||||
|
*
|
||||||
|
* @author Tim Su <tim@todoroo.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class FilterCategory extends FilterListItem {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Filter}s contained by this category
|
||||||
|
*/
|
||||||
|
public Filter[] children;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for creating a new FilterCategory
|
||||||
|
*
|
||||||
|
* @param listingTitle
|
||||||
|
* Title of this item as displayed on the lists page, e.g. Inbox
|
||||||
|
* @param children
|
||||||
|
* filters belonging to this category
|
||||||
|
*/
|
||||||
|
public FilterCategory(String listingTitle,
|
||||||
|
Filter[] children) {
|
||||||
|
this.listingTitle = listingTitle;
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blank constructor
|
||||||
|
*/
|
||||||
|
public FilterCategory() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- parcelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
super.writeToParcel(dest, flags);
|
||||||
|
dest.writeParcelableArray(children, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parcelable creator
|
||||||
|
*/
|
||||||
|
public static final Parcelable.Creator<FilterCategory> CREATOR = new Parcelable.Creator<FilterCategory>() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FilterCategory createFromParcel(Parcel source) {
|
||||||
|
FilterCategory item = new FilterCategory();
|
||||||
|
item.readFromParcel(source);
|
||||||
|
|
||||||
|
Parcelable[] parcelableChildren = source.readParcelableArray(
|
||||||
|
FilterCategory.class.getClassLoader());
|
||||||
|
item.children = new Filter[parcelableChildren.length];
|
||||||
|
for(int i = 0; i < item.children.length; i++) {
|
||||||
|
if(parcelableChildren[i] instanceof FilterListItem)
|
||||||
|
item.children[i] = (Filter) parcelableChildren[i];
|
||||||
|
else
|
||||||
|
item.children[i] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FilterCategory[] newArray(int size) {
|
||||||
|
return new FilterCategory[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* See the file "LICENSE" for the full license governing this code.
|
||||||
|
*/
|
||||||
|
package com.todoroo.astrid.api;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Section Header for Filter List
|
||||||
|
*
|
||||||
|
* @author Tim Su <tim@todoroo.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class FilterListHeader extends FilterListItem {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for creating a new FilterListHeader
|
||||||
|
*
|
||||||
|
* @param listingTitle
|
||||||
|
* @param listingIconResource
|
||||||
|
* @param priority
|
||||||
|
*/
|
||||||
|
public FilterListHeader(String listingTitle) {
|
||||||
|
this.listingTitle = listingTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty constructor
|
||||||
|
*/
|
||||||
|
public FilterListHeader() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- parcelable
|
||||||
|
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
super.writeToParcel(dest, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Parcelable.Creator<FilterListHeader> CREATOR = new Parcelable.Creator<FilterListHeader>() {
|
||||||
|
|
||||||
|
public FilterListHeader createFromParcel(Parcel source) {
|
||||||
|
FilterListHeader item = new FilterListHeader();
|
||||||
|
item.readFromParcel(source);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FilterListHeader[] newArray(int size) {
|
||||||
|
return new FilterListHeader[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* See the file "LICENSE" for the full license governing this code.
|
||||||
|
*/
|
||||||
|
package com.todoroo.astrid.api;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an item displayed by Astrid's FilterListActivity
|
||||||
|
*
|
||||||
|
* @author Tim Su <tim@todoroo.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
abstract public class FilterListItem implements Parcelable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Title of this item displayed on the Filters page
|
||||||
|
*/
|
||||||
|
public String listingTitle = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bitmap for icon used on listing page. <code>null</code> => no icon
|
||||||
|
*/
|
||||||
|
public Bitmap listingIcon = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context Menu labels. The context menu will be displayed when users
|
||||||
|
* long-press on this filter list item.
|
||||||
|
*/
|
||||||
|
public String contextMenuLabels[] = new String[0];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context menu intents. This intent will be started when the corresponding
|
||||||
|
* content menu label is invoked. This array must be the same size as
|
||||||
|
* the contextMenuLabels array.
|
||||||
|
*/
|
||||||
|
public Intent contextMenuIntents[] = new Intent[0];
|
||||||
|
|
||||||
|
// --- parcelable helpers
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeString(listingTitle);
|
||||||
|
dest.writeParcelable(listingIcon, 0);
|
||||||
|
|
||||||
|
// write array lengths before arrays
|
||||||
|
dest.writeInt(contextMenuLabels.length);
|
||||||
|
dest.writeStringArray(contextMenuLabels);
|
||||||
|
dest.writeInt(contextMenuIntents.length);
|
||||||
|
dest.writeTypedArray(contextMenuIntents, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility method to read FilterListItem properties from a parcel.
|
||||||
|
* @param source
|
||||||
|
*/
|
||||||
|
public void readFromParcel(Parcel source) {
|
||||||
|
listingTitle = source.readString();
|
||||||
|
listingIcon = source.readParcelable(Bitmap.class.getClassLoader());
|
||||||
|
|
||||||
|
int length = source.readInt();
|
||||||
|
contextMenuLabels = new String[length];
|
||||||
|
source.readStringArray(contextMenuLabels);
|
||||||
|
length = source.readInt();
|
||||||
|
contextMenuIntents = new Intent[length];
|
||||||
|
source.readTypedArray(contextMenuIntents, Intent.CREATOR);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* See the file "LICENSE" for the full license governing this code.
|
||||||
|
*/
|
||||||
|
package com.todoroo.astrid.api;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a line of text displayed in the Task List
|
||||||
|
*
|
||||||
|
* @author Tim Su <tim@todoroo.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TaskDetail implements Parcelable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text of detail
|
||||||
|
*/
|
||||||
|
public String text = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color to use for text. 0 is default
|
||||||
|
*/
|
||||||
|
public int color = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a TaskDetail object
|
||||||
|
*
|
||||||
|
* @param text
|
||||||
|
* text to display
|
||||||
|
* @param color
|
||||||
|
* color to use for text. Use <code>0</code> for default color
|
||||||
|
*/
|
||||||
|
public TaskDetail(String text, int color) {
|
||||||
|
super();
|
||||||
|
this.text = text;
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience constructor to make a TaskDetail with default color
|
||||||
|
*
|
||||||
|
* @param text
|
||||||
|
* text to display
|
||||||
|
*/
|
||||||
|
public TaskDetail(String text) {
|
||||||
|
this(text, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --- parcelable helpers
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeString(text);
|
||||||
|
dest.writeInt(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parcelable creator
|
||||||
|
*/
|
||||||
|
public static final Parcelable.Creator<TaskDetail> CREATOR = new Parcelable.Creator<TaskDetail>() {
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public TaskDetail createFromParcel(Parcel source) {
|
||||||
|
return new TaskDetail(source.readString(), source.readInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public TaskDetail[] newArray(int size) {
|
||||||
|
return new TaskDetail[size];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -1,58 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# BzrToGit - SCM migration tool for going from bzr to git
|
|
||||||
# Copyright (C) 2009 Henrik Nilsson
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License, version 3, as
|
|
||||||
# published by the Free Software Foundation.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
keepbzr="no"
|
|
||||||
for x in $@; do
|
|
||||||
if [ "$x" = "--keepbzr" ]; then keepbzr="yes"
|
|
||||||
elif [ "$x" = "--help" ]; then
|
|
||||||
echo "--keepbzr = Keep the .bzr directory so that it can still be used by bazaar"
|
|
||||||
echo "--help = Display this list"
|
|
||||||
exit
|
|
||||||
else echo "${x}: unknown argument, type --help to see available arguments"; exit 1; fi
|
|
||||||
done
|
|
||||||
|
|
||||||
rev=1
|
|
||||||
git init
|
|
||||||
while bzr revert -r revno:$rev 2> /dev/null; do
|
|
||||||
logentry="`bzr log -r $rev`"
|
|
||||||
committer="`echo "$logentry" | sed -n -e "/^committer:/{s/^committer: //;p;}"`"
|
|
||||||
timestamp="`echo "$logentry" | sed -n -e "/^timestamp:/{s/^timestamp: //;p;}"`"
|
|
||||||
export GIT_AUTHOR_DATE="$timestamp"
|
|
||||||
msg=`echo "$logentry" | sed -e "1,/^message:/d"`
|
|
||||||
committer_name=`echo "$committer" | sed -e "s/ *<[^<]*\$//;"`
|
|
||||||
committer_email=`echo "$committer" | sed -e "s/.*<//;s/>//;"`
|
|
||||||
|
|
||||||
if [ "$committer_email" == "tim@todoroo.com" -o \
|
|
||||||
"$committer_email" == "dev.astrid" -o \
|
|
||||||
"$committer_email" == "timsu@global" -o \
|
|
||||||
"$committer_email" == "timsu@ayumi" -o \
|
|
||||||
"$committer_email" == "timsu@betaful.com" ]; then
|
|
||||||
committer_name="Tim Su"
|
|
||||||
committer_email="tim@todoroo.com"
|
|
||||||
echo ts hack
|
|
||||||
fi
|
|
||||||
|
|
||||||
git config user.name "$committer_name"
|
|
||||||
git config user.email "$committer_email"
|
|
||||||
ls -a1 | while read x; do
|
|
||||||
if [ "$x" != ".bzr" ] && [ "$x" != "." ] && [ "$x" != ".." ]; then git add "$x"; fi
|
|
||||||
done
|
|
||||||
git commit -a -m "$msg"
|
|
||||||
# --author="$committer"
|
|
||||||
let rev+=1
|
|
||||||
done
|
|
||||||
|
|
||||||
[ "$keepbzr" != "yes" ] && rm -r .bzr
|
|
@ -0,0 +1,5 @@
|
|||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 29
|
||||||
|
/svn/!svn/ver/9/trunk/src/com
|
||||||
|
END
|
@ -0,0 +1,5 @@
|
|||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 42
|
||||||
|
/svn/!svn/ver/9/trunk/src/com/thoughtworks
|
||||||
|
END
|
@ -0,0 +1,89 @@
|
|||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 46
|
||||||
|
/svn/!svn/ver/9/trunk/src/com/thoughtworks/sql
|
||||||
|
END
|
||||||
|
Join.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 56
|
||||||
|
/svn/!svn/ver/2/trunk/src/com/thoughtworks/sql/Join.java
|
||||||
|
END
|
||||||
|
JoinType.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 60
|
||||||
|
/svn/!svn/ver/2/trunk/src/com/thoughtworks/sql/JoinType.java
|
||||||
|
END
|
||||||
|
Field.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 57
|
||||||
|
/svn/!svn/ver/9/trunk/src/com/thoughtworks/sql/Field.java
|
||||||
|
END
|
||||||
|
EqCriterion.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 63
|
||||||
|
/svn/!svn/ver/6/trunk/src/com/thoughtworks/sql/EqCriterion.java
|
||||||
|
END
|
||||||
|
Query.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 57
|
||||||
|
/svn/!svn/ver/9/trunk/src/com/thoughtworks/sql/Query.java
|
||||||
|
END
|
||||||
|
GroupBy.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 59
|
||||||
|
/svn/!svn/ver/8/trunk/src/com/thoughtworks/sql/GroupBy.java
|
||||||
|
END
|
||||||
|
Table.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 57
|
||||||
|
/svn/!svn/ver/2/trunk/src/com/thoughtworks/sql/Table.java
|
||||||
|
END
|
||||||
|
Operator.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 60
|
||||||
|
/svn/!svn/ver/6/trunk/src/com/thoughtworks/sql/Operator.java
|
||||||
|
END
|
||||||
|
Order.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 57
|
||||||
|
/svn/!svn/ver/2/trunk/src/com/thoughtworks/sql/Order.java
|
||||||
|
END
|
||||||
|
DBObject.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 60
|
||||||
|
/svn/!svn/ver/2/trunk/src/com/thoughtworks/sql/DBObject.java
|
||||||
|
END
|
||||||
|
Constants.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 61
|
||||||
|
/svn/!svn/ver/6/trunk/src/com/thoughtworks/sql/Constants.java
|
||||||
|
END
|
||||||
|
UnaryCriterion.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 66
|
||||||
|
/svn/!svn/ver/6/trunk/src/com/thoughtworks/sql/UnaryCriterion.java
|
||||||
|
END
|
||||||
|
OrderType.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 61
|
||||||
|
/svn/!svn/ver/2/trunk/src/com/thoughtworks/sql/OrderType.java
|
||||||
|
END
|
||||||
|
Criterion.java
|
||||||
|
K 25
|
||||||
|
svn:wc:ra_dav:version-url
|
||||||
|
V 61
|
||||||
|
/svn/!svn/ver/9/trunk/src/com/thoughtworks/sql/Criterion.java
|
||||||
|
END
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
static final String SELECT = "SELECT";
|
||||||
|
static final String SPACE = " ";
|
||||||
|
static final String AS = "AS";
|
||||||
|
static final String COMMA = ",";
|
||||||
|
static final String FROM = "FROM";
|
||||||
|
static final String ON = "ON";
|
||||||
|
static final String JOIN = "JOIN";
|
||||||
|
static final String ALL = "*";
|
||||||
|
static final String LEFT_PARENTHESIS = "(";
|
||||||
|
static final String RIGHT_PARENTHESIS = ")";
|
||||||
|
static final String AND = "AND";
|
||||||
|
static final String BETWEEN = "BETWEEN";
|
||||||
|
static final String LIKE = "LIKE";
|
||||||
|
static final String OR = "OR";
|
||||||
|
static final String ORDER_BY = "ORDER BY";
|
||||||
|
static final String GROUP_BY = "GROUP BY";
|
||||||
|
static final String WHERE = "WHERE";
|
||||||
|
public static final String EXISTS = "EXISTS";
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.AND;
|
||||||
|
import static com.thoughtworks.sql.Constants.EXISTS;
|
||||||
|
import static com.thoughtworks.sql.Constants.LEFT_PARENTHESIS;
|
||||||
|
import static com.thoughtworks.sql.Constants.OR;
|
||||||
|
import static com.thoughtworks.sql.Constants.RIGHT_PARENTHESIS;
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
|
||||||
|
public abstract class Criterion {
|
||||||
|
protected final Operator operator;
|
||||||
|
|
||||||
|
Criterion(Operator operator) {
|
||||||
|
this.operator = operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion and(final Criterion criterion, final Criterion... criterions) {
|
||||||
|
return new Criterion(Operator.and) {
|
||||||
|
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(criterion);
|
||||||
|
for (Criterion criterion : criterions) {
|
||||||
|
sb.append(SPACE).append(AND).append(SPACE).append(criterion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion or(final Criterion criterion, final Criterion... criterions) {
|
||||||
|
return new Criterion(Operator.or) {
|
||||||
|
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(criterion);
|
||||||
|
for (Criterion criterion : criterions) {
|
||||||
|
sb.append(SPACE).append(OR).append(SPACE).append(criterion.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion exists(final Query query) {
|
||||||
|
return new Criterion(Operator.exists) {
|
||||||
|
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(EXISTS).append(SPACE).append(LEFT_PARENTHESIS).append(query).append(RIGHT_PARENTHESIS);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion not(Criterion criterion) {
|
||||||
|
return new Criterion(null) {
|
||||||
|
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void populate(StringBuilder sb);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder builder = new StringBuilder(LEFT_PARENTHESIS);
|
||||||
|
populate(builder);
|
||||||
|
builder.append(RIGHT_PARENTHESIS);
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
import static com.thoughtworks.sql.Constants.AS;
|
||||||
|
|
||||||
|
public abstract class DBObject<T extends DBObject> {
|
||||||
|
protected String alias;
|
||||||
|
protected final String expression;
|
||||||
|
|
||||||
|
protected DBObject(String expression){
|
||||||
|
this.expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T as(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasAlias() {
|
||||||
|
return alias != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
DBObject dbObject = (DBObject) o;
|
||||||
|
|
||||||
|
if (alias != null ? !alias.equals(dbObject.alias) : dbObject.alias != null) return false;
|
||||||
|
if (expression != null ? !expression.equals(dbObject.expression) : dbObject.expression != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = alias != null ? alias.hashCode() : 0;
|
||||||
|
result = 31 * result + (expression != null ? expression.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder(expression);
|
||||||
|
if (hasAlias()) {
|
||||||
|
sb.append(SPACE).append(AS).append(SPACE).append(alias);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
public class EqCriterion extends UnaryCriterion {
|
||||||
|
private final Object value;
|
||||||
|
|
||||||
|
EqCriterion(Field field, Object value) {
|
||||||
|
super(field, Operator.eq, value);
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.AND;
|
||||||
|
import static com.thoughtworks.sql.Constants.BETWEEN;
|
||||||
|
import static com.thoughtworks.sql.Constants.COMMA;
|
||||||
|
import static com.thoughtworks.sql.Constants.LEFT_PARENTHESIS;
|
||||||
|
import static com.thoughtworks.sql.Constants.RIGHT_PARENTHESIS;
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
|
||||||
|
public class Field extends DBObject<Field> {
|
||||||
|
|
||||||
|
protected Field(String expression) {
|
||||||
|
super(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Field field(String expression) {
|
||||||
|
return new Field(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion eq(Object value) {
|
||||||
|
return UnaryCriterion.eq(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion neq(Object value) {
|
||||||
|
return UnaryCriterion.neq(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion gt(Object value) {
|
||||||
|
return UnaryCriterion.gt(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion lt(final Object value) {
|
||||||
|
return UnaryCriterion.lt(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion isNull() {
|
||||||
|
return UnaryCriterion.isNull(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion isNotNull() {
|
||||||
|
return UnaryCriterion.isNotNull(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion between(final Object lower, final Object upper) {
|
||||||
|
final Field field = this;
|
||||||
|
return new Criterion(null) {
|
||||||
|
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(field).append(SPACE).append(BETWEEN).append(SPACE).append(lower).append(SPACE).append(AND)
|
||||||
|
.append(SPACE).append(upper);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion like(final String value) {
|
||||||
|
return UnaryCriterion.like(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> Criterion in(final T... value) {
|
||||||
|
final Field field = this;
|
||||||
|
return new Criterion(Operator.in) {
|
||||||
|
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(field).append(SPACE).append(Operator.in).append(SPACE).append(LEFT_PARENTHESIS);
|
||||||
|
for (T t : value) {
|
||||||
|
sb.append(t.toString()).append(COMMA);
|
||||||
|
}
|
||||||
|
sb.deleteCharAt(sb.length() - 1).append(RIGHT_PARENTHESIS);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion in(final Field expression, final Query query) {
|
||||||
|
final Field field = this;
|
||||||
|
return new Criterion(Operator.in) {
|
||||||
|
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(field).append(SPACE).append(Operator.in).append(SPACE).append(LEFT_PARENTHESIS).append(query)
|
||||||
|
.append(RIGHT_PARENTHESIS);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class GroupBy {
|
||||||
|
private List<Field> fields = new ArrayList<Field>();
|
||||||
|
|
||||||
|
public static GroupBy groupBy(Field field) {
|
||||||
|
GroupBy groupBy = new GroupBy();
|
||||||
|
groupBy.fields.add(field);
|
||||||
|
return groupBy;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
import static com.thoughtworks.sql.Constants.JOIN;
|
||||||
|
import static com.thoughtworks.sql.Constants.ON;
|
||||||
|
|
||||||
|
public class Join {
|
||||||
|
private final Table joinTable;
|
||||||
|
private final JoinType joinType;
|
||||||
|
private final Criterion[] criterions;
|
||||||
|
|
||||||
|
private Join(Table table, JoinType joinType, Criterion... criterions) {
|
||||||
|
joinTable = table;
|
||||||
|
this.joinType = joinType;
|
||||||
|
this.criterions = criterions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Join inner(Table expression, Criterion... criterions) {
|
||||||
|
return new Join(expression, JoinType.INNER, criterions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Join left(Table table, Criterion... criterions) {
|
||||||
|
return new Join(table, JoinType.LEFT, criterions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Join right(Table table, Criterion... criterions) {
|
||||||
|
return new Join(table, JoinType.RIGHT, criterions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Join out(Table table, Criterion... criterions) {
|
||||||
|
return new Join(table, JoinType.OUT, criterions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(joinType).append(SPACE).append(JOIN).append(SPACE).append(joinTable).append(SPACE).append(ON);
|
||||||
|
for (Criterion criterion : criterions) {
|
||||||
|
sb.append(SPACE).append(criterion);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
public enum JoinType {
|
||||||
|
INNER, LEFT, RIGHT, OUT
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class Operator {
|
||||||
|
|
||||||
|
private final String operator;
|
||||||
|
private static final Operator ZERO = new Operator("");
|
||||||
|
public static final Operator eq = new Operator("=");
|
||||||
|
public static final Operator neq = new Operator("<>");
|
||||||
|
public static final Operator isNull = new Operator("IS NULL");
|
||||||
|
public static final Operator isNotNull = new Operator("IS NOT NULL");
|
||||||
|
public static final Operator gt = new Operator(">");
|
||||||
|
public static final Operator lt = new Operator("<");
|
||||||
|
public static final Operator gte = new Operator(">=");
|
||||||
|
public static final Operator lte = new Operator("<=");
|
||||||
|
public static final Operator and = new Operator("AND");
|
||||||
|
public static final Operator or = new Operator("OR");
|
||||||
|
public static final Operator not = new Operator("NOT");
|
||||||
|
public static final Operator exists = new Operator("EXISTS");
|
||||||
|
public static final Operator like = new Operator("LIKE");
|
||||||
|
public static final Operator in = new Operator("IN");
|
||||||
|
|
||||||
|
private static final Map<Operator, Operator> contraryRegistry = new HashMap<Operator, Operator>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
contraryRegistry.put(eq, neq);
|
||||||
|
contraryRegistry.put(neq, eq);
|
||||||
|
contraryRegistry.put(isNull, isNotNull);
|
||||||
|
contraryRegistry.put(isNotNull, isNull);
|
||||||
|
contraryRegistry.put(gt, lte);
|
||||||
|
contraryRegistry.put(lte, gt);
|
||||||
|
contraryRegistry.put(lt, gte);
|
||||||
|
contraryRegistry.put(gte, lt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Operator(String operator) {
|
||||||
|
this.operator = operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operator getContrary() {
|
||||||
|
if(!contraryRegistry.containsKey(this)){
|
||||||
|
Operator opposite = new Operator(not.toString() + SPACE + this.toString());
|
||||||
|
contraryRegistry.put(this, opposite);
|
||||||
|
contraryRegistry.put(opposite, this);
|
||||||
|
}
|
||||||
|
return contraryRegistry.get(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.operator.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
|
||||||
|
public class Order {
|
||||||
|
private final Field expression;
|
||||||
|
private final OrderType orderType;
|
||||||
|
|
||||||
|
private Order(Field expression) {
|
||||||
|
this(expression, OrderType.ASC);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Order(Field expression, OrderType orderType) {
|
||||||
|
this.expression = expression;
|
||||||
|
this.orderType = orderType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Order asc(Field expression) {
|
||||||
|
return new Order(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Order desc(Field expression) {
|
||||||
|
return new Order(expression, OrderType.DESC);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return expression + SPACE + orderType;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
public enum OrderType {
|
||||||
|
DESC, ASC
|
||||||
|
}
|
@ -0,0 +1,153 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.*;
|
||||||
|
import static com.thoughtworks.sql.Table.table;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Query {
|
||||||
|
|
||||||
|
private Table table;
|
||||||
|
private List<Criterion> criterions = new ArrayList<Criterion>();
|
||||||
|
private List<Field> fields = new ArrayList<Field>();
|
||||||
|
private List<Join> joins = new ArrayList<Join>();
|
||||||
|
private List<Field> groupBies = new ArrayList<Field>();
|
||||||
|
private List<Order> orders = new ArrayList<Order>();
|
||||||
|
private List<Criterion> havings = new ArrayList<Criterion>();
|
||||||
|
|
||||||
|
private Query(Field... fields) {
|
||||||
|
this.fields.addAll(asList(fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Query select(Field... fields) {
|
||||||
|
return new Query(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query from(Table table) {
|
||||||
|
this.table = table;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query join(Join... join) {
|
||||||
|
joins.addAll(asList(join));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query where(Criterion criterion) {
|
||||||
|
criterions.add(criterion);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query groupBy(Field... groupBy) {
|
||||||
|
groupBies.addAll(asList(groupBy));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query orderBy(Order... order) {
|
||||||
|
orders.addAll(asList(order));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query appendSelectFields(Field... fields) {
|
||||||
|
this.fields.addAll(asList(fields));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return this == o || !(o == null || getClass() != o.getClass()) && this.toString().equals(o.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return toString().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sql = new StringBuilder();
|
||||||
|
visitSelectClause(sql);
|
||||||
|
visitFromClause(sql);
|
||||||
|
visitJoinClause(sql);
|
||||||
|
visitWhereClause(sql);
|
||||||
|
visitGroupByClause(sql);
|
||||||
|
visitOrderByClause(sql);
|
||||||
|
return sql.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitOrderByClause(StringBuilder sql) {
|
||||||
|
if (orders.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sql.append(ORDER_BY);
|
||||||
|
for (Order order : orders) {
|
||||||
|
sql.append(SPACE).append(order).append(COMMA);
|
||||||
|
}
|
||||||
|
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitGroupByClause(StringBuilder sql) {
|
||||||
|
if (groupBies.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sql.append(GROUP_BY);
|
||||||
|
for (Field groupBy : groupBies) {
|
||||||
|
sql.append(SPACE).append(groupBy).append(COMMA);
|
||||||
|
}
|
||||||
|
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||||
|
if (havings.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sql.append("HAVING");
|
||||||
|
for (Criterion havingCriterion : havings) {
|
||||||
|
sql.append(SPACE).append(havingCriterion).append(COMMA);
|
||||||
|
}
|
||||||
|
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitWhereClause(StringBuilder sql) {
|
||||||
|
if (criterions.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sql.append(WHERE);
|
||||||
|
for (Criterion criterion : criterions) {
|
||||||
|
sql.append(SPACE).append(criterion).append(SPACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitJoinClause(StringBuilder sql) {
|
||||||
|
for (Join join : joins) {
|
||||||
|
sql.append(join).append(SPACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitFromClause(StringBuilder sql) {
|
||||||
|
if (table == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sql.append(FROM).append(SPACE).append(table).append(SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitSelectClause(StringBuilder sql) {
|
||||||
|
sql.append(SELECT).append(SPACE);
|
||||||
|
if (fields.isEmpty()) {
|
||||||
|
sql.append(ALL).append(SPACE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Field field : fields) {
|
||||||
|
sql.append(field).append(COMMA);
|
||||||
|
}
|
||||||
|
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Table as(String alias) {
|
||||||
|
return table(LEFT_PARENTHESIS + this.toString() + RIGHT_PARENTHESIS).as(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query having(Criterion criterion) {
|
||||||
|
this.havings.add(criterion);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
public class Table extends DBObject<Table> {
|
||||||
|
|
||||||
|
protected Table(String expression) {
|
||||||
|
super(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Table table(String table) {
|
||||||
|
return new Table(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field field(String fieldName) {
|
||||||
|
if (hasAlias()) {
|
||||||
|
return Field.field(alias + "." + fieldName);
|
||||||
|
}
|
||||||
|
return Field.field(expression+"."+fieldName);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
|
||||||
|
public class UnaryCriterion extends Criterion {
|
||||||
|
protected final Field expression;
|
||||||
|
protected final Object value;
|
||||||
|
|
||||||
|
UnaryCriterion(Field expression, Operator operator, Object value) {
|
||||||
|
super(operator);
|
||||||
|
this.expression = expression;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
beforePopulateOperator(sb);
|
||||||
|
populateOperator(sb);
|
||||||
|
afterPopulateOperator(sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion eq(Field expression, Object value) {
|
||||||
|
return new UnaryCriterion(expression, Operator.eq, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void beforePopulateOperator(StringBuilder sb) {
|
||||||
|
sb.append(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void populateOperator(StringBuilder sb) {
|
||||||
|
sb.append(operator);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void afterPopulateOperator(StringBuilder sb) {
|
||||||
|
sb.append(value == null ? "" : value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion neq(Field field, Object value) {
|
||||||
|
return new UnaryCriterion(field, Operator.neq, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion gt(Field field, Object value) {
|
||||||
|
return new UnaryCriterion(field, Operator.gt, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion lt(Field field, Object value) {
|
||||||
|
return new UnaryCriterion(field, Operator.lt, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion isNull(Field field) {
|
||||||
|
return new UnaryCriterion(field, Operator.isNull, null) {
|
||||||
|
@Override
|
||||||
|
protected void populateOperator(StringBuilder sb) {
|
||||||
|
sb.append(SPACE).append(operator);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion isNotNull(Field field) {
|
||||||
|
return new UnaryCriterion(field, Operator.isNotNull, null) {
|
||||||
|
@Override
|
||||||
|
protected void populateOperator(StringBuilder sb) {
|
||||||
|
sb.append(SPACE).append(operator);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion like(Field field, String value) {
|
||||||
|
return new UnaryCriterion(field, Operator.like, value) {
|
||||||
|
@Override
|
||||||
|
protected void populateOperator(StringBuilder sb) {
|
||||||
|
sb.append(SPACE).append(operator).append(SPACE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
public class Constants {
|
||||||
|
static final String SELECT = "SELECT";
|
||||||
|
static final String SPACE = " ";
|
||||||
|
static final String AS = "AS";
|
||||||
|
static final String COMMA = ",";
|
||||||
|
static final String FROM = "FROM";
|
||||||
|
static final String ON = "ON";
|
||||||
|
static final String JOIN = "JOIN";
|
||||||
|
static final String ALL = "*";
|
||||||
|
static final String LEFT_PARENTHESIS = "(";
|
||||||
|
static final String RIGHT_PARENTHESIS = ")";
|
||||||
|
static final String AND = "AND";
|
||||||
|
static final String BETWEEN = "BETWEEN";
|
||||||
|
static final String LIKE = "LIKE";
|
||||||
|
static final String OR = "OR";
|
||||||
|
static final String ORDER_BY = "ORDER BY";
|
||||||
|
static final String GROUP_BY = "GROUP BY";
|
||||||
|
static final String WHERE = "WHERE";
|
||||||
|
public static final String EXISTS = "EXISTS";
|
||||||
|
public static final String NOT = "NOT";
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.AND;
|
||||||
|
import static com.thoughtworks.sql.Constants.EXISTS;
|
||||||
|
import static com.thoughtworks.sql.Constants.LEFT_PARENTHESIS;
|
||||||
|
import static com.thoughtworks.sql.Constants.NOT;
|
||||||
|
import static com.thoughtworks.sql.Constants.OR;
|
||||||
|
import static com.thoughtworks.sql.Constants.RIGHT_PARENTHESIS;
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
|
||||||
|
public abstract class Criterion {
|
||||||
|
protected final Operator operator;
|
||||||
|
|
||||||
|
Criterion(Operator operator) {
|
||||||
|
this.operator = operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion and(final Criterion criterion, final Criterion... criterions) {
|
||||||
|
return new Criterion(Operator.and) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(criterion);
|
||||||
|
for (Criterion c : criterions) {
|
||||||
|
sb.append(SPACE).append(AND).append(SPACE).append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion or(final Criterion criterion, final Criterion... criterions) {
|
||||||
|
return new Criterion(Operator.or) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(criterion);
|
||||||
|
for (Criterion c : criterions) {
|
||||||
|
sb.append(SPACE).append(OR).append(SPACE).append(c.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion exists(final Query query) {
|
||||||
|
return new Criterion(Operator.exists) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(EXISTS).append(SPACE).append(LEFT_PARENTHESIS).append(query).append(RIGHT_PARENTHESIS);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion not(final Criterion criterion) {
|
||||||
|
return new Criterion(Operator.not) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(NOT).append(SPACE);
|
||||||
|
criterion.populate(sb);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void populate(StringBuilder sb);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder builder = new StringBuilder(LEFT_PARENTHESIS);
|
||||||
|
populate(builder);
|
||||||
|
builder.append(RIGHT_PARENTHESIS);
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.AS;
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
|
||||||
|
public abstract class DBObject<T extends DBObject<?>> {
|
||||||
|
protected String alias;
|
||||||
|
protected final String expression;
|
||||||
|
|
||||||
|
protected DBObject(String expression){
|
||||||
|
this.expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T as(String newAlias) {
|
||||||
|
this.alias = newAlias;
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasAlias() {
|
||||||
|
return alias != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
DBObject dbObject = (DBObject) o;
|
||||||
|
|
||||||
|
if (alias != null ? !alias.equals(dbObject.alias) : dbObject.alias != null) return false;
|
||||||
|
if (expression != null ? !expression.equals(dbObject.expression) : dbObject.expression != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = alias != null ? alias.hashCode() : 0;
|
||||||
|
result = 31 * result + (expression != null ? expression.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder(expression);
|
||||||
|
if (hasAlias()) {
|
||||||
|
sb.append(SPACE).append(AS).append(SPACE).append(alias);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
public class EqCriterion extends UnaryCriterion {
|
||||||
|
EqCriterion(Field field, Object value) {
|
||||||
|
super(field, Operator.eq, value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.AND;
|
||||||
|
import static com.thoughtworks.sql.Constants.BETWEEN;
|
||||||
|
import static com.thoughtworks.sql.Constants.COMMA;
|
||||||
|
import static com.thoughtworks.sql.Constants.LEFT_PARENTHESIS;
|
||||||
|
import static com.thoughtworks.sql.Constants.RIGHT_PARENTHESIS;
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
|
||||||
|
public class Field extends DBObject<Field> {
|
||||||
|
|
||||||
|
protected Field(String expression) {
|
||||||
|
super(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Field field(String expression) {
|
||||||
|
return new Field(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion eq(Object value) {
|
||||||
|
return UnaryCriterion.eq(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion neq(Object value) {
|
||||||
|
return UnaryCriterion.neq(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion gt(Object value) {
|
||||||
|
return UnaryCriterion.gt(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion lt(final Object value) {
|
||||||
|
return UnaryCriterion.lt(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion isNull() {
|
||||||
|
return UnaryCriterion.isNull(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion isNotNull() {
|
||||||
|
return UnaryCriterion.isNotNull(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion between(final Object lower, final Object upper) {
|
||||||
|
final Field field = this;
|
||||||
|
return new Criterion(null) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(field).append(SPACE).append(BETWEEN).append(SPACE).append(lower).append(SPACE).append(AND)
|
||||||
|
.append(SPACE).append(upper);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion like(final String value) {
|
||||||
|
return UnaryCriterion.like(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> Criterion in(final T... value) {
|
||||||
|
final Field field = this;
|
||||||
|
return new Criterion(Operator.in) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(field).append(SPACE).append(Operator.in).append(SPACE).append(LEFT_PARENTHESIS);
|
||||||
|
for (T t : value) {
|
||||||
|
sb.append(t.toString()).append(COMMA);
|
||||||
|
}
|
||||||
|
sb.deleteCharAt(sb.length() - 1).append(RIGHT_PARENTHESIS);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criterion in(final Query query) {
|
||||||
|
final Field field = this;
|
||||||
|
return new Criterion(Operator.in) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
sb.append(field).append(SPACE).append(Operator.in).append(SPACE).append(LEFT_PARENTHESIS).append(query)
|
||||||
|
.append(RIGHT_PARENTHESIS);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class GroupBy {
|
||||||
|
private List<Field> fields = new ArrayList<Field>();
|
||||||
|
|
||||||
|
public static GroupBy groupBy(Field field) {
|
||||||
|
GroupBy groupBy = new GroupBy();
|
||||||
|
groupBy.fields.add(field);
|
||||||
|
return groupBy;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
import static com.thoughtworks.sql.Constants.JOIN;
|
||||||
|
import static com.thoughtworks.sql.Constants.ON;
|
||||||
|
|
||||||
|
public class Join {
|
||||||
|
private final Table joinTable;
|
||||||
|
private final JoinType joinType;
|
||||||
|
private final Criterion[] criterions;
|
||||||
|
|
||||||
|
private Join(Table table, JoinType joinType, Criterion... criterions) {
|
||||||
|
joinTable = table;
|
||||||
|
this.joinType = joinType;
|
||||||
|
this.criterions = criterions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Join inner(Table expression, Criterion... criterions) {
|
||||||
|
return new Join(expression, JoinType.INNER, criterions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Join left(Table table, Criterion... criterions) {
|
||||||
|
return new Join(table, JoinType.LEFT, criterions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Join right(Table table, Criterion... criterions) {
|
||||||
|
return new Join(table, JoinType.RIGHT, criterions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Join out(Table table, Criterion... criterions) {
|
||||||
|
return new Join(table, JoinType.OUT, criterions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(joinType).append(SPACE).append(JOIN).append(SPACE).append(joinTable).append(SPACE).append(ON);
|
||||||
|
for (Criterion criterion : criterions) {
|
||||||
|
sb.append(SPACE).append(criterion);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
public enum JoinType {
|
||||||
|
INNER, LEFT, RIGHT, OUT
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
public final class Operator {
|
||||||
|
|
||||||
|
private final String operator;
|
||||||
|
public static final Operator eq = new Operator("=");
|
||||||
|
public static final Operator neq = new Operator("<>");
|
||||||
|
public static final Operator isNull = new Operator("IS NULL");
|
||||||
|
public static final Operator isNotNull = new Operator("IS NOT NULL");
|
||||||
|
public static final Operator gt = new Operator(">");
|
||||||
|
public static final Operator lt = new Operator("<");
|
||||||
|
public static final Operator gte = new Operator(">=");
|
||||||
|
public static final Operator lte = new Operator("<=");
|
||||||
|
public static final Operator and = new Operator("AND");
|
||||||
|
public static final Operator or = new Operator("OR");
|
||||||
|
public static final Operator not = new Operator("NOT");
|
||||||
|
public static final Operator exists = new Operator("EXISTS");
|
||||||
|
public static final Operator like = new Operator("LIKE");
|
||||||
|
public static final Operator in = new Operator("IN");
|
||||||
|
|
||||||
|
private static final Map<Operator, Operator> contraryRegistry = new HashMap<Operator, Operator>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
contraryRegistry.put(eq, neq);
|
||||||
|
contraryRegistry.put(neq, eq);
|
||||||
|
contraryRegistry.put(isNull, isNotNull);
|
||||||
|
contraryRegistry.put(isNotNull, isNull);
|
||||||
|
contraryRegistry.put(gt, lte);
|
||||||
|
contraryRegistry.put(lte, gt);
|
||||||
|
contraryRegistry.put(lt, gte);
|
||||||
|
contraryRegistry.put(gte, lt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Operator(String operator) {
|
||||||
|
this.operator = operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operator getContrary() {
|
||||||
|
if(!contraryRegistry.containsKey(this)){
|
||||||
|
Operator opposite = new Operator(not.toString() + SPACE + this.toString());
|
||||||
|
contraryRegistry.put(this, opposite);
|
||||||
|
contraryRegistry.put(opposite, this);
|
||||||
|
}
|
||||||
|
return contraryRegistry.get(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.operator.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
|
||||||
|
public class Order {
|
||||||
|
private final Field expression;
|
||||||
|
private final OrderType orderType;
|
||||||
|
|
||||||
|
private Order(Field expression) {
|
||||||
|
this(expression, OrderType.ASC);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Order(Field expression, OrderType orderType) {
|
||||||
|
this.expression = expression;
|
||||||
|
this.orderType = orderType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Order asc(Field expression) {
|
||||||
|
return new Order(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Order desc(Field expression) {
|
||||||
|
return new Order(expression, OrderType.DESC);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return expression + SPACE + orderType;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
public enum OrderType {
|
||||||
|
DESC, ASC
|
||||||
|
}
|
@ -0,0 +1,163 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.ALL;
|
||||||
|
import static com.thoughtworks.sql.Constants.COMMA;
|
||||||
|
import static com.thoughtworks.sql.Constants.FROM;
|
||||||
|
import static com.thoughtworks.sql.Constants.GROUP_BY;
|
||||||
|
import static com.thoughtworks.sql.Constants.LEFT_PARENTHESIS;
|
||||||
|
import static com.thoughtworks.sql.Constants.ORDER_BY;
|
||||||
|
import static com.thoughtworks.sql.Constants.RIGHT_PARENTHESIS;
|
||||||
|
import static com.thoughtworks.sql.Constants.SELECT;
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
import static com.thoughtworks.sql.Constants.WHERE;
|
||||||
|
import static com.thoughtworks.sql.Table.table;
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Query {
|
||||||
|
|
||||||
|
private Table table;
|
||||||
|
private List<Criterion> criterions = new ArrayList<Criterion>();
|
||||||
|
private List<Field> fields = new ArrayList<Field>();
|
||||||
|
private List<Join> joins = new ArrayList<Join>();
|
||||||
|
private List<Field> groupBies = new ArrayList<Field>();
|
||||||
|
private List<Order> orders = new ArrayList<Order>();
|
||||||
|
private List<Criterion> havings = new ArrayList<Criterion>();
|
||||||
|
|
||||||
|
private Query(Field... fields) {
|
||||||
|
this.fields.addAll(asList(fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Query select(Field... fields) {
|
||||||
|
return new Query(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query from(Table fromTable) {
|
||||||
|
this.table = fromTable;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query join(Join... join) {
|
||||||
|
joins.addAll(asList(join));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query where(Criterion criterion) {
|
||||||
|
criterions.add(criterion);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query groupBy(Field... groupBy) {
|
||||||
|
groupBies.addAll(asList(groupBy));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query orderBy(Order... order) {
|
||||||
|
orders.addAll(asList(order));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query appendSelectFields(Field... selectFields) {
|
||||||
|
this.fields.addAll(asList(selectFields));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return this == o || !(o == null || getClass() != o.getClass()) && this.toString().equals(o.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return toString().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sql = new StringBuilder();
|
||||||
|
visitSelectClause(sql);
|
||||||
|
visitFromClause(sql);
|
||||||
|
visitJoinClause(sql);
|
||||||
|
visitWhereClause(sql);
|
||||||
|
visitGroupByClause(sql);
|
||||||
|
visitOrderByClause(sql);
|
||||||
|
return sql.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitOrderByClause(StringBuilder sql) {
|
||||||
|
if (orders.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sql.append(ORDER_BY);
|
||||||
|
for (Order order : orders) {
|
||||||
|
sql.append(SPACE).append(order).append(COMMA);
|
||||||
|
}
|
||||||
|
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
private void visitGroupByClause(StringBuilder sql) {
|
||||||
|
if (groupBies.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sql.append(GROUP_BY);
|
||||||
|
for (Field groupBy : groupBies) {
|
||||||
|
sql.append(SPACE).append(groupBy).append(COMMA);
|
||||||
|
}
|
||||||
|
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||||
|
if (havings.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sql.append("HAVING");
|
||||||
|
for (Criterion havingCriterion : havings) {
|
||||||
|
sql.append(SPACE).append(havingCriterion).append(COMMA);
|
||||||
|
}
|
||||||
|
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitWhereClause(StringBuilder sql) {
|
||||||
|
if (criterions.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sql.append(WHERE);
|
||||||
|
for (Criterion criterion : criterions) {
|
||||||
|
sql.append(SPACE).append(criterion).append(SPACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitJoinClause(StringBuilder sql) {
|
||||||
|
for (Join join : joins) {
|
||||||
|
sql.append(join).append(SPACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitFromClause(StringBuilder sql) {
|
||||||
|
if (table == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sql.append(FROM).append(SPACE).append(table).append(SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitSelectClause(StringBuilder sql) {
|
||||||
|
sql.append(SELECT).append(SPACE);
|
||||||
|
if (fields.isEmpty()) {
|
||||||
|
sql.append(ALL).append(SPACE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Field field : fields) {
|
||||||
|
sql.append(field).append(COMMA);
|
||||||
|
}
|
||||||
|
sql.deleteCharAt(sql.length() - 1).append(SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Table as(String alias) {
|
||||||
|
return table(LEFT_PARENTHESIS + this.toString() + RIGHT_PARENTHESIS).as(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query having(Criterion criterion) {
|
||||||
|
this.havings.add(criterion);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
public class Table extends DBObject<Table> {
|
||||||
|
|
||||||
|
protected Table(String expression) {
|
||||||
|
super(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Table table(String table) {
|
||||||
|
return new Table(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
public Field field(String fieldName) {
|
||||||
|
if (hasAlias()) {
|
||||||
|
return Field.field(alias + "." + fieldName);
|
||||||
|
}
|
||||||
|
return Field.field(expression+"."+fieldName);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package com.thoughtworks.sql;
|
||||||
|
|
||||||
|
import static com.thoughtworks.sql.Constants.SPACE;
|
||||||
|
|
||||||
|
public class UnaryCriterion extends Criterion {
|
||||||
|
protected final Field expression;
|
||||||
|
protected final Object value;
|
||||||
|
|
||||||
|
UnaryCriterion(Field expression, Operator operator, Object value) {
|
||||||
|
super(operator);
|
||||||
|
this.expression = expression;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void populate(StringBuilder sb) {
|
||||||
|
beforePopulateOperator(sb);
|
||||||
|
populateOperator(sb);
|
||||||
|
afterPopulateOperator(sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion eq(Field expression, Object value) {
|
||||||
|
return new UnaryCriterion(expression, Operator.eq, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void beforePopulateOperator(StringBuilder sb) {
|
||||||
|
sb.append(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void populateOperator(StringBuilder sb) {
|
||||||
|
sb.append(operator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
protected void afterPopulateOperator(StringBuilder sb) {
|
||||||
|
sb.append(value == null ? "" : value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion neq(Field field, Object value) {
|
||||||
|
return new UnaryCriterion(field, Operator.neq, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion gt(Field field, Object value) {
|
||||||
|
return new UnaryCriterion(field, Operator.gt, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion lt(Field field, Object value) {
|
||||||
|
return new UnaryCriterion(field, Operator.lt, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion isNull(Field field) {
|
||||||
|
return new UnaryCriterion(field, Operator.isNull, null) {
|
||||||
|
@Override
|
||||||
|
protected void populateOperator(StringBuilder sb) {
|
||||||
|
sb.append(SPACE).append(operator);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion isNotNull(Field field) {
|
||||||
|
return new UnaryCriterion(field, Operator.isNotNull, null) {
|
||||||
|
@Override
|
||||||
|
protected void populateOperator(StringBuilder sb) {
|
||||||
|
sb.append(SPACE).append(operator);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Criterion like(Field field, String value) {
|
||||||
|
return new UnaryCriterion(field, Operator.like, value) {
|
||||||
|
@Override
|
||||||
|
protected void populateOperator(StringBuilder sb) {
|
||||||
|
sb.append(SPACE).append(operator).append(SPACE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue