diff --git a/projects/elinrin/pom.xml b/projects/elinrin/pom.xml
new file mode 100644
index 0000000..da941db
--- /dev/null
+++ b/projects/elinrin/pom.xml
@@ -0,0 +1,115 @@
+
+ 4.0.0
+
+ ru.mipt.diht.students
+ elinrin
+ 1.0-SNAPSHOT
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+
+
+
+
+ jar
+
+ elinrin
+ http://maven.apache.org
+
+
+ UTF-8
+
+
+
+
+
+ com.h2database
+ h2
+ 1.4.190
+
+
+
+ junit
+ junit
+ 3.8.1
+ test
+
+
+
+ com.beust
+ jcommander
+ 1.48
+
+
+
+ org.twitter4j
+ twitter4j-stream
+ 4.0.4
+
+
+
+ org.json
+ json
+ 20141113
+
+
+
+ com.google.guava
+ guava
+ 17.0
+
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+
+ org.mockito
+ mockito-all
+ 1.9.5
+
+
+
+ org.powermock
+ powermock-module-junit4
+ 1.6.1
+ test
+ true
+
+
+ junit
+ junit
+
+
+
+
+
+ org.powermock
+ powermock-api-mockito
+ 1.6.1
+ test
+ true
+
+
+ mockito-all
+ org.mockito
+
+
+
+
+ com.tngtech.java
+ junit-dataprovider
+ 1.10.1
+
+
+
+
diff --git a/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/ClassConverter.java b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/ClassConverter.java
new file mode 100644
index 0000000..52b0777
--- /dev/null
+++ b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/ClassConverter.java
@@ -0,0 +1,38 @@
+package ru.mipt.diht.students.elinrin.miniorm;
+
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+
+public class
+ClassConverter {
+ private static Map classes;
+ static {
+ classes = new HashMap<>();
+ classes.put(Integer.class, "INTEGER");
+ classes.put(Boolean.class, "BOOLEAN");
+ classes.put(Byte.class, "TINYINT");
+ classes.put(Short.class, "SMALLINT");
+ classes.put(Long.class, "BIGINT");
+ classes.put(Double.class, "DOUBLE");
+ classes.put(Float.class, "FLOAT");
+ classes.put(Time.class, "TIME");
+ classes.put(Date.class, "DATE");
+ classes.put(Timestamp.class, "TIMESTAMP");
+ classes.put(Character.class, "CHAR");
+ classes.put(String.class, "CLOB");
+ classes.put(UUID.class, "UUID");
+ }
+
+ public static String convert(final Class currClass) {
+ if (classes.containsKey(currClass)) {
+ return classes.get(currClass);
+ }
+ return "OTHER";
+ }
+
+}
diff --git a/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/DatabaseService.java b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/DatabaseService.java
new file mode 100644
index 0000000..6151400
--- /dev/null
+++ b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/DatabaseService.java
@@ -0,0 +1,255 @@
+package ru.mipt.diht.students.elinrin.miniorm;
+import com.google.common.base.CaseFormat;
+import ru.mipt.diht.students.elinrin.miniorm.annotations.Column;
+import ru.mipt.diht.students.elinrin.miniorm.annotations.PrimaryKey;
+import ru.mipt.diht.students.elinrin.miniorm.annotations.Table;
+import ru.mipt.diht.students.elinrin.miniorm.exception.HandlerOfException;
+
+import javax.management.OperationsException;
+import java.lang.reflect.Field;
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+
+T queryById(K) - возвращает запись по первичному ключу
+T queryForAll() - возвращает все записи из таблицы
+void insert(T) - добавляет запись
+void update(T) - редактирует запись по первичному ключу
+void delete(T) - удаляет запись по первичному ключу
+void createTable() - создаёт таблицу по метаданным класса T. См. аннотации ниже.
+void dropTable() - удаляет таблицу, соответствующую T. Класс нужно покрыть модульными тестами.
+*/
+public class DatabaseService {
+ //Классы JDSC
+ private Connection connection = null;
+ private Statement statement = null;
+ private ResultSet resultSet = null;
+ private Field primaryKey = null;
+ private List columns = null;
+ private Field[] fields;
+ private String[] namesOfColumns;
+ private Class tableClass = null;
+ private String tableName = "";
+ private int primaryKeyFieldNumber = -1;
+
+ private boolean hasTableYet = false;
+
+
+ /*protected void finalize ( ) throws SQLException {
+ resultSet.close();
+ statement.close();
+ connection.close();
+ }*/
+
+ // DatabaseService(Class) - коструктор, принимает тип объекта, с которым хотим работать
+ DatabaseService(final Class elementClass) throws ClassNotFoundException,
+ SQLException, InstantiationException, IllegalAccessException {
+
+ Class.forName("org.h2.Driver").newInstance();
+ //путь к файлу с БД, соединение с драйверами БД
+ connection = DriverManager.getConnection("jdbc:h2:~/test", "test", "test");
+ statement = connection.createStatement();
+
+ columns = new ArrayList<>();
+ tableClass = elementClass;
+ Table table = tableClass.getAnnotation(Table.class);
+ if (table == null) {
+ throw new IllegalArgumentException("Class should be annotated with Table");
+ }
+ tableName = table.name();
+ if (tableName.equals("")) {
+ tableName = "MY_TABLE";
+ }
+ int i = 0;
+ for (Field elem : tableClass.getDeclaredFields()) {
+ if (elem.getAnnotation(Column.class) != null) {
+ columns.add(elem);
+ }
+ if (elem.getAnnotation(PrimaryKey.class) != null) {
+ if (elem.getAnnotation(Column.class) == null) {
+ throw new IllegalArgumentException("Not all fields are columns");
+ }
+ if (primaryKey != null) {
+ throw new IllegalArgumentException("Not one primary Key");
+ }
+ primaryKey = elem;
+ primaryKeyFieldNumber = i;
+ }
+ ++i;
+ }
+
+ resultSet = connection.getMetaData().getTables(null, null,
+ CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, tableName), null);
+ resultSet.next();
+ }
+ public final T queryById(final K id) throws OperationsException,
+ SQLException, IllegalAccessException, InstantiationException {
+ if (!hasTableYet) {
+ throw new OperationsException("Для данного запроа необходимо создать таблицу");
+ }
+ if (primaryKey == null) {
+ throw new OperationsException("Должен суущестовать первичный ключ");
+ }
+ /*if (!id.getClass().isInstance(primaryKey.getType())){
+ throw new IllegalArgumentException("Ключ должен иметь тот же тип, что и первичные ключи таблицы");
+ }*/
+ StringBuilder newRequest = new StringBuilder();
+ newRequest.append("SELECT * FROM ").append(tableName).append(" WHERE ")
+ .append(columns.get(primaryKeyFieldNumber).getAnnotation(Column.class)
+ .name()).append(" = ").append(id.toString());
+ resultSet = statement.executeQuery(newRequest.toString());
+ List list = new ArrayList<>();
+ while (resultSet.next()) {
+ T item = tableClass.newInstance();
+ for (Field field: columns) {
+ if (field.getType().equals(Integer.class)) {
+ field.set(item, resultSet.getInt(field.getAnnotation(Column.class).name()));
+ }
+ if (field.getType().equals(String.class)) {
+ field.set(item, resultSet.getString(field.getAnnotation(Column.class).name()));
+ }
+ }
+ list.add(item);
+ }
+ if (list.size() == 0) {
+ return null;
+ }
+ if (list.size() > 1) {
+ throw new OperationsException("Ошибка получения результата");
+ }
+ return list.get(0);
+ }
+
+ final List queryForAll() throws OperationsException, SQLException, IllegalAccessException,
+ InstantiationException {
+
+ if (!hasTableYet) {
+ throw new OperationsException("Для данного запроа необходимо создать таблицу");
+ }
+ if (primaryKey == null) {
+ throw new OperationsException("Должен суущестовать первичный ключ");
+ }
+ StringBuilder newRequest = new StringBuilder();
+ newRequest.append("SELECT * FROM ").append(tableName);
+ resultSet = statement.executeQuery(newRequest.toString());
+ List list = new ArrayList<>();
+ while (resultSet.next()) {
+ T item = tableClass.newInstance();
+ for (Field field: columns) {
+ if (field.getType().equals(Integer.class)) {
+ field.set(item, resultSet.getInt(field.getAnnotation(Column.class).name()));
+ }
+ if (field.getType().equals(String.class)) {
+ field.set(item, resultSet.getString(field.getAnnotation(Column.class).name()));
+ }
+ }
+ list.add(item);
+ }
+ return list;
+ }
+
+ final void insert(final T key) throws SQLException {
+ StringBuilder newRequest = new StringBuilder();
+ newRequest.append("INSERT INTO ").append(tableName).append(" VALUES(");
+ boolean first = true;
+ for (Field field:columns) {
+ if (!first) {
+ newRequest.append(", ");
+ } else {
+ first = false;
+ }
+ newRequest.append("?");
+ }
+ newRequest.append(")");
+ //System.out.println(newRequest);
+ PreparedStatement preparedStatement = connection.prepareStatement(newRequest.toString());
+
+ for (int i = 0; i < columns.size(); i++) {
+ try {
+ preparedStatement.setObject(i + 1, columns.get(i).get(key));
+ } catch (IllegalAccessException e) {
+ HandlerOfException.handler(e);
+ }
+ }
+ //System.out.println(preparedStatement.toString());
+ preparedStatement.execute();
+
+ }
+
+ final void update(final T key) throws SQLException {
+ StringBuilder newRequest = new StringBuilder().append("UPDATE ").append(tableName).append(" SET ");
+ for (int i = 0; i < columns.size(); ++i) {
+ if (i != 0) {
+ newRequest.append(", ");
+ }
+ newRequest.append(columns.get(i).getAnnotation(Column.class).name()).append(" = ?");
+ }
+
+ newRequest.append(" WHERE ").append(columns.get(primaryKeyFieldNumber).getAnnotation(Column.class).name())
+ .append(" = ?");
+ PreparedStatement prepareStatement = connection.prepareStatement(newRequest.toString());
+ for (int i = 0; i < columns.size(); i++) {
+ try {
+ prepareStatement.setObject(1, columns.get(i).get(key));
+ prepareStatement.setObject(2, columns.get(primaryKeyFieldNumber).get(key));
+ } catch (IllegalAccessException e) {
+ HandlerOfException.handler(e);
+ }
+ prepareStatement.execute();
+ }
+
+
+
+ }
+
+
+ final void delete(final T key) throws SQLException {
+ StringBuilder newRequest = new StringBuilder();
+ newRequest.append("DELETE FROM ").append(tableName).append(columns.get(primaryKeyFieldNumber)
+ .getAnnotation(Column.class).name()).append(" = ").append("?");
+ PreparedStatement preparedStatement = connection.prepareStatement(newRequest.toString());
+ try {
+ preparedStatement.setObject(1, columns.get(primaryKeyFieldNumber).get(key));
+ preparedStatement.execute();
+ } catch (IllegalAccessException e) {
+ HandlerOfException.handler(e);
+ }
+ }
+
+ final void createTable() throws OperationsException, SQLException {
+ if (hasTableYet) {
+ throw new OperationsException("Невозможно повторно создать таблицу");
+ }
+ hasTableYet = true;
+ StringBuilder newRequest = new StringBuilder();
+ newRequest.append("CREATE TABLE IF NOT EXISTS ").append(tableName).append(" (");
+ int i = 0;
+ for (Field field : columns) {
+ //System.out.println(field.getType().toString());
+ if (i != 0) {
+ newRequest.append(", ");
+ }
+ newRequest.append(field.getAnnotation(Column.class).name()).append(" ");
+ newRequest.append(ClassConverter.convert(columns.get(i).getType())).append(" ");
+ if (field.isAnnotationPresent(PrimaryKey.class)) {
+ newRequest.append("PRIMARY KEY");
+ primaryKeyFieldNumber = i;
+ }
+ i++;
+ }
+ newRequest.append(") ");
+ //System.out.println(newRequest);
+ statement.execute(newRequest.toString());
+ }
+
+ final void dropTable() {
+ try {
+ statement.execute("DROP TABLE IF EXISTS " + tableName);
+ hasTableYet = false;
+ } catch (SQLException e) {
+ HandlerOfException.handler(e);
+ }
+ }
+}
diff --git a/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/User.java b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/User.java
new file mode 100644
index 0000000..8101341
--- /dev/null
+++ b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/User.java
@@ -0,0 +1,80 @@
+package ru.mipt.diht.students.elinrin.miniorm;
+
+/*
+import ru.mipt.diht.students.elinrin.miniorm.annotations.Column;
+import ru.mipt.diht.students.elinrin.miniorm.annotations.PrimaryKey;
+import ru.mipt.diht.students.elinrin.miniorm.annotations.Table;
+import ru.mipt.diht.students.elinrin.miniorm.exception.HandlerOfException;
+
+import javax.management.OperationsException;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Objects;
+*/
+
+
+public class User {
+ /*@Table(name = "TESTTABLE")
+ static class Tab {
+ @PrimaryKey
+ @Column(name = "ID")
+ Integer a;
+
+ @Column(name = "STRING")
+ String s;
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Tab) {
+ return ((Objects.equals(this.a, ((Tab) obj).a)) && (Objects.equals(this.s, ((Tab) obj).s)));
+ }
+ return false;
+ }
+
+ Tab(Object a, Object s) {
+ this.a = (Integer) a;
+ this.s = (String) s;
+ }
+
+ Tab() {
+ this.a = 0;
+ this.s = "";
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder().append("Id = ").append(a).append(", String = ").append(s);
+ return result.toString();
+ }
+ }
+
+ public static void main(String[] argv) {
+ DatabaseService bd = null;
+ try {
+ bd = new DatabaseService(Tab.class);
+ } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | SQLException e) {
+ HandlerOfException.handler(e);
+ }
+
+ try {
+ bd.createTable();
+ bd.insert(new Tab(1, "one"));
+ List all = bd.queryForAll();
+ all.forEach(System.out::println);
+
+ bd.insert(new Tab(2, "two"));
+ bd.insert(new Tab(3, "three"));
+ bd.insert(new Tab(4, "four"));
+
+ Tab elem = bd.queryById(3);
+ System.out.println(elem);
+
+ all = bd.queryForAll();
+ all.forEach(System.out::println);
+ } catch (IllegalAccessException | InstantiationException | OperationsException | SQLException e) {
+ HandlerOfException.handler(e);
+ } finally {
+ bd.dropTable();
+ }
+ }*/
+}
diff --git a/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/annotations/Column.java b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/annotations/Column.java
new file mode 100644
index 0000000..cbb2322
--- /dev/null
+++ b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/annotations/Column.java
@@ -0,0 +1,13 @@
+package ru.mipt.diht.students.elinrin.miniorm.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(value = ElementType.FIELD)
+@Retention(value = RetentionPolicy.RUNTIME)
+public @interface Column {
+ String name() default "";
+}
+
diff --git a/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/annotations/PrimaryKey.java b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/annotations/PrimaryKey.java
new file mode 100644
index 0000000..6234828
--- /dev/null
+++ b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/annotations/PrimaryKey.java
@@ -0,0 +1,11 @@
+package ru.mipt.diht.students.elinrin.miniorm.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(value = ElementType.FIELD)
+@Retention(value = RetentionPolicy.RUNTIME)
+public @interface PrimaryKey {
+}
diff --git a/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/annotations/Table.java b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/annotations/Table.java
new file mode 100644
index 0000000..bc3a545
--- /dev/null
+++ b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/annotations/Table.java
@@ -0,0 +1,12 @@
+package ru.mipt.diht.students.elinrin.miniorm.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(value = ElementType.TYPE)
+@Retention(value = RetentionPolicy.RUNTIME)
+public @interface Table {
+ String name() default "";
+}
diff --git a/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/exception/HandlerOfException.java b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/exception/HandlerOfException.java
new file mode 100644
index 0000000..57f24a1
--- /dev/null
+++ b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/miniorm/exception/HandlerOfException.java
@@ -0,0 +1,23 @@
+package ru.mipt.diht.students.elinrin.miniorm.exception;
+
+public class HandlerOfException {
+ static final String USER_MOD = "user";
+
+ public static void handler(final String message, final Throwable cause) {
+ System.err.println(message + ". " + cause.getMessage());
+ System.exit(1);
+ }
+ public static void handler(final Throwable cause) {
+ System.err.println(cause.getMessage());
+ System.exit(1);
+ }
+
+ public static void handler(final Throwable cause, final String mod) {
+ if (mod.equals(USER_MOD)) {
+ System.err.println(cause.getMessage());
+ } else {
+ System.err.println(cause.getMessage());
+ System.exit(1);
+ }
+ }
+}
diff --git a/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/threads/BlockingQueue.java b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/threads/BlockingQueue.java
new file mode 100644
index 0000000..2d9b413
--- /dev/null
+++ b/projects/elinrin/src/main/java/ru/mipt/diht/students/elinrin/threads/BlockingQueue.java
@@ -0,0 +1,89 @@
+package ru.mipt.diht.students.elinrin.threads;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class BlockingQueue {
+ private int maxQueueSize;
+ private Queue queue;
+ private Lock queueLock = new ReentrantLock();
+ private Lock offerLock = new ReentrantLock();
+ private Lock takeLock = new ReentrantLock();
+ private Object pushWait = new Object();
+ private Object popWait = new Object();
+
+ public final void offer(final List list) {
+ offerLock.lock();
+ try {
+ Integer last = 0;
+ while (last != list.size()) {
+ synchronized (popWait) {
+ while (queue.size() == maxQueueSize) {
+ try {
+ popWait.wait();
+ } catch (InterruptedException e) {
+ System.err.println(e.getMessage());
+ System.exit(1);
+ }
+ }
+ try {
+ queueLock.lock();
+ while (last < Integer.min(last + maxQueueSize - queue.size(), list.size())) {
+ queue.add(list.get(last));
+ last++;
+ }
+ } finally {
+ queueLock.unlock();
+ }
+ }
+ }
+ } finally {
+ synchronized (pushWait) {
+ pushWait.notifyAll();
+ }
+ offerLock.unlock();
+ }
+ }
+
+ public final List