diff --git a/projects/annnvl/.gitignore b/projects/annnvl/.gitignore new file mode 100644 index 0000000..5746aab --- /dev/null +++ b/projects/annnvl/.gitignore @@ -0,0 +1 @@ +twitter4j.properties diff --git a/projects/annnvl/pom.xml b/projects/annnvl/pom.xml new file mode 100644 index 0000000..2ca0a92 --- /dev/null +++ b/projects/annnvl/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + ru.mipt.diht.students + parent + 1.0-SNAPSHOT + + ru.mipt.diht.students + annnvl + 1.0-SNAPSHOT + annnvl + http://maven.apache.org + + UTF-8 + + + + junit + junit + 4.8.2 + test + + + org.twitter4j + twitter4j-stream + 4.0.4 + + + org.mockito + mockito-core + 1.10.19 + test + + + + org.hamcrest + hamcrest-junit + 2.0.0.0 + + + + com.google.code.geocoder-java + geocoder-java + 0.16 + + + com.google.maps + google-maps-services + 0.1.7 + + + com.beust + jcommander + 1.48 + + + diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/Aggregates.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/Aggregates.java new file mode 100644 index 0000000..7ea8271 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/Aggregates.java @@ -0,0 +1,60 @@ +package ru.mipt.diht.students.annnvl.CQL; +/** + * Aggregate functions. + */ +import java.util.function.Function; +import ru.mipt.diht.students.annnvl.CQL.impl.Avg; +import ru.mipt.diht.students.annnvl.CQL.impl.Count; +import ru.mipt.diht.students.annnvl.CQL.impl.Max; +import ru.mipt.diht.students.annnvl.CQL.impl.Min; + +public class Aggregates { + + /** + * Maximum value for expression for elements of given collecdtion. + * + * @param expression + * @param + * @param + * @return + */ + public static > Function max(Function expression) { + return new Max<>(expression); + } + + /** + * Minimum value for expression for elements of given collecdtion. + * + * @param expression + * @param + * @param + * @return + */ + public static > Function min(Function expression) { + return new Min<>(expression); + } + + /** + * Number of items in source collection that turns this expression into not null. + * + * @param expression + * @param + * @return + */ + public static Function count(Function expression) { + return new Count<>(expression); + } + + + /** + * Average value for expression for elements of given collection. + * + * @param expression + * @param + * @return + */ + public static Function avg(Function expression) { + return new Avg<>(expression); + } + +} \ No newline at end of file diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/CollectionQuery.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/CollectionQuery.java new file mode 100644 index 0000000..8e4d161 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/CollectionQuery.java @@ -0,0 +1,107 @@ +package ru.mipt.diht.students.annnvl.CQL; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; + +import static ru.mipt.diht.students.annnvl.CQL.Aggregates.avg; +import static ru.mipt.diht.students.annnvl.CQL.Aggregates.count; +import static ru.mipt.diht.students.annnvl.CQL.CollectionQuery.Student.student; +import static ru.mipt.diht.students.annnvl.CQL.Conditions.rlike; +import static ru.mipt.diht.students.annnvl.CQL.OrderByConditions.asc; +import static ru.mipt.diht.students.annnvl.CQL.OrderByConditions.desc; +import static ru.mipt.diht.students.annnvl.CQL.Sources.list; +import static ru.mipt.diht.students.annnvl.CQL.impl.FromStmt.from; + +public class CollectionQuery { + + public static void main(String[] args) { + Iterable statistics = + from(list( + student("ivanov", LocalDate.parse("1986-08-06"), "494"), + student("ivanov", LocalDate.parse("1986-08-06"), "494"))) + .select(Statistics.class, Student::getGroup, count(Student::getGroup), avg(Student::age)) + .where(rlike(Student::getName, ".*ov").and(s -> s.age() > 20)) + .groupBy(Student::getGroup) + .having(s -> s.getCount() > 0) + .orderBy(asc(Student::getGroup), desc(count(Student::getGroup))) + .limit(100) + .union() + .from(list(student("ivanov", LocalDate.parse("1985-08-06"), "494"))) + .selectDistinct(Statistics.class, s -> "all", count(s -> 1), avg(Student::age)) + .execute(); + System.out.println(statistics); + } + + + public static class Student { + private final String name; + + private final LocalDate dateOfBith; + + private final String group; + + public String getName() { + return name; + } + + public Student(String name, LocalDate dateOfBith, String group) { + this.name = name; + this.dateOfBith = dateOfBith; + this.group = group; + } + + public LocalDate getDateOfBith() { + return dateOfBith; + } + + public String getGroup() { + return group; + } + + public long age() { + return ChronoUnit.YEARS.between(getDateOfBith(), LocalDateTime.now()); + } + + public static Student student(String name, LocalDate dateOfBith, String group) { + return new Student(name, dateOfBith, group); + } + } + + + public static class Statistics { + + private final String group; + private final Long count; + private final Long age; + + public String getGroup() { + return group; + } + + public Long getCount() { + return count; + } + + + public Long getAge() { + return age; + } + + public Statistics(String group, Long count, Long age) { + this.group = group; + this.count = count; + this.age = age; + } + + @Override + public String toString() { + return "Statistics{" + + "group='" + group + '\'' + + ", count=" + count + + ", age=" + age + + '}'; + } + } + +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/Conditions.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/Conditions.java new file mode 100644 index 0000000..5ed9e17 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/Conditions.java @@ -0,0 +1,37 @@ +package ru.mipt.diht.students.annnvl.CQL; + +import java.util.function.Function; +import java.util.function.Predicate; + +/** + * Where clause conditions. + */ +public class Conditions { + + /** + * Matches string result of expression against regexp pattern. + * + * @param expression expression result to match + * @param regexp pattern to match to + * @param source object type + * @return + */ + public static Predicate rlike(Function expression, String regexp) { + return element -> expression.apply(element).matches(regexp); + } + + /** + * Matches string result of expression against SQL like pattern. + * + * @param expression expression result to match + * @param pattern pattern to match to + * @param source object type + * @return + */ + public static Predicate like(Function expression, String pattern) { + String newpattern = pattern.toLowerCase(); + newpattern = newpattern.replace(".", "\\.").replace("?", ".").replace("%", ".*"); + return rlike(expression, newpattern); + } + +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/OrderByConditions.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/OrderByConditions.java new file mode 100644 index 0000000..a9772d4 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/OrderByConditions.java @@ -0,0 +1,37 @@ +package ru.mipt.diht.students.annnvl.CQL; + +import java.util.Comparator; +import java.util.function.Function; + +/** + * OrderBy sort order helper methods. + */ +public class OrderByConditions { + + /** + * Ascending comparator. + * + * @param expression + * @param + * @param + * @return + */ + public static > Comparator asc(Function expression) { + return (o1, o2) -> expression.apply(o1).compareTo(expression.apply(o2)); + } + + /** + * Descending comparator. + * + * @param expression + * @param + * @param + * @return + */ + public static > Comparator desc(Function expression) { + return (o1, o2) -> expression.apply(o2).compareTo(expression.apply(o1)); + } + +} + + diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/Sources.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/Sources.java new file mode 100644 index 0000000..99ca271 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/Sources.java @@ -0,0 +1,54 @@ +package ru.mipt.diht.students.annnvl.CQL; + +import java.io.InputStream; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; + +/** + * Helper methods to create collections. + */ +public class Sources { + + /** + * @param items + * @param + * @return + */ + @SafeVarargs + public static List list(T... items) { + return Arrays.asList(items); + } + + /** + * @param items + * @param + * @return + */ + @SafeVarargs + public static Set set(T... items) { + throw new UnsupportedOperationException(); + } + + /** + * @param inputStream + * @param + * @return + */ + public static Stream lines(InputStream inputStream) { + throw new UnsupportedOperationException(); + } + + /** + * @param file + * @param + * @return + */ + public static Stream lines(Path file) { + throw new UnsupportedOperationException(); + } + +} + diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Aggregator.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Aggregator.java new file mode 100644 index 0000000..11ba369 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Aggregator.java @@ -0,0 +1,8 @@ +package ru.mipt.diht.students.annnvl.CQL.impl; + +import java.util.List; +import java.util.function.Function; + +public interface Aggregator extends Function { + R apply(List elements); +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Avg.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Avg.java new file mode 100644 index 0000000..dc79538 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Avg.java @@ -0,0 +1,27 @@ +package ru.mipt.diht.students.annnvl.CQL.impl; + +import java.util.List; +import java.util.function.Function; + +public class Avg implements Aggregator { + + private Function function; + public Avg(Function expression) { + this.function = expression; + } + + @Override + public Double apply(List elements) { + return elements + .stream() + .map(function) + .mapToDouble(element -> (Double) element) + .average() + .getAsDouble(); + } + + @Override + public Double apply(T t) { + return null; + } +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Count.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Count.java new file mode 100644 index 0000000..8553f70 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Count.java @@ -0,0 +1,26 @@ +package ru.mipt.diht.students.annnvl.CQL.impl; + +import java.util.List; +import java.util.function.Function; + +public class Count implements Aggregator { + + private Function function; + public Count(Function expression) { + this.function = expression; + } + + @Override + public Integer apply(List elements) { + Long longAns = elements + .stream() + .map(function) + .distinct() + .count(); + return longAns.intValue(); + } + @Override + public Integer apply(T t) { + return null; + } +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/FromStmt.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/FromStmt.java new file mode 100644 index 0000000..308073e --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/FromStmt.java @@ -0,0 +1,91 @@ +package ru.mipt.diht.students.annnvl.CQL.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.function.BiPredicate; +import java.util.function.Function; + +public class FromStmt { + + private List elements = new ArrayList(); + + public FromStmt(Iterable iterable) { + for (T element : iterable) { + elements.add(element); + } + } + + public static FromStmt from(Iterable iterable) { + return new FromStmt<>(iterable); + } + + @SafeVarargs + public final SelectStmt select(Class returnClass, Function... functions) { + return new SelectStmt<>(elements, returnClass, false, functions); + } + + @SafeVarargs + public final SelectStmt selectDistinct(Class returnClass, Function... functions) { + return new SelectStmt<>(elements, returnClass, true, functions); + } + + public final SelectStmt> select(Function first, Function second) { + return new SelectStmt<>(elements, false, first, second); + } + + public JoinClause join(Iterable iterable) { + return new JoinClause(elements, iterable); + } + + public class JoinClause { + + + private List firstElements = new ArrayList<>(); + private List secondElements = new ArrayList<>(); + private List> elements = new ArrayList<>(); + + public JoinClause(List firstElements, Iterable secondElements) { + this.firstElements.addAll(firstElements); + secondElements.forEach(this.secondElements::add); + } + + public FromStmt> on(BiPredicate condition) { + for (S first : firstElements) { + for (J second : secondElements) { + if (condition.test(first, second)) { + elements.add(new Tuple<>(first, second)); + } + } + } + return new FromStmt<>(elements); + } + + public > FromStmt> on( + Function leftKey, + Function rightKey) { + HashMap> map = new HashMap<>(); + for (J element : secondElements) { + K key = rightKey.apply(element); + if (!map.containsKey(key)) { + map.put(key, new ArrayList<>()); + } + map.get(key).add(element); + } + for (S first : firstElements) { + K key = leftKey.apply(first); + if (map.containsKey(key)) { + List second = map.get(key); + second.forEach(s -> elements.add(new Tuple<>(first, s))); + } + } + return new FromStmt<>(elements); + } + } + + public List getElements() { + return elements; + } +} + + diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Max.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Max.java new file mode 100644 index 0000000..4133fae --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Max.java @@ -0,0 +1,37 @@ +package ru.mipt.diht.students.annnvl.CQL.impl; + +import java.util.List; +import java.util.function.Function; + +public class Max> implements Aggregator { + + private Function function; + public Max(Function expression) { + this.function = expression; + } + + @Override + public R apply(List elements) { + return elements + .stream() + .map(function) + .reduce(null, (a, b) -> { + if (a == null) { + return b; + } + if (b == null) { + return a; + } + if (a.compareTo(b) > 0) { + return a; + } else { + return b; + } + }); + } + + @Override + public R apply(T t) { + return null; + } +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Min.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Min.java new file mode 100644 index 0000000..a737cd6 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Min.java @@ -0,0 +1,38 @@ +package ru.mipt.diht.students.annnvl.CQL.impl; + +import java.util.List; +import java.util.function.Function; + +public class Min> implements Aggregator { + + private Function function; + public Min(Function expression) { + this.function = expression; + } + + @Override + public R apply(List elements) { + return elements + .stream() + .map(function) + + .reduce(null, (a, b) -> { + if (a == null) { + return b; + } + if (b == null) { + return a; + } + if (a.compareTo(b) < 0) { + return a; + } else { + return b; + } + }); + } + + @Override + public R apply(T t) { + return null; + } +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Query.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Query.java new file mode 100644 index 0000000..3b94998 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Query.java @@ -0,0 +1,13 @@ +package ru.mipt.diht.students.annnvl.CQL.impl; + +import java.lang.reflect.InvocationTargetException; +import java.util.stream.Stream; + +public interface Query { + + Iterable execute() throws NoSuchMethodException, IllegalAccessException, + InvocationTargetException, InstantiationException; + + Stream stream(); +} + diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/SelectStmt.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/SelectStmt.java new file mode 100644 index 0000000..54c57de --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/SelectStmt.java @@ -0,0 +1,230 @@ +package ru.mipt.diht.students.annnvl.CQL.impl; + +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class SelectStmt { + + private boolean isDistinct; + private Class returnClass; + private Function[] functions; + private List elements; + + private List pastElements; + + private Predicate whereCondition; + private Comparator[] comparators; + private Predicate havingCondition; + private int numberOfObjects; + private Function[] groupByConditions; + + private CQLComparator cqlComparator; + private boolean isUnion; + private boolean isJoin; + + @SafeVarargs + public SelectStmt(List elements, Class returnClass, boolean isDistinct, Function... functions) { + this.elements = new ArrayList<>(); + this.elements.addAll(elements); + this.returnClass = returnClass; + this.isDistinct = isDistinct; + this.functions = functions; + this.numberOfObjects = -1; + this.isUnion = false; + this.isJoin = false; + } + + public SelectStmt(List elements, boolean isDistinct, Function first, Function second) { + this.elements = new ArrayList<>(); + this.elements.addAll(elements); + this.returnClass = elements.get(0).getClass(); + this.isDistinct = isDistinct; + this.functions = new Function[]{first, second}; + this.numberOfObjects = -1; + this.isUnion = false; + this.isJoin = true; + } + + @SafeVarargs + public SelectStmt(List pastElements, List elements, Class returnClass, + boolean isDistinct, Function... functions) { + this.elements = new ArrayList<>(); + this.elements.addAll(elements); + this.returnClass = returnClass; + this.isDistinct = isDistinct; + this.functions = functions; + this.numberOfObjects = -1; + this.isUnion = true; + this.pastElements = pastElements; + } + + public SelectStmt(List pastElements, List elements, boolean isDistinct, Function first, + Function second) { + this.elements = new ArrayList<>(); + this.elements.addAll(elements); + this.returnClass = elements.get(0).getClass(); + this.isDistinct = isDistinct; + this.functions = new Function[]{first, second}; + this.numberOfObjects = -1; + this.isUnion = true; + this.isJoin = true; + this.pastElements = pastElements; + } + + public SelectStmt where(Predicate predicate) { + this.whereCondition = predicate; + return this; + } + + @SafeVarargs + public final SelectStmt groupBy(Function... expressions) { + groupByConditions = expressions; + //groupByConditions = Arrays.asList(expressions); + return this; + } + + @SafeVarargs + public final SelectStmt orderBy(Comparator... comparators) { + this.comparators = comparators; + this.cqlComparator = new CQLComparator(comparators); + return this; + } + + public SelectStmt having(Predicate condition) { + this.havingCondition = condition; + return this; + } + + public SelectStmt limit(int amount) { + this.numberOfObjects = amount; + return this; + } + + public Iterable execute() throws NoSuchMethodException, IllegalAccessException, + InvocationTargetException, InstantiationException { + List result = new ArrayList<>(); + Class[] returnClasses = new Class[functions.length]; + if (whereCondition != null) { + elements = elements + .stream() + .filter(whereCondition::test) + .collect(Collectors.toList()); + } + if (groupByConditions != null) { + + Map> groupedMap = elements + .stream() + .collect(Collectors.groupingBy((T element) -> { + List answer = new ArrayList<>(); + for (int i = 0; i < groupByConditions.length; ++i) { + answer.add(groupByConditions[i].apply(element)); + } +/* + List answer = groupByConditions + .stream() + .map(cond -> cond.apply(element)) + .collect(Collectors.toList()); +*/ + return answer.hashCode(); + })); + + List> groupedList = groupedMap + .entrySet() + .stream() + .map(Map.Entry::getValue) + .collect(Collectors.toList()); + + Object[] arguments = new Object[functions.length]; + for (List group : groupedList) { + for (int i = 0; i < functions.length; i++) { + if (functions[i] instanceof Aggregator) { + arguments[i] = ((Aggregator) functions[i]).apply(group); + } else { + arguments[i] = functions[i].apply(group.get(0)); + } + returnClasses[i] = arguments[i].getClass(); + } + if (isJoin) { + Tuple newElement = new Tuple(arguments[0], arguments[1]); + result.add((R) newElement); + } else { + R newElement = (R) returnClass.getConstructor(returnClasses).newInstance(arguments); + result.add(newElement); + } + } + } else { + Object[] arguments = new Object[functions.length]; + for (T element : this.elements) { + for (int i = 0; i < functions.length; i++) { + arguments[i] = functions[i].apply(element); + if (functions[i] instanceof Aggregator) { + List currArg = new ArrayList<>(); + currArg.add(element); + arguments[i] = ((Aggregator) functions[i]).apply(currArg); + } else { + arguments[i] = functions[i].apply(element); + } + returnClasses[i] = arguments[i].getClass(); + } + if (isJoin) { + Tuple newElement = new Tuple(arguments[0], arguments[1]); + result.add((R) newElement); + } else { + R newElement = (R) returnClass.getConstructor(returnClasses).newInstance(arguments); + result.add(newElement); + } + } + } + Stream resultStream = result.stream(); + if (havingCondition != null) { + resultStream = resultStream.filter(havingCondition::test); + } + if (isDistinct) { + resultStream = resultStream.distinct(); + } + if (comparators != null) { + resultStream = resultStream.sorted(cqlComparator); + } + if (numberOfObjects != -1) { + resultStream = resultStream.limit(numberOfObjects); + } + result = resultStream.collect(Collectors.toList()); + if (isUnion) { + pastElements.addAll(result); + result = pastElements; + } + return result; + } + + public UnionStmt union() throws InvocationTargetException, NoSuchMethodException, + InstantiationException, IllegalAccessException { + List result = (List) this.execute(); + if (isJoin) { + return new UnionStmt<>(result, true); + } else { + return new UnionStmt<>(result); + } + } + + public class CQLComparator implements Comparator { + private Comparator[] comparators; + @SafeVarargs + public CQLComparator(Comparator... comparators) { + this.comparators = comparators; + } + + @Override + public int compare(K first, K second) { + for (Comparator comparator : comparators) { + if (comparator.compare(first, second) != 0) { + return comparator.compare(first, second); + } + } + return 0; + } + } +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Tuple.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Tuple.java new file mode 100644 index 0000000..cefbaad --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/Tuple.java @@ -0,0 +1,28 @@ +package ru.mipt.diht.students.annnvl.CQL.impl; + +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 + + '}'; + } +} \ No newline at end of file diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/UnionStmt.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/UnionStmt.java new file mode 100644 index 0000000..64c2497 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/CQL/impl/UnionStmt.java @@ -0,0 +1,119 @@ +package ru.mipt.diht.students.annnvl.CQL.impl; + +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 pastElements = new ArrayList<>(); + + private List elements = new ArrayList<>(); + + private boolean isTuple; + + public UnionStmt(Iterable iterable) { + for (R curr : iterable) { + pastElements.add(curr); + } + this.isTuple = false; + } + + public UnionStmt(Iterable iterable, boolean isTuple) { + for (R curr : iterable) { + pastElements.add(curr); + } + this.isTuple = true; + } + + public FromClause from(Iterable elements) { + if (isTuple) { + return new FromClause(pastElements, elements); + } else { + return new FromClause(pastElements, /*(Iterable)*/ elements); + } + } + + public class FromClause { + private List pastElements = new ArrayList<>(); + + private List elements = new ArrayList<>(); + + public FromClause(Iterable pastElements, Iterable elements) { + for (R curr : pastElements) { + this.pastElements.add(curr); + } + for (S curr : elements) { + this.elements.add(curr); + } + } + @SafeVarargs + public final SelectStmt select(Class returnClass, Function... functions) { + return new SelectStmt((List) pastElements, elements, returnClass, false, functions); + } + + public final SelectStmt> select(Function first, Function second) { + return new SelectStmt>((List>) pastElements, elements, false, first, second); + } + + @SafeVarargs + public final SelectStmt selectDistinct(Class returnClass, Function... functions) { + return new SelectStmt((List) pastElements, elements, returnClass, true, functions); + } + + public JoinClause join(Iterable iterable) { + return new JoinClause(pastElements, elements, iterable); + } + } + + public class JoinClause { + + private List firstElements = new ArrayList<>(); + private List secondElements = new ArrayList<>(); + private List pastElements = new ArrayList<>(); + private List> elements = new ArrayList<>(); + + public JoinClause(List pastElements, List firstElements, Iterable secondElements) { + this.pastElements.addAll(pastElements.stream().collect(Collectors.toList())); + this.firstElements.addAll(firstElements.stream().collect(Collectors.toList())); + for (J curr : secondElements) { + this.secondElements.add(curr); + } + } + + public FromClause, R> on(BiPredicate condition) { + for (F first : firstElements) { + for (J second : secondElements) { + if (condition.test(first, second)) { + elements.add(new Tuple<>(first, second)); + } + } + } + return new FromClause<>(pastElements, elements); + } + + public > FromClause, R> on( + Function leftKey, + Function rightKey) { + HashMap> map = new HashMap<>(); + for (J element : secondElements) { + K key = rightKey.apply(element); + if (!map.containsKey(key)) { + map.put(key, new ArrayList<>()); + } + map.get(key).add(element); + } + for (F first : firstElements) { + K key = leftKey.apply(first); + if (map.containsKey(key)) { + List second = map.get(key); + second.forEach(s -> elements.add(new Tuple<>(first, s))); + } + } + return new FromClause<>(pastElements, elements); + } + } +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Reverser/Reverser.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Reverser/Reverser.java deleted file mode 100644 index 0111247..0000000 --- a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Reverser/Reverser.java +++ /dev/null @@ -1,10 +0,0 @@ -package main.java.ru.mipt.diht.students.annnvl.Reverser; -public class Reverser { - public static void main(String[] args) { - for (int i = args.length - 1; i >= 0; i--) { - String[] numbers = args[i].split("\\s+"); - for (int j = numbers.length - 1; j >= 0; j--) - System.out.print(numbers[j] + " "); - } - } -} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/BlockingQueue/BlockingQueue.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/BlockingQueue/BlockingQueue.java new file mode 100644 index 0000000..f1aa545 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/BlockingQueue/BlockingQueue.java @@ -0,0 +1,66 @@ +package ru.mipt.diht.students.annnvl.Threads.BlockingQueue; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +public class BlockingQueue { + private final int maxQueueSize; + private Queue data; + + BlockingQueue(int size) { + maxQueueSize = size; + data = new LinkedList(); + } + + public final int size() { + return data.size(); + } + + synchronized void offer(List e) { + while (data.size() + e.size() > maxQueueSize) { + Thread.yield(); + } + data.addAll(e); + } + + synchronized void offer(List e, long timeout) throws InterruptedException{ + timeout += System.currentTimeMillis(); + while ((data.size() + e.size() > maxQueueSize) && (timeout - System.currentTimeMillis()) > 0) { + wait(timeout - System.currentTimeMillis()); + } + if (timeout > 0) { + data.addAll(e); + } + notifyAll(); + } + + synchronized List take(int n) { + while (data.size() < n) { + Thread.yield(); + } + List answer = new ArrayList(); + for (int i = 0; i < n; i++) { + answer.add(data.remove()); + } + return answer; + } + + synchronized List take(int n, long timeout) throws InterruptedException{ + timeout += System.currentTimeMillis(); + while ((data.size() < n) && (timeout - System.currentTimeMillis()) > 0) { + wait(timeout - System.currentTimeMillis()); + } + if (timeout > 0) { + List answer = new ArrayList(); + for (int i = 0; i < n; i++) { + answer.add(data.remove()); + } + notifyAll(); + return answer; + } + notifyAll(); + return null; + } +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/Counter/CountedThread.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/Counter/CountedThread.java new file mode 100644 index 0000000..aec2b59 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/Counter/CountedThread.java @@ -0,0 +1,26 @@ +package ru.mipt.diht.students.annnvl.Threads.Counter; + +public class CountedThread extends Thread { + private static int numberOfThreads; + private static volatile int currentThread = 0; + private final int myNumber; + + CountedThread(int mynum) { + myNumber = mynum; + } + + public static void setNumberOfThreads(int num) { + numberOfThreads = num; + } + + @Override + public final void run() { + while (true) { + while (myNumber != currentThread) { + Thread.yield(); + } + System.out.println("Thread-" + (myNumber + 1)); + currentThread = (currentThread + 1) % numberOfThreads; + } + } +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/Counter/Counter.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/Counter/Counter.java new file mode 100644 index 0000000..c51271e --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/Counter/Counter.java @@ -0,0 +1,14 @@ +package ru.mipt.diht.students.annnvl.Threads.Counter; + +public class Counter { + public static void main(String[] args) { + if (args.length < 1) { + throw new IllegalArgumentException("Please type number of threads"); + } + int threads = Integer.parseInt(args[0]); + CountedThread.setNumberOfThreads(threads); + for (int i = 0; i < threads; i++) { + (new CountedThread(i)).start(); + } + } +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/RollCall/RollCall.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/RollCall/RollCall.java new file mode 100644 index 0000000..11ffca8 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/RollCall/RollCall.java @@ -0,0 +1,27 @@ +package ru.mipt.diht.students.annnvl.Threads.RollCall; + +public class RollCall { + public static void main(String[] args) { + if (args.length < 1) { + throw new IllegalArgumentException("Please type number of threads"); + } + int threads = Integer.parseInt(args[0]); + RollCallerThread.setNumberOfThreads(threads); + for (int i = 0; i < threads; i++) { + (new RollCallerThread()).start(); + } + while (true) { + RollCallerThread.makeEverybodyOk(); + System.out.println("Are you ready?"); + RollCallerThread.nextRollCall(); + while (!RollCallerThread.everybodyasked()) { + Thread.yield(); + } + if (RollCallerThread.isEverybodyOk()) { + RollCallerThread.yes(); + RollCallerThread.nextRollCall(); + return; + } + } + } +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/RollCall/RollCallerThread.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/RollCall/RollCallerThread.java new file mode 100644 index 0000000..a0fd3c3 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/Threads/RollCall/RollCallerThread.java @@ -0,0 +1,67 @@ +package ru.mipt.diht.students.annnvl.Threads.RollCall; + +import java.util.Random; + +public class RollCallerThread extends Thread { + private static final int HUNDREED = 100; + private static final double LOWERBOUND = 0.1; + private static int numberOfThreads; + private static volatile int asked = 0; + private static volatile int timesShouldBe = -1; //какой раз мы проводим опрос + private static boolean yes4all = false; + private static boolean everybodyOk = true; + private Random rand; + private int timesNum; //какой раз мы вызываем конкретный процесс + + RollCallerThread() { + rand = new Random(HUNDREED); + timesNum = 0; + } + + public static void setNumberOfThreads(int num) { + numberOfThreads = num; + } + + public static void yes() { + yes4all = true; + } + + public static boolean isEverybodyOk() { + return everybodyOk; + } + + public static void makeEverybodyOk() { + everybodyOk = true; + } + + public static void nextRollCall() { + timesShouldBe++; + asked = 0; + } + + public static boolean everybodyasked() { + return (asked == numberOfThreads); + } + + @Override + public final void run() { + while (true) { + synchronized (this) { + while (timesNum != timesShouldBe) { + Thread.yield(); + } + if (yes4all) { + return; + } + timesNum++; + if (rand.nextDouble() < LOWERBOUND) { + System.out.println("No"); + everybodyOk = false; + } else { + System.out.println("Yes"); + } + asked++; + } + } + } +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/FindPlace.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/FindPlace.java new file mode 100644 index 0000000..6285497 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/FindPlace.java @@ -0,0 +1,51 @@ +package ru.mipt.diht.students.annnvl.TwitterStream; + +import com.google.maps.GeoApiContext; +import com.google.maps.GeocodingApi; +import com.google.maps.model.Bounds; +import com.google.maps.model.GeocodingResult; +import com.google.maps.model.LatLng; + +public class FindPlace { + private static final double R = 6371; + private GeocodingResult[] result; + private double radius; + + FindPlace(String place) { + GeoApiContext context = new GeoApiContext().setApiKey("AIzaSyCAhkvmjepUzQUh9pA7g0K4QoQY2ncBno8"); + try { + result = GeocodingApi.geocode(context, place).await(); + radius = calculateRadius(); + } catch (Exception e) { + System.out.println(e.getMessage()); + System.exit(-1); + } + } + + private double calculateRadius() { + double x1 = Math.toRadians(result[0].geometry.bounds.northeast.lat); + double x2 = Math.toRadians(result[0].geometry.bounds.southwest.lat); + double dx = x1 - x2; + double lambda1; + lambda1 = Math.toRadians(result[0].geometry.bounds.northeast.lng); + double lambda2; + lambda2 = Math.toRadians(result[0].geometry.bounds.southwest.lng); + double dLambda = lambda1 - lambda2; + + double a = Math.sin(dx / 2) * Math.sin(dx / 2) + Math.cos(x1) * Math.cos(x2) + * Math.sin(dLambda / 2) * Math.sin(dLambda / 2); + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + double distance = R * c; + return distance / 2; + } + + public final LatLng getLocation() { + return result[0].geometry.location; + } + public final double getRadius() { + return radius; + } + public final Bounds getBounds() { + return result[0].geometry.bounds; + } +}; diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/Format.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/Format.java new file mode 100644 index 0000000..2144491 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/Format.java @@ -0,0 +1,27 @@ +package ru.mipt.diht.students.annnvl.TwitterStream; + +public class Format { + + public static final String[] MINUTES = {" минуту ", " минуты ", " минут "}; + public static final String[] HOURS = {" час ", " часа ", " часов "}; + public static final String[] DAYS = {" день ", " дня ", " дней "}; + public static final String[] RETWEETS = {" ретвит", " ретвита", " ретвитов"}; + + public static final short FIVE = 5; + public static final short TEN = 10; + public static final short ELEVEN = 11; + public static final long FIFTEEN = 15; + public static final long HUNDRED = 100; + + public static int strForm(long number) { + if (number % TEN == 1 && number % HUNDRED != ELEVEN) { + return 0; + } + if (number % TEN > 1 && number % TEN < FIVE && (number % HUNDRED < FIVE || number % HUNDRED > FIFTEEN)) { + return 1; + } + return 2; + } +} + + diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/Parameters.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/Parameters.java new file mode 100644 index 0000000..338b42a --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/Parameters.java @@ -0,0 +1,62 @@ +package ru.mipt.diht.students.annnvl.TwitterStream; + +import com.beust.jcommander.Parameter; + +class Parameters { + + public static final int HUNDRED = 100; + @Parameter(names = {"-q", "--query"}, + description = "Запрос или ключевые слова") + private String query = ""; + @Parameter(names = {"-p", "--place"}, + description = "Место поиска") + private String place = ""; + @Parameter(names = {"-s", "--stream"}, + description = "Стрим") + private boolean stream = false; + @Parameter(names = {"--hideRetwitts"}, + description = "Прятать ретвиты") + private boolean hideRetweets = false; + @Parameter(names = {"-h", "--help"}, + description = "Выводит подсказку") + private boolean help = false; + @Parameter(names = {"-l", "--limit"}, + description = "Ограничение на количество" + " выводимых твитов (не в стриме)") + private Integer limit = HUNDRED; + + public final String getQuery() { + return query; + } + + public final String getPlace() { + return place; + } + + public final Integer getLimit() { + return limit; + } + + public final boolean isStream() { + return stream; + } + + public final boolean isHideRetweets() { + return hideRetweets; + } + + public final boolean isHelp() { + return help; + } + + public final void setQuery(String query) { query = query; } + + public final void setLimit(Integer limit) { limit = limit; } + + public final void setStream(boolean stream) { stream = stream; } + + public final void setHideRetweets(boolean hideRetweets) { hideRetweets = hideRetweets; } + + public final void setHelp(boolean help) { help = help; } + + public final void setPlace(String place) { place = place; } +}; diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/PrintTime.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/PrintTime.java new file mode 100644 index 0000000..7ce73b7 --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/PrintTime.java @@ -0,0 +1,43 @@ +package ru.mipt.diht.students.annnvl.TwitterStream; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.temporal.ChronoUnit; +import java.util.Date; + +public class PrintTime { + + public static String printTime(long tweetForm, long curForm) { + + Format timeFormat = new Format(); + + LocalDateTime curTime = new Date(curForm).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + LocalDateTime tweetTime = new Date(tweetForm).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + + if (ChronoUnit.MINUTES.between(tweetTime, curTime) < 2) { + return "только что"; + } else { + if (ChronoUnit.HOURS.between(tweetTime, curTime) < 1) { + return new StringBuilder().append(ChronoUnit.MINUTES.between(tweetTime, curTime)) + .append(timeFormat.MINUTES[timeFormat.strForm(ChronoUnit.MINUTES.between(tweetTime, curTime))]) + .append("назад").toString(); + } else { + if (ChronoUnit.DAYS.between(tweetTime, curTime) < 1) { + return new StringBuilder().append(ChronoUnit.HOURS.between(tweetTime, curTime)) + .append(timeFormat.HOURS[timeFormat.strForm(ChronoUnit.HOURS.between(tweetTime, curTime))]) + .append("назад").toString(); + } else { + LocalDateTime tweetDateTime = tweetTime.toLocalDate().atStartOfDay(); + LocalDateTime curDateTime = curTime.toLocalDate().atStartOfDay(); + if (ChronoUnit.DAYS.between(tweetDateTime, curDateTime) == 1) { + return "вчера"; + } else { + return new StringBuilder().append(ChronoUnit.DAYS.between(tweetDateTime, curDateTime)) + .append(timeFormat.DAYS[timeFormat.strForm(ChronoUnit.DAYS.between(tweetDateTime, curDateTime))]) + .append("назад").toString(); + } + } + } + } + } +} diff --git a/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/TwitterStream.java b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/TwitterStream.java new file mode 100644 index 0000000..d96639b --- /dev/null +++ b/projects/annnvl/src/main/java/ru/mipt/diht/students/annnvl/TwitterStream/TwitterStream.java @@ -0,0 +1,145 @@ +package ru.mipt.diht.students.annnvl.TwitterStream; + +import twitter4j.*; +import com.beust.jcommander.JCommander; + +import java.util.ArrayList; +import java.util.List; + +import static java.lang.Thread.sleep; + +public class TwitterStream { + + public static final int PAUSE = 1000; + + public static void printTime(Status status) { + PrintTime printer = new PrintTime(); + System.out.print(new StringBuilder().append("[") + .append(printer.printTime(status.getCreatedAt().getTime(), System.currentTimeMillis())).append("]")); + } + + public static void printTweet(Status status, boolean hideRetweets) { + if (status.isRetweet()) { + if (!hideRetweets) { + printTime(status); + System.out.println(new StringBuilder().append("@").append(status.getUser().getName()) + .append(" ретвитнул: @").append(status.getRetweetedStatus().getUser().getName()).append(": ") + .append(status.getRetweetedStatus().getText()).toString()); + } + } else { + Format retweetFormat = new Format(); + printTime(status); + System.out.print(new StringBuilder().append("@").append(status.getUser().getName()).append(": ") + .append(status.getText()).append(retweetFormat.strForm(status.getRetweetCount()))); + System.out.println(); + } + } + + public static Query setQuery(Parameters param) throws Exception { + Query query = new Query(param.getQuery()); + if (!param.getPlace().isEmpty()) { + FindPlace googleFindPlace; + googleFindPlace = new FindPlace(param.getPlace()); + GeoLocation geoLocation; + geoLocation = new GeoLocation(googleFindPlace.getLocation().lat, googleFindPlace.getLocation().lng); + query.setGeoCode(geoLocation, googleFindPlace.getRadius(), Query.KILOMETERS); + } + return query; + } + + public static List search(Parameters param) throws Exception { + Twitter twitter = new TwitterFactory().getInstance(); + Query query = setQuery(param); + QueryResult result; + int limit = param.getLimit(); + int statusCount = 0; + List tweets = new ArrayList<>(); + do { + result = twitter.search(query); + for (Status status : result.getTweets()) { + if (status.isRetweet() && param.isHideRetweets()) + continue; + tweets.add(status); + printTime(status); + printTweet(status, param.isHideRetweets()); + statusCount++; + limit--; + if (limit == 0) { + break; + } + } + query = result.nextQuery(); + } while (query != null && limit > 0); + if (statusCount == 0) { + System.out.println("Подходящих твитов нет"); + } + return tweets; + } + + public static FilterQuery setFilter(Parameters param) throws Exception{ + String[] track = new String[1]; + track[0] = param.getQuery(); + long[] follow = new long[0]; + FilterQuery filter = new FilterQuery(0, follow, track); + if (!param.getPlace().isEmpty()) { + FindPlace googleFindPlace; + googleFindPlace = new FindPlace(param.getPlace()); + double[][] bounds = {{googleFindPlace.getBounds().southwest.lng, googleFindPlace.getBounds().southwest.lat}, + {googleFindPlace.getBounds().northeast.lng, googleFindPlace.getBounds().northeast.lat}}; + filter.locations(bounds); + } + return filter; + } + + public static void stream(Parameters param, StatusListener listener) throws Exception { + twitter4j.TwitterStream twitterStream; + twitterStream = new TwitterStreamFactory().getInstance(); + twitterStream.addListener(listener); + if (param.getQuery() == "" && param.getPlace() == "") { + twitterStream.sample(); + } else { + FilterQuery filter = setFilter(param); + twitterStream.filter(filter); + } + } + + public static void main(String[] args) throws Exception { + final Parameters param = new Parameters(); + JCommander cmd = new JCommander(param, args); + if (param.isHelp()) { + cmd.usage(); + System.exit(0); + } + if (param.isStream()) { + StatusListener listener = new StatusAdapter() { + @Override + public void onStatus(Status status) { + printTweet(status, param.isHideRetweets()); + try { + sleep(PAUSE); + } catch (InterruptedException e) { + System.out.println(e.getMessage()); + } + } + }; + try { + stream(param, listener); + } catch (TwitterException e) { + System.out.println(e.getMessage()); + stream(param, listener); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + try { + search(param); + } catch (TwitterException e) { + System.out.println(e.getMessage()); + search(param); + } catch (Exception e) { + e.printStackTrace(); + } + } + } +}; + diff --git a/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/FindPlaceTest.java b/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/FindPlaceTest.java new file mode 100644 index 0000000..246eea4 --- /dev/null +++ b/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/FindPlaceTest.java @@ -0,0 +1,35 @@ +package ru.mipt.diht.students.annnvl.TwitterStream; + + +import org.junit.Test; +import org.junit.runner.RunWith; +import junit.framework.TestCase; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class FindPlaceTest extends TestCase { + + static final double LAT_Moscow = 55.755826; + static final double LONG_Moscow = 37.6173; + + static final double LAT_London = 51.5085300; + static final double LONG_London = -0.1257400; + + static final double LAT_NewYork = 40.7142700; + static final double LONG_NewYork = -74.0059700; + + @Test + public void LocationTest() throws Exception { + FindPlace location1 = new FindPlace("Moscow"); + assert (LAT_Moscow == Math.rint(location1.getLocation().lat * 1000000.0) / 1000000.0); + assert (LONG_Moscow == Math.rint(location1.getLocation().lng * 1000000.0) / 1000000.0); + + FindPlace location2= new FindPlace("London"); + assert (LAT_London == Math.rint(location2.getLocation().lat * 1000000.0) / 1000000.0); + assert (LONG_London == Math.rint(location2.getLocation().lng * 1000000.0) / 1000000.0); + + FindPlace location3= new FindPlace("NewYork"); + assert (LAT_NewYork == Math.rint(location3.getLocation().lat * 1000000.0) / 1000000.0); + assert (LONG_NewYork == Math.rint(location3.getLocation().lng * 1000000.0) / 1000000.0); + } +} diff --git a/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/FormatTest.java b/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/FormatTest.java new file mode 100644 index 0000000..c6e0840 --- /dev/null +++ b/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/FormatTest.java @@ -0,0 +1,50 @@ +package ru.mipt.diht.students.annnvl.TwitterStream; + +import org.junit.Assert; +import org.junit.Test; + +public class FormatTest { + @Test + public void testFormat() throws Exception { + Assert.assertEquals("минут", Format.MINUTES[Format.strForm(0)]); + Assert.assertEquals("минуту", Format.MINUTES[Format.strForm(1)]); + Assert.assertEquals("минуты", Format.MINUTES[Format.strForm(2)]); + Assert.assertEquals("минут", Format.MINUTES[Format.strForm(10)]); + Assert.assertEquals("минуты", Format.MINUTES[Format.strForm(32)]); + Assert.assertEquals("минут", Format.MINUTES[Format.strForm(55)]); + Assert.assertEquals("минуту", Format.MINUTES[Format.strForm(121)]); + Assert.assertEquals("минут", Format.MINUTES[Format.strForm(500)]); + Assert.assertEquals("минуты", Format.MINUTES[Format.strForm(672)]); + Assert.assertEquals("минут", Format.MINUTES[Format.strForm(765)]); + Assert.assertEquals("дней", Format.DAYS[Format.strForm(0)]); + Assert.assertEquals("день", Format.DAYS[Format.strForm(1)]); + Assert.assertEquals("дня", Format.DAYS[Format.strForm(2)]); + Assert.assertEquals("дня", Format.DAYS[Format.strForm(32)]); + Assert.assertEquals("дней", Format.DAYS[Format.strForm(55)]); + Assert.assertEquals("день", Format.DAYS[Format.strForm(121)]); + Assert.assertEquals("дней", Format.DAYS[Format.strForm(500)]); + Assert.assertEquals("дня", Format.DAYS[Format.strForm(672)]); + Assert.assertEquals("дней", Format.DAYS[Format.strForm(765)]); + Assert.assertEquals("часов", Format.HOURS[Format.strForm(0)]); + Assert.assertEquals("час", Format.HOURS[Format.strForm(1)]); + Assert.assertEquals("часа", Format.HOURS[Format.strForm(2)]); + Assert.assertEquals("часа", Format.HOURS[Format.strForm(3)]); + Assert.assertEquals("часов", Format.HOURS[Format.strForm(5)]); + Assert.assertEquals("часов", Format.HOURS[Format.strForm(7)]); + Assert.assertEquals("час", Format.HOURS[Format.strForm(21)]); + Assert.assertEquals("часа", Format.HOURS[Format.strForm(32)]); + Assert.assertEquals("часов", Format.HOURS[Format.strForm(55)]); + Assert.assertEquals("час", Format.HOURS[Format.strForm(121)]); + Assert.assertEquals("ретвитов", Format.RETWEETS[Format.strForm(0)]); + Assert.assertEquals("ретвит", Format.RETWEETS[Format.strForm(1)]); + Assert.assertEquals("ретвита", Format.RETWEETS[Format.strForm(2)]); + Assert.assertEquals("ретвита", Format.RETWEETS[Format.strForm(3)]); + Assert.assertEquals("ретвитов", Format.RETWEETS[Format.strForm(5)]); + Assert.assertEquals("ретвитов", Format.RETWEETS[Format.strForm(7)]); + Assert.assertEquals("ретвитов", Format.RETWEETS[Format.strForm(10)]); + Assert.assertEquals("ретвита", Format.RETWEETS[Format.strForm(32)]); + Assert.assertEquals("ретвитов",Format.RETWEETS[Format.strForm(55)]); + Assert.assertEquals("ретвит", Format.RETWEETS[Format.strForm(121)]); + Assert.assertEquals("ретвитов", Format.RETWEETS[Format.strForm(500)]); + } +} diff --git a/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/PrintTimeTest.java b/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/PrintTimeTest.java new file mode 100644 index 0000000..4357830 --- /dev/null +++ b/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/PrintTimeTest.java @@ -0,0 +1,44 @@ +package ru.mipt.diht.students.annnvl.TwitterStream; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; + +import java.time.LocalDate; +import java.time.Month; +import java.time.ZoneId; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +@RunWith(MockitoJUnitRunner.class) +public class PrintTimeTest { + @Test + public void timePrinterTest() { + + assertThat(PrintTime.printTime(LocalDate.of(2009, Month.MARCH, 20).atTime(23, 59, 59) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(), + LocalDate.of(2009, Month.DECEMBER, 21).atTime(0, 0, 0) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()), is("только что")); + + assertThat(PrintTime.printTime(LocalDate.of(2009, Month.MARCH, 19).atTime(0, 0, 1) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(), + LocalDate.of(2009, Month.MARCH, 20).atTime(0, 0, 2) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()), is("вчера")); + + assertThat(PrintTime.printTime(LocalDate.of(2009, Month.MARCH, 20).atTime(0, 0, 1) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(), + LocalDate.of(2009, Month.MARCH, 21).atTime(0, 0, 0) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()), is("23 часа назад")); + + assertThat(PrintTime.printTime(LocalDate.of(2009, Month.MARCH, 19).atTime(23, 59, 59) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(), + LocalDate.of(2009, Month.MARCH, 21).atTime(0, 0, 0) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()), is("2 дня назад")); + + assertThat(PrintTime.printTime(LocalDate.of(2009, Month.MARCH, 19).atTime(23, 59, 59) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(), + LocalDate.of(2009, Month.MARCH, 20).atTime(0, 2, 0) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()), is("2 минуты назад")); + } +} diff --git a/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/TwitterSearchTest.java b/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/TwitterSearchTest.java new file mode 100644 index 0000000..d3d3cd9 --- /dev/null +++ b/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/TwitterSearchTest.java @@ -0,0 +1,82 @@ +package ru.mipt.diht.students.annnvl.TwitterStream; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import twitter4j.Query; +import twitter4j.QueryResult; +import twitter4j.Status; +import twitter4j.Twitter; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.hasSize; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class TwitterSearchTest { + @Mock + private Twitter twitter; + + @InjectMocks + private TwitterStream search; + public static List statuses; + + @Before + public void setUp() throws Exception { + QueryResult queryResult = mock(QueryResult.class); + when(queryResult.getTweets()).thenReturn(statuses); + when(queryResult.nextQuery()).thenReturn(null); + QueryResult emptyQueryResult = mock(QueryResult.class); + when(emptyQueryResult.getTweets()).thenReturn(new ArrayList()); + when(queryResult.nextQuery()).thenReturn(null); + } + + @Test + public void simpleSetQueryTest() throws Exception { + Parameters param = new Parameters(); + param.setQuery("cook"); + param.setStream(true); + param.setLimit(40); + param.setHideRetweets(true); + param.setHelp(false); + param.setPlace("Moscow"); + Query query = search.setQuery(param); + assertEquals(query.getQuery(), "cook"); + } + + @Test + public void limitSearchResultTest() throws Exception { + Parameters param = new Parameters(); + param.setQuery("cook"); + param.setStream(true); + param.setLimit(40); + param.setHideRetweets(false); + param.setHelp(false); + param.setPlace(""); + List tweets = search.search(param); + assertThat(tweets, hasSize(40)); + verify(twitter).search((Query) argThat(hasProperty("query", equalTo("cook")))); + } + + @Test + public void emptySearchResultTest() throws Exception { + Parameters param = new Parameters(); + param.setQuery("cook"); + param.setStream(true); + param.setLimit(40); + param.setHideRetweets(false); + param.setHelp(false); + param.setPlace(""); + List tweets = search.search(param); + assertThat(tweets, hasSize(0)); + } +} diff --git a/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/TwitterStreamTest.java b/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/TwitterStreamTest.java new file mode 100644 index 0000000..70e6984 --- /dev/null +++ b/projects/annnvl/src/test/java/ru/mipt/diht/students/annnvl/TwitterStream/TwitterStreamTest.java @@ -0,0 +1,60 @@ +package ru.mipt.diht.students.annnvl.TwitterStream; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import twitter4j.*; +import static org.mockito.Mockito.verify; +import org.mockito.ArgumentCaptor; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(MockitoJUnitRunner.class) +public class TwitterStreamTest { + @Mock + twitter4j.TwitterStream twitterStream; + + @InjectMocks + TwitterStream stream; + public static List statuses; + + @BeforeClass + public static void loadSampleData() { + statuses = Twitter4jTestUtils.tweetsFromJson("/statuses.json"); + } + + @Test + public void streamResultTest() throws Exception { + ArgumentCaptor statusListener = ArgumentCaptor.forClass(StatusListener.class); + doNothing().when(twitterStream).addListener((StatusListener) statusListener.capture()); + doAnswer(i -> { + statuses.forEach(s -> statusListener.getValue().onStatus(s)); + return null; + }).when(twitterStream).filter(any(FilterQuery.class)); + List tweets = new ArrayList<>(); + + Parameters param = new Parameters(); + param.setQuery("mipt"); + param.setStream(true); + param.setLimit(100); + param.setHideRetweets(false); + param.setHelp(false); + param.setPlace(""); + + stream.stream(param, tweets::add); + assertTrue(tweets.size() == 13); + + verify(twitterStream).addListener((StatusListener) any(StatusAdapter.class)); + verify(twitterStream).filter(any(FilterQuery.class)); + } +} + diff --git a/projects/annnvl/src/test/java/twitter4j/Twitter4jTestUtils.java b/projects/annnvl/src/test/java/twitter4j/Twitter4jTestUtils.java new file mode 100644 index 0000000..1f789a7 --- /dev/null +++ b/projects/annnvl/src/test/java/twitter4j/Twitter4jTestUtils.java @@ -0,0 +1,25 @@ +package twitter4j; + +import org.apache.commons.io.IOUtils; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +public class Twitter4jTestUtils { + public static List tweetsFromJson(String resource) { + try (InputStream inputStream = Twitter4jTestUtils.class.getResourceAsStream(resource)) { + JSONObject json = new JSONObject(IOUtils.toString(inputStream)); + JSONArray array = json.getJSONArray("statuses"); + List tweets = new ArrayList(array.length()); + for (int i = 0; i < array.length(); i++) { + JSONObject tweet = array.getJSONObject(i); + tweets.add(new StatusJSONImpl(tweet)); + } + return tweets; + } catch (IOException | JSONException | TwitterException e) { + throw new RuntimeException(e); + } + } +} + diff --git a/projects/pom.xml b/projects/pom.xml index 7b6298b..c85f1f5 100644 --- a/projects/pom.xml +++ b/projects/pom.xml @@ -1,11 +1,12 @@ - + + 4.0.0 - ru.mipt.diht.students - parent - 1.0-SNAPSHOT - pom + ru.mipt.diht.students + parent + 1.0-SNAPSHOT + + pom fizteh-java-2015 https://github.com/KhurtinDN/fizteh-java-2015 @@ -28,8 +29,9 @@ dkhurtin - - + annnvl + + @@ -131,4 +133,4 @@ - + \ No newline at end of file