diff --git a/Jettriangle/pom.xml b/Jettriangle/pom.xml index 99aed8c8..4c926c53 100644 --- a/Jettriangle/pom.xml +++ b/Jettriangle/pom.xml @@ -43,5 +43,21 @@ 2.4 test - + + com.google.guava + guava + r05 + + + com.h2database + h2 + 1.4.190 + + + junit + junit + 4.11 + test + + diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/Aggregates.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/Aggregates.java new file mode 100644 index 00000000..544b5b6e --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/Aggregates.java @@ -0,0 +1,62 @@ +package ru.fizteh.fivt.students.Jettriangle.collectionquery; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Function; + +public class Aggregates { + public static Function count(Function expression) { + return new Count<>(expression); + } + + public static Function avg(Function expression) { + return new Avg<>(expression); + } + + public interface Aggregator extends Function { + C apply(List list); + } + + public static class Count implements Aggregator { + + private Function function; + public Count(Function expression) { + this.function = expression; + } + + @Override + public Integer apply(List list) { + Set distinctedList = new HashSet<>(); + list.stream().filter(e -> !distinctedList.contains(function.apply(e))).forEach(e -> { + distinctedList.add(function.apply(e)); + }); + return distinctedList.size(); + } + @Override + public Integer apply(T t) { + return null; + } + } + + public static class Avg implements Aggregator { + private Function function; + public Avg(Function expression) { + this.function = expression; + } + + @Override + public Double apply(List list) { + Double result = 0.0; + for (T e : list) { + result += function.apply(e).floatValue(); + } + return result / list.size(); + } + + @Override + public Double apply(T t) { + return null; + } + } +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/Conditions.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/Conditions.java new file mode 100644 index 00000000..3a454718 --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/Conditions.java @@ -0,0 +1,14 @@ +package ru.fizteh.fivt.students.Jettriangle.collectionquery; + +/** + * Created by rtriangle on 19.12.15. + */ + +import java.util.function.Function; +import java.util.function.Predicate; + +public class Conditions { + public static Predicate rlike(Function expression, String regexp) { + return element -> expression.apply(element).matches(regexp); + } +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/OrderByConditions.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/OrderByConditions.java new file mode 100644 index 00000000..fa7e7132 --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/OrderByConditions.java @@ -0,0 +1,19 @@ +package ru.fizteh.fivt.students.Jettriangle.collectionquery; + +/** + * Created by rtriangle on 19.12.15. + */ +import java.util.Comparator; +import java.util.function.Function; + +public class OrderByConditions { + + public static > Comparator asc(Function expression) { + return (o1, o2) -> expression.apply(o1).compareTo(expression.apply(o2)); + } + + public static > Comparator desc(Function expression) { + return (o1, o2) -> expression.apply(o2).compareTo(expression.apply(o1)); + } + +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/Sources.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/Sources.java new file mode 100644 index 00000000..87283927 --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/Sources.java @@ -0,0 +1,25 @@ +package ru.fizteh.fivt.students.Jettriangle.collectionquery; + +/** + * Created by rtriangle on 19.12.15. + */ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Created by ocksumoron on 17.12.15. + */ +public class Sources { + + /** + * @param items + * @param + * @return + */ + @SafeVarargs + public static List list(T... items) { + return new ArrayList<>(Arrays.asList(items)); + } + +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/FromStmt.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/FromStmt.java new file mode 100644 index 00000000..fb9009df --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/FromStmt.java @@ -0,0 +1,85 @@ +package ru.fizteh.fivt.students.Jettriangle.collectionquery.impl; + +/** + * Created by rtriangle on 19.12.15. + */ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.function.BiPredicate; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class FromStmt { + private List list = new ArrayList(); + + public FromStmt(Iterable iterable) { + for (T curr : iterable) { + list.add(curr); + } + } + + public static FromStmt from(Iterable iterable) { + return new FromStmt<>(iterable); + } + + @SafeVarargs + public final SelectStmt select(Class clazz, Function... functions) { + return new SelectStmt<>(list, clazz, false, functions); + } + + @SafeVarargs + public final SelectStmt selectDistinct(Class clazz, Function... functions) { + return new SelectStmt<>(list, clazz, true, functions); + } + + public final SelectStmt> select(Function first, Function second) { + return new SelectStmt<>(list, false, first, second); + } + + public JoinClause join(Iterable iterable) { + return new JoinClause(list, iterable); + } + + public class JoinClause { + private List firstList = new ArrayList<>(); + private List secondList = new ArrayList<>(); + private List> list = new ArrayList<>(); + + public JoinClause(List firstList, Iterable secondList) { + this.firstList.addAll(firstList.stream().collect(Collectors.toList())); + for (J curr : secondList) { + this.secondList.add(curr); + } + } + + public FromStmt> on(BiPredicate condition) { + for (S first : firstList) { + list.addAll(secondList.stream().filter(second -> condition.test(first, second)) + .map(second -> new Tuple<>(first, second)).collect(Collectors.toList())); + } + return new FromStmt<>(list); + } + + public > FromStmt> on( + Function leftKey, + Function rightKey) { + HashMap> map = new HashMap<>(); + for (J e : secondList) { + K key = rightKey.apply(e); + if (!map.containsKey(key)) { + map.put(key, new ArrayList<>()); + } + map.get(key).add(e); + } + for (S first : firstList) { + K key = leftKey.apply(first); + if (map.containsKey(key)) { + List second = map.get(key); + second.forEach(s -> list.add(new Tuple<>(first, s))); + } + } + return new FromStmt<>(list); + } + } +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/Query.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/Query.java new file mode 100644 index 00000000..f82bc7dd --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/Query.java @@ -0,0 +1,11 @@ +package ru.fizteh.fivt.students.Jettriangle.collectionquery.impl; + +/** + * Created by rtriangle on 19.12.15. + */ +import java.lang.reflect.InvocationTargetException; + +public interface Query { + Iterable execute() throws NoSuchMethodException, + IllegalAccessException, InvocationTargetException, InstantiationException; +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/SelectStmt.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/SelectStmt.java new file mode 100644 index 00000000..ac48854b --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/SelectStmt.java @@ -0,0 +1,224 @@ +package ru.fizteh.fivt.students.Jettriangle.collectionquery.impl; + +/** + * Created by rtriangle on 19.12.15. + */ +import javafx.util.Pair; +import ru.fizteh.fivt.students.Jettriangle.collectionquery.Aggregates; + +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public class SelectStmt implements Query { + private boolean isDistinct; + private Class clazz; + private Function[] functions; + private List list; + private List pastList; + private Predicate wherePredicate; + private Comparator[] orderByComparators; + private Predicate havingPredicate; + private int limit; + private Function[] groupByFunctions; + private CQLComparator cqlComparator; + private boolean isUnion; + private boolean isJoin; + + private void init(List list, Class clazz, boolean isDistinct, Function[] functions, + boolean isUnion, boolean isJoin, List pastList) { + this.list = new ArrayList<>(); + this.list.addAll(list.stream().collect(Collectors.toList())); + this.clazz = clazz; + this.isDistinct = isDistinct; + this.functions = functions; + this.limit = -1; + this.isUnion = isUnion; + this.isJoin = isJoin; + this.pastList = pastList; + } + + @SafeVarargs + public SelectStmt(List list, Class clazz, boolean isDistinct, Function... functions) { + init(list, clazz, isDistinct, functions, false, false, null); + } + + public SelectStmt(List list, boolean isDistinct, Function first, Function second) { + init(list, list.get(0).getClass(), isDistinct, new Function[]{first, second}, false, true, null); + } + + @SafeVarargs + public SelectStmt(List pastList, List list, Class clazz, boolean isDistinct, Function... functions) { + init(list, clazz, isDistinct, functions, true, false, pastList); + } + + public SelectStmt(List pastList, List list, boolean isDistinct, Function first, Function second) { + init(list, list.get(0).getClass(), isDistinct, new Function[]{first, second}, true, true, pastList); + } + + public SelectStmt where(Predicate predicate) { + this.wherePredicate = predicate; + return this; + } + + @SafeVarargs + public final SelectStmt groupBy(Function... functions) { + this.groupByFunctions = functions; + return this; + } + + @SafeVarargs + public final SelectStmt orderBy(Comparator... orderByComparators) { + this.orderByComparators = orderByComparators; + this.cqlComparator = new CQLComparator(orderByComparators); + return this; + } + + public SelectStmt having(Predicate predicate) { + this.havingPredicate = predicate; + return this; + } + + public SelectStmt limit(int amount) { + this.limit = amount; + return this; + } + + public Iterable execute() throws NoSuchMethodException, IllegalAccessException, + InvocationTargetException, InstantiationException { + List result = new ArrayList<>(); + Object[] arguments = new Object[functions.length]; + Class[] clazzes = new Class[functions.length]; + if (wherePredicate != null) { + List filtered = new ArrayList<>(); + list.stream().filter(wherePredicate::test).forEach(filtered::add); + list = filtered; + } + if (groupByFunctions != null) { + Map mapped = new HashMap<>(); + String[] results = new String[groupByFunctions.length]; + List> groupped = new ArrayList<>(); + list.stream().forEach( + element -> { + for (int i = 0; i < groupByFunctions.length; i++) { + results[i] = (String) groupByFunctions[i].apply(element); + } + if (!mapped.containsKey(Objects.hash(results))) { + mapped.put(Objects.hash(results), mapped.size()); + } + groupped.add(new Pair(element, mapped.get(Objects.hash(results)))); + } + ); + List> grouppedList = new ArrayList<>(); + for (int i = 0; i < mapped.size(); i++) { + grouppedList.add(new ArrayList()); + } + + for (Pair element : groupped) { + grouppedList.get(element.getValue()).add(element.getKey()); + } + for (List group : grouppedList) { + for (int i = 0; i < functions.length; i++) { + if (functions[i] instanceof Aggregates.Aggregator) { + arguments[i] = ((Aggregates.Aggregator) functions[i]).apply(group); + } else { + arguments[i] = functions[i].apply(group.get(0)); + } + clazzes[i] = arguments[i].getClass(); + } + if (isJoin) { + Tuple newElement = new Tuple(arguments[0], arguments[1]); + result.add((R) newElement); + } else { + R newElement = (R) clazz.getConstructor(clazzes).newInstance(arguments); + result.add(newElement); + } + } + } else { + for (T element : this.list) { + for (int i = 0; i < functions.length; i++) { + arguments[i] = functions[i].apply(element); + if (functions[i] instanceof Aggregates.Aggregator) { + List currArg = new ArrayList<>(); + currArg.add(element); + arguments[i] = ((Aggregates.Aggregator) functions[i]).apply(currArg); + } else { + arguments[i] = functions[i].apply(element); + } + clazzes[i] = arguments[i].getClass(); + } + if (isJoin) { + Tuple newElement = new Tuple(arguments[0], arguments[1]); + result.add((R) newElement); + } else { + R newElement = (R) clazz.getConstructor(clazzes).newInstance(arguments); + result.add(newElement); + } + } + } + if (havingPredicate != null) { + List filtered = new ArrayList<>(); + result.stream().filter(havingPredicate::test).forEach(filtered::add); + result = filtered; + } + if (isDistinct) { + Set hashes = new HashSet<>(); + List flags = new ArrayList<>(); + for (R element : result) { + if (!hashes.contains(element.toString().hashCode())) { + flags.add(1); + hashes.add(element.toString().hashCode()); + } else { + flags.add(0); + } + } + List distincted = new ArrayList<>(); + for (int i = 0; i < result.size(); i++) { + if (flags.get(i) == 1) { + distincted.add(result.get(i)); + } + } + result = distincted; + } + if (orderByComparators != null) { + result.sort(cqlComparator); + } + if (limit != -1) { + while (result.size() > limit) { + result.remove(result.size() - 1); + } + } + if (isUnion) { + pastList.addAll(result); + result = pastList; + } + return result; + } + + public UnionStmt union() throws InvocationTargetException, NoSuchMethodException, + InstantiationException, IllegalAccessException { + List result = (List) this.execute(); + return new UnionStmt<>(result); + } + + public class CQLComparator implements Comparator { + private Comparator[] orderByComparators; + @SafeVarargs + public CQLComparator(Comparator... orderByComparators) { + this.orderByComparators = orderByComparators; + } + + @Override + public int compare(K first, K second) { + for (Comparator comparator : orderByComparators) { + if (comparator.compare(first, second) != 0) { + return comparator.compare(first, second); + } + } + return 0; + } + } + +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/Tuple.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/Tuple.java new file mode 100644 index 00000000..cc4da39f --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/Tuple.java @@ -0,0 +1,31 @@ +package ru.fizteh.fivt.students.Jettriangle.collectionquery.impl; + +/** + * Created by rtriangle on 19.12.15. + */ +public class Tuple { + + private final F first; + private final S second; + + public Tuple(F first, S second) { + this.first = first; + this.second = second; + } + + public F getFirst() { + return first; + } + + public S getSecond() { + return second; + } + + @Override + public String toString() { + return "Tuple{" + + "first=" + first + + ", second=" + second + + '}'; + } +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/UnionStmt.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/UnionStmt.java new file mode 100644 index 00000000..00ee1aaa --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/collectionquery/impl/UnionStmt.java @@ -0,0 +1,104 @@ +package ru.fizteh.fivt.students.Jettriangle.collectionquery.impl; + +/** + * Created by rtriangle on 19.12.15. + */ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.function.BiPredicate; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class UnionStmt { + private List pastList = new ArrayList<>(); + + public UnionStmt(Iterable iterable) { + for (R curr : iterable) { + pastList.add(curr); + } + } + + public FromClause from(Iterable list) { + return new FromClause(pastList, list); + } + + public class FromClause { + private List pastList = new ArrayList<>(); + private List list = new ArrayList<>(); + + public FromClause(Iterable pastList, Iterable list) { + for (R curr : pastList) { + this.pastList.add(curr); + } + for (S curr : list) { + this.list.add(curr); + } + } + @SafeVarargs + public final SelectStmt select(Class clazz, Function... functions) { + return new SelectStmt((List) pastList, list, clazz, false, functions); + } + + public final SelectStmt> select(Function first, Function second) { + return new SelectStmt>((List>) pastList, list, false, first, second); + } + + @SafeVarargs + public final SelectStmt selectDistinct(Class clazz, Function... functions) { + return new SelectStmt((List) pastList, list, clazz, true, functions); + } + + public JoinClause join(Iterable iterable) { + return new JoinClause(pastList, list, iterable); + } + } + + public class JoinClause { + + private List firstList = new ArrayList<>(); + private List secondList = new ArrayList<>(); + private List pastList = new ArrayList<>(); + private List> list = new ArrayList<>(); + + public JoinClause(List pastList, List firstList, Iterable secondList) { + this.pastList.addAll(pastList.stream().collect(Collectors.toList())); + this.firstList.addAll(firstList.stream().collect(Collectors.toList())); + for (J curr : secondList) { + this.secondList.add(curr); + } + } + + public FromClause, R> on(BiPredicate condition) { + for (F first : firstList) { + for (J second : secondList) { + if (condition.test(first, second)) { + list.add(new Tuple<>(first, second)); + } + } + } + return new FromClause<>(pastList, list); + } + + public > FromClause, R> on( + Function leftKey, + Function rightKey) { + HashMap> map = new HashMap<>(); + for (J e : secondList) { + K key = rightKey.apply(e); + if (!map.containsKey(key)) { + map.put(key, new ArrayList<>()); + } + map.get(key).add(e); + } + for (F first : firstList) { + K key = leftKey.apply(first); + if (map.containsKey(key)) { + List second = map.get(key); + second.forEach(s -> list.add(new Tuple<>(first, s))); + } + } + return new FromClause<>(pastList, list); + } + } +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/Column.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/Column.java new file mode 100644 index 00000000..5f45a782 --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/Column.java @@ -0,0 +1,14 @@ +package ru.fizteh.fivt.students.Jettriangle.miniORM; + +/** + * Created by rtriangle on 18.12.15. + */ + +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Retention; + + +@Retention(RetentionPolicy.RUNTIME) +public @interface Column { + String name() default ""; +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/DatabaseService.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/DatabaseService.java new file mode 100644 index 00000000..a1adeee0 --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/DatabaseService.java @@ -0,0 +1,286 @@ +package ru.fizteh.fivt.students.Jettriangle.miniORM; + + +/** + * Created by rtriangle on 18.12.15. + */ + + +import com.google.common.base.CaseFormat; +import org.h2.jdbcx.JdbcConnectionPool; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.sql.*; +import java.util.*; +import static ru.fizteh.fivt.students.Jettriangle.miniORM + .RightNameResolver.isGood; + + +public class DatabaseService implements Closeable { + + private int pkIndex = -1; + private final String connectionName; + private final String username; + private final String password; + private Class classs; + private JdbcConnectionPool pool; + private String tableName; + private Field[] tableFields; + + void init() throws IllegalArgumentException, IOException { + if (!classs.isAnnotationPresent(Table.class)) { + throw new IllegalArgumentException("no @Table annotation"); + } + tableName = classs.getAnnotation(Table.class).name(); + if (tableName.equals("")) { + tableName = convert(classs.getSimpleName()); + } + if (!isGood(tableName)) { + throw new IllegalArgumentException("Bad table name"); + } + Set names = new HashSet<>(); + List tableFieldsList = new ArrayList<>(); + for (Field f: classs.getDeclaredFields()) { + if (f.isAnnotationPresent(Column.class)) { + String name = getColumnName(f); + names.add(name); + if (!isGood(name)) { + throw new IllegalArgumentException("Bad column name"); + } + f.setAccessible(true); + tableFieldsList.add(f); + if (f.isAnnotationPresent(PrimaryKey.class)) { + if (pkIndex == -1) { + pkIndex = tableFieldsList.size() - 1; + } else { + throw new + IllegalArgumentException("Several @PrimaryKey"); + } + } + } else if (f.isAnnotationPresent(PrimaryKey.class)) { + throw new + IllegalArgumentException("@PrimaryKey without @Column"); + } + } + if (names.size() != tableFieldsList.size()) { + throw new IllegalArgumentException("Duplicate columns"); + } + tableFields = new Field[tableFieldsList.size()]; + tableFields = tableFieldsList.toArray(tableFields); + try { + Class.forName("org.h2.Driver"); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("No H2 driver found"); + } + pool = JdbcConnectionPool.create(connectionName, username, password); + } + + static String convert(String name) { + if ('a' <= name.charAt(0) && name.charAt(0) <= 'z') { + return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name); + } + return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name); + } + + String getColumnName(Field f) { + String name = f.getAnnotation(Column.class).name(); + if (name.equals("")) { + return convert(f.getName()); + } + return name; + } + + DatabaseService(Class newClazz, String properties) throws IOException { + Properties credits = new Properties(); + try (InputStream inputStream + = this.getClass().getResourceAsStream(properties)) { + credits.load(inputStream); + } + connectionName = credits.getProperty("connection_name"); + username = credits.getProperty("username"); + password = credits.getProperty("password"); + classs = newClazz; + init(); + } + + DatabaseService(Class newClazz) throws IOException { + this(newClazz, "/h2.properties"); + } + + void createTable() throws SQLException { + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("CREATE TABLE IF NOT EXISTS ") + .append(tableName) + .append("("); + for (int i = 0; i < tableFields.length; ++i) { + if (i != 0) { + queryBuilder.append(", "); + } + queryBuilder.append(getColumnName(tableFields[i])).append(" ") + .append(H2StringsResolver.resolve(tableFields[i].getType())); + if (i == pkIndex) { + queryBuilder.append(" PRIMARY KEY"); + } + } + queryBuilder.append(")"); + try (Connection conn = pool.getConnection()) { + conn.createStatement().execute(queryBuilder.toString()); + } + } + + void dropTable() throws SQLException { + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("DROP TABLE IF EXISTS ") + .append(tableName); + try (Connection conn = pool.getConnection()) { + conn.createStatement().execute(queryBuilder.toString()); + } + } + + public void insert(T record) throws SQLException, IllegalAccessException { + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("INSERT INTO ").append(tableName).append(" ("); + for (int i = 0; i < tableFields.length; ++i) { + if (i != 0) { + queryBuilder.append(", "); + } + queryBuilder.append(getColumnName(tableFields[i])).append(" "); + } + queryBuilder.append(") VALUES ("); + for (int i = 0; i < tableFields.length; ++i) { + if (i != 0) { + queryBuilder.append(", "); + } + queryBuilder.append("?"); + } + queryBuilder.append(")"); + + try (Connection conn = pool.getConnection()) { + PreparedStatement statement + = conn.prepareStatement(queryBuilder.toString()); + for (int i = 0; i < tableFields.length; ++i) { + statement.setObject(i + 1, tableFields[i].get(record)); + } + statement.execute(); + } + } + + public void delete(T record) throws IllegalArgumentException, + IllegalAccessException, SQLException { + if (pkIndex == -1) { + throw new IllegalArgumentException("NO @PrimaryKey"); + } + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("DELETE FROM ").append(tableName) + .append(" WHERE ").append(tableFields[pkIndex].getName()) + .append(" = ?"); + try (Connection conn = pool.getConnection()) { + PreparedStatement statement = conn.prepareStatement(queryBuilder.toString()); + statement.setObject(1, tableFields[pkIndex].get(record)); + statement.execute(); + } + } + + public void update(T record) throws IllegalArgumentException, + SQLException, IllegalAccessException { + if (pkIndex == -1) { + throw new IllegalArgumentException("NO @PrimaryKey"); + } + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("UPDATE ").append(tableName).append(" SET "); + for (int i = 0; i < tableFields.length; ++i) { + if (i != 0) { + queryBuilder.append(", "); + } + queryBuilder.append(getColumnName(tableFields[i])).append(" = ?"); + } + queryBuilder.append(" WHERE ").append(getColumnName(tableFields[pkIndex])) + .append(" = ?"); + + try (Connection conn = pool.getConnection()) { + PreparedStatement statement + = conn.prepareStatement(queryBuilder.toString()); + for (int i = 0; i < tableFields.length; ++i) { + statement.setObject(i + 1, tableFields[i].get(record)); + } + statement.setObject(tableFields.length + 1, tableFields[pkIndex].get(record)); + statement.execute(); + } + } + + public T queryById(K key) throws IllegalArgumentException, + SQLException { + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("SELECT * FROM ").append(tableName) + .append(" WHERE ").append(tableFields[pkIndex].getName()) + .append(" = ?"); + try (Connection conn = pool.getConnection()) { + PreparedStatement statement + = conn.prepareStatement(queryBuilder.toString()); + statement.setString(1, key.toString()); + + try (ResultSet rs = statement.executeQuery()) { + rs.next(); + T record = classs.newInstance(); + for (int i = 0; i < tableFields.length; ++i) { + if (tableFields[i].getClass() + .isAssignableFrom(Number.class)) { + Long val = rs.getLong(i + 1); + tableFields[i].set(record, val); + } else if (tableFields[i].getType() != String.class) { + tableFields[i].set(record, rs.getObject(i + 1)); + } else { + Clob data = rs.getClob(i + 1); + tableFields[i].set(record, + data.getSubString(1, (int) data.length())); + } + } + return record; + } catch (InstantiationException | IllegalAccessException e) { + throw new IllegalArgumentException("wrong class"); + } + } + + } + + public List queryForAll() throws SQLException { + List result = new ArrayList<>(); + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("SELECT * FROM ").append(tableName); + try (Connection conn = pool.getConnection()) { + try (ResultSet rs = conn.createStatement() + .executeQuery(queryBuilder.toString())) { + while (rs.next()) { + T record = classs.newInstance(); + for (int i = 0; i < tableFields.length; ++i) { + if (tableFields[i].getClass() + .isAssignableFrom(Number.class)) { + Long val = rs.getLong(i + 1); + tableFields[i].set(record, val); + } else + if (tableFields[i].getType() != String.class) { + tableFields[i].set(record, rs.getObject(i + 1)); + } else { + Clob data = rs.getClob(i + 1); + tableFields[i].set(record, + data.getSubString(1, (int) data.length())); + } + } + result.add(record); + } + } catch (InstantiationException | IllegalAccessException e) { + throw new IllegalArgumentException("wrong class"); + } + } + return result; + } + + @Override + public void close() throws IOException { + if (pool != null) { + pool.dispose(); + } + } +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/H2StringsResolver.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/H2StringsResolver.java new file mode 100644 index 00000000..c5135513 --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/H2StringsResolver.java @@ -0,0 +1,43 @@ +package ru.fizteh.fivt.students.Jettriangle.miniORM; + +/** + * Created by rtriangle on 18.12.15. + */ + +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +class H2StringsResolver { + + private static Map h2Mapper; + static { + h2Mapper = new HashMap<>(); + h2Mapper.put(Integer.class, "INTEGER"); + h2Mapper.put(Boolean.class, "BOOLEAN"); + h2Mapper.put(Byte.class, "TINYINT"); + h2Mapper.put(Short.class, "SMALLINT"); + h2Mapper.put(Long.class, "BIGINT"); + h2Mapper.put(Double.class, "DOUBLE"); + h2Mapper.put(Float.class, "FLOAT"); + h2Mapper.put(Time.class, "TIME"); + h2Mapper.put(Date.class, "DATE"); + h2Mapper.put(Timestamp.class, "TIMESTAMP"); + h2Mapper.put(Character.class, "CHAR"); + h2Mapper.put(String.class, "CLOB"); + h2Mapper.put(UUID.class, "UUID"); + } + + public static String resolve(Class clazz) { + if (clazz.isArray()) { + return "ARRAY"; + } + if (h2Mapper.containsKey(clazz)) { + return h2Mapper.get(clazz); + } + return "OTHER"; + } +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/PrimaryKey.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/PrimaryKey.java new file mode 100644 index 00000000..0f43d5af --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/PrimaryKey.java @@ -0,0 +1,12 @@ +package ru.fizteh.fivt.students.Jettriangle.miniORM; + +/** + * Created by rtriangle on 18.12.15. + */ + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface PrimaryKey { +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/RightNameResolver.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/RightNameResolver.java new file mode 100644 index 00000000..adf357a2 --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/RightNameResolver.java @@ -0,0 +1,12 @@ +package ru.fizteh.fivt.students.Jettriangle.miniORM; + +/** + * Created by rtriangle on 18.12.15. + */ + +class RightNameResolver { + static final String REGEX = "[A-Za-z0-9_-]*"; + public static Boolean isGood(String name) { + return name.matches(REGEX); + } +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/Table.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/Table.java new file mode 100644 index 00000000..ead50254 --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/miniORM/Table.java @@ -0,0 +1,13 @@ +package ru.fizteh.fivt.students.Jettriangle.miniORM; + +/** + * Created by rtriangle on 18.12.15. + */ + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Table { + String name() default ""; +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/threads/BlockingQueue.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/threads/BlockingQueue.java new file mode 100644 index 00000000..5829cb1a --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/threads/BlockingQueue.java @@ -0,0 +1,75 @@ +package ru.fizteh.fivt.students.Jettriangle.threads; + +/** + * Created by rtriangle on 17.12.15. + */ + +import java.util.*; + +public class BlockingQueue { + + private Queue q; + private final int maxQueueSize; + + BlockingQueue(int maxSize) { + q = new LinkedList<>(); + maxQueueSize = maxSize; + } + + synchronized List take(int size) throws InterruptedException { + while (q.size() < size) { + wait(); + } + List result = new ArrayList<>(); + for (int i = 0; i < size; ++i) { + result.add(q.remove()); + } + notifyAll(); + return result; + } + + synchronized List take(int n, long timeout) throws InterruptedException { + long timeLeft = timeout; + long currentTime = System.currentTimeMillis(); + while (0 < timeLeft && q.size() < n) { + wait(timeLeft); + long actualCurrentTime = System.currentTimeMillis(); + timeLeft = timeLeft - (actualCurrentTime - currentTime); + currentTime = actualCurrentTime; + } + if (timeLeft <= 0) { + return null; + } + + List result = new ArrayList<>(); + for (int i = 0; i < n; ++i) { + result.add(q.remove()); + } + return result; + } + + synchronized void offer(List e) throws InterruptedException { + while (maxQueueSize < q.size() + e.size()) { + wait(); + } + q.addAll(e); + notifyAll(); + } + + synchronized void offer(List e, long timeout) + throws InterruptedException { + long timeLeft = timeout; + long currentTime = System.currentTimeMillis(); + while (q.size() + e.size() > maxQueueSize && timeLeft > 0) { + wait(timeLeft); + long actualCurrentTime = System.currentTimeMillis(); + timeLeft -= (actualCurrentTime - currentTime); + currentTime = actualCurrentTime; + } + if (timeLeft <= 0) { + return; + } + q.addAll(e); + notifyAll(); + } +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/threads/Counter.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/threads/Counter.java new file mode 100644 index 00000000..39a79c04 --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/threads/Counter.java @@ -0,0 +1,66 @@ +package ru.fizteh.fivt.students.Jettriangle.threads; + +/** + * Created by rtriangle on 17.12.15. + */ + +public class Counter { + private static volatile int printId; + + public static class ParameterException extends Exception { + public ParameterException(String message) { + super(message); + } + } + + public static void main(String[] args) { + Integer n = 0; + try { + if (args.length != 1) { + throw new ParameterException("Argument must be exactly one positive number"); + } + n = Integer.valueOf(args[0]); + if (n <= 0) { + throw new ParameterException("Argument must be positive"); + } + } catch (ParameterException e) { + e.printStackTrace(); + System.exit(1); + } + printId = 0; + for (int id = 0; id < n; id++) { + CounterThread thread = new CounterThread(id, (id + 1) % n); + thread.start(); + } + } + + private static Object monitor = new Object(); + + private static class CounterThread extends Thread { + private Integer myId, nextId; + + CounterThread(Integer id1, Integer id2) { + myId = id1; + nextId = id2; + } + + @Override + public void run() { + while (true) { + synchronized (monitor) { + while (myId != printId) { + try { + monitor.wait(); + } catch (InterruptedException e) { + System.err.println(e.getMessage()); + System.exit(1); + } + } + System.out.println("Thread-" + String.valueOf(nextId)); + printId = nextId; + monitor.notifyAll(); + } + } + } + } +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/threads/Rollcall.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/threads/Rollcall.java new file mode 100644 index 00000000..6c95b80f --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/threads/Rollcall.java @@ -0,0 +1,99 @@ +package ru.fizteh.fivt.students.Jettriangle.threads; + +/** + * Created by rtriangle on 17.12.15. + */ + +import java.util.Random; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; + +public class Rollcall { + public static class ParameterException extends Exception { + public ParameterException(String message) { + super(message); + } + } + + private static volatile boolean yesEveryThread = false; + private static CyclicBarrier threadsToAsk, waitingAnswers; + + public static void main(String[] args) { + Integer n = 0; + try { + if (args.length != 1) { + throw new ParameterException("Argument must be exactly one positive number"); + } + n = Integer.valueOf(args[0]); + if (n <= 0) { + throw new ParameterException("Argument must be positive"); + } + } catch (ParameterException e) { + System.err.println(e.getMessage()); + System.exit(1); + } + + RollcallThread[] threads = new RollcallThread[n]; + threadsToAsk = new CyclicBarrier(n + 1); + waitingAnswers = new CyclicBarrier(n + 1); + + for (int i = 0; i < n; i++) { + threads[i] = new RollcallThread(); + threads[i].start(); + } + + while (!yesEveryThread) { + System.out.println("Are you ready?"); + yesEveryThread = true; + try { + threadsToAsk.await(); + } catch (InterruptedException | BrokenBarrierException e) { + System.err.println(e.getMessage()); + System.exit(1); + } + threadsToAsk.reset(); + try { + waitingAnswers.await(); + } catch (InterruptedException | BrokenBarrierException e) { + System.err.println(e.getMessage()); + System.exit(1); + } + waitingAnswers.reset(); + if (yesEveryThread) { + System.exit(0); + } + } + } + + private static class RollcallThread extends Thread { + private Boolean result; + private Random rand = new Random(); + + @Override + public void run() { + while (true) { + try { + threadsToAsk.await(); + } catch (InterruptedException | BrokenBarrierException e) { + System.err.println(e.getMessage()); + System.exit(1); + } + result = rand.nextInt(10) != 0; + if (result) { + System.out.println("Yes"); + } else { + System.out.println("No"); + } + if (!result) { + yesEveryThread = false; + } + try { + waitingAnswers.await(); + } catch (InterruptedException | BrokenBarrierException e) { + System.err.println(e.getMessage()); + System.exit(1); + } + } + } + } +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/InvalidLocationException.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/InvalidLocationException.java new file mode 100644 index 00000000..d890c4cc --- /dev/null +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/InvalidLocationException.java @@ -0,0 +1,14 @@ +package ru.fizteh.fivt.students.Jettriangle.twitterstream; + +/** + * Created by rtriangle on 19.12.15. + */ + +public class InvalidLocationException extends Exception { + public InvalidLocationException() { + } + + public InvalidLocationException(String message) { + super(message); + } +} diff --git a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/LocationBuilder.java b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/LocationBuilder.java index 9e9d9ce7..242a0813 100644 --- a/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/LocationBuilder.java +++ b/Jettriangle/src/main/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/LocationBuilder.java @@ -21,7 +21,7 @@ public class LocationBuilder { private static final int DEFAULT_RADIUS = 5; - private GeoLocation getCoordinates(NodeList sections) { + private static GeoLocation getCoordinates(NodeList sections) { Element section = (Element) sections.item(0); String coordinates = section.getTextContent(); String[] coordinatesParsed = coordinates.split(" "); @@ -30,7 +30,7 @@ private GeoLocation getCoordinates(NodeList sections) { return new GeoLocation(latitude, longitude); } - private Document documentResolver(URL url) + private static Document documentResolver(URL url) throws IOException, ParserConfigurationException, SAXException { URLConnection geoConnection = url.openConnection(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); @@ -45,7 +45,7 @@ private Document documentResolver(URL url) return document; } - private String getNearLocation() throws MalformedURLException { + private static String getNearLocation() throws MalformedURLException { Document document = null; try { document = documentResolver(new URL("http://api.hostip.info/")); @@ -62,7 +62,7 @@ private String getNearLocation() throws MalformedURLException { return place; } - public Location getLocation(String place) { + public static Location getLocation(String place) { try { if (place.equals("nearby")) { place = getNearLocation(); diff --git a/Jettriangle/src/test/java/ru/fizteh/fivt/students/Jettriangle/threads/BlockingQueueTests.java b/Jettriangle/src/test/java/ru/fizteh/fivt/students/Jettriangle/threads/BlockingQueueTests.java new file mode 100644 index 00000000..e95cd563 --- /dev/null +++ b/Jettriangle/src/test/java/ru/fizteh/fivt/students/Jettriangle/threads/BlockingQueueTests.java @@ -0,0 +1,105 @@ +package ru.fizteh.fivt.students.Jettriangle.threads; + +import org.junit.Assert; +import org.junit.Test; +import java.util.*; + +/** + * Created by rtriangle on 18.12.15. + */ + +public class BlockingQueueTests { + public static class BlockingQueueTest { + @Test + public void testSimpleWithoutThreads() throws InterruptedException { + BlockingQueue queue = new BlockingQueue(40); + ArrayList list1 = new ArrayList(); + list1.add(100); + list1.add(1000); + list1.add(100000); + ArrayList list2 = new ArrayList(); + list2.add(100); + list2.add(1000); + ArrayList list3 = new ArrayList(); + list3.add(11); + list3.add(111); + ArrayList list4 = new ArrayList(); + list4.add(1); + list4.add(11); + list4.add(111); + queue.offer(list1); + List answer1 = queue.take(100000); + queue.offer(list3); + List answer2 = queue.take(1); + Assert.assertEquals(answer1, list2); + Assert.assertEquals(answer2, list4); + } + + @Test + public void testSimpleWithThreads() throws InterruptedException { + BlockingQueue queue = new BlockingQueue<>(5); + SimpleThread thread1 = new SimpleThread("take", 1, 0.05, 10, queue); + SimpleThread thread2 = new SimpleThread("offer", 10, 0.001, 1, queue); + thread1.start(); + thread2.start(); + try { + thread1.join(); + thread2.join(); + } catch (InterruptedException e) { + System.err.println(e.getMessage()); + System.exit(1); + } + } + + private static class SimpleThread extends Thread { + private String action; + private Integer times, value; + private Double interval; + private BlockingQueue queue; + SimpleThread(String newAction, Integer newValue, Double newInterval, Integer newTimes, BlockingQueue newQueue) { + interval = newInterval; + value = newValue; + action = newAction; + times = newTimes; + queue = newQueue; + } + + @Override + public void run() { + Integer last = 0; + for (int i = 0; i < times; ++i) { + try { + sleep((int) (1000 * interval)); + } catch (InterruptedException e) { + System.err.println(e.getMessage()); + System.exit(1); + } + if (Objects.equals(action, "take")) { + List list = null; + try { + list = queue.take(value); + } catch (InterruptedException e) { + e.printStackTrace(); + } + for (int j = 0; j < value; ++j) { + ++last; + Assert.assertEquals(list.get(j), last); + } + + } else { + ArrayList list = new ArrayList(value); + for (int j = 0; j < value; ++j) { + ++last; + list.add(last); + } + try { + queue.offer(list); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + } + } +} diff --git a/Jettriangle/src/test/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/FormatFactoryTest.java b/Jettriangle/src/test/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/FormatFactoryTest.java new file mode 100644 index 00000000..69f5679b --- /dev/null +++ b/Jettriangle/src/test/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/FormatFactoryTest.java @@ -0,0 +1,219 @@ +package ru.fizteh.fivt.students.Jettriangle.twitterstream; + +/** + * Created by rtriangle on 14.10.15. + */ +import com.beust.jcommander.JCommander; +import org.junit.Test; +import twitter4j.Status; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import twitter4j.User; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import static org.junit.Assert.*; + +public class FormatFactoryTest { + + static final String SEPARATOR = + "\n----------------------------------------------------------------------------------------\n";; + + @Test + public void testForrmatRetweets() { + + User user1 = mock(User.class); + when(user1.getName()).thenReturn("user1"); + + User user2 = mock(User.class); + when(user2.getName()).thenReturn("user2"); + + Status statusRetweeted = mock(Status.class); + + String [] argv = {""}; + JCommanderTwitter jct = new JCommanderTwitter(); + JCommander jcparser = new JCommander(jct, argv); + + when(statusRetweeted.getCreatedAt()).thenReturn( + Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant())); + when(statusRetweeted.isRetweet()).thenReturn(false); + when(statusRetweeted.getUser()).thenReturn(user2); + when(statusRetweeted.getText()).thenReturn("Hello."); + when(statusRetweeted.isRetweeted()).thenReturn(true); + when(statusRetweeted.getRetweetCount()).thenReturn(10); + + assertEquals("[только что] @user2: Hello. (10 ретвитов)" + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweeted, jct)); + when(statusRetweeted.getRetweetCount()).thenReturn(2); + assertEquals("[только что] @user2: Hello. (2 ретвита)" + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweeted, jct)); + when(statusRetweeted.getRetweetCount()).thenReturn(21); + assertEquals("[только что] @user2: Hello. (21 ретвит)" + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweeted, jct)); + when(statusRetweeted.getRetweetCount()).thenReturn(117); + assertEquals("[только что] @user2: Hello. (117 ретвитов)" + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweeted, jct)); + when(statusRetweeted.getRetweetCount()).thenReturn(204); + assertEquals("[только что] @user2: Hello. (204 ретвита)" + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweeted, jct)); + Status statusRetweet = mock(Status.class); + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant())); + + when(statusRetweet.isRetweet()).thenReturn(true); + when(statusRetweet.getUser()).thenReturn(user1); + when(statusRetweet.getRetweetedStatus()).thenReturn(statusRetweeted); + assertEquals("[только что] @user1 ретвитнул @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + + } + + @Test + public void testFormatNoRetweets() { + + String [] argv = {"--hideRetweets"}; + JCommanderTwitter jct = new JCommanderTwitter(); + JCommander jcparser = new JCommander(jct, argv); + + User marlonBrando = mock(User.class); + when(marlonBrando.getName()).thenReturn("user2"); + + Status status = mock(Status.class); + when(status.getCreatedAt()).thenReturn( + Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant())); + + when(status.isRetweet()).thenReturn(false); + when(status.getUser()).thenReturn(marlonBrando); + when(status.getText()).thenReturn("Hello."); + when(status.isRetweet()).thenReturn(false); + assertEquals("[только что] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(status, jct)); + } + + @Test + public void testTimeForms() { + + String [] argv = {"--hideRetweets"}; + JCommanderTwitter jct = new JCommanderTwitter(); + JCommander jcparser = new JCommander(jct, argv); + + User marlonBrando = mock(User.class); + when(marlonBrando.getName()).thenReturn("user2"); + + Status statusRetweet = mock(Status.class); + LocalDateTime currentTime = LocalDateTime.now(); + LocalDateTime newTime; + + + when(statusRetweet.isRetweet()).thenReturn(false); + when(statusRetweet.getUser()).thenReturn(marlonBrando); + when(statusRetweet.getText()).thenReturn("Hello."); + when(statusRetweet.isRetweet()).thenReturn(false); + + newTime = currentTime.minusHours(3); + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant())); + if (ChronoUnit.DAYS.between(newTime, currentTime) == 0) { + assertEquals("[3 часа назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + } else { + assertEquals("[вчера] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + } + + + newTime = currentTime.minusHours(1); + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant())); + if (ChronoUnit.DAYS.between(newTime, currentTime) == 0) { + assertEquals("[1 час назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + } else { + assertEquals("[вчера] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + } + + + newTime = currentTime.minusHours(10); + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant())); + if (ChronoUnit.DAYS.between(newTime, currentTime) == 0) { + assertEquals("[10 часов назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + } else { + assertEquals("[вчера] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + } + + newTime = currentTime.minusDays(1); + if (ChronoUnit.DAYS.between(newTime, currentTime) == 0) { + newTime = currentTime.minusDays(2); + } + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant())); + assertEquals("[вчера] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + + newTime = currentTime.minusDays(2); + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant())); + assertEquals("[2 дня назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + newTime = currentTime.minusDays(5); + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant())); + assertEquals("[5 дней назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + newTime = currentTime.minusDays(31); + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant())); + assertEquals("[31 день назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + newTime = currentTime.minusDays(1543); + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant())); + assertEquals("[1543 дня назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + newTime = currentTime.minusDays(111); + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant())); + assertEquals("[111 дней назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + + newTime = currentTime.minusMinutes(3); + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant())); + if (ChronoUnit.HOURS.between(newTime, currentTime) == 0) { + assertEquals("[3 минуты назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + } else { + assertEquals("[1 час назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + } + + newTime = currentTime.minusMinutes(21); + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant())); + if (ChronoUnit.HOURS.between(newTime, currentTime) == 0) { + assertEquals("[21 минуту назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + } else { + assertEquals("[1 час назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + } + + newTime = currentTime.minusMinutes(5); + when(statusRetweet.getCreatedAt()).thenReturn( + Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant())); + if (ChronoUnit.HOURS.between(newTime, currentTime) == 0) { + assertEquals("[5 минут назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + } else { + assertEquals("[1 час назад] @user2: Hello." + SEPARATOR, + FormatFactory.getTweetFormat(statusRetweet, jct)); + } + + + } +} diff --git a/Jettriangle/src/test/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/LocationMasterTest.java b/Jettriangle/src/test/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/LocationMasterTest.java new file mode 100644 index 00000000..cdf9da4c --- /dev/null +++ b/Jettriangle/src/test/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/LocationMasterTest.java @@ -0,0 +1,19 @@ +package ru.fizteh.fivt.students.Jettriangle.twitterstream; + +/** + * Created by rtriangle on 19.12.15. + */ +import org.junit.Test; + +import static org.junit.Assert.*; + +public class LocationMasterTest { + @Test + public void testGetLocation() throws Exception { + String place = "Moscow"; + double eps = 1e-5; + Location location = LocationBuilder.getLocation(place); + assertEquals(location.getLatitudeCenter(), 55.75396, eps); + assertEquals(location.getLongitudeCenter(), 37.620393, eps); + } +} diff --git a/Jettriangle/src/test/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/TwitterTest.java b/Jettriangle/src/test/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/TwitterTest.java deleted file mode 100644 index a4be372b..00000000 --- a/Jettriangle/src/test/java/ru/fizteh/fivt/students/Jettriangle/twitterstream/TwitterTest.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.fizteh.fivt.students.Jettriangle.twitterstream; - -/** - * Created by rtriangle on 14.10.15. - */ -public class TwitterTest { - -} diff --git a/Jettriangle/src/test/resources/h2test.properties b/Jettriangle/src/test/resources/h2test.properties new file mode 100644 index 00000000..3c9ddeb5 --- /dev/null +++ b/Jettriangle/src/test/resources/h2test.properties @@ -0,0 +1,3 @@ +connection_name=jdbc:h2:~/test1 +username=test1 +password=test1