diff --git a/solutions/bradikhin/ANkoR911/CQL/Aggregates.java b/solutions/bradikhin/ANkoR911/CQL/Aggregates.java new file mode 100644 index 0000000..fc9a486 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/Aggregates.java @@ -0,0 +1,173 @@ + + +import impl.EmptyCollectionException; + +import java.util.Collection; +import java.util.Collections; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Created by Владимир on 19.12.2015. + */ + +public class Aggregates +{ + + public interface Agregator extends Function + { + T apply(Collection collection) throws EmptyCollectionException; + } + + /** + * Maximum value for expression for elements of given collecdtion. + * + * @param expression + * @param + * @param + * @return + */ + public static > Agregator max(Function expression) + { + return new Agregator() + { + @Override + public T apply(Collection collection) throws EmptyCollectionException + { + if (collection.isEmpty()) + { + throw new EmptyCollectionException("Method max was called for empty collection."); + } + return Collections.max(collection.stream().map(expression).collect(Collectors.toList())); + } + + @Override + public T apply(C c) + { + return expression.apply(c); + } + }; + } + + /** + * Minimum value for expression for elements of given collecdtion. + * + * @param expression + * @param + * @param + * @return + */ + public static > Agregator min(Function expression) + { + return new Agregator() + { + @Override + public T apply(Collection collection) throws EmptyCollectionException + { + if (collection.isEmpty()) + { + throw new EmptyCollectionException("Method min was called for empty collection."); + } + return Collections.min(collection.stream().map(expression).collect(Collectors.toList())); + } + + @Override + public T apply(C c) + { + return expression.apply(c); + } + }; + } + + /** + * Number of items in source collection that turns this expression into not null. + * + * @param expression + * @param + * @param + * @return + */ + public static > Agregator count(Function expression) + { + return new Agregator() + { + @Override + public Long apply(Collection collection) + { + if (collection.isEmpty()) + { + return 0L; + } + return collection.stream().map(expression).count(); + } + + @Override + public Long apply(C c) + { + if (expression.apply(c) != null) + { + return 1L; + } + return 0L; + } + }; + } + + /** + * Average value for expression for elements of given collection. + * + * @param expression + * @param + * @param + * @return + */ + public static Agregator avg(Function expression) + { + return new Agregator() + { + @Override + public T apply(Collection collection) throws EmptyCollectionException + { + if (collection.isEmpty()) + { + throw new EmptyCollectionException("Method avg was called for empty collection."); + } + T example = expression.apply(collection.iterator().next()); + if (example instanceof Integer) + { + int sum = 0; + for (C elem : collection) + { + sum += (Integer) expression.apply(elem); + } + return (T) Integer.valueOf(sum / collection.size()); + } + if (example instanceof Long) + { + int sum = 0; + for (C elem : collection) + { + sum += (Long) expression.apply(elem); + } + return (T) Long.valueOf(sum / collection.size()); + } + if (example instanceof Double || example instanceof Float) + { + double sum = 0; + for (C elem : collection) + { + sum += (Long) expression.apply(elem); + } + return (T) Double.valueOf(sum / collection.size()); + } + throw new ClassCastException("Class type is not detected!"); + } + + @Override + public T apply(C c) + { + return expression.apply(c); + } + }; + } +} \ No newline at end of file diff --git a/solutions/bradikhin/ANkoR911/CQL/Conditions.java b/solutions/bradikhin/ANkoR911/CQL/Conditions.java new file mode 100644 index 0000000..28134ee --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/Conditions.java @@ -0,0 +1,18 @@ +import java.util.function.Function; +import java.util.function.Predicate; + +/** + * Created by Владимир on 19.12.2015. + */ +public class Conditions +{ + public static Predicate rlike(Function expression, String regexp) + { + return element -> expression.apply(element).matches(regexp); + } + + public static Predicate like(Function expression, String pattern) + { + throw new UnsupportedOperationException(); + } +} \ No newline at end of file diff --git a/solutions/bradikhin/ANkoR911/CQL/OrderByConditions.java b/solutions/bradikhin/ANkoR911/CQL/OrderByConditions.java new file mode 100644 index 0000000..5c6ec51 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/OrderByConditions.java @@ -0,0 +1,20 @@ +import java.util.Comparator; +import java.util.function.Function; + +/** + * Created by Владимир on 19.12.2015. + */ + + +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/solutions/bradikhin/ANkoR911/CQL/Sources.java b/solutions/bradikhin/ANkoR911/CQL/Sources.java new file mode 100644 index 0000000..5eafde8 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/Sources.java @@ -0,0 +1,70 @@ +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.*; +import java.util.stream.Stream; + +/** + * Created by Владимир on 19.12.2015. + */ + +public class Sources +{ + + /** + * @param items + * @param + * @return + */ + @SafeVarargs + public static List list(T... items) { + return Arrays.asList(items); + } + + /** + * @param items + * @param + * @return + */ + @SafeVarargs + public static Set set(T... items) { + return new HashSet<>(Arrays.asList(items)); + } + + /** + * @param inputStream + * @param + * @return + * @throws IOException + * @throws ClassCastException + */ + public static Stream lines(InputStream inputStream) throws IOException, ClassCastException { + final int bufferSize = 1000; + StringBuilder builder = new StringBuilder(); + byte[] data = new byte[bufferSize]; + Stream.Builder stream = Stream.builder(); + + while (inputStream.read(data) > 0) { + builder.append(data); + } + String[] lines = builder.toString().split("[\n]"); + //предполагается что каждый элемент на отдельной строке + for (String line : lines) { + stream.add((T) line); + } + return stream.build(); + } + + /** + * @param file + * @param + * @return + * @throws IOException + * @throws ClassCastException + * @throws UnsupportedOperationException if this {@code Path} is not associated with the default provider + */ + public static Stream lines(Path file) throws IOException, ClassCastException { + return lines(new FileInputStream(file.toFile())); + } +} diff --git a/solutions/bradikhin/ANkoR911/CQL/impl/EmptyCollectionException.java b/solutions/bradikhin/ANkoR911/CQL/impl/EmptyCollectionException.java new file mode 100644 index 0000000..eab57ab --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/impl/EmptyCollectionException.java @@ -0,0 +1,10 @@ +/** + * Created by Владимир on 19.12.2015. + */ +public class EmptyCollectionException extends Exception +{ + public EmptyCollectionException(String message) + { + super(message); + } +} \ No newline at end of file diff --git a/solutions/bradikhin/ANkoR911/CQL/impl/FromStmt.java b/solutions/bradikhin/ANkoR911/CQL/impl/FromStmt.java new file mode 100644 index 0000000..6e49695 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/impl/FromStmt.java @@ -0,0 +1,208 @@ +import java.util.*; +import java.util.function.BiPredicate; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Created by Владимир on 19.12.2015. + */ + + +public class FromStmt { + private Iterable previousQuery; + private Iterable data; + + FromStmt(Iterable iterable) { + this.data = iterable; + } + + FromStmt(Iterable iterable, Iterable previous) { + data = iterable; + previousQuery = previous; + } + + private FromStmt(Stream stream) { + data = stream.collect(Collectors.toList()); + } + + public static FromStmt from(Iterable iterable) { + return new FromStmt<>(iterable); + } + + public static FromStmt from(Stream stream) { + return new FromStmt<>(stream); + } + + public static FromStmt from(Query query) throws QueryExecuteException, EmptyCollectionException { + return new FromStmt<>(query.execute()); + } + + @SafeVarargs + public final SelectStmt select(Class clazz, Function... s) throws UnequalUnionClassesException { + try { + return new SelectStmt<>((Iterable) previousQuery, data, clazz, false, s); + } catch (ClassCastException ex) { + try { + List newIterable = new ArrayList<>(); + previousQuery.forEach(el -> newIterable.add((R) el)); + return new SelectStmt<>(newIterable, data, clazz, false, s); + } catch (ClassCastException exeption) { + throw new UnequalUnionClassesException("Uncasted classes can't be union.", ex); + } + } + } + + + public final SelectStmt select(Function s) throws UnequalUnionClassesException { + try { + return new SelectStmt<>((Iterable) previousQuery, data, false, s); + } catch (ClassCastException ex) { + try { + List newIterable = new ArrayList<>(); + previousQuery.forEach(el -> newIterable.add((R) el)); + return new SelectStmt<>(newIterable, data, false, s); + } catch (ClassCastException exception) { + throw new UnequalUnionClassesException("Uncasted classes can't be union.", ex); + } + } + } + + + public final SelectStmt> select(Function first, Function second) + throws UnequalUnionClassesException { + try { + return new SelectStmt<>((Iterable>) previousQuery, data, false, first, second); + } catch (ClassCastException ex) { + try { + List> newIterable = new ArrayList<>(); + previousQuery.forEach(el -> newIterable.add((Tuple) el)); + return new SelectStmt<>(newIterable, data, false, first, second); + } catch (ClassCastException exception) { + throw new UnequalUnionClassesException("Uncasted classes can't be union.", ex); + } + } + } + + @SafeVarargs + public final SelectStmt selectDistinct(Class clazz, Function... s) + throws UnequalUnionClassesException { + try { + return new SelectStmt<>((Iterable) previousQuery, data, clazz, true, s); + } catch (ClassCastException ex) { + try { + List newIterable = new ArrayList<>(); + previousQuery.forEach(el -> newIterable.add((R) el)); + return new SelectStmt<>(newIterable, data, clazz, false, s); + } catch (ClassCastException exception) { + throw new UnequalUnionClassesException("Uncasted classes can't be union.", ex); + } + } + } + + + public final SelectStmt selectDistinct(Function s) throws UnequalUnionClassesException { + try { + return new SelectStmt<>((Iterable) previousQuery, data, false, s); + } catch (ClassCastException ex) { + try { + List newIterable = new ArrayList<>(); + previousQuery.forEach(el -> newIterable.add((R) el)); + return new SelectStmt<>(newIterable, data, false, s); + } catch (ClassCastException exception) { + throw new UnequalUnionClassesException("Uncasted classes can't be union.", ex); + } + } + } + + public final SelectStmt> selectDistinct(Function first, Function second) + throws UnequalUnionClassesException { + try { + return new SelectStmt<>((Iterable>) previousQuery, data, false, first, second); + } catch (ClassCastException ex) { + try { + List> newIterable = new ArrayList<>(); + previousQuery.forEach(el -> newIterable.add((Tuple) el)); + return new SelectStmt<>(newIterable, data, false, first, second); + } catch (ClassCastException exception) { + throw new UnequalUnionClassesException("Uncasted classes can't be union.", ex); + } + } + } + + public final JoinClause join(Iterable iterable) { + return new JoinClause<>(data, iterable); + } + + public final JoinClause join(Stream stream) { + return new JoinClause<>(data, stream.collect(Collectors.toList())); + } + + public final JoinClause join(Query stream) throws QueryExecuteException, EmptyCollectionException { + return new JoinClause<>(data, stream.execute()); + } + + public class JoinClause { + private Iterable first; + private Iterable second; + + JoinClause(Iterable fst, Iterable snd) { + this.first = fst; + this.second = snd; + } + + public final FromStmt> on(BiPredicate condition) { + List list = new LinkedList<>(); + first.forEach(list::add); + + List> result = new ArrayList<>(); + second.forEach(element -> { + for (int i = 0; i < list.size(); i++) { + if (condition.test(list.get(i), element)) { + result.add(new Tuple<>(list.get(i), element)); + list.remove(i); + break; + } + } + }); + + return new FromStmt<>(result); + } + + public final > FromStmt> on( + Function leftKey, + Function rightKey) { + + Map> mapOfT = new HashMap<>(); + first.forEach(elem -> { + K key = leftKey.apply(elem); + if (!mapOfT.containsKey(key)) { + List inserted = new LinkedList<>(); + inserted.add(elem); + mapOfT.put(key, inserted); + } else { + List inserted = mapOfT.get(key); + inserted.add(elem); + mapOfT.put(key, inserted); + } + }); + + List> result = new ArrayList<>(); + second.forEach((elem) -> { + K key = rightKey.apply(elem); + if (mapOfT.containsKey(key)) { + List replaced = mapOfT.get(key); + result.add(new Tuple<>(replaced.get(0), elem)); + replaced.remove(0); + if (replaced.isEmpty()) { + mapOfT.remove(key); + } else { + mapOfT.put(key, replaced); + } + } + }); + + return new FromStmt<>(result); + } + } +} diff --git a/solutions/bradikhin/ANkoR911/CQL/impl/Query.java b/solutions/bradikhin/ANkoR911/CQL/impl/Query.java new file mode 100644 index 0000000..affeb70 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/impl/Query.java @@ -0,0 +1,13 @@ +import java.util.stream.Stream; + +/** + * Created by Владимир on 19.12.2015. + */ + + +public interface Query { + + Iterable execute() throws QueryExecuteException, EmptyCollectionException; + + Stream stream() throws QueryExecuteException, EmptyCollectionException; +} diff --git a/solutions/bradikhin/ANkoR911/CQL/impl/QueryExecuteException.java b/solutions/bradikhin/ANkoR911/CQL/impl/QueryExecuteException.java new file mode 100644 index 0000000..543f190 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/impl/QueryExecuteException.java @@ -0,0 +1,10 @@ +/** + * Created by Владимир on 19.12.2015. + */ + +public class QueryExecuteException extends Exception +{ + QueryExecuteException(String message, Throwable reason) { + super(message, reason); + } +} diff --git a/solutions/bradikhin/ANkoR911/CQL/impl/SelectStmt.java b/solutions/bradikhin/ANkoR911/CQL/impl/SelectStmt.java new file mode 100644 index 0000000..5124bf3 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/impl/SelectStmt.java @@ -0,0 +1,98 @@ +import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * Created by Владимир on 19.12.2015. + */ + +public class SelectStmt implements Query +{ + private Iterable data; + private Iterable previous; + private Function[] functions; + private Class returnedClass; + private boolean isDistinct; + private boolean isTupleR; + + @SafeVarargs + SelectStmt(Iterable prvious, Iterable dta, Class clazz, boolean isDistnct, Function... s) { + this.data = dta; + this.previous = prvious; + functions = s; + returnedClass = clazz; + this.isDistinct = isDistnct; + isTupleR = false; + } + + SelectStmt(Iterable prvious, Iterable dta, boolean isDistnct, Function func) { + this.data = dta; + this.previous = prvious; + functions = new Function[]{func}; + returnedClass = (Class) func.apply(data.iterator().next()).getClass(); + this.isDistinct = isDistnct; + isTupleR = false; + } + + SelectStmt(Iterable prvious, Iterable dta, boolean isDistnct, + Function first, Function second) { + this.data = dta; + this.previous = prvious; + functions = new Function[]{first, second}; + returnedClass = (Class) (new Tuple(first.apply(data.iterator().next()), + second.apply(data.iterator().next()))).getClass(); + this.isDistinct = isDistnct; + isTupleR = true; + } + + public final WhereStmt where(Predicate predicate) { + return new WhereStmt<>(previous, data, returnedClass, predicate, isDistinct, isTupleR, functions); + } + + @Override + public final Iterable execute() throws QueryExecuteException { + if (data == null) { + return new ArrayList<>(); + } + + Object[] constructorArguments = new Object[functions.length]; + Class[] resultClasses = new Class[functions.length]; + for (int i = 0; i < functions.length; i++) { + resultClasses[i] = functions[i].apply(data.iterator().next()).getClass(); + } + + ArrayList result = new ArrayList<>(); + for (T element : data) { + for (int i = 0; i < functions.length; i++) { + constructorArguments[i] = functions[i].apply(element); + } + try { + if (isTupleR) { + //почему-то не находит его конструктор, пришлось отдельно рассмотреть + result.add((R) new Tuple(constructorArguments[0], constructorArguments[1])); + } else { + result.add(returnedClass.getConstructor(resultClasses).newInstance(constructorArguments)); + } + } catch (Exception ex) { + throw new QueryExecuteException("Failed to construct output class!", ex); + } + } + + if (previous != null) { + previous.forEach(result::add); + } + + if (isDistinct) { + return result.stream().distinct().collect(Collectors.toList()); + } + return result; + } + + @Override + public final Stream stream() throws QueryExecuteException { + return StreamSupport.stream(execute().spliterator(), false); + } +} diff --git a/solutions/bradikhin/ANkoR911/CQL/impl/Tuple.java b/solutions/bradikhin/ANkoR911/CQL/impl/Tuple.java new file mode 100644 index 0000000..59bb0d3 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/impl/Tuple.java @@ -0,0 +1,30 @@ +/** + * Created by Владимир on 19.12.2015. + */ +public class Tuple +{ + + private final F first; + private final S second; + + public Tuple(F fst, S snd) { + this.first = fst; + this.second = snd; + } + + public final F getFirst() { + return first; + } + + public final S getSecond() { + return second; + } + + @Override + public final String toString() { + return "Tuple{" + + "first=" + first + + ", second=" + second + + '}'; + } +} \ No newline at end of file diff --git a/solutions/bradikhin/ANkoR911/CQL/impl/UnequalUnionClassesException.java b/solutions/bradikhin/ANkoR911/CQL/impl/UnequalUnionClassesException.java new file mode 100644 index 0000000..473eb88 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/impl/UnequalUnionClassesException.java @@ -0,0 +1,9 @@ +/** + * Created by Владимир on 19.12.2015. + */ + +public class UnequalUnionClassesException extends Exception { + UnequalUnionClassesException(String message, Throwable reason) { + super(message, reason); + } +} \ No newline at end of file diff --git a/solutions/bradikhin/ANkoR911/CQL/impl/UnionStmt.java b/solutions/bradikhin/ANkoR911/CQL/impl/UnionStmt.java new file mode 100644 index 0000000..c9e883d --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/impl/UnionStmt.java @@ -0,0 +1,18 @@ +/** + * Created by Владимир on 19.12.2015. + */ + +public class UnionStmt +{ + private Iterable previous; + + UnionStmt(Iterable iterable) + { + previous = iterable; + } + + public final FromStmt from(Iterable list) + { + return new FromStmt<>(list, previous); + } +} \ No newline at end of file diff --git a/solutions/bradikhin/ANkoR911/CQL/impl/WhereStmt.java b/solutions/bradikhin/ANkoR911/CQL/impl/WhereStmt.java new file mode 100644 index 0000000..d0c3cf9 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/CQL/impl/WhereStmt.java @@ -0,0 +1,187 @@ +import javafx.util.Pair; +import Aggregates; + +import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * Created by Владимир on 19.12.2015. + */ +public class WhereStmt implements Query +{ + private Stream stream; + private Iterable previous; + private Function[] convertFunctions; + private Class returnedClass; + private Function>[] groupingFunctions; + private Predicate groupingCondition; + private Comparator resultComparator; + private T example; //for initialization of out output class constructor arguments + private boolean isDistinct; + private boolean isTupleR; + private long maxResultSize = -1; + + private Object[] constructorArguments; + private Class[] resultClasses; + + WhereStmt(Iterable prev, Iterable iterable, Class clazz, Predicate predicate, + boolean isDistnct, boolean isTuplR, Function[] convFunctions) { + stream = StreamSupport.stream(iterable.spliterator(), false).filter(predicate); + returnedClass = clazz; + this.previous = prev; + this.convertFunctions = convFunctions; + this.isDistinct = isDistnct; + this.isTupleR = isTuplR; + groupingCondition = null; + if (iterable.iterator().hasNext()) { + example = iterable.iterator().next(); + } else { + example = null; + } + } + + @SafeVarargs + public final WhereStmt groupBy(Function>... expressions) { + groupingFunctions = expressions; + return this; + } + + @SafeVarargs + public final WhereStmt orderBy(Comparator... comparators) { + resultComparator = getCombinedComparator(Arrays.asList(comparators)); + return this; + } + + public final WhereStmt having(Predicate condition) { + groupingCondition = condition; + return this; + } + + public final WhereStmt limit(int amount) { + maxResultSize = amount; + return this; + } + + public final UnionStmt union() throws UnequalUnionClassesException, + QueryExecuteException, EmptyCollectionException { + return new UnionStmt<>(this.execute()); + } + + @Override + public final Iterable execute() throws QueryExecuteException, EmptyCollectionException { + return this.stream().collect(Collectors.toList()); + } + + @Override + public final Stream stream() throws QueryExecuteException, EmptyCollectionException { + constructorArguments = new Object[convertFunctions.length]; + resultClasses = new Class[convertFunctions.length]; + + if (example == null) { + return (new ArrayList()).stream(); + } + + for (int i = 0; i < convertFunctions.length; i++) { + resultClasses[i] = convertFunctions[i].apply(example).getClass(); + } + + ArrayList result = new ArrayList<>(); + if (groupingFunctions != null) { + Map mapped = new HashMap<>(); + List> groupedElements = new ArrayList<>(); + List> grouped = new ArrayList<>(); + String[] results = new String[groupingFunctions.length]; + stream.forEach( + element -> { + for (int i = 0; i < groupingFunctions.length; i++) { + results[i] = (String) groupingFunctions[i].apply(element); + } + if (!mapped.containsKey(Objects.hash(results))) { + mapped.put(Objects.hash(results), mapped.size()); + } + grouped.add(new Pair<>(element, mapped.get(Objects.hash(results)))); + } + ); + + for (int i = 0; i < mapped.size(); i++) { + groupedElements.add(new ArrayList<>()); + } + + for (Pair element : grouped) { + groupedElements.get(element.getValue()).add(element.getKey()); + } + for (List group : groupedElements) { + for (int i = 0; i < convertFunctions.length; i++) { + if (convertFunctions[i] instanceof Aggregates.Agregator) { + constructorArguments[i] = ((Aggregates.Agregator) convertFunctions[i]).apply(group); + } else { + constructorArguments[i] = convertFunctions[i].apply(group.get(0)); + } + resultClasses[i] = constructorArguments[i].getClass(); + } + try { + if (isTupleR) { + result.add((R) new Tuple<>(constructorArguments[0], constructorArguments[1])); + } else { + result.add(returnedClass.getConstructor(resultClasses) + .newInstance(constructorArguments)); + } + } catch (Exception ex) { + throw new QueryExecuteException("Failed to construct output class!", ex); + } + } + } else { + if (resultComparator != null) { + stream.sorted(resultComparator); + } + for (T element : stream.collect(Collectors.toList())) { + addToList(result, element); + } + } + + if (previous != null) { + previous.forEach(result::add); + } + + Stream finalResult; + if (isDistinct) { + finalResult = result.stream().distinct(); + } else { + finalResult = result.stream(); + } + if (maxResultSize != -1) { + finalResult = finalResult.limit(maxResultSize); + } + if (groupingCondition != null) { + finalResult = finalResult.filter(groupingCondition); + } + return finalResult; + } + + private void addToList(List list, T element) throws QueryExecuteException { + for (int i = 0; i < convertFunctions.length; i++) { + constructorArguments[i] = convertFunctions[i].apply(element); + } + try { + list.add(returnedClass.getConstructor(resultClasses).newInstance(constructorArguments)); + } catch (Exception ex) { + throw new QueryExecuteException("Failed to construct output class!", ex); + } + } + + private static Comparator getCombinedComparator(List> comparators) { + return (o1, o2) -> { + for (Comparator comp : comparators) { + int res = comp.compare(o1, o2); + if (res != 0) { + return res; + } + } + return 0; + }; + } +} \ No newline at end of file diff --git a/solutions/bradikhin/ANkoR911/Reverser/mainclass.java b/solutions/bradikhin/ANkoR911/Reverser/mainclass.java new file mode 100644 index 0000000..59363a6 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/Reverser/mainclass.java @@ -0,0 +1,19 @@ +/** + * Created by Владимир on 19.12.2015. + */ + +public class mainclass +{ + public static void main(String[] args) + { + for(int i = args.length - 1; i >= 0; --i) + { + String[] str = args[i].split("\\s+"); + } + for(int i = str.length - 1; i >= 0; i--) + { + System.out.print(str[i] + " "); + } + } + System.out.println(); +} diff --git a/solutions/bradikhin/ANkoR911/Threads/BlQueue.java b/solutions/bradikhin/ANkoR911/Threads/BlQueue.java new file mode 100644 index 0000000..8eb1e42 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/Threads/BlQueue.java @@ -0,0 +1,85 @@ +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Created by Владимир on 19.12.2015. + */ + +@SuppressWarnings("checkstyle:designforextension") +public class BlQueue +{ + private Queue ourQueue = new LinkedList<>(); + private Lock ourLock = new ReentrantLock(); + private Lock offerLock = new ReentrantLock(); + private Lock takeLock = new ReentrantLock(); + + private int maxQueueSize; + private int currentQueueSize = 0; + + private Condition queueNotFull = ourLock.newCondition(); + private Condition queueNotEmpty = ourLock.newCondition(); + + BlQueue(int maXQueueSize) + { + maxQueueSize = maXQueueSize; + } + + void offer(List toInsert) throws InterruptedException + { + try { + offerLock.lock(); + try { + ourLock.lock(); + for (T element : toInsert) { + while (!(currentQueueSize + 1 < maxQueueSize)) { + queueNotFull.await(); + } + ourQueue.add(element); + currentQueueSize++; + queueNotEmpty.signalAll(); + } + } finally { + ourLock.unlock(); + } + } finally { + offerLock.unlock(); + } + } + List take(int howManyToTake) throws Exception + { + List listToReturn = new ArrayList<>(); + try { + takeLock.lock(); + try { + ourLock.lock(); + for (int i = 0; i < howManyToTake; i++) { + while ((currentQueueSize == 0)) { + queueNotEmpty.await(); + } + T element = ourQueue.element(); + currentQueueSize--; + queueNotFull.signalAll(); + } + } finally { + ourLock.unlock(); + } + } finally { + takeLock.unlock(); + } + return listToReturn; + } + void offer(List toInsert, long timeOut) + { + + } + List take(int howManyToTake, long timeout) + { + return new ArrayList<>(); + } + +} \ No newline at end of file diff --git a/solutions/bradikhin/ANkoR911/Threads/RollCall.java b/solutions/bradikhin/ANkoR911/Threads/RollCall.java new file mode 100644 index 0000000..86afb94 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/Threads/RollCall.java @@ -0,0 +1,68 @@ + import java.util.Random; + import java.util.concurrent.BrokenBarrierException; + import java.util.concurrent.CyclicBarrier; + import java.util.concurrent.ExecutorService; + import java.util.concurrent.Executors; + +/** + * Created by Владимир on 19.12.2015. + */ + + +public class RollCall +{ + private final Random random = new Random(); + private ExecutorService executorService = Executors.newFixedThreadPool(THREADS_NUMBER); + private final Object lock = new Object(); + private volatile boolean ready = true; + private static final int THREADS_NUMBER = 10; + private CyclicBarrier queue; + public final void performRollCall() { + System.out.println("Are you ready, kids?"); + queue = new CyclicBarrier(THREADS_NUMBER, new FatherTask()); + for (int i = 0; i < THREADS_NUMBER; i++) { + executorService.execute(new ChildTask()); + } + } + private class FatherTask implements Runnable + { + @Override + public void run() { + if (!ready) { + synchronized (lock) { + ready = true; + System.out.println("again"); + } + } else { + System.out.println("Who lives in a pine-apple under the sea?"); + System.out.println("SPONGE BOB SQUARE PANTS!"); + executorService.shutdownNow(); + } + } + } + private class ChildTask implements Runnable + { + @Override + public void run() { + while (!Thread.interrupted()) { + final int edge = 10; + final int max = 100; + if (random.nextInt(max) > edge) { + System.out.println("AYE AYE CAPTAIN!"); + } else { + System.out.println("NO"); + synchronized (lock) { + ready = false; + } + } + try { + queue.await(); + } catch (InterruptedException i) { + System.out.println("Na pravah reklamy"); + } catch (BrokenBarrierException i) { + i.printStackTrace(); + } + } + } + } +} diff --git a/solutions/bradikhin/ANkoR911/Threads/Threads.java b/solutions/bradikhin/ANkoR911/Threads/Threads.java new file mode 100644 index 0000000..a014af8 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/Threads/Threads.java @@ -0,0 +1,11 @@ +/** + * Created by Владимир on 19.12.2015. + */ +public class Threads +{ + public static void main(String[] args) + { + final int threadsNumber = 10; + RollCall rollCall = new RollCall(); + } +} \ No newline at end of file diff --git a/solutions/bradikhin/ANkoR911/Threads/ThreadsCount.java b/solutions/bradikhin/ANkoR911/Threads/ThreadsCount.java new file mode 100644 index 0000000..ce3b42e --- /dev/null +++ b/solutions/bradikhin/ANkoR911/Threads/ThreadsCount.java @@ -0,0 +1,57 @@ +/** + * Created by Владимир on 19.12.2015. + */ + +@SuppressWarnings("checkstyle:magicnumber") +public class ThreadsCount +{ + private final Object lock = new Object(); + private int currentNumber = 0; + private int threadsNumber; + + ThreadsCount(int numberOfThreadsToStart) { + threadsNumber = numberOfThreadsToStart; + for (int i = 0; i < numberOfThreadsToStart; i++) { + MyThread myThread = new MyThread(i); + myThread.start(); + } + } + + class MyThread extends Thread + { + private int id; + + MyThread(int ourId) { + id = ourId; + } + + + @Override + public String toString() { + return "Thread-" + id; + } + + @Override + public void run() + { + for (; !Thread.currentThread().isInterrupted();) { + synchronized (lock) { + if (currentNumber == id) { + System.out.println(this.toString()); + Thread.yield(); + currentNumber = (currentNumber + 1) % threadsNumber; + try { + Thread.sleep(400); + } catch (InterruptedException i) { + System.out.println("Error : " + i); + } + lock.notify(); + } else { + lock.notify(); + } + } + } + } + } +} + diff --git a/solutions/bradikhin/ANkoR911/miniORM/Column.java b/solutions/bradikhin/ANkoR911/miniORM/Column.java new file mode 100644 index 0000000..c2b07d4 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/miniORM/Column.java @@ -0,0 +1,13 @@ +/** + * Created by Владимир on 19.12.2015. + */ + +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Retention; + + +@Retention(RetentionPolicy.RUNTIME) +public @interface Column +{ + String name() default ""; +} \ No newline at end of file diff --git a/solutions/bradikhin/ANkoR911/miniORM/DatabaseService.java b/solutions/bradikhin/ANkoR911/miniORM/DatabaseService.java new file mode 100644 index 0000000..f63fa8e --- /dev/null +++ b/solutions/bradikhin/ANkoR911/miniORM/DatabaseService.java @@ -0,0 +1,276 @@ +/** + * Created by Владимир on 19.12.2015. + */ + +import com.google.common.base.CaseFormat; +import org.h2.jdbcx.JdbcConnectionPool; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.sql.*; +import java.util.*; +import static RightNameResolver.isGood; + +public class DatabaseService implements Closeable +{ + + private int pkIndex = -1; + private final String connectionName; + private final String username; + private final String password; + private Class classs; + private JdbcConnectionPool pool; + private String tableName; + private Field[] tableFields; + + void init() throws IllegalArgumentException, IOException { + if (!classs.isAnnotationPresent(Table.class)) { + throw new IllegalArgumentException("no @Table annotation"); + } + tableName = classs.getAnnotation(Table.class).name(); + if (tableName.equals("")) { + tableName = convert(classs.getSimpleName()); + } + if (!isGood(tableName)) { + throw new IllegalArgumentException("Bad table name"); + } + Set names = new HashSet<>(); + List tableFieldsList = new ArrayList<>(); + for (Field f : classs.getDeclaredFields()) { + if (f.isAnnotationPresent(Column.class)) { + String name = getColumnName(f); + names.add(name); + if (!isGood(name)) { + throw new IllegalArgumentException("Bad column name"); + } + f.setAccessible(true); + tableFieldsList.add(f); + if (f.isAnnotationPresent(PrimaryKey.class)) { + if (pkIndex == -1) { + pkIndex = tableFieldsList.size() - 1; + } else { + throw new + IllegalArgumentException("Several @PrimaryKey"); + } + } + } else if (f.isAnnotationPresent(PrimaryKey.class)) { + throw new + IllegalArgumentException("@PrimaryKey without @Column"); + } + } + if (names.size() != tableFieldsList.size()) { + throw new IllegalArgumentException("Duplicate columns"); + } + tableFields = new Field[tableFieldsList.size()]; + tableFields = tableFieldsList.toArray(tableFields); + try { + Class.forName("org.h2.Driver"); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("No H2 driver found"); + } + pool = JdbcConnectionPool.create(connectionName, username, password); + } + + static String convert(String name) { + if ('a' <= name.charAt(0) && name.charAt(0) <= 'z') { + return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name); + } + return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name); + } + + String getColumnName(Field f) { + String name = f.getAnnotation(Column.class).name(); + if (name.equals("")) { + return convert(f.getName()); + } + return name; + } + + DatabaseService(Class newClazz, String properties) throws IOException { + Properties credits = new Properties(); + try (InputStream inputStream + = this.getClass().getResourceAsStream(properties)) { + credits.load(inputStream); + } + connectionName = credits.getProperty("connection_name"); + username = credits.getProperty("username"); + password = credits.getProperty("password"); + classs = newClazz; + init(); + } + + DatabaseService(Class newClazz) throws IOException { + this(newClazz, "/h2.properties"); + } + + void createTable() throws SQLException { + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("CREATE TABLE IF NOT EXISTS ") + .append(tableName) + .append("("); + for (int i = 0; i < tableFields.length; ++i) { + if (i != 0) { + queryBuilder.append(", "); + } + queryBuilder.append(getColumnName(tableFields[i])).append(" ") + .append(H2StringsResolver.resolve(tableFields[i].getType())); + if (i == pkIndex) + queryBuilder.append(" PRIMARY KEY"); + } + queryBuilder.append(")"); + try (Connection conn = pool.getConnection()) { + conn.createStatement().execute(queryBuilder.toString()); + } + } + + void dropTable() throws SQLException { + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("DROP TABLE IF EXISTS ") + .append(tableName); + try (Connection conn = pool.getConnection()) { + conn.createStatement().execute(queryBuilder.toString()); + } + } + + public void insert(T record) throws SQLException, IllegalAccessException { + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("INSERT INTO ").append(tableName).append(" ("); + for (int i = 0; i < tableFields.length; ++i) { + if (i != 0) { + queryBuilder.append(", "); + } + queryBuilder.append(getColumnName(tableFields[i])).append(" "); + } + queryBuilder.append(") VALUES ("); + for (int i = 0; i < tableFields.length; ++i) { + if (i != 0) { + queryBuilder.append(", "); + } + queryBuilder.append("?"); + } + queryBuilder.append(")"); + + try (Connection conn = pool.getConnection()) { + PreparedStatement statement + = conn.prepareStatement(queryBuilder.toString()); + for (int i = 0; i < tableFields.length; ++i) { + statement.setObject(i + 1, tableFields[i].get(record)); + } + statement.execute(); + } + } + + public void delete(T record) throws IllegalArgumentException, + IllegalAccessException, SQLException { + if (pkIndex == -1) + throw new IllegalArgumentException("NO @PrimaryKey"); + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("DELETE FROM ").append(tableName) + .append(" WHERE ").append(tableFields[pkIndex].getName()) + .append(" = ?"); + try (Connection conn = pool.getConnection()) { + PreparedStatement statement = conn.prepareStatement(queryBuilder.toString()); + statement.setObject(1, tableFields[pkIndex].get(record)); + statement.execute(); + } + } + + public void update(T record) throws IllegalArgumentException, + SQLException, IllegalAccessException { + if (pkIndex == -1) { + throw new IllegalArgumentException("NO @PrimaryKey"); + } + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("UPDATE ").append(tableName).append(" SET "); + for (int i = 0; i < tableFields.length; ++i) { + if (i != 0) + queryBuilder.append(", "); + queryBuilder.append(getColumnName(tableFields[i])).append(" = ?"); + } + queryBuilder.append(" WHERE ").append(getColumnName(tableFields[pkIndex])) + .append(" = ?"); + + try (Connection conn = pool.getConnection()) { + PreparedStatement statement + = conn.prepareStatement(queryBuilder.toString()); + for (int i = 0; i < tableFields.length; ++i) + statement.setObject(i + 1, tableFields[i].get(record)); + statement.setObject(tableFields.length + 1, tableFields[pkIndex].get(record)); + statement.execute(); + } + } + + public T queryById(K key) throws IllegalArgumentException, + SQLException { + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("SELECT * FROM ").append(tableName) + .append(" WHERE ").append(tableFields[pkIndex].getName()) + .append(" = ?"); + try (Connection conn = pool.getConnection()) { + PreparedStatement statement + = conn.prepareStatement(queryBuilder.toString()); + statement.setString(1, key.toString()); + + try (ResultSet rs = statement.executeQuery()) { + rs.next(); + T record = classs.newInstance(); + for (int i = 0; i < tableFields.length; ++i) { + if (tableFields[i].getClass() + .isAssignableFrom(Number.class)) { + Long val = rs.getLong(i + 1); + tableFields[i].set(record, val); + } else if (tableFields[i].getType() != String.class) { + tableFields[i].set(record, rs.getObject(i + 1)); + } else { + Clob data = rs.getClob(i + 1); + tableFields[i].set(record, + data.getSubString(1, (int) data.length())); + } + } + return record; + } catch (InstantiationException | IllegalAccessException e) { + throw new IllegalArgumentException("wrong class"); + } + } + + } + + public List queryForAll() throws SQLException { + List result = new ArrayList<>(); + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("SELECT * FROM ").append(tableName); + try (Connection conn = pool.getConnection()) { + try (ResultSet rs = conn.createStatement() + .executeQuery(queryBuilder.toString())) { + while (rs.next()) { + T record = classs.newInstance(); + for (int i = 0; i < tableFields.length; ++i) { + if (tableFields[i].getClass() + .isAssignableFrom(Number.class)) { + Long val = rs.getLong(i + 1); + tableFields[i].set(record, val); + } else if (tableFields[i].getType() != String.class) { + tableFields[i].set(record, rs.getObject(i + 1)); + } else { + Clob data = rs.getClob(i + 1); + tableFields[i].set(record, + data.getSubString(1, (int) data.length())); + } + } + result.add(record); + } + } catch (InstantiationException | IllegalAccessException e) { + throw new IllegalArgumentException("wrong class"); + } + } + return result; + } + + @Override + public void close() throws IOException { + if (pool != null) { + pool.dispose(); + } + } +} diff --git a/solutions/bradikhin/ANkoR911/miniORM/H2StringsResolver.java b/solutions/bradikhin/ANkoR911/miniORM/H2StringsResolver.java new file mode 100644 index 0000000..6a418e9 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/miniORM/H2StringsResolver.java @@ -0,0 +1,41 @@ +/** + * Created by Владимир on 19.12.2015. + */ + +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +class H2StringsResolver { + + private static Map h2Mapper; + static { + h2Mapper = new HashMap<>(); + h2Mapper.put(Integer.class, "INTEGER"); + h2Mapper.put(Boolean.class, "BOOLEAN"); + h2Mapper.put(Byte.class, "TINYINT"); + h2Mapper.put(Short.class, "SMALLINT"); + h2Mapper.put(Long.class, "BIGINT"); + h2Mapper.put(Double.class, "DOUBLE"); + h2Mapper.put(Float.class, "FLOAT"); + h2Mapper.put(Time.class, "TIME"); + h2Mapper.put(Date.class, "DATE"); + h2Mapper.put(Timestamp.class, "TIMESTAMP"); + h2Mapper.put(Character.class, "CHAR"); + h2Mapper.put(String.class, "CLOB"); + h2Mapper.put(UUID.class, "UUID"); + } + + public static String resolve(Class clazz) { + if (clazz.isArray()) { + return "ARRAY"; + } + if (h2Mapper.containsKey(clazz)) { + return h2Mapper.get(clazz); + } + return "OTHER"; + } +} diff --git a/solutions/bradikhin/ANkoR911/miniORM/PrimaryKey.java b/solutions/bradikhin/ANkoR911/miniORM/PrimaryKey.java new file mode 100644 index 0000000..a18159d --- /dev/null +++ b/solutions/bradikhin/ANkoR911/miniORM/PrimaryKey.java @@ -0,0 +1,10 @@ +/** + * Created by Владимир on 19.12.2015. + */ + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface PrimaryKey { +} diff --git a/solutions/bradikhin/ANkoR911/miniORM/RightNameResolver.java b/solutions/bradikhin/ANkoR911/miniORM/RightNameResolver.java new file mode 100644 index 0000000..c45fa97 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/miniORM/RightNameResolver.java @@ -0,0 +1,11 @@ +/** + * Created by Владимир on 19.12.2015. + */ + +class RightNameResolver +{ + static final String REGEX = "[A-Za-z0-9_-]*"; + public static Boolean isGood(String name) { + return name.matches(REGEX); + } +} diff --git a/solutions/bradikhin/ANkoR911/miniORM/Table.java b/solutions/bradikhin/ANkoR911/miniORM/Table.java new file mode 100644 index 0000000..e746e30 --- /dev/null +++ b/solutions/bradikhin/ANkoR911/miniORM/Table.java @@ -0,0 +1,12 @@ +/** + * Created by Владимир on 19.12.2015. + */ + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Table +{ + String name() default ""; +} \ No newline at end of file