diff --git a/mamaevads/pom.xml b/mamaevads/pom.xml index bdbeb7f5..b28bc69e 100644 --- a/mamaevads/pom.xml +++ b/mamaevads/pom.xml @@ -21,6 +21,19 @@ junit 3.8.1 + + com.beust + jcommander + 1.48 + + + + junit + junit + 4.12 + test + + org.twitter4j twitter4j-stream @@ -31,5 +44,10 @@ jcommander 1.48 + + com.h2database + h2 + 1.4.190 + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/Aggregates.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/Aggregates.java new file mode 100644 index 00000000..dd35207c --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/Aggregates.java @@ -0,0 +1,102 @@ +package ru.fizteh.fivt.students.mamaevads.collectionquery; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.function.Function; + + +public class Aggregates { + + public interface Aggregate extends Function { + T forGroup(Set set); + } + + private static Collection getValues(Collection set, Function expression) { + Set values = new HashSet<>(); + for (C element : set) { + values.add(expression.apply(element)); + } + return values; + } + + public static > Aggregate max(Function expression) { + return new Aggregate() { + + @Override + public T apply(C element) { + return (T) expression.apply(element); + } + + @Override + public T forGroup(Set set) throws ClassCastException, NoSuchElementException { + return Collections.max(getValues(set, expression)); + } + }; + } + + public static > Aggregate min(Function expression) { + return new Aggregate() { + + @Override + public T apply(C element) { + return (T) expression.apply(element); + } + + @Override + public T forGroup(Set set) throws ClassCastException, NoSuchElementException { + return Collections.min(getValues(set, expression)); + } + }; + } + + public static > Aggregate count(Function expression) { + return new Aggregate() { + + @Override + public Long apply(C element) { + return Long.valueOf(1); + } + + @Override + public Long forGroup(Set set) { + return (long) set.size(); + } + }; + } + + public static > Aggregate avg(Function expression) { + return new Aggregate() { + + @Override + public T apply(C element) { + return expression.apply(element); + } + + @Override + public T forGroup(Set set) throws ClassCastException, NoSuchElementException { + if (set.isEmpty()) { + throw new NoSuchElementException("set is empty"); + } + T sample = expression.apply(set.iterator().next()); + if (sample instanceof Long || sample instanceof Integer || sample instanceof Short) { + long average = 0; + for (C element : set) { + average += (Long) (expression.apply(element)); + } + return (T) Long.valueOf(average / set.size()); + } else if (sample instanceof Float || sample instanceof Double) { + double average = 0; + for (C element : set) { + average += (Double) (expression.apply(element)); + } + return (T) Double.valueOf(average / set.size()); + } + throw new ClassCastException("wrong type"); + } + }; + } + +} diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/Conditions.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/Conditions.java new file mode 100644 index 00000000..ecbfe184 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/Conditions.java @@ -0,0 +1,22 @@ +package ru.fizteh.fivt.students.mamaevads.collectionquery; + +import java.util.function.Function; +import java.util.function.Predicate; + +public class Conditions { + + public static Predicate rlike(Function expression, String regexp) { + return new Predicate() { + + @Override + public boolean test(T element) { + return expression.apply(element).matches(regexp); + } + }; + } + + public static Predicate like(Function expression, String pattern) { + throw new UnsupportedOperationException(); + } + +} diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/OrderByConditions.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/OrderByConditions.java new file mode 100644 index 00000000..23755d67 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/OrderByConditions.java @@ -0,0 +1,17 @@ +package ru.fizteh.fivt.students.mamaevads.collectionquery; + +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/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/Sources.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/Sources.java new file mode 100644 index 00000000..bc502a03 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/Sources.java @@ -0,0 +1,54 @@ +package ru.fizteh.fivt.students.mamaevads.collectionquery; + + import java.io.FileInputStream; + import java.io.IOException; + import java.io.InputStream; + import java.nio.file.Path; + import java.util.Arrays; + import java.util.HashSet; + import java.util.List; + import java.util.Set; + import java.util.stream.Stream; + +public class Sources { + + @SafeVarargs + public static List list(T... items) { + return Arrays.asList(items); + } + + @SafeVarargs + public static Set set(T... items) { + Set result = new HashSet<>(); + for (T element : items) { + result.add(element); + } + return result; + } + + static final int READ_BLOCK_SIZE = 100; + + + public static Stream lines(InputStream inputStream) throws IOException, ClassCastException { + StringBuilder builder = new StringBuilder(); + byte[] data = new byte[READ_BLOCK_SIZE]; + int readed = inputStream.read(data); + while (readed > 0) { + builder.append(data); + readed = inputStream.read(data); + } + inputStream.close(); + String[] lines = builder.toString().split("[\n]"); + Stream.Builder stream = Stream.builder(); + for (String line : lines) { + stream.add((T) line); + } + return stream.build(); + } + + public static Stream lines(Path file) throws ClassCastException, IOException { + InputStream input = new FileInputStream(file.toFile()); + return lines(input); + } + +} diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/CollectionQueryExecuteException.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/CollectionQueryExecuteException.java new file mode 100644 index 00000000..7d9b3097 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/CollectionQueryExecuteException.java @@ -0,0 +1,9 @@ +package ru.fizteh.fivt.students.mamaevads.collectionquery.impl; + +public class CollectionQueryExecuteException extends Exception { + + CollectionQueryExecuteException(String message, Throwable cause) { + super(message, cause); + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/CollectionQuerySyntaxException.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/CollectionQuerySyntaxException.java new file mode 100644 index 00000000..77949b75 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/CollectionQuerySyntaxException.java @@ -0,0 +1,13 @@ +package ru.fizteh.fivt.students.mamaevads.collectionquery.impl; + +public class CollectionQuerySyntaxException extends Exception { + + CollectionQuerySyntaxException(String message, Throwable cause) { + super(message, cause); + } + + CollectionQuerySyntaxException(String message) { + super(message); + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/FinalRow.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/FinalRow.java new file mode 100644 index 00000000..e8e8fbbb --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/FinalRow.java @@ -0,0 +1,33 @@ +package ru.fizteh.fivt.students.mamaevads.collectionquery.impl; + +import java.util.HashSet; +import java.util.Set; + +class FinalRow { + private R row; + private Set from; + + FinalRow(R newRow, T elementFrom) { + from = new HashSet(); + from.add(elementFrom); + row = newRow; + } + + public R get() { + return row; + } + + public Set getFrom() { + return from; + } + + public T getAnyFrom() { + return from.iterator().next(); + } + + public void updateRow(R newRow) { + row = newRow; + } +} + + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/FromStmt.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/FromStmt.java new file mode 100644 index 00000000..bf5ffe97 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/FromStmt.java @@ -0,0 +1,162 @@ +package ru.fizteh.fivt.students.mamaevads.collectionquery.impl; +import java.util.function.Function; +import java.util.stream.Stream; + +/** + * Created by Даша on 01.11.2015. + */ + + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; + +public final class FromStmt { + private Iterable base; + private ExecutedTable previousTable = null; + + private FromStmt() { } + + private static final class ExecutedTable { + private final Iterable outputTable; + private final Class outputClass; + + private ExecutedTable(Class clazz, Iterable table) { + outputTable = table; + outputClass = clazz; + } + } + + public static FromStmt from(Iterable iterable) { + FromStmt stmt = new FromStmt<>(); + stmt.base = iterable; + return stmt; + } + + public static FromStmt from(Stream stream) { + FromStmt stmt = new FromStmt<>(); + List list = new ArrayList<>(); + stream.forEach(s -> list.add(s)); + stmt.base = list; + return stmt; + } + + public static FromStmt from(WhereStmt subStmt) throws CollectionQueryExecuteException { + Iterable subQueryResult = subStmt.execute(); + return from(subQueryResult); + } + + void setPreviousPart(Class clazz, Iterable table) { + previousTable = new ExecutedTable(clazz, table); + } + + private SelectStmt innerSelect(Class clazz, Function[] s, boolean isDistinct) + throws CollectionQuerySyntaxException { + if (previousTable == null) { + return new SelectStmt(base, null, clazz, isDistinct, s); + } else { + if (!previousTable.outputClass.equals(clazz)) { + throw new CollectionQuerySyntaxException("parts of union has different types"); + } + return new SelectStmt(base, (Iterable) previousTable.outputTable, clazz, isDistinct, s); + } + } + + @SafeVarargs + public final SelectStmt select(Class clazz, Function... s) + throws CollectionQuerySyntaxException { + return innerSelect(clazz, s, false); + } + + @SafeVarargs + public final SelectStmt selectDistinct(Class clazz, Function... s) + throws CollectionQuerySyntaxException { + return innerSelect(clazz, s, true); + } + + public static final class Tuple { + private F firstPart; + private S secondPart; + + private Tuple(F first, S second) { + firstPart = first; + secondPart = second; + } + + public F first() { + return firstPart; + } + + public S second() { + return secondPart; + } + } + + + public final class JoinStmt { + private Iterable secondTable; + + private JoinStmt(Iterable tableOnJoin) { + secondTable = tableOnJoin; + } + + public FromStmt> on(Predicate> joiningPredicate) { + Collection> joinedCollection = new ArrayList<>(); + for (T first : base) { + for (S second : secondTable) { + Tuple joinedRow = new Tuple(first, second); + if (joiningPredicate.test(joinedRow)) { + joinedCollection.add(joinedRow); + } + } + } + FromStmt> stmt = new FromStmt<>(); + stmt.base = joinedCollection; + stmt.previousTable = previousTable; + return stmt; + } + + public FromStmt> on(Function leftKey, Function rightKey) { + Map, Set>> possibleValues = new HashMap<>(); + for (T row : base) { + R value = leftKey.apply(row); + if (value != null) { + if (!possibleValues.containsKey(value)) { + possibleValues.put(value, new Tuple<>(new HashSet<>(), new HashSet<>())); + } + possibleValues.get(value).firstPart.add(row); + } + } + for (S row : secondTable) { + R value = rightKey.apply(row); + if (value != null) { + if (!possibleValues.containsKey(value)) { + continue; + } + possibleValues.get(value).secondPart.add(row); + } + } + + Collection> joinedCollection = new ArrayList<>(); + + possibleValues.forEach((v, tuple) -> { + for (T firstRow : tuple.first()) { + for (S secondRow : tuple.second()) { + joinedCollection.add(new Tuple(firstRow, secondRow)); + } + } + }); + return from(joinedCollection); + } + } + + public JoinStmt join(Iterable secondTable) { + return new JoinStmt<>(secondTable); + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/SelectStmt.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/SelectStmt.java new file mode 100644 index 00000000..d731762d --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/SelectStmt.java @@ -0,0 +1,260 @@ +package ru.fizteh.fivt.students.mamaevads.collectionquery.impl; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import java.util.Comparator; + +/** + * Created by Даша on 01.11.2015. + */ + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + + +import ru.fizteh.fivt.students.mamaevads.collectionquery.Aggregates.Aggregate; + +public class SelectStmt { + + private Stream stream; + private Iterable baseCollection; + private Class outputClass; + private Iterable previousPart; + private Function[] convertFunctions; + + private Function>[] groupingFunctions; + private Predicate groupingCondition = null; + private Comparator finalComparator = null; + private int finalLimit = -1; + + private boolean isDistinct; + + @SafeVarargs + SelectStmt(Iterable newBaseCollection, Iterable previousTable, + Class clazz, boolean distinct, Function... s) { + baseCollection = newBaseCollection; + previousPart = previousTable; + stream = StreamSupport.stream(newBaseCollection.spliterator(), false); + outputClass = clazz; + convertFunctions = s; + isDistinct = distinct; + groupingFunctions = null; + } + + final Class getOutputClass() { + return outputClass; + } + + private static Comparator getCombinedComparator(Iterable> comparators) { + return new Comparator() { + @Override + public int compare(T first, T second) { + for (Comparator comparator : comparators) { + int result = comparator.compare(first, second); + if (result != 0) { + return result; + } + } + return 0; + } + }; + } + + public final WhereStmt where(Predicate predicate) { + stream = stream.filter(predicate); + return new WhereStmt<>(this); + } + + @SafeVarargs + public final void groupBy(Function>... expressions) throws CollectionQuerySyntaxException { + if (groupingFunctions != null) { + throw new CollectionQuerySyntaxException("group table in the query"); + } + groupingFunctions = expressions; + } + + public final void having(Predicate condition) throws CollectionQuerySyntaxException { + if (groupingCondition != null) { + throw new CollectionQuerySyntaxException("set grouping conditions"); + } + groupingCondition = condition; + } + + private class Applier implements Consumer { + private Collection> output; + private Constructor constructor; + + Applier(Collection> outputCollection, Constructor resultConstructor) { + output = outputCollection; + constructor = resultConstructor; + } + + @Override + public void accept(T element) { + Object[] parametrs = new Object[convertFunctions.length]; + for (int i = 0; i < convertFunctions.length; ++i) { + parametrs[i] = convertFunctions[i].apply(element); + } + try { + output.add(new FinalRow(constructor.newInstance(parametrs), element)); + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + throw new RuntimeException("construct", e); + } + } + + } + + private Constructor getAskedConstructor() throws CollectionQueryExecuteException { + Class[] outputParametrsTypes = new Class[convertFunctions.length]; + for (int i = 0; i < convertFunctions.length; ++i) { + outputParametrsTypes[i] = convertFunctions[i].apply(baseCollection.iterator().next()).getClass(); + } + try { + return outputClass.getConstructor(outputParametrsTypes); + } catch (NoSuchMethodException | SecurityException e) { + throw new CollectionQueryExecuteException("Can not found constructor", e); + } + } + + private Collection> goodGroups(Collection> table) { + List> output = new ArrayList<>(); + for (FinalRow row : table) { + if (groupingCondition == null || groupingCondition.test(row.get())) { + output.add(row); + } + } + return output; + } + + private void aggregatingGroups(Collection> table) throws CollectionQueryExecuteException { + Constructor constructor = getAskedConstructor(); + Object[] parametrs = new Object[convertFunctions.length]; + for (FinalRow row : table) { + for (int i = 0; i < convertFunctions.length; ++i) { + if (convertFunctions[i] instanceof Aggregate) { + parametrs[i] = ((Aggregate) convertFunctions[i]).forGroup(row.getFrom()); + } else { + parametrs[i] = convertFunctions[i].apply(row.getAnyFrom()); + } + } + try { + row.updateRow(constructor.newInstance(parametrs)); + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + throw new CollectionQueryExecuteException("output class not instantiated", e); + } + } + } + + private Collection convertToFinal(Collection> table) { + List output = new ArrayList<>(); + if (previousPart != null) { + for (R row : previousPart) { + output.add(row); + } + } + for (FinalRow row : table) { + output.add(row.get()); + } + return output; + } + + public final Collection execute() throws CollectionQueryExecuteException { + Collection> output = null; + output = new ArrayList<>(); + + try { + stream.forEach(new Applier(output, getAskedConstructor())); + } catch (RuntimeException e) { + if (e.getMessage().equals("constructor")) { + throw new CollectionQueryExecuteException("constructor", e.getCause()); + } else { + throw e; + } + } + + if (groupingFunctions != null) { + List> preCalcSortedTable = new ArrayList<>(); + for (FinalRow element : output) { + preCalcSortedTable.add(element); + } + List>> resultComparators = new ArrayList<>(); + for (Function> function : groupingFunctions) { + resultComparators.add((r1, r2) -> { + Comparable result1 = function.apply(r1.getAnyFrom()); + return result1.compareTo(function.apply(r2.getAnyFrom())); + }); + } + Comparator> groupsComparator = getCombinedComparator(resultComparators); + preCalcSortedTable.sort(groupsComparator); + Collection> groupedTable = new ArrayList<>(); + + FinalRow currentGroup = null; + for (FinalRow row : preCalcSortedTable) { + if (currentGroup != null && groupsComparator.compare(row, currentGroup) == 0) { + currentGroup.getFrom().add(row.getAnyFrom()); + } else { + if (currentGroup != null) { + groupedTable.add(currentGroup); + } + currentGroup = row; + } + } + groupedTable.add(currentGroup); + + aggregatingGroups(output); + output = goodGroups(groupedTable); + } + Stream finalOutput = convertToFinal(output).stream(); + if (finalLimit >= 0) { + finalOutput = finalOutput.limit(finalLimit); + } + if (finalComparator != null) { + finalOutput = finalOutput.sorted(finalComparator); + } + if (isDistinct) { + finalOutput = finalOutput.distinct(); + } + return finalOutput.collect(() -> new ArrayList(), (l, e) -> l.add(e), (l1, l2) -> l1.addAll(l2)); + } + + public final void limit(int limit) throws CollectionQuerySyntaxException { + if (limit >= 0) { + throw new CollectionQuerySyntaxException("limitation"); + } + finalLimit = limit; + } + + @SafeVarargs + public final void orderBy(Comparator... comparators) throws CollectionQuerySyntaxException { + if (finalComparator != null) { + throw new CollectionQuerySyntaxException("ordering functions"); + } + finalComparator = getCombinedComparator(Arrays.asList(comparators)); + } + + public final Stream stream() throws CollectionQueryExecuteException { + return execute().stream(); + } + + final Stream currentStream() { + return stream; + } + + + public final UnionStmt union() throws CollectionQueryExecuteException { + return new UnionStmt(this); + } + +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/UnionStmt.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/UnionStmt.java new file mode 100644 index 00000000..2ae2379a --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/UnionStmt.java @@ -0,0 +1,24 @@ +package ru.fizteh.fivt.students.mamaevads.collectionquery.impl; + +/** + * Created by Даша on 01.11.2015. + */ + +import java.util.Collection; + +public class UnionStmt { + private Collection previousPart; + private Class previousOutputClass; + + UnionStmt(SelectStmt previousStmt) throws CollectionQueryExecuteException { + previousOutputClass = previousStmt.getOutputClass(); + previousPart = previousStmt.execute(); + } + + public final FromStmt from(Iterable list) { + FromStmt stmt = FromStmt.from(list); + stmt.setPreviousPart(previousOutputClass, previousPart); + return stmt; + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/WhereStmt.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/WhereStmt.java new file mode 100644 index 00000000..f705b729 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/collectionquery/impl/WhereStmt.java @@ -0,0 +1,46 @@ +package ru.fizteh.fivt.students.mamaevads.collectionquery.impl; + + +import java.util.Comparator; +import java.util.function.Function; +import java.util.function.Predicate; + +public class WhereStmt { + private SelectStmt baseStmt; + + WhereStmt(SelectStmt selectStmt) { + baseStmt = selectStmt; + } + + @SafeVarargs + public final WhereStmt groupBy(Function>... expressions) + throws CollectionQuerySyntaxException { + baseStmt.groupBy(expressions); + return this; + } + + @SafeVarargs + public final WhereStmt orderBy(Comparator... comparators) throws CollectionQuerySyntaxException { + baseStmt.orderBy(comparators); + return this; + } + + public final WhereStmt having(Predicate condition) throws CollectionQuerySyntaxException { + baseStmt.having(condition); + return this; + } + + public final WhereStmt limit(int amount) throws CollectionQuerySyntaxException { + baseStmt.limit(amount); + return this; + } + + public final Iterable execute() throws CollectionQueryExecuteException { + return baseStmt.execute(); + } + + public final UnionStmt union() throws CollectionQueryExecuteException { + return baseStmt.union(); + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/Column.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/Column.java new file mode 100644 index 00000000..0fe41d8c --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/Column.java @@ -0,0 +1,14 @@ +package ru.fizteh.fivt.students.mamaevads.miniorm; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Column { + String name() default ""; +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/DatabaseService.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/DatabaseService.java new file mode 100644 index 00000000..0f06dccc --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/DatabaseService.java @@ -0,0 +1,285 @@ +package ru.fizteh.fivt.students.mamaevads.miniorm; + +/** + * Created by Даша on 17.12.2015. + */ + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +//import org.h2.jdbcx.JdbcConnectionPool; + +public class DatabaseService { + private Class tableClass; + private String tableName; + private Connection dbConnection; + private List columns; + private TypedColumn primaryKeyColumn; + + private static final String STANDARD_DATABASE_PATH = "./mamaevadb"; + + private enum DataType { + INTEGER("INT", Boolean.class, Byte.class, Short.class, Integer.class, Long.class), + DOUBLE("DOUBLE", Float.class, Double.class), + TEXT("VARCHAR(255)", String.class); + + private final String nameSQL; + private final Class[] examples; + + DataType(String sqllikeName, Class... variety) { + nameSQL = sqllikeName; + examples = variety; + } + + private static DataType valueOf(Class typeClass) throws DatabaseServiceException { + for (DataType type : values()) { + for (Class testClass : type.examples) { + if (typeClass.equals(testClass)) { + return type; + } + } + } + throw new DatabaseServiceException("This type is not supported" + + typeClass.getSimpleName()); + } + } + + private final class TypedColumn { + private DataType type; + private String name; + private Field field; + + private TypedColumn(Field realField) throws DatabaseServiceException { + field = realField; + field.setAccessible(true); + Column columnAnnotation = field.getAnnotation(Column.class); + if (columnAnnotation == null) { + throw new DatabaseServiceException("annotate the field"); + } + name = columnAnnotation.name(); + if (name.equals("")) { + name = toSnakeCase(field.getName()); + } + type = DataType.valueOf(field.getType()); + } + } + + private static String toSnakeCase(String camelCase) { + StringBuilder nameBuilder = new StringBuilder(); + for (int i = 0; i < camelCase.length(); ++i) { + if (camelCase.charAt(i) >= 'A' && camelCase.charAt(i) <= 'Z') { + if (i > 0 && camelCase.charAt(i - 1) >= 'a' && camelCase.charAt(i - 1) <= 'z') { + nameBuilder.append('_'); + } + nameBuilder.append((char) (camelCase.charAt(i) - 'A' + 'a')); + } else { + nameBuilder.append(camelCase.charAt(i)); + } + } + return nameBuilder.toString(); + } + + private String createColumnsPattern(Function convert) { + StringBuilder values = new StringBuilder(); + for (TypedColumn column : columns) { + values.append(convert.apply(column)) + .append(','); + } + values.deleteCharAt(values.length() - 1); + return values.toString(); + } + + private void initDatabaseTable(Class annotatedTableClass) throws DatabaseServiceException { + tableClass = annotatedTableClass; + Table tableAnnotation = tableClass.getAnnotation(Table.class); + if (tableAnnotation == null) { + throw new DatabaseServiceException("annotate the table class"); + } + tableName = tableAnnotation.name(); + if (tableName.equals("")) { + tableName = toSnakeCase(tableClass.getSimpleName()); + } + Field[] allFields = tableClass.getDeclaredFields(); + columns = new ArrayList<>(); + for (Field field : allFields) { + if (field.isAnnotationPresent(Column.class)) { + columns.add(new TypedColumn(field)); + if (field.isAnnotationPresent(PrimaryKey.class)) { + if (primaryKeyColumn != null) { + throw new DatabaseServiceException("please enter one prim key"); + } + primaryKeyColumn = columns.get(columns.size() - 1); + } + } + } + } + + private void initConnection(String databasePath) throws DatabaseServiceException { + try { + dbConnection = DriverManager.getConnection("jdbc:h2:" + databasePath, "sa", ""); + } catch (SQLException e) { + throw new DatabaseServiceException("Connection not found: " + e.getMessage(), e); + } + } + + public DatabaseService(Class annotatedTableClass) throws DatabaseServiceException { + initDatabaseTable(annotatedTableClass); + initConnection(STANDARD_DATABASE_PATH); + } + + public final void createTable() throws DatabaseServiceException { + StringBuilder columnsString = new StringBuilder(); + for (TypedColumn column : columns) { + columnsString.append(column.name) + .append(' ') + .append(column.type.nameSQL); + if (column.field.isAnnotationPresent(PrimaryKey.class)) { + columnsString.append(" PRIMARY KEY CAN'T BE NULL"); + } + columnsString.append(','); + } + columnsString.deleteCharAt(columnsString.length() - 1); + try { + dbConnection.createStatement().execute("CREATE TABLE " + tableName + + "(" + columnsString.toString() + ")"); + } catch (SQLException e) { + throw new DatabaseServiceException("can't create: " + e.getMessage(), e); + } + } + + + public final void dropTable() throws DatabaseServiceException { + try { + dbConnection.createStatement().execute("DROP TABLE " + tableName); + } catch (SQLException e) { + throw new DatabaseServiceException("can't drop table: " + e.getMessage(), e); + } + } + + + public final void insert(T row) throws DatabaseServiceException { + try { + PreparedStatement statement = dbConnection.prepareStatement("INSERT INTO " + tableName + + " VALUES (" + createColumnsPattern(c -> "?") + ")"); + for (int i = 0; i < columns.size(); ++i) { + statement.setString(i + 1, String.valueOf(columns.get(i).field.get(row))); + } + statement.execute(); + } catch (SQLException | IllegalArgumentException | IllegalAccessException e) { + throw new DatabaseServiceException("can't insert: " + e.getMessage()); + } + } + + + public final void update(T row) throws DatabaseServiceException { + if (primaryKeyColumn == null) { + throw new DatabaseServiceException("no prim key"); + } + try { + PreparedStatement statement = dbConnection.prepareStatement("UPDATE " + tableName + + " SET " + createColumnsPattern(c -> c.name + "=?") + " WHERE " + primaryKeyColumn.name + "=?"); + for (int i = 0; i < columns.size(); ++i) { + statement.setString(i + 1, String.valueOf(columns.get(i).field.get(row))); + } + statement.setString(columns.size() + 1, primaryKeyColumn.field.get(row).toString()); + statement.execute(); + } catch (SQLException | IllegalArgumentException | IllegalAccessException e) { + throw new DatabaseServiceException("Can't update: " + e.getMessage()); + } + } + + + public final void deleteByKey(K key) throws DatabaseServiceException { + if (primaryKeyColumn == null) { + throw new DatabaseServiceException("no prim key"); + } + try { + PreparedStatement statement = dbConnection.prepareStatement("DELETE FROM " + tableName + + " WHERE " + primaryKeyColumn.name + "=?"); + statement.setString(1, key.toString()); + statement.execute(); + } catch (SQLException | IllegalArgumentException e) { + throw new DatabaseServiceException("Can't delete" + e.getMessage()); + } + } + + + public final void delete(T row) throws DatabaseServiceException { + try { + deleteByKey(primaryKeyColumn.field.get(row).toString()); + } catch (IllegalAccessException e) { + throw new DatabaseServiceException("Can't delete: " + e.getMessage()); + } + } + + private List getRealClasses(ResultSet result) throws IllegalArgumentException, IllegalAccessException, + SQLException, InstantiationException, InvocationTargetException, NoSuchMethodException, SecurityException { + List output = new ArrayList<>(); + while (result.next()) { + T row = tableClass.newInstance(); + for (int i = 0; i < columns.size(); ++i) { + String value = result.getString(i + 1); + if (columns.get(i).field.getType().equals(String.class)) { + columns.get(i).field.set(row, value); + } else { + columns.get(i).field.set(row, columns.get(i).field.getType().getMethod("valueOf", String.class) + .invoke(null, value)); + } + } + output.add(row); + } + result.close(); + return output; + } + + public final T queryById(K key) throws DatabaseServiceException { + if (primaryKeyColumn == null) { + throw new DatabaseServiceException("need prim key"); + } + if (!primaryKeyColumn.field.getType().isInstance(key)) { + throw new DatabaseServiceException("key type is not type of primary key"); + } + + try { + PreparedStatement statement = dbConnection.prepareStatement("SELECT " + createColumnsPattern(c -> c.name) + + " FROM " + tableName + " WHERE " + primaryKeyColumn.name + "=?"); + statement.setString(1, key.toString()); + List result = getRealClasses(statement.executeQuery()); + if (result.isEmpty()) { + return null; + } + return result.get(0); + } catch (SQLException | IllegalArgumentException | IllegalAccessException | InstantiationException + | InvocationTargetException | NoSuchMethodException | SecurityException e) { + throw new DatabaseServiceException("Can't get the instantiate the row: " + e.getMessage(), e); + } + } + + + public final List queryForAll() throws DatabaseServiceException { + try { + return getRealClasses(dbConnection.prepareStatement("SELECT " + createColumnsPattern(c -> c.name) + + " FROM " + tableName).executeQuery()); + } catch (SQLException | IllegalArgumentException | IllegalAccessException + | InstantiationException | InvocationTargetException | NoSuchMethodException | SecurityException e) { + throw new DatabaseServiceException("Can't get or instantiate the row: " + e.getMessage(), e); + } + } + + @Override + protected final void finalize() { + try { + dbConnection.close(); + } catch (SQLException e) { + System.err.println("can not close connection: " + e.getMessage()); + } + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/DatabaseServiceException.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/DatabaseServiceException.java new file mode 100644 index 00000000..3864471e --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/DatabaseServiceException.java @@ -0,0 +1,14 @@ +package ru.fizteh.fivt.students.mamaevads.miniorm; + +public class DatabaseServiceException extends Exception { + + public DatabaseServiceException(String message) { + super(message); + } + + public DatabaseServiceException(String message, Throwable cause) { + super(message, cause); + } +} + + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/PrimaryKey.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/PrimaryKey.java new file mode 100644 index 00000000..248d33b9 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/PrimaryKey.java @@ -0,0 +1,12 @@ +package ru.fizteh.fivt.students.mamaevads.miniorm; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface PrimaryKey { +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/Table.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/Table.java new file mode 100644 index 00000000..85520df0 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/miniorm/Table.java @@ -0,0 +1,14 @@ +package ru.fizteh.fivt.students.mamaevads.miniorm; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Table { + String name() default ""; +} + + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/Arguments.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/Arguments.java new file mode 100644 index 00000000..3710b217 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/Arguments.java @@ -0,0 +1,50 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; +import com.beust.jcommander.Parameter; + +public class Arguments { + private final int maxLimit = 100; + @Parameter(names = { "-q", "--query" }, + description = "ключевые слова для поиска") + private String query = ""; + @Parameter(names = { "-p", "--place" }, + description = "поиск твитов в некотором регионе") + private String place = ""; + @Parameter(names = { "-l", "--limit" }, + description = "количество твитов") + private Integer limit = maxLimit; + @Parameter(names = { "-s", "--stream" }, + description = "вывод твитов в стриминге") + private boolean stream = false; + @Parameter(names = { "--hideRetweets" }, + description = "скрывать ретвиты") + private boolean hideRetweets = false; + @Parameter(names = { "-h", "--help" }, + description = "помошь") + private boolean help = false; + + + 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; + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/ArgumentsInput.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/ArgumentsInput.java new file mode 100644 index 00000000..b985b3ae --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/ArgumentsInput.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; +import com.beust.jcommander.JCommander; + + +public class ArgumentsInput { + public static Arguments inputArguments(String[] args) throws InvalidArgumentsException { + Arguments arguments = new Arguments(); + try { + JCommander commander = new JCommander(arguments, args); + if (arguments.isHelp()) { + commander.usage(); + System.exit(0); + } + } catch (Exception ex) { + System.err.print("Invalid arguments exception"); + } + return arguments; + } +} + + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/FakeTwitter.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/FakeTwitter.java new file mode 100644 index 00000000..78f985c2 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/FakeTwitter.java @@ -0,0 +1,7 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; + +/** + * Created by Даша on 02.12.2015. + */ +public class FakeTwitter { +} diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/GeoFeatures.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/GeoFeatures.java new file mode 100644 index 00000000..9a7c2676 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/GeoFeatures.java @@ -0,0 +1,80 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; + +import twitter4j.*; +import java.util.List; + +public class GeoFeatures { + + private static final double[][] MOSCOW = {{55.489926, 37.31932}, {56.009657, 37.9456611}}; + private static final double HALF_CIRCLE = 180.0; + private static final double ONE = 60; + private static final double TWO = 1.1515; + private static final double KILOMETERS = 0.8684; + public static double getBetween(double[][] square) { + double lat1 = square[0][1]; + double lat2 = square[1][1]; + double lon1 = square[0][0]; + double lon2 = square[1][0]; + double theta = lon1 - lon2; + double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta)); + dist = Math.acos(dist); + dist = rad2deg(dist); + dist = dist * ONE * TWO; + dist = dist * KILOMETERS; + + return (dist); + } + + private static double deg2rad(double deg) { + return (deg * Math.PI / HALF_CIRCLE); + } + + private static double rad2deg(double rad) { + return (rad * HALF_CIRCLE / Math.PI); + } + + public static double[] getLocation(String place, Twitter twitter) { + double[][] square = getFilter(place); + double minimumLatitude = square[0][1]; + double minimumLongitude = square[0][0]; + double maximumLatitude = square[1][1]; + double maximumLongitude = square[1][0]; + return new double[]{ + (minimumLatitude + maximumLatitude) / 2, + (minimumLongitude + maximumLongitude) / 2, + getBetween(square) / 2 + }; + } + + public static double[][] getFilter(String place) { + Twitter twitter = new TwitterFactory().getInstance(); + try { + GeoQuery geoQuery = new GeoQuery((String) null); + geoQuery.setQuery(place); + List placeResponseList = twitter.searchPlaces(geoQuery); + double minimumLatitude = Double.MAX_VALUE, + maximumLatitude = -Double.MAX_VALUE, + minimumLongitude = Double.MAX_VALUE, + maximumLongitude = -Double.MAX_VALUE; + for (GeoLocation location : placeResponseList.get(0).getBoundingBoxCoordinates()[0]) { + minimumLongitude = Math.min(minimumLongitude, location.getLongitude()); + maximumLongitude = Math.max(maximumLongitude, location.getLongitude()); + minimumLatitude = Math.min(minimumLatitude, location.getLatitude()); + maximumLatitude = Math.max(maximumLatitude, location.getLatitude()); + + } + + double[][] coordinates = new double[2][2]; + coordinates[0][0] = minimumLongitude; + coordinates[0][1] = minimumLatitude; + coordinates[1][0] = maximumLongitude; + coordinates[1][1] = maximumLatitude; + return coordinates; + } catch (Exception e) { + System.err.println("Error, while trying to get location."); + } + return MOSCOW; + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/InvalidArgumentsException.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/InvalidArgumentsException.java new file mode 100644 index 00000000..fcd994cb --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/InvalidArgumentsException.java @@ -0,0 +1,10 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; + +/** + * Created by Даша on 05.10.2015. + */ +public class InvalidArgumentsException extends Exception { + public InvalidArgumentsException(String message) { + super(message); + } +} diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/LostInformationException.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/LostInformationException.java new file mode 100644 index 00000000..551bbdf7 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/LostInformationException.java @@ -0,0 +1,10 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; + +/** + * Created by Даша on 05.10.2015. + */ +public class LostInformationException extends Exception { + public LostInformationException(String message) { + super(message); + } +} diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/MakeMassage.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/MakeMassage.java new file mode 100644 index 00000000..2496dec5 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/MakeMassage.java @@ -0,0 +1,39 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; +import twitter4j.*; + +import java.time.LocalDateTime; +import java.time.ZoneId; + +public class MakeMassage { + + static String getName(Status st) { + return "@" + st.getUser().getName() + " : "; + } + static String getRetweets(Status st) { + int retweet = st.getRetweetCount(); + if (retweet == 0) { + return ""; + } else { + return "(" + retweet + WordForms.getForm(retweet, WordForms.RE_FORMS) + ")"; + } + } + static String getMessage(Status st) { + String text = st.getText(); + if (st.isRetweet()) { + text = " ретвитнул " + st.getRetweetedStatus().getUser().getScreenName() + " : "; + } + return text; + } + + static String getTime(Status st) { + LocalDateTime tweetDate = st.getCreatedAt().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + LocalDateTime curDate = LocalDateTime.now(); + return TimeHandler.getType(tweetDate, curDate); + } + + static String info(Status st) throws LostInformationException { + String message = getTime(st) + " " + getName(st) + getMessage(st) + " " + getRetweets(st) + "\n"; + message += "-----------------------------------------------------------------------------------"; + return message; + } +} diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TimeHandler.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TimeHandler.java new file mode 100644 index 00000000..ee7923ce --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TimeHandler.java @@ -0,0 +1,35 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; + +//dontreadme +//tweet.getCreatedAt().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime( +// LocalDateTime curDate = LocalDateTime.now(); + +public class TimeHandler { + public static final int TWO_MINUTES = 120; + + static String getType(LocalDateTime myDayTime, LocalDateTime nowDayTime) { + LocalDateTime tweetDate = myDayTime; + LocalDateTime curDate = nowDayTime; + if (ChronoUnit.SECONDS.between(tweetDate, curDate) < TWO_MINUTES) { + return "только что"; + } else if (ChronoUnit.HOURS.between(tweetDate, curDate) == 0) { + long between = ChronoUnit.MINUTES.between(tweetDate, curDate); + return between + " " + WordForms.getForm(between, WordForms.MINUTES_FORMS) + " назад"; + } else if (ChronoUnit.DAYS.between(tweetDate, curDate) <= 1) { + if (tweetDate.getDayOfMonth() == nowDayTime.getDayOfMonth()) { + long between = ChronoUnit.HOURS.between(tweetDate, curDate); + return between + " " + WordForms.getForm(between, WordForms.HOUR_FORMS) + " назад"; + } else { + return "вчера"; + } + } else { + long between = ChronoUnit.DAYS.between(tweetDate, curDate); + return between + " " + WordForms.getForm(between, WordForms.DAYS_FORMS) + " назад"; + } + } +} + + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TweetSearch.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TweetSearch.java new file mode 100644 index 00000000..fd09871f --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TweetSearch.java @@ -0,0 +1,72 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; +import twitter4j.*; +import java.util.List; + +public class TweetSearch { + public static void noStreamSearch(Arguments arguments) throws TweetSearchException { + Twitter twitter = new TwitterFactory().getInstance(); + Query query = new Query(arguments.getQuery()); + int lim = arguments.getLimit(); + if (arguments.getPlace() != "") { + double[] location = GeoFeatures.getLocation(arguments.getPlace(), twitter); + query.geoCode(new GeoLocation(location[0], location[1]), location[2], "km"); + } + QueryResult queryresult; + boolean any = false; + try { + while (true) { + queryresult = twitter.search(query); + List tweets = queryresult.getTweets(); + for (Status status : tweets) { + if (!arguments.isHideRetweets() || !status.isRetweet()) { + try { + System.out.print(MakeMassage.info(status) + "\n"); + any = true; + lim--; + if (lim == 0) { + return; + } + } catch (LostInformationException ex) { + System.out.print("Message part was lost."); + } + } + } + query = queryresult.nextQuery(); + if (query == null) { + if (!any) { + System.out.print("No tweets found."); + } + return; + } + } + } catch (TwitterException e) { + System.err.println(e.getMessage()); + } + } + + public static void twitterStream(Arguments arguments)throws TweetSearchException { + TwitterStream twitterStream = new TwitterStreamFactory().getInstance(); + StatusListener listener = new StatusAdapter() { + @Override + public void onStatus(Status status) { + if (!arguments.isHideRetweets() || !status.isRetweet()) { + try { + System.out.print(MakeMassage.info(status) + "\n"); + } catch (LostInformationException ex) { + System.err.print("Message part was lost."); + } + } + } + }; + String[] query = {arguments.getQuery()}; + double[][]location = GeoFeatures.getFilter(arguments.getPlace()); + FilterQuery filter = new FilterQuery(); + filter.track(query); + if (arguments.getPlace() != "") { + filter.locations(location); + } + twitterStream.addListener(listener); + twitterStream.filter(filter); + } + +} diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TweetSearchException.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TweetSearchException.java new file mode 100644 index 00000000..d0c8de48 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TweetSearchException.java @@ -0,0 +1,11 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; + +/** + * Created by Даша on 05.10.2015. + */ +public class TweetSearchException extends Exception { + public TweetSearchException(String message) { + super(message); + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TwitterStreamer.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TwitterStreamer.java new file mode 100644 index 00000000..c1c16831 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TwitterStreamer.java @@ -0,0 +1,32 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; +import twitter4j.*; + +public class TwitterStreamer { + public static void main(String[] args) throws TwitterException { + Arguments arguments; + try { + arguments = ArgumentsInput.inputArguments(args); + } catch (InvalidArgumentsException e) { + arguments = new Arguments(); + System.exit(1); + } + + if (!arguments.isStream()) { + try { + TweetSearch.noStreamSearch(arguments); + } catch (TweetSearchException ex) { + System.err.print(ex.getMessage()); + System.exit(1); + } + } else { + try { + TweetSearch.twitterStream(arguments); + } catch (TweetSearchException ex) { + System.err.print(ex.getMessage()); + System.exit(1); + } + } + } +} + + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/WordForms.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/WordForms.java new file mode 100644 index 00000000..2325525a --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/WordForms.java @@ -0,0 +1,27 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; + +public class WordForms { + public static final String[] HOUR_FORMS = {"час", "часа", "часов"}; + public static final String[] MINUTES_FORMS = {"минуту", "минуты", "минут"}; + public static final String[] DAYS_FORMS = {"день", "дня", "дней"}; + public static final String[] RE_FORMS = {"ретвит", "ретвита", "ретвитов"}; + + public static final int ONE = 1; + public static final int TEN = 10; + public static final int TWO_TEN = 20; + public static final int TEN_ONE = 11; + public static final int TWO = 2; + public static final int TEN_TEN = 100; + public static final int TWO_TWO = 4; + + static String getForm(long number, String[] words) { + if (number == ONE || (number > TWO_TEN && number % TEN == ONE && number % TEN_TEN != TEN_ONE)) { + return words[0]; + } else if ((number % TEN_TEN < TEN || number % TEN_TEN > TWO_TEN) + && number % TEN >= TWO && number % TEN <= TWO_TWO) { + return words[1]; + } else { + return words[2]; + } + } +} diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/Arguments.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/Arguments.java new file mode 100644 index 00000000..28bec4c3 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/Arguments.java @@ -0,0 +1,50 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; +import com.beust.jcommander.Parameter; + +public class Arguments { + private final int maxLimit = 100; + @Parameter(names = { "-q", "--query" }, + description = "ключевые слова для поиска") + private String query = ""; + @Parameter(names = { "-p", "--place" }, + description = "поиск твитов в некотором регионе") + private String place = ""; + @Parameter(names = { "-l", "--limit" }, + description = "количество твитов") + private Integer limit = maxLimit; + @Parameter(names = { "-s", "--stream" }, + description = "вывод твитов в стриминге") + private boolean stream = false; + @Parameter(names = { "--hideRetweets" }, + description = "скрывать ретвиты") + private boolean hideRetweets = false; + @Parameter(names = { "-h", "--help" }, + description = "помошь") + private boolean help = false; + + + 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; + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/ArgumentsInput.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/ArgumentsInput.java new file mode 100644 index 00000000..c162476b --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/ArgumentsInput.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; +import com.beust.jcommander.JCommander; + + +public class ArgumentsInput { + public static Arguments inputArguments(String[] args) throws InvalidArgumentsException { + Arguments arguments = new Arguments(); + try { + JCommander commander = new JCommander(arguments, args); + if (arguments.isHelp()) { + commander.usage(); + System.exit(0); + } + } catch (Exception ex) { + System.err.print("Invalid arguments exception"); + } + return arguments; + } +} + + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/GeoFeatures.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/GeoFeatures.java new file mode 100644 index 00000000..d0a2506f --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/GeoFeatures.java @@ -0,0 +1,79 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; +import twitter4j.*; +import java.util.List; + +public class GeoFeatures { + + private static final double[][] MOSCOW = {{55.489926, 37.31932}, {56.009657, 37.9456611}}; + private static final double HALF_CIRCLE = 180.0; + private static final double ONE = 60; + private static final double TWO = 1.1515; + private static final double KILOMETERS = 0.8684; + public static double getBetween(double[][] square) { + double lat1 = square[0][1]; + double lat2 = square[1][1]; + double lon1 = square[0][0]; + double lon2 = square[1][0]; + double theta = lon1 - lon2; + double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta)); + dist = Math.acos(dist); + dist = rad2deg(dist); + dist = dist * ONE * TWO; + dist = dist * KILOMETERS; + + return (dist); + } + + private static double deg2rad(double deg) { + return (deg * Math.PI / HALF_CIRCLE); + } + + private static double rad2deg(double rad) { + return (rad * HALF_CIRCLE / Math.PI); + } + + public static double[] getLocation(String place, Twitter twitter) { + double[][] square = getFilter(place); + double minimumLatitude = square[0][1]; + double minimumLongitude = square[0][0]; + double maximumLatitude = square[1][1]; + double maximumLongitude = square[1][0]; + return new double[]{ + (minimumLatitude + maximumLatitude) / 2, + (minimumLongitude + maximumLongitude) / 2, + getBetween(square) / 2 + }; + } + + public static double[][] getFilter(String place) { + Twitter twitter = new TwitterFactory().getInstance(); + try { + GeoQuery geoQuery = new GeoQuery((String) null); + geoQuery.setQuery(place); + List placeResponseList = twitter.searchPlaces(geoQuery); + double minimumLatitude = Double.MAX_VALUE, + maximumLatitude = -Double.MAX_VALUE, + minimumLongitude = Double.MAX_VALUE, + maximumLongitude = -Double.MAX_VALUE; + for (GeoLocation location : placeResponseList.get(0).getBoundingBoxCoordinates()[0]) { + minimumLongitude = Math.min(minimumLongitude, location.getLongitude()); + maximumLongitude = Math.max(maximumLongitude, location.getLongitude()); + minimumLatitude = Math.min(minimumLatitude, location.getLatitude()); + maximumLatitude = Math.max(maximumLatitude, location.getLatitude()); + + } + + double[][] coordinates = new double[2][2]; + coordinates[0][0] = minimumLongitude; + coordinates[0][1] = minimumLatitude; + coordinates[1][0] = maximumLongitude; + coordinates[1][1] = maximumLatitude; + return coordinates; + } catch (Exception e) { + System.err.println("Error, while trying to get location."); + } + return MOSCOW; + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/InvalidArgumentsException.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/InvalidArgumentsException.java new file mode 100644 index 00000000..66146941 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/InvalidArgumentsException.java @@ -0,0 +1,10 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; + +/** + * Created by Даша on 05.10.2015. + */ +public class InvalidArgumentsException extends Exception { + public InvalidArgumentsException(String message) { + super(message); + } +} diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/LostInformationException.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/LostInformationException.java new file mode 100644 index 00000000..8129d137 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/LostInformationException.java @@ -0,0 +1,10 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; + +/** + * Created by Даша on 05.10.2015. + */ +public class LostInformationException extends Exception { + public LostInformationException(String message) { + super(message); + } +} diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/MakeMassage.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/MakeMassage.java new file mode 100644 index 00000000..228b4a0c --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/MakeMassage.java @@ -0,0 +1,40 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; +import twitter4j.*; + +import java.time.LocalDateTime; +import java.time.ZoneId; + +public class MakeMassage { + + static String getName(Status st) { + return "@" + st.getUser().getName() + " : "; + } + static String getRetweets(Status st) { + int retweet = st.getRetweetCount(); + if (retweet == 0) { + return ""; + } else { + return "(" + retweet + WordForms.getForm(retweet, WordForms.RE_FORMS) + ")"; + } + } + static String getMessage(Status st) { + String text = st.getText(); + if (st.isRetweet()) { + text = " ретвитнул " + st.getRetweetedStatus().getUser().getScreenName() + " : "; + } + return text; + } + + static String getTime(Status st) { + LocalDateTime tweetDate = st.getCreatedAt().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + LocalDateTime curDate = LocalDateTime.now(); + return TimeHandler.getType(tweetDate, curDate); + } + + static String info(Status st) throws LostInformationException { + String message = getTime(st) + " " + getName(st) + getMessage(st) + " " + getRetweets(st) + "\n"; + message += "-----------------------------------------------------------------------------------"; + return message; + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/TimeHandler.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/TimeHandler.java new file mode 100644 index 00000000..9bb97dd8 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/TimeHandler.java @@ -0,0 +1,34 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; + +//dontreadme +//tweet.getCreatedAt().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime( +// LocalDateTime curDate = LocalDateTime.now(); + +public class TimeHandler { + public static final int TWO_MINUTES = 120; + + static String getType(LocalDateTime myDayTime, LocalDateTime nowDayTime) { + LocalDateTime tweetDate = myDayTime; + LocalDateTime curDate = nowDayTime; + if (ChronoUnit.SECONDS.between(tweetDate, curDate) < TWO_MINUTES) { + return "только что"; + } else if (ChronoUnit.HOURS.between(tweetDate, curDate) == 0) { + long between = ChronoUnit.MINUTES.between(tweetDate, curDate); + return between + " " + WordForms.getForm(between, WordForms.MINUTES_FORMS) + " назад"; + } else if (ChronoUnit.DAYS.between(tweetDate, curDate) <= 1) { + if (tweetDate.getDayOfMonth() == nowDayTime.getDayOfMonth()) { + long between = ChronoUnit.HOURS.between(tweetDate, curDate); + return between + " " + WordForms.getForm(between, WordForms.HOUR_FORMS) + " назад"; + } else { + return "вчера"; + } + } else { + long between = ChronoUnit.DAYS.between(tweetDate, curDate); + return between + " " + WordForms.getForm(between, WordForms.DAYS_FORMS) + " назад"; + } + } +} + + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/TweetSearch.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/TweetSearch.java new file mode 100644 index 00000000..5a2ce1bc --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/TweetSearch.java @@ -0,0 +1,72 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; +import twitter4j.*; +import java.util.List; + +public class TweetSearch { + public static void noStreamSearch(Arguments arguments) throws TweetSearchException { + Twitter twitter = new TwitterFactory().getInstance(); + Query query = new Query(arguments.getQuery()); + int lim = arguments.getLimit(); + if (arguments.getPlace() != "") { + double[] location = GeoFeatures.getLocation(arguments.getPlace(), twitter); + query.geoCode(new GeoLocation(location[0], location[1]), location[2], "km"); + } + QueryResult queryresult; + boolean any = false; + try { + while (true) { + queryresult = twitter.search(query); + List tweets = queryresult.getTweets(); + for (Status status : tweets) { + if (!arguments.isHideRetweets() || !status.isRetweet()) { + try { + System.out.print(MakeMassage.info(status) + "\n"); + any = true; + lim--; + if (lim == 0) { + return; + } + } catch (LostInformationException ex) { + System.out.print("Message part was lost."); + } + } + } + query = queryresult.nextQuery(); + if (query == null) { + if (!any) { + System.out.print("No tweets found."); + } + return; + } + } + } catch (TwitterException e) { + System.err.println(e.getMessage()); + } + } + + public static void twitterStream(Arguments arguments)throws TweetSearchException { + TwitterStream twitterStream = new TwitterStreamFactory().getInstance(); + StatusListener listener = new StatusAdapter() { + @Override + public void onStatus(Status status) { + if (!arguments.isHideRetweets() || !status.isRetweet()) { + try { + System.out.print(MakeMassage.info(status) + "\n"); + } catch (LostInformationException ex) { + System.err.print("Message part was lost."); + } + } + } + }; + String[] query = {arguments.getQuery()}; + double[][]location = GeoFeatures.getFilter(arguments.getPlace()); + FilterQuery filter = new FilterQuery(); + filter.track(query); + if (arguments.getPlace() != "") { + filter.locations(location); + } + twitterStream.addListener(listener); + twitterStream.filter(filter); + } + +} diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/TweetSearchException.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/TweetSearchException.java new file mode 100644 index 00000000..632aed83 --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/TweetSearchException.java @@ -0,0 +1,11 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; + +/** + * Created by Даша on 05.10.2015. + */ +public class TweetSearchException extends Exception { + public TweetSearchException(String message) { + super(message); + } +} + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/TwitterStreamer.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/TwitterStreamer.java new file mode 100644 index 00000000..e5dafc5b --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/TwitterStreamer.java @@ -0,0 +1,32 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; +import twitter4j.*; + +public class TwitterStreamer { + public static void main(String[] args) throws TwitterException { + Arguments arguments; + try { + arguments = ArgumentsInput.inputArguments(args); + } catch (InvalidArgumentsException e) { + arguments = new Arguments(); + System.exit(1); + } + + if (!arguments.isStream()) { + try { + TweetSearch.noStreamSearch(arguments); + } catch (TweetSearchException ex) { + System.err.print(ex.getMessage()); + System.exit(1); + } + } else { + try { + TweetSearch.twitterStream(arguments); + } catch (TweetSearchException ex) { + System.err.print(ex.getMessage()); + System.exit(1); + } + } + } +} + + diff --git a/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/WordForms.java b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/WordForms.java new file mode 100644 index 00000000..47ad7ffe --- /dev/null +++ b/mamaevads/src/main/java/ru/fizteh/fivt/students/mamaevads/supertests/WordForms.java @@ -0,0 +1,26 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; +public class WordForms { + public static final String[] HOUR_FORMS = {"час", "часа", "часов"}; + public static final String[] MINUTES_FORMS = {"минуту", "минуты", "минут"}; + public static final String[] DAYS_FORMS = {"день", "дня", "дней"}; + public static final String[] RE_FORMS = {"ретвит", "ретвита", "ретвитов"}; + + public static final int ONE = 1; + public static final int TEN = 10; + public static final int TWO_TEN = 20; + public static final int TEN_ONE = 11; + public static final int TWO = 2; + public static final int TEN_TEN = 100; + public static final int TWO_TWO = 4; + + static String getForm(long number, String[] words) { + if (number == ONE || (number > TWO_TEN && number % TEN == ONE && number % TEN_TEN != TEN_ONE)) { + return words[0]; + } else if ((number % TEN_TEN < TEN || number % TEN_TEN > TWO_TEN) + && number % TEN >= TWO && number % TEN <= TWO_TWO) { + return words[1]; + } else { + return words[2]; + } + } +} diff --git a/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/miniorm/DatabaseServiceTest.java b/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/miniorm/DatabaseServiceTest.java new file mode 100644 index 00000000..34d91026 --- /dev/null +++ b/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/miniorm/DatabaseServiceTest.java @@ -0,0 +1,75 @@ +package ru.fizteh.fivt.students.mamaevads.miniorm; +/*import java.util.List; + + +import junit.framework.TestCase; +import org.junit.Test; +import ru.fizteh.fivt.students.mamaevads.miniorm.Column; +import ru.fizteh.fivt.students.mamaevads.miniorm.DatabaseService; +import ru.fizteh.fivt.students.mamaevads.miniorm.PrimaryKey; +import ru.fizteh.fivt.students.mamaevads.miniorm.Table; + +public class DatabaseServiceTest extends TestCase { + + @Table + public static class Student { + @Column + @PrimaryKey + private String name; + @Column(name="roomnum") + private String room; + @Column + private Integer age; + + public Student() {} + + private Student(String name, String room, int age) { + this.name = name; + this.room = room; + this.age = age; + } + + @Override + public String toString() { + return "Student{" + name + "|" + room + "|" + age + "}"; + } + } + + @Test + public void testTableCreation() { + try { + DatabaseService service = new DatabaseService<>(Student.class); + service.createTable(); + service.dropTable(); + } catch (Exception e) { + e.printStackTrace(); + fail("failed: " + e.getMessage()); + } + } + + @Test + public void testRowOperations() { + try { + DatabaseService service = new DatabaseService<>(Student.class); + service.createTable(); + service.insert(new Student("ivanov", "305", 18)); + service.insert(new Student("petrov", "305", 18)); + service.insert(new Student("sidorov", "306", 19)); + service.insert(new Student("nobody", "306", 17)); + service.update(new Student("petrov", "308", 18)); + service.deleteByKey("sidorov"); + service.delete(new Student("nobody", "308", 30)); + + assertNull(service.queryById("sidorov")); + assertEquals("[Student{ivanov|305|18}, Student{petrov|308|18}]", service.queryForAll().toString()); + service.dropTable(); + } catch (Exception e) { + e.printStackTrace(); + fail("failed: " + e.getMessage()); + } + } + + +} + +*/ \ No newline at end of file diff --git a/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TimeHandlerTest.java b/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TimeHandlerTest.java new file mode 100644 index 00000000..fad64f7c --- /dev/null +++ b/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/TimeHandlerTest.java @@ -0,0 +1,52 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; + +import junit.framework.TestCase; +import org.junit.Test; +import junit.framework.Assert; + +import java.time.LocalDateTime; +import java.time.Month; + + +public class TimeHandlerTest extends TestCase { + + @Test + public void testGetType() throws Exception { + LocalDateTime timeOne = LocalDateTime.of(2010, Month.JANUARY, 20, 15, 0, 4); + LocalDateTime timeTwo = LocalDateTime.of(2010, Month.JANUARY, 20, 15, 2, 3); + assertEquals("только что", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2010, Month.JANUARY, 20, 23, 59, 25); + timeTwo = LocalDateTime.of(2010, Month.JANUARY, 21, 00, 00, 30); + assertEquals("только что", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2010, Month.JANUARY, 20, 15, 1, 1); + timeTwo = LocalDateTime.of(2010, Month.JANUARY, 20, 15, 3, 3); + assertEquals("2 минуты назад", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2010, Month.JANUARY, 20, 15, 1, 1); + timeTwo = LocalDateTime.of(2010, Month.JANUARY, 20, 16, 1, 0); + assertEquals("59 минут назад", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2010, Month.JANUARY, 20, 13, 1, 1); + timeTwo = LocalDateTime.of(2010, Month.JANUARY, 20, 16, 1, 0); + assertEquals("2 часа назад", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2010, Month.JANUARY, 20, 23, 1, 1); + timeTwo = LocalDateTime.of(2010, Month.JANUARY, 21, 02, 1, 0); + assertEquals("вчера", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2012, Month.FEBRUARY, 26, 00, 1, 1); + timeTwo = LocalDateTime.of(2012, Month.FEBRUARY, 27, 23, 59, 59); + assertEquals("вчера", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2012, Month.FEBRUARY, 25, 00, 1, 1); + timeTwo = LocalDateTime.of(2012, Month.FEBRUARY, 27, 23, 59, 59); + assertEquals("2 дня назад", TimeHandler.getType(timeOne, timeTwo)); + timeOne = LocalDateTime.of(2012, Month.FEBRUARY, 28, 00, 1, 1); //Leap year + timeTwo = LocalDateTime.of(2012, Month.MARCH, 01, 23, 59, 59); + assertEquals("2 дня назад", TimeHandler.getType(timeOne, timeTwo)); + timeOne = LocalDateTime.of(2012, Month.FEBRUARY, 29, 1, 1, 1); + timeTwo = LocalDateTime.of(2012, Month.MARCH, 01, 22, 59, 59); + assertEquals("вчера", TimeHandler.getType(timeOne, timeTwo)); + timeOne = LocalDateTime.of(2012, Month.FEBRUARY, 28, 1, 1, 1); + timeTwo = LocalDateTime.of(2012, Month.MARCH, 06, 22, 59, 59); + assertEquals("7 дней назад", TimeHandler.getType(timeOne, timeTwo)); + timeOne = LocalDateTime.of(2011, Month.FEBRUARY, 28, 1, 1, 1); + timeTwo = LocalDateTime.of(2011, Month.MARCH, 06, 22, 59, 59); + assertEquals("6 дней назад", TimeHandler.getType(timeOne, timeTwo)); + } +} \ No newline at end of file diff --git a/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/WordFormsTest.java b/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/WordFormsTest.java new file mode 100644 index 00000000..6dfd9785 --- /dev/null +++ b/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/moduletests/library/WordFormsTest.java @@ -0,0 +1,45 @@ +package ru.fizteh.fivt.students.mamaevads.moduletests.library; + +import junit.framework.Assert; +import junit.framework.TestCase; +import org.junit.Test; + +public class WordFormsTest extends TestCase { + + @Test + public void testGetForm() throws Exception { + Assert.assertEquals("день", WordForms.getForm(1, WordForms.DAYS_FORMS)); + Assert.assertEquals("минуту", WordForms.getForm(1, WordForms.MINUTES_FORMS)); + Assert.assertEquals("час", WordForms.getForm(1, WordForms.HOUR_FORMS)); + Assert.assertEquals("дня", WordForms.getForm(2, WordForms.DAYS_FORMS)); + Assert.assertEquals("минуты", WordForms.getForm(2, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часа", WordForms.getForm(2, WordForms.HOUR_FORMS)); + Assert.assertEquals("дня", WordForms.getForm(4, WordForms.DAYS_FORMS)); + Assert.assertEquals("минуты", WordForms.getForm(4, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часа", WordForms.getForm(4, WordForms.HOUR_FORMS)); + Assert.assertEquals("дней", WordForms.getForm(12, WordForms.DAYS_FORMS)); + Assert.assertEquals("минут", WordForms.getForm(12, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часов", WordForms.getForm(12, WordForms.HOUR_FORMS)); + Assert.assertEquals("дней", WordForms.getForm(14, WordForms.DAYS_FORMS)); + Assert.assertEquals("минут", WordForms.getForm(14, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часов", WordForms.getForm(14, WordForms.HOUR_FORMS)); + Assert.assertEquals("дня", WordForms.getForm(22, WordForms.DAYS_FORMS)); + Assert.assertEquals("минуты", WordForms.getForm(22, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часа", WordForms.getForm(22, WordForms.HOUR_FORMS)); + Assert.assertEquals("дня", WordForms.getForm(24, WordForms.DAYS_FORMS)); + Assert.assertEquals("минуты", WordForms.getForm(24, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часа", WordForms.getForm(24, WordForms.HOUR_FORMS)); + Assert.assertEquals("дней", WordForms.getForm(11, WordForms.DAYS_FORMS)); + Assert.assertEquals("минут", WordForms.getForm(11, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часов", WordForms.getForm(11, WordForms.HOUR_FORMS)); + Assert.assertEquals("дней", WordForms.getForm(111, WordForms.DAYS_FORMS)); + Assert.assertEquals("минут", WordForms.getForm(111, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часов", WordForms.getForm(111, WordForms.HOUR_FORMS)); + Assert.assertEquals("день", WordForms.getForm(131, WordForms.DAYS_FORMS)); + Assert.assertEquals("минуту", WordForms.getForm(131, WordForms.MINUTES_FORMS)); + Assert.assertEquals("час", WordForms.getForm(131, WordForms.HOUR_FORMS)); + Assert.assertEquals("дней", WordForms.getForm(113, WordForms.DAYS_FORMS)); + Assert.assertEquals("минут", WordForms.getForm(113, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часов", WordForms.getForm(113, WordForms.HOUR_FORMS)); + } +} \ No newline at end of file diff --git a/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/supertests/TimeHandlerTest.java b/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/supertests/TimeHandlerTest.java new file mode 100644 index 00000000..af0ec718 --- /dev/null +++ b/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/supertests/TimeHandlerTest.java @@ -0,0 +1,53 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; + + +import junit.framework.TestCase; +import org.junit.Test; +import junit.framework.Assert; + +import java.time.LocalDateTime; +import java.time.Month; + + +public class TimeHandlerTest extends TestCase { + + @Test + public void testGetType() throws Exception { + LocalDateTime timeOne = LocalDateTime.of(2010, Month.JANUARY, 20, 15, 0, 4); + LocalDateTime timeTwo = LocalDateTime.of(2010, Month.JANUARY, 20, 15, 2, 3); + assertEquals("только что", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2010, Month.JANUARY, 20, 23, 59, 25); + timeTwo = LocalDateTime.of(2010, Month.JANUARY, 21, 00, 00, 30); + assertEquals("только что", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2010, Month.JANUARY, 20, 15, 1, 1); + timeTwo = LocalDateTime.of(2010, Month.JANUARY, 20, 15, 3, 3); + assertEquals("2 минуты назад", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2010, Month.JANUARY, 20, 15, 1, 1); + timeTwo = LocalDateTime.of(2010, Month.JANUARY, 20, 16, 1, 0); + assertEquals("59 минут назад", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2010, Month.JANUARY, 20, 13, 1, 1); + timeTwo = LocalDateTime.of(2010, Month.JANUARY, 20, 16, 1, 0); + assertEquals("2 часа назад", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2010, Month.JANUARY, 20, 23, 1, 1); + timeTwo = LocalDateTime.of(2010, Month.JANUARY, 21, 02, 1, 0); + assertEquals("вчера", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2012, Month.FEBRUARY, 26, 00, 1, 1); + timeTwo = LocalDateTime.of(2012, Month.FEBRUARY, 27, 23, 59, 59); + assertEquals("вчера", TimeHandler.getType(timeOne,timeTwo)); + timeOne = LocalDateTime.of(2012, Month.FEBRUARY, 25, 00, 1, 1); + timeTwo = LocalDateTime.of(2012, Month.FEBRUARY, 27, 23, 59, 59); + assertEquals("2 дня назад", TimeHandler.getType(timeOne, timeTwo)); + timeOne = LocalDateTime.of(2012, Month.FEBRUARY, 28, 00, 1, 1); //Leap year + timeTwo = LocalDateTime.of(2012, Month.MARCH, 01, 23, 59, 59); + assertEquals("2 дня назад", TimeHandler.getType(timeOne, timeTwo)); + timeOne = LocalDateTime.of(2012, Month.FEBRUARY, 29, 1, 1, 1); + timeTwo = LocalDateTime.of(2012, Month.MARCH, 01, 22, 59, 59); + assertEquals("вчера", TimeHandler.getType(timeOne, timeTwo)); + timeOne = LocalDateTime.of(2012, Month.FEBRUARY, 28, 1, 1, 1); + timeTwo = LocalDateTime.of(2012, Month.MARCH, 06, 22, 59, 59); + assertEquals("7 дней назад", TimeHandler.getType(timeOne, timeTwo)); + timeOne = LocalDateTime.of(2011, Month.FEBRUARY, 28, 1, 1, 1); + timeTwo = LocalDateTime.of(2011, Month.MARCH, 06, 22, 59, 59); + assertEquals("6 дней назад", TimeHandler.getType(timeOne, timeTwo)); + } +} \ No newline at end of file diff --git a/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/supertests/WordFormsTest.java b/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/supertests/WordFormsTest.java new file mode 100644 index 00000000..d28a2601 --- /dev/null +++ b/mamaevads/src/test/java/ru/fizteh/fivt/students/mamaevads/supertests/WordFormsTest.java @@ -0,0 +1,45 @@ +package ru.fizteh.fivt.students.mamaevads.supertests; + +import junit.framework.Assert; +import junit.framework.TestCase; +import org.junit.Test; + +public class WordFormsTest extends TestCase { + + @Test + public void testGetForm() throws Exception { + Assert.assertEquals("день", WordForms.getForm(1, WordForms.DAYS_FORMS)); + Assert.assertEquals("минуту", WordForms.getForm(1, WordForms.MINUTES_FORMS)); + Assert.assertEquals("час", WordForms.getForm(1, WordForms.HOUR_FORMS)); + Assert.assertEquals("дня", WordForms.getForm(2, WordForms.DAYS_FORMS)); + Assert.assertEquals("минуты", WordForms.getForm(2, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часа", WordForms.getForm(2, WordForms.HOUR_FORMS)); + Assert.assertEquals("дня", WordForms.getForm(4, WordForms.DAYS_FORMS)); + Assert.assertEquals("минуты", WordForms.getForm(4, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часа", WordForms.getForm(4, WordForms.HOUR_FORMS)); + Assert.assertEquals("дней", WordForms.getForm(12, WordForms.DAYS_FORMS)); + Assert.assertEquals("минут", WordForms.getForm(12, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часов", WordForms.getForm(12, WordForms.HOUR_FORMS)); + Assert.assertEquals("дней", WordForms.getForm(14, WordForms.DAYS_FORMS)); + Assert.assertEquals("минут", WordForms.getForm(14, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часов", WordForms.getForm(14, WordForms.HOUR_FORMS)); + Assert.assertEquals("дня", WordForms.getForm(22, WordForms.DAYS_FORMS)); + Assert.assertEquals("минуты", WordForms.getForm(22, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часа", WordForms.getForm(22, WordForms.HOUR_FORMS)); + Assert.assertEquals("дня", WordForms.getForm(24, WordForms.DAYS_FORMS)); + Assert.assertEquals("минуты", WordForms.getForm(24, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часа", WordForms.getForm(24, WordForms.HOUR_FORMS)); + Assert.assertEquals("дней", WordForms.getForm(11, WordForms.DAYS_FORMS)); + Assert.assertEquals("минут", WordForms.getForm(11, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часов", WordForms.getForm(11, WordForms.HOUR_FORMS)); + Assert.assertEquals("дней", WordForms.getForm(111, WordForms.DAYS_FORMS)); + Assert.assertEquals("минут", WordForms.getForm(111, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часов", WordForms.getForm(111, WordForms.HOUR_FORMS)); + Assert.assertEquals("день", WordForms.getForm(131, WordForms.DAYS_FORMS)); + Assert.assertEquals("минуту", WordForms.getForm(131, WordForms.MINUTES_FORMS)); + Assert.assertEquals("час", WordForms.getForm(131, WordForms.HOUR_FORMS)); + Assert.assertEquals("дней", WordForms.getForm(113, WordForms.DAYS_FORMS)); + Assert.assertEquals("минут", WordForms.getForm(113, WordForms.MINUTES_FORMS)); + Assert.assertEquals("часов", WordForms.getForm(113, WordForms.HOUR_FORMS)); + } +} \ No newline at end of file