+ * The constructor can convert a JSON text into a Java object. The + * {@code}toString{/code} method converts to JSON text. + *
+ * A {@code}get{/code} method returns a value if one can be found, and throws an + * exception if one cannot be found. An {@code}opt{/code} method returns a + * default value instead of throwing an exception, and so is useful for + * obtaining optional values. + *
+ * The generic {@code}get(){/code} and {@code}opt(){/code} methods return an + * object which you can cast or query for type. There are also typed + * {@code}get{/code} and {@code}opt{/code} methods that do type checking and type + * coercion for you. + *
+ * The texts produced by the {@code}toString{/code} methods strictly conform to + * JSON syntax rules. The constructors are more forgiving in the texts they will + * accept: + *
+ * Warning: This method assumes that the data structure is acyclical. + * + * @return a printable, displayable, transmittable + * representation of the array. + */ + public String toString() { + try { + return '[' + join(",") + ']'; + } catch (Exception e) { + return null; + } + } + + + /** + * Make a prettyprinted JSON text of this JSONArray. + * Warning: This method assumes that the data structure is acyclical. + * + * @param indentFactor The number of spaces to add to each level of + * indentation. + * @return a printable, displayable, transmittable + * representation of the object, beginning + * with {@code}[{/code} (left bracket) and ending + * with {@code}]{/code} (right bracket). + * @throws JSONException when failed to stringify + */ + public String toString(int indentFactor) throws JSONException { + return toString(indentFactor, 0); + } + + + /** + * Make a prettyprinted JSON text of this JSONArray. + * Warning: This method assumes that the data structure is acyclical. + * + * @param indentFactor The number of spaces to add to each level of + * indentation. + * @param indent The indention of the top level. + * @return a printable, displayable, transmittable + * representation of the array. + * @throws JSONException when failed to stringify + */ + String toString(int indentFactor, int indent) throws JSONException { + int len = length(); + if (len == 0) { + return "[]"; + } + int i; + StringBuilder sb = new StringBuilder("["); + if (len == 1) { + sb.append(JSONObject.valueToString(this.myArrayList.get(0), + indentFactor, indent)); + } else { + int newindent = indent + indentFactor; + sb.append('\n'); + for (i = 0; i < len; i += 1) { + if (i > 0) { + sb.append(",\n"); + } + for (int j = 0; j < newindent; j += 1) { + sb.append(' '); + } + sb.append(JSONObject.valueToString(this.myArrayList.get(i), + indentFactor, newindent)); + } + sb.append('\n'); + for (i = 0; i < indent; i += 1) { + sb.append(' '); + } + } + sb.append(']'); + return sb.toString(); + } + + + /** + * Write the contents of the JSONArray as JSON text to a writer. + * For compactness, no whitespace is added. + *
+ * Warning: This method assumes that the data structure is acyclical. + * + * @param writer writer + * @return The writer. + * @throws JSONException when failed to write the content + */ + public Writer write(Writer writer) throws JSONException { + try { + boolean b = false; + int len = length(); + + writer.write('['); + + for (int i = 0; i < len; i += 1) { + if (b) { + writer.write(','); + } + Object v = this.myArrayList.get(i); + if (v instanceof JSONObject) { + ((JSONObject) v).write(writer); + } else if (v instanceof JSONArray) { + ((JSONArray) v).write(writer); + } else { + writer.write(JSONObject.valueToString(v)); + } + b = true; + } + writer.write(']'); + return writer; + } catch (IOException e) { + throw new JSONException(e); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/github/langsdorf/blackbird/json/JSONException.java b/src/main/java/com/github/langsdorf/blackbird/json/JSONException.java new file mode 100644 index 0000000..766561c --- /dev/null +++ b/src/main/java/com/github/langsdorf/blackbird/json/JSONException.java @@ -0,0 +1,31 @@ +package com.github.langsdorf.blackbird.json; + +/** + * The JSONException is thrown by the JSON.org classes when things are amiss. + * + * @author JSON.org + * @version 2010-12-24 + */ +public class JSONException extends Exception { + private static final long serialVersionUID = -4144585377907783745L; + private Throwable cause; + + /** + * Constructs a JSONException with an explanatory message. + * + * @param message Detail about the reason for the exception. + */ + public JSONException(String message) { + super(message); + } + + public JSONException(Throwable cause) { + super(cause.getMessage()); + this.cause = cause; + } + + @Override + public Throwable getCause() { + return this.cause; + } +} diff --git a/src/main/java/com/github/langsdorf/blackbird/json/JSONObject.java b/src/main/java/com/github/langsdorf/blackbird/json/JSONObject.java new file mode 100644 index 0000000..a71c5e2 --- /dev/null +++ b/src/main/java/com/github/langsdorf/blackbird/json/JSONObject.java @@ -0,0 +1,1245 @@ +package com.github.langsdorf.blackbird.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.io.IOException; +import java.io.Writer; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; + +/** + * A JSONObject is an unordered collection of name/value pairs. Its + * external form is a string wrapped in curly braces with colons between the + * names and values, and commas between the values and names. The internal form + * is an object having {@code}get{/code} and {@code}opt{/code} methods for + * accessing the values by name, and {@code}put{/code} methods for adding or + * replacing values by name. The values can be any of these types: + * {@code}Boolean{/code}, {@code}JSONArray{/code}, {@code}JSONObject{/code}, + * {@code}Number{/code}, {@code}String{/code}, or the {@code}JSONObject.NULL{/code} + * object. A JSONObject constructor can be used to convert an external form + * JSON text into an internal form whose values can be retrieved with the + * {@code}get{/code} and {@code}opt{/code} methods, or to convert values into a + * JSON text using the {@code}put{/code} and {@code}toString{/code} methods. + * A {@code}get{/code} method returns a value if one can be found, and throws an + * exception if one cannot be found. An {@code}opt{/code} method returns a + * default value instead of throwing an exception, and so is useful for + * obtaining optional values. + *
+ * The generic {@code}get(){/code} and {@code}opt(){/code} methods return an + * object, which you can cast or query for type. There are also typed + * {@code}get{/code} and {@code}opt{/code} methods that do type checking and type + * coercion for you. The opt methods differ from the get methods in that they + * do not throw. Instead, they return a specified value, such as null. + *
+ * The {@code}put{/code} methods add or replace values in an object. For example, + *
myString = new JSONObject().put("JSON", "Hello, World!").toString();+ * produces the string {@code}{"JSON": "Hello, World"}{/code}. + *
+ * The texts produced by the {@code}toString{/code} methods strictly conform to + * the JSON syntax rules. + * The constructors are more forgiving in the texts they will accept: + *
+ * The key is formed by removing the {@code}"get"{/code} or {@code}"is"{/code} prefix. + * If the second remaining character is not upper case, then the first + * character is converted to lower case. + *
+ * For example, if an object has a method named {@code}"getName"{/code}, and
+ * if the result of calling {@code}object.getName(){/code} is {@code}"Larry Fine"{/code},
+ * then the JSONObject will contain {@code}"name": "Larry Fine"{/code}.
+ *
+ * @param bean An object that has getter methods that should be used
+ * to make a JSONObject.
+ */
+ public JSONObject(Object bean) {
+ this();
+ populateMap(bean);
+ }
+
+
+ /**
+ * Construct a JSONObject from an Object, using reflection to find the
+ * public members. The resulting JSONObject's keys will be the strings
+ * from the names array, and the values will be the field values associated
+ * with those keys in the object. If a key is not found or not visible,
+ * then it will not be copied into the new JSONObject.
+ *
+ * @param object An object that has fields that should be used to make a
+ * JSONObject.
+ * @param names An array of strings, the names of the fields to be obtained
+ * from the object.
+ */
+ public JSONObject(Object object, String names[]) {
+ this();
+ Class c = object.getClass();
+ for (String name : names) {
+ try {
+ putOpt(name, c.getField(name).get(object));
+ } catch (Exception ignore) {
+ }
+ }
+ }
+
+
+ /**
+ * Construct a JSONObject from a source JSON text string.
+ * This is the most commonly used JSONObject constructor.
+ *
+ * @param source A string beginning
+ * with {@code}{{/code} (left brace) and ending
+ * with {@code}}{/code} (right brace).
+ * @throws JSONException If there is a syntax error in the source
+ * string or a duplicated key.
+ */
+ public JSONObject(String source) throws JSONException {
+ this(new JSONTokener(source));
+ }
+
+
+ /**
+ * Construct a JSONObject from a ResourceBundle.
+ *
+ * @param baseName The ResourceBundle base name.
+ * @param locale The Locale to load the ResourceBundle for.
+ * @throws JSONException If any JSONExceptions are detected.
+ */
+ public JSONObject(String baseName, Locale locale) throws JSONException {
+ this();
+ ResourceBundle r = ResourceBundle.getBundle(baseName, locale,
+ Thread.currentThread().getContextClassLoader());
+
+// Iterate through the keys in the bundle.
+
+ Enumeration
+ * Warning: This method assumes that the data structure is acyclical.
+ *
+ * @return a printable, displayable, portable, transmittable
+ * representation of the object, beginning
+ * with {@code}{{/code} (left brace) and ending
+ * with {@code}}{/code} (right brace).
+ */
+ public String toString() {
+ try {
+ Iterator keys = keys();
+ StringBuilder sb = new StringBuilder("{");
+
+ while (keys.hasNext()) {
+ if (sb.length() > 1) {
+ sb.append(',');
+ }
+ Object o = keys.next();
+ sb.append(quote(o.toString()));
+ sb.append(':');
+ sb.append(valueToString(this.map.get(o)));
+ }
+ sb.append('}');
+ return sb.toString();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+
+ /**
+ * Make a prettyprinted JSON text of this JSONObject.
+ *
+ * Warning: This method assumes that the data structure is acyclical.
+ *
+ * @param indentFactor The number of spaces to add to each level of
+ * indentation.
+ * @return a printable, displayable, portable, transmittable
+ * representation of the object, beginning
+ * with {@code}{{/code} (left brace) and ending
+ * with {@code}}{/code} (right brace).
+ * @throws JSONException If the object contains an invalid number.
+ */
+ public String toString(int indentFactor) throws JSONException {
+ return toString(indentFactor, 0);
+ }
+
+
+ /**
+ * Make a prettyprinted JSON text of this JSONObject.
+ *
+ * Warning: This method assumes that the data structure is acyclical.
+ *
+ * @param indentFactor The number of spaces to add to each level of
+ * indentation.
+ * @param indent The indentation of the top level.
+ * @return a printable, displayable, transmittable
+ * representation of the object, beginning
+ * with {@code}{{/code} (left brace) and ending
+ * with {@code}}{/code} (right brace).
+ * @throws JSONException If the object contains an invalid number.
+ */
+ String toString(int indentFactor, int indent) throws JSONException {
+ int i;
+ int length = this.length();
+ if (length == 0) {
+ return "{}";
+ }
+ Iterator keys = sortedKeys();
+ int newindent = indent + indentFactor;
+ Object object;
+ StringBuilder sb = new StringBuilder("{");
+ if (length == 1) {
+ object = keys.next();
+ sb.append(quote(object.toString()));
+ sb.append(": ");
+ sb.append(valueToString(this.map.get(object), indentFactor,
+ indent));
+ } else {
+ while (keys.hasNext()) {
+ object = keys.next();
+ if (sb.length() > 1) {
+ sb.append(",\n");
+ } else {
+ sb.append('\n');
+ }
+ for (i = 0; i < newindent; i += 1) {
+ sb.append(' ');
+ }
+ sb.append(quote(object.toString()));
+ sb.append(": ");
+ sb.append(valueToString(this.map.get(object), indentFactor,
+ newindent));
+ }
+ if (sb.length() > 1) {
+ sb.append('\n');
+ for (i = 0; i < indent; i += 1) {
+ sb.append(' ');
+ }
+ }
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+
+
+ /**
+ * Make a JSON text of an Object value. If the object has an
+ * value.toJSONString() method, then that method will be used to produce
+ * the JSON text. The method is required to produce a strictly
+ * conforming text. If the object does not contain a toJSONString
+ * method (which is the most common case), then a text will be
+ * produced by other means. If the value is an array or Collection,
+ * then a JSONArray will be made from it and its toJSONString method
+ * will be called. If the value is a MAP, then a JSONObject will be made
+ * from it and its toJSONString method will be called. Otherwise, the
+ * value's toString method will be called, and the result will be quoted.
+ *
+ * Warning: This method assumes that the data structure is acyclical.
+ *
+ * @param value The value to be serialized.
+ * @return a printable, displayable, transmittable
+ * representation of the object, beginning
+ * with {@code}{{/code} (left brace) and ending
+ * with {@code}}{/code} (right brace).
+ * @throws JSONException If the value is or contains an invalid number.
+ */
+ public static String valueToString(Object value) throws JSONException {
+ if (value == null || value.equals(null)) {
+ return "null";
+ }
+ if (value instanceof Number) {
+ return numberToString((Number) value);
+ }
+ if (value instanceof Boolean || value instanceof JSONObject ||
+ value instanceof JSONArray) {
+ return value.toString();
+ }
+ if (value instanceof Map) {
+ return new JSONObject((Map) value).toString();
+ }
+ if (value instanceof Collection) {
+ return new JSONArray((Collection) value).toString();
+ }
+ if (value.getClass().isArray()) {
+ return new JSONArray(value).toString();
+ }
+ return quote(value.toString());
+ }
+
+
+ /**
+ * Make a prettyprinted JSON text of an object value.
+ *
+ * Warning: This method assumes that the data structure is acyclical.
+ *
+ * @param value The value to be serialized.
+ * @param indentFactor The number of spaces to add to each level of
+ * indentation.
+ * @param indent The indentation of the top level.
+ * @return a printable, displayable, transmittable
+ * representation of the object, beginning
+ * with {@code}{{/code} (left brace) and ending
+ * with {@code}}{/code} (right brace).
+ * @throws JSONException If the object contains an invalid number.
+ */
+ static String valueToString(Object value, int indentFactor, int indent)
+ throws JSONException {
+ if (value == null || value.equals(null)) {
+ return "null";
+ }
+ if (value instanceof Number) {
+ return numberToString((Number) value);
+ }
+ if (value instanceof Boolean) {
+ return value.toString();
+ }
+ if (value instanceof JSONObject) {
+ return ((JSONObject) value).toString(indentFactor, indent);
+ }
+ if (value instanceof JSONArray) {
+ return ((JSONArray) value).toString(indentFactor, indent);
+ }
+ if (value instanceof Map) {
+ return new JSONObject((Map) value).toString(indentFactor, indent);
+ }
+ if (value instanceof Collection) {
+ return new JSONArray((Collection) value).toString(indentFactor, indent);
+ }
+ if (value.getClass().isArray()) {
+ return new JSONArray(value).toString(indentFactor, indent);
+ }
+ return quote(value.toString());
+ }
+
+
+ /**
+ * Wrap an object, if necessary. If the object is null, return the NULL
+ * object. If it is an array or collection, wrap it in a JSONArray. If
+ * it is a map, wrap it in a JSONObject. If it is a standard property
+ * (Double, String, et al) then it is already wrapped. Otherwise, if it
+ * comes from one of the java packages, turn it into a string. And if
+ * it doesn't, try to wrap it in a JSONObject. If the wrapping fails,
+ * then null is returned.
+ *
+ * @param object The object to wrap
+ * @return The wrapped value
+ */
+ public static Object wrap(Object object) {
+ try {
+ if (object == null) {
+ return NULL;
+ }
+ if (object instanceof JSONObject || object instanceof JSONArray ||
+ NULL.equals(object) ||
+ object instanceof Byte || object instanceof Character ||
+ object instanceof Short || object instanceof Integer ||
+ object instanceof Long || object instanceof Boolean ||
+ object instanceof Float || object instanceof Double ||
+ object instanceof String) {
+ return object;
+ }
+
+ if (object instanceof Collection) {
+ return new JSONArray((Collection) object);
+ }
+ if (object.getClass().isArray()) {
+ return new JSONArray(object);
+ }
+ if (object instanceof Map) {
+ return new JSONObject((Map) object);
+ }
+ Package objectPackage = object.getClass().getPackage();
+ String objectPackageName = (objectPackage != null ? objectPackage.getName() : "");
+ if (objectPackageName.startsWith("java.") ||
+ objectPackageName.startsWith("javax.") ||
+ object.getClass().getClassLoader() == null) {
+ return object.toString();
+ }
+ return new JSONObject(object);
+ } catch (Exception exception) {
+ return null;
+ }
+ }
+
+
+ public Writer write(Writer writer) throws JSONException {
+ try {
+ boolean commanate = false;
+ Iterator keys = keys();
+ writer.write('{');
+
+ while (keys.hasNext()) {
+ if (commanate) {
+ writer.write(',');
+ }
+ Object key = keys.next();
+ writer.write(quote(key.toString()));
+ writer.write(':');
+ Object value = this.map.get(key);
+ if (value instanceof JSONObject) {
+ ((JSONObject) value).write(writer);
+ } else if (value instanceof JSONArray) {
+ ((JSONArray) value).write(writer);
+ } else {
+ writer.write(valueToString(value));
+ }
+ commanate = true;
+ }
+ writer.write('}');
+ return writer;
+ } catch (IOException exception) {
+ throw new JSONException(exception);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/github/langsdorf/blackbird/json/JSONTokener.java b/src/main/java/com/github/langsdorf/blackbird/json/JSONTokener.java
new file mode 100644
index 0000000..58f134c
--- /dev/null
+++ b/src/main/java/com/github/langsdorf/blackbird/json/JSONTokener.java
@@ -0,0 +1,352 @@
+package com.github.langsdorf.blackbird.json;
+
+import java.io.*;
+
+/*
+Copyright (c) 2002 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+/**
+ * A JSONTokener takes a source string and extracts characters and tokens from
+ * it. It is used by the JSONObject and JSONArray constructors to parse
+ * JSON source strings.
+ *
+ * @author JSON.org
+ * @version 2010-12-24
+ */
+public class JSONTokener {
+
+ private int character;
+ private boolean eof;
+ private int index;
+ private int line;
+ private char previous;
+ private final Reader reader;
+ private boolean usePrevious;
+
+
+ /**
+ * Construct a JSONTokener from a Reader.
+ *
+ * @param reader A reader.
+ */
+ public JSONTokener(Reader reader) {
+ this.reader = reader.markSupported() ?
+ reader : new BufferedReader(reader);
+ this.eof = false;
+ this.usePrevious = false;
+ this.previous = 0;
+ this.index = 0;
+ this.character = 1;
+ this.line = 1;
+ }
+
+
+ /**
+ * Construct a JSONTokener from an InputStream.
+ * @param inputStream input stream
+ * @throws JSONException when failed to construct
+ */
+ public JSONTokener(InputStream inputStream) throws JSONException {
+ this(new InputStreamReader(inputStream));
+ }
+
+
+ /**
+ * Construct a JSONTokener from a string.
+ *
+ * @param s A source string.
+ */
+ public JSONTokener(String s) {
+ this(new StringReader(s));
+ }
+
+
+ /**
+ * Back up one character. This provides a sort of lookahead capability,
+ * so that you can test for a digit or letter before attempting to parse
+ * the next number or identifier.
+ * @throws JSONException when tried to back two steps
+ */
+ public void back() throws JSONException {
+ if (usePrevious || index <= 0) {
+ throw new JSONException("Stepping back two steps is not supported");
+ }
+ this.index -= 1;
+ this.character -= 1;
+ this.usePrevious = true;
+ this.eof = false;
+ }
+
+
+ public boolean end() {
+ return eof && !usePrevious;
+ }
+
+
+ /**
+ * Determine if the source string still contains characters that next()
+ * can consume.
+ *
+ * @return true if not yet at the end of the source.
+ * @throws JSONException when failed to determine
+ */
+ public boolean more() throws JSONException {
+ next();
+ if (end()) {
+ return false;
+ }
+ back();
+ return true;
+ }
+
+
+ /**
+ * Get the next character in the source string.
+ *
+ * @return The next character, or 0 if past the end of the source string.
+ * @throws JSONException when failed to read the next character from the reader
+ */
+ public char next() throws JSONException {
+ int c;
+ if (this.usePrevious) {
+ this.usePrevious = false;
+ c = this.previous;
+ } else {
+ try {
+ c = this.reader.read();
+ } catch (IOException exception) {
+ throw new JSONException(exception);
+ }
+
+ if (c <= 0) { // End of stream
+ this.eof = true;
+ c = 0;
+ }
+ }
+ this.index += 1;
+ if (this.previous == '\r') {
+ this.line += 1;
+ this.character = c == '\n' ? 0 : 1;
+ } else if (c == '\n') {
+ this.line += 1;
+ this.character = 0;
+ } else {
+ this.character += 1;
+ }
+ this.previous = (char) c;
+ return this.previous;
+ }
+
+
+ /**
+ * Consume the next character, and check that it matches a specified
+ * character.
+ *
+ * @param c The character to match.
+ * @return The character.
+ * @throws JSONException if the character does not match.
+ */
+ public char next(char c) throws JSONException {
+ char n = next();
+ if (n != c) {
+ throw syntaxError("Expected '" + c + "' and instead saw '" +
+ n + "'");
+ }
+ return n;
+ }
+
+
+ /**
+ * Get the next n characters.
+ *
+ * @param n The number of characters to take.
+ * @return A string of n characters.
+ * @throws JSONException Substring bounds error if there are not
+ * n characters remaining in the source string.
+ */
+ public String next(int n) throws JSONException {
+ if (n == 0) {
+ return "";
+ }
+
+ char[] chars = new char[n];
+ int pos = 0;
+
+ while (pos < n) {
+ chars[pos] = next();
+ if (end()) {
+ throw syntaxError("Substring bounds error");
+ }
+ pos += 1;
+ }
+ return new String(chars);
+ }
+
+
+ /**
+ * Get the next char in the string, skipping whitespace.
+ *
+ * @return A character, or 0 if there are no more characters.
+ * @throws JSONException when failed to read the content from the reader
+ */
+ public char nextClean() throws JSONException {
+ for (; ; ) {
+ char c = next();
+ if (c == 0 || c > ' ') {
+ return c;
+ }
+ }
+ }
+
+
+ /**
+ * Return the characters up to the next close quote character.
+ * Backslash processing is done. The formal JSON format does not
+ * allow strings in single quotes, but an implementation is allowed to
+ * accept them.
+ *
+ * @param quote The quoting character, either
+ * {@code "} (double quote) or
+ * {@code '} (single quote).
+ * @return A String.
+ * @throws JSONException Unterminated string.
+ */
+ public String nextString(char quote) throws JSONException {
+ char c;
+ StringBuilder sb = new StringBuilder();
+ for (; ; ) {
+ c = next();
+ switch (c) {
+ case 0:
+ case '\n':
+ case '\r':
+ throw syntaxError("Unterminated string");
+ case '\\':
+ c = next();
+ switch (c) {
+ case 'b':
+ sb.append('\b');
+ break;
+ case 't':
+ sb.append('\t');
+ break;
+ case 'n':
+ sb.append('\n');
+ break;
+ case 'f':
+ sb.append('\f');
+ break;
+ case 'r':
+ sb.append('\r');
+ break;
+ case 'u':
+ sb.append((char) Integer.parseInt(next(4), 16));
+ break;
+ case '"':
+ case '\'':
+ case '\\':
+ case '/':
+ sb.append(c);
+ break;
+ default:
+ throw syntaxError("Illegal escape.");
+ }
+ break;
+ default:
+ if (c == quote) {
+ return sb.toString();
+ }
+ sb.append(c);
+ }
+ }
+ }
+
+ /**
+ * Get the next value. The value can be a Boolean, Double, Integer,
+ * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
+ *
+ * @return An object.
+ * @throws JSONException If syntax error.
+ */
+ public Object nextValue() throws JSONException {
+ char c = nextClean();
+ String string;
+
+ switch (c) {
+ case '"':
+ case '\'':
+ return nextString(c);
+ case '{':
+ back();
+ return new JSONObject(this);
+ case '[':
+ back();
+ return new JSONArray(this);
+ }
+
+ /*
+ * Handle unquoted text. This could be the values true, false, or
+ * null, or it can be a number. An implementation (such as this one)
+ * is allowed to also accept non-standard forms.
+ *
+ * Accumulate characters until we reach the end of the text or a
+ * formatting character.
+ */
+
+ StringBuilder sb = new StringBuilder();
+ while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
+ sb.append(c);
+ c = next();
+ }
+ back();
+
+ string = sb.toString().trim();
+ if (string.equals("")) {
+ throw syntaxError("Missing value");
+ }
+ return JSONObject.stringToValue(string);
+ }
+
+
+ /**
+ * Make a JSONException to signal a syntax error.
+ *
+ * @param message The error message.
+ * @return A JSONException object, suitable for throwing
+ */
+ public JSONException syntaxError(String message) {
+ return new JSONException(message + toString());
+ }
+
+
+ /**
+ * Make a printable string of this JSONTokener.
+ *
+ * @return " at {index} [character {character} line {line}]"
+ */
+ public String toString() {
+ return " at " + index + " [character " + this.character + " line " +
+ this.line + "]";
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/github/langsdorf/blackbird/tweet/Tweet.java b/src/main/java/com/github/langsdorf/blackbird/tweet/Tweet.java
new file mode 100644
index 0000000..bd8a5cd
--- /dev/null
+++ b/src/main/java/com/github/langsdorf/blackbird/tweet/Tweet.java
@@ -0,0 +1,23 @@
+package com.github.langsdorf.blackbird.tweet;
+
+import com.github.langsdorf.blackbird.user.User;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class Tweet {
+
+ private long tweetId;
+ private String text;
+ private String createdAt;
+ private int retweetCount;
+ private int favoriteCount;
+ private User user;
+
+}
diff --git a/src/main/java/com/github/langsdorf/blackbird/tweet/TweetI.java b/src/main/java/com/github/langsdorf/blackbird/tweet/TweetI.java
new file mode 100644
index 0000000..b5d0fe3
--- /dev/null
+++ b/src/main/java/com/github/langsdorf/blackbird/tweet/TweetI.java
@@ -0,0 +1,190 @@
+package com.github.langsdorf.blackbird.tweet;
+
+import java.util.List;
+
+import com.github.langsdorf.blackbird.exception.TwitterException;
+import com.github.langsdorf.blackbird.user.list.BirdList;
+
+public interface TweetI {
+
+ /**
+ * Updates the authenticating user’s current status, also known as Tweeting.
+ *
+ * Publica um tweet.
+ *
+ * https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update
+ *
+ *
+ * https://api.twitter.com/1.1/statuses/update.json
+ *
+ * @return Tweet
+ * @throws TwitterException
+ */
+ Tweet createTweet(String status) throws TwitterException;
+
+ /**
+ * Destroys the status specified by the required ID parameter. The authenticating user must be the author of the specified status.
+ *
+ * Deleta um tweet. O autor do tweet deve ser o usuário autenticado.
+ *
+ * https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-destroy-id
+ *
+ *
+ * https://api.twitter.com/1.1/statuses/destroy/:id.json
+ *
+ * @return Tweet
+ * @throws TwitterException
+ */
+ Tweet deleteTweet(long tweetId) throws TwitterException;
+
+ /**
+ * Returns a single Tweet, specified by the id parameter.
+ *
+ * Retorna um tweet específico.
+ *
+ * https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-show-id
+ *
+ *
+ * https://api.twitter.com/1.1/statuses/show.json
+ *
+ * @return Tweet
+ * @throws TwitterException
+ */
+ Tweet showTweet(long tweetId) throws TwitterException;
+
+ /**
+ * Returns fully-hydrated Tweet objects for up to 100 Tweets per request, as specified by comma-separated values passed to the id parameter.
+ *
+ * Retorna todos os tweets específicados (Máximo 100 tweets por request).
+ *
+ * https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-lookup
+ *
+ *
+ * https://api.twitter.com/1.1/statuses/lookup.json
+ *
+ * @return List
+ *
+ * Retweeta um tweet.
+ *
+ * https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-retweet-id
+ *
+ *
+ * https://api.twitter.com/1.1/statuses/retweet/:id.json
+ *
+ * @return Tweet
+ * @throws TwitterException
+ */
+ Tweet retweet(long tweetId) throws TwitterException;
+
+ /**
+ * Untweets a retweeted status. Returns the original Tweet with Retweet details embedded.
+ *
+ * Remove o retweet de um tweet.
+ *
+ * https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-unretweet-id
+ *
+ *
+ * https://api.twitter.com/1.1/statuses/unretweet/:id.json
+ *
+ * @return Tweet
+ * @throws TwitterException
+ */
+ Tweet unretweet(long tweetId) throws TwitterException;
+
+ /**
+ * Returns a collection of the 100 most recent retweets of the Tweet specified by the id parameter.
+ *
+ * Retorna os 100 retweets mais recentes de um tweet.
+ *
+ * https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-retweets-id
+ *
+ *
+ * https://api.twitter.com/1.1/statuses/retweets/:id.json
+ *
+ * @return List
+ *
+ * Retorna 100 ids de usuários que tenham dado retweet em um tweet.
+ *
+ * https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-retweeters-ids
+ *
+ *
+ * https://api.twitter.com/1.1/statuses/retweeters/ids.json
+ *
+ * @return BirdList
+ *
+ * Favorita (like) um tweet.
+ *
+ * https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-favorites-create
+ *
+ *
+ * https://api.twitter.com/1.1/favorites/create.json
+ *
+ * @return Tweet
+ * @throws TwitterException
+ */
+ Tweet like(long tweetId) throws TwitterException;
+
+ /**
+ * Unfavorites (un-likes) the Tweet specified in the ID parameter as the authenticating user. Returns the un-liked Tweet when successful.
+ *
+ * Desfavorita (un-like) um tweet.
+ *
+ * https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-favorites-destroy
+ *
+ *
+ * https://api.twitter.com/1.1/favorites/destroy.json
+ *
+ * @return Tweet
+ * @throws TwitterException
+ */
+ Tweet unlike(long tweetId) throws TwitterException;
+
+ /**
+ * Returns the 20 most recent Tweets liked by the authenticating or specified user.
+ *
+ * Retorna os 20 mais recentes tweets que um usuário curtiu.
+ *
+ * https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-favorites-list
+ *
+ *
+ * https://api.twitter.com/1.1/favorites/list.json
+ *
+ * @return List
+ *
+ * Retorna os 20 mais recentes tweets que um usuário curtiu.
+ *
+ * https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-favorites-list
+ *
+ *
+ * https://api.twitter.com/1.1/favorites/list.json
+ *
+ * @return List
+ *
+ * Retorna as configurações (incluindo trend, geo e sleep time) do usuário
+ * autenticado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-settings
+ *
+ *
+ * https://api.twitter.com/1.1/account/settings.json
+ *
+ * @return AccountSettings
+ * @throws TwitterException
+ */
+ AccountSettings getAccountSettings() throws TwitterException;
+
+ /**
+ * Returns a map of the available size variations of the specified user’s
+ * profile banner. If the user has not uploaded a profile banner, a HTTP 404
+ * will be served instead.
+ *
+ * Retorna um mapa das variações de tamanho disponíveis do banner de perfil do
+ * usuário especificado. Se o usuário não tiver um banner de perfil, um código
+ * HTTP 404 será exibido.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-verify_credentials
+ *
+ *
+ * https://api.twitter.com/1.1/account/verify_credentials.json
+ *
+ * @return User
+ * @throws TwitterException
+ */
+ List
+ *
+ * Retorna um mapa das variações de tamanho disponíveis do banner de perfil do
+ * usuário especificado. Se o usuário não tiver um banner de perfil, um código
+ * HTTP 404 será exibido.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-verify_credentials
+ *
+ *
+ * https://api.twitter.com/1.1/account/verify_credentials.json
+ *
+ * @return User
+ * @throws TwitterException
+ */
+ List
+ *
+ * Remove o banner de perfil do usuário autenticado. Retorna um código HTTP 200
+ * se tiver sucesso.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-verify_credentials
+ *
+ *
+ * https://api.twitter.com/1.1/account/verify_credentials.json
+ *
+ * @throws TwitterException
+ */
+ void removeProfileBanner() throws TwitterException;
+
+ /**
+ * Updates the authenticating user’s settings. Only the parameters specified
+ * will be updated.
+ *
+ * Atualiza as configurações do usuário autenticado. Somente parâmetros
+ * especificados serão atualizados.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-settings
+ *
+ *
+ * https://api.twitter.com/1.1/account/settings.json
+ *
+ * @return AccountSettings
+ * @param time_zone http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html
+ * @param lang https://developer.twitter.com/en/docs/developer-utilities/supported-languages/api-reference/get-help-languages
+ * @throws TwitterException
+ */
+ AccountSettings updateAccountSettings(boolean sleep_time_enabled, int start_sleep_time, int end_sleep_time,
+ String time_zone, int trend_location_woeid, String lang) throws TwitterException;
+
+ /**
+ * Updates the authenticating user’s profile. Only the parameters specified will
+ * be updated.
+ *
+ * Atualiza o perfil do usuário autenticado. Somente parâmetros especificados
+ * serão atualizados.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile
+ *
+ *
+ * https://api.twitter.com/1.1/account/update_profile.json
+ *
+ * @return AccountSettings
+ * @throws TwitterException
+ */
+ User updateProfile(String name, String url, String location, String description, String profile_link_color) throws TwitterException;
+
+ /**
+ * Uploads a profile banner on behalf of the authenticating user.
+ *
+ * Atualiza o banner de perfil do usuário autenticado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_banner
+ *
+ *
+ * https://api.twitter.com/1.1/account/update_profile_banner.json
+ *
+ * @throws TwitterException
+ */
+ void updateProfileBanner(String image) throws TwitterException;
+
+ /**
+ * Uploads a profile banner on behalf of the authenticating user.
+ *
+ * Atualiza o banner de perfil do usuário autenticado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_banner
+ *
+ *
+ * https://api.twitter.com/1.1/account/update_profile_banner.json
+ *
+ * @throws TwitterException
+ */
+ void updateProfileBanner(String image, int width, int height, int offset_left, int offset_top) throws TwitterException;
+
+ /**
+ * Updates the authenticating user’s profile image. Note that this method expects raw multipart data, not a URL to an image.
+ *
+ * Atualiza a imagem de perfil do usuário autenticado. Note que esse método espera raw multipart data, não uma URL de alguma imagem.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_image
+ *
+ *
+ * https://api.twitter.com/1.1/account/update_profile_image.json
+ *
+ * @throws TwitterException
+ */
+ void updateProfileImage(String image) throws TwitterException;
+
+ /**
+ * Returns an array of numeric user ids the authenticating user is blocking.
+ *
+ * Retorna uma lista de ids das pessoas bloqueadas pelo usuário autenticado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-blocks-ids
+ *
+ *
+ * https://api.twitter.com/1.1/blocks/ids.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de ids das pessoas bloqueadas pelo usuário autenticado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-blocks-ids
+ *
+ *
+ * https://api.twitter.com/1.1/blocks/ids.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de usuários bloqueados pelo usuário autenticado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-blocks-list
+ *
+ *
+ * https://api.twitter.com/1.1/blocks/list.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de usuários bloqueados pelo usuário autenticado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-blocks-list
+ *
+ *
+ * https://api.twitter.com/1.1/blocks/list.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de ids das pessoas mutadas pelo usuário autenticado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-mutes-users-ids
+ *
+ *
+ * https://api.twitter.com/1.1/mutes/users/ids.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de usuários mutados pelo usuário autenticado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-mutes-users-list
+ *
+ *
+ * https://api.twitter.com/1.1/mutes/users/list.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de ids das pessoas mutadas pelo usuário autenticado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-mutes-users-ids
+ *
+ *
+ * https://api.twitter.com/1.1/mutes/users/ids.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de usuários mutados pelo usuário autenticado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-mutes-users-list
+ *
+ *
+ * https://api.twitter.com/1.1/mutes/users/list.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Bloqueia um usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-blocks-create
+ *
+ *
+ * https://api.twitter.com/1.1/blocks/create.json
+ *
+ * @throws TwitterException
+ */
+ User blockUser(String screenName) throws TwitterException;
+
+ /**
+ * Blocks the specified user from following the authenticating user.
+ *
+ * Bloqueia um usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-blocks-create
+ *
+ *
+ * https://api.twitter.com/1.1/blocks/create.json
+ *
+ * @throws TwitterException
+ */
+ User blockUser(long userId) throws TwitterException;
+
+ /**
+ * Un-blocks the user specified in the ID parameter for the authenticating user.
+ *
+ * Desbloqueia um usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-blocks-destroy
+ *
+ *
+ * https://api.twitter.com/1.1/blocks/destroy.json
+ *
+ * @throws TwitterException
+ */
+ User unblockUser(String screenName) throws TwitterException;
+
+ /**
+ * Un-blocks the user specified in the ID parameter for the authenticating user.
+ *
+ * Desbloqueia um usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-blocks-destroy
+ *
+ *
+ * https://api.twitter.com/1.1/blocks/destroy.json
+ *
+ * @throws TwitterException
+ */
+ User unblockUser(long userId) throws TwitterException;
+
+ //
+
+ /**
+ * Mutes the user specified in the ID parameter for the authenticating user.
+ *
+ * Muta um usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-mutes-users-create
+ *
+ *
+ * https://api.twitter.com/1.1/mutes/users/create.json
+ *
+ * @throws TwitterException
+ */
+ User muteUser(String screenName) throws TwitterException;
+
+ /**
+ * Mutes the user specified in the ID parameter for the authenticating user.
+ *
+ * Muta um usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-mutes-users-create
+ *
+ *
+ * https://api.twitter.com/1.1/mutes/users/create.json
+ *
+ * @throws TwitterException
+ */
+ User muteUser(long userId) throws TwitterException;
+
+ /**
+ * Un-mutes the user specified in the ID parameter for the authenticating user.
+ *
+ * Desmuta um usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-mutes-users-destroy
+ *
+ *
+ * https://api.twitter.com/1.1/mutes/users/destroy.json
+ *
+ * @throws TwitterException
+ */
+ User unmuteUser(String screenName) throws TwitterException;
+
+ /**
+ * Un-mutes the user specified in the ID parameter for the authenticating user.
+ *
+ * Desmuta um usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-mutes-users-destroy
+ *
+ *
+ * https://api.twitter.com/1.1/mutes/users/destroy.json
+ *
+ * @throws TwitterException
+ */
+ User unmuteUser(long userId) throws TwitterException;
+
+ /**
+ * Report the specified user as a spam account to Twitter.
+ *
+ * Reporta um usuário como spam.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-users-report_spam
+ *
+ *
+ * https://api.twitter.com/1.1/users/report_spam.json
+ *
+ * @throws TwitterException
+ */
+ User reportSpam(String screenName, boolean block) throws TwitterException;
+
+ /**
+ * Report the specified user as a spam account to Twitter.
+ *
+ * Reporta um usuário como spam.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-users-report_spam
+ *
+ *
+ * https://api.twitter.com/1.1/users/report_spam.json
+ *
+ * @throws TwitterException
+ */
+ User reportSpam(long userId, boolean block) throws TwitterException;
+
+ /**
+ * Returns a cursored collection of user IDs for every user following the specified user.
+ *
+ * Retorna uma lista de id de todos os seguidores de um usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-followers-ids
+ *
+ *
+ * https://api.twitter.com/1.1/followers/ids.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de id de todos os seguidores de um usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-followers-ids
+ *
+ *
+ * https://api.twitter.com/1.1/followers/ids.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de usuários de todos os seguidores de um usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-followers-list
+ *
+ *
+ * https://api.twitter.com/1.1/followers/list.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de usuários de todos os seguidores de um usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-followers-list
+ *
+ *
+ * https://api.twitter.com/1.1/followers/list.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de id de todas as pessoas que o usuário segue.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friends-ids
+ *
+ *
+ * https://api.twitter.com/1.1/friends/ids.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de id de todas as pessoas que o usuário segue.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friends-ids
+ *
+ *
+ * https://api.twitter.com/1.1/friends/ids.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de usuários de todos as pessoas que o usuário segue.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friends-list
+ *
+ *
+ * https://api.twitter.com/1.1/friends/list.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de usuários de todos as pessoas que o usuário segue.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friends-list
+ *
+ *
+ * https://api.twitter.com/1.1/friends/list.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de id de todos os usuários que possuem um pedido de follow para o usuário autenticado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-incoming
+ *
+ *
+ * https://api.twitter.com/1.1/friendships/incoming.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna as relações entre o usuário autenticado e o(s) usuário(s) (Máximo 100 usuários por request).
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-lookup
+ *
+ *
+ * https://api.twitter.com/1.1/friendships/lookup.json
+ *
+ * @throws TwitterException
+ */
+ List
+ *
+ * Retorna as relações entre o usuário autenticado e o(s) usuário(s) (Máximo 100 usuários por request).
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-lookup
+ *
+ *
+ * https://api.twitter.com/1.1/friendships/lookup.json
+ *
+ * @throws TwitterException
+ */
+ List
+ *
+ * Retorna uma lista de id de todos os usuários que o usuário autenticado pediu para seguir.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-outgoing
+ *
+ *
+ * https://api.twitter.com/1.1/friendships/outgoing.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de usuários (Máximo 100 usuários por request).
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-lookup
+ *
+ *
+ * https://api.twitter.com/1.1/users/lookup.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna uma lista de usuários (Máximo 100 usuários por request).
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-lookup
+ *
+ *
+ * https://api.twitter.com/1.1/users/lookup.json
+ *
+ * @throws TwitterException
+ */
+ BirdList
+ *
+ * Retorna um usuário especificado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-show
+ *
+ *
+ * https://api.twitter.com/1.1/users/show.json
+ *
+ * @throws TwitterException
+ */
+ User getUser(String screenName) throws TwitterException;
+
+ /**
+ * Returns a variety of information about the user specified by the required user_id or screen_name parameter.
+ *
+ * Retorna um usuário especificado.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-show
+ *
+ *
+ * https://api.twitter.com/1.1/users/show.json
+ *
+ * @throws TwitterException
+ */
+ User getUser(long userId) throws TwitterException;
+
+ /**
+ * Allows the authenticating user to follow (friend) the user specified in the ID parameter.
+ *
+ * Faz o usuário autenticado seguir outro usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-create
+ *
+ *
+ * https://api.twitter.com/1.1/friendships/create.json
+ *
+ * @throws TwitterException
+ */
+ User followUser(String screenName) throws TwitterException;
+
+ /**
+ * Allows the authenticating user to follow (friend) the user specified in the ID parameter.
+ *
+ * Faz o usuário autenticado seguir outro usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-create
+ *
+ *
+ * https://api.twitter.com/1.1/friendships/create.json
+ *
+ * @throws TwitterException
+ */
+ User followUser(long userId) throws TwitterException;
+
+ /**
+ * Allows the authenticating user to unfollow the user specified in the ID parameter.
+ *
+ * Faz o usuário autenticado parar de seguir outro usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-destroy
+ *
+ *
+ * https://api.twitter.com/1.1/friendships/destroy.json
+ *
+ * @throws TwitterException
+ */
+ User unfollowUser(String screenName) throws TwitterException;
+
+ /**
+ * Allows the authenticating user to unfollow the user specified in the ID parameter.
+ *
+ * Faz o usuário autenticado parar de seguir outro usuário.
+ *
+ * https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-destroy
+ *
+ *
+ * https://api.twitter.com/1.1/friendships/destroy.json
+ *
+ * @throws TwitterException
+ */
+ User unfollowUser(long userId) throws TwitterException;
+
+ //wip
+}
\ No newline at end of file
diff --git a/src/main/java/com/github/langsdorf/blackbird/user/list/BirdList.java b/src/main/java/com/github/langsdorf/blackbird/user/list/BirdList.java
new file mode 100644
index 0000000..d902dfe
--- /dev/null
+++ b/src/main/java/com/github/langsdorf/blackbird/user/list/BirdList.java
@@ -0,0 +1,13 @@
+package com.github.langsdorf.blackbird.user.list;
+
+import java.util.List;
+
+public interface BirdList