diff --git a/OWNER.md b/OWNER.md new file mode 100644 index 00000000..fd6ab5fb --- /dev/null +++ b/OWNER.md @@ -0,0 +1,2 @@ +Айнулин Ринат Рафикович + diff --git a/src/main/java/track/container/Container.java b/src/main/java/track/container/Container.java index 36c4bd9d..3c9b0e29 100644 --- a/src/main/java/track/container/Container.java +++ b/src/main/java/track/container/Container.java @@ -1,34 +1,100 @@ package track.container; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import track.container.config.Bean; +import track.container.config.InvalidConfigurationException; +import track.container.config.Property; +import track.container.config.ValueType; /** * Основной класс контейнера * У него определено 2 публичных метода, можете дописывать свои методы и конструкторы */ public class Container { - + private Map beanById; + private Map beanByClassName; + private Map objByName; + private Map objByClassName; // Реализуйте этот конструктор, используется в тестах! public Container(List beans) { - + beanById = new HashMap<>(); + beanByClassName = new HashMap<>(); + objByName = new HashMap<>(); + objByClassName = new HashMap<>(); + for (Bean bean : beans) { + beanById.put(bean.getId(), bean); + beanByClassName.put(bean.getClassName(), bean); + } } /** - * Вернуть объект по имени бина из конфига - * Например, Car car = (Car) container.getById("carBean") + * Вернуть объект по имени бина из конфига + * Например, Car car = (Car) container.getById("carBean") */ - public Object getById(String id) { - return null; + public Object getById(String id) throws ClassNotFoundException, InvalidConfigurationException, IllegalAccessException, + InstantiationException, NoSuchFieldException { + if (objByName.containsKey(id)) { + return objByName.get(id); + } else { + Bean bean = beanById.get(id); + if (bean == null) { + throw new InvalidConfigurationException("There are not bean with this id"); + } + Class clazz = Class.forName(bean.getClassName()); + Object object = clazz.newInstance(); + for (Map.Entry entry : bean.getProperties().entrySet()) { + Property property = entry.getValue(); + Field field = clazz.getDeclaredField(property.getName()); + field.setAccessible(true); + if (property.getType().equals(ValueType.VAL)) { + Object value = Integer.parseInt(property.getValue()); + field.set(object, value); + } else if (property.getType().equals(ValueType.REF)) { + String depClassName = beanById.get(property.getValue()).getClassName(); + if (!objByClassName.containsKey(depClassName)) { + Class depClazz = Class.forName(depClassName); + if (isCircularDependency(bean.getClassName(), depClazz.getDeclaredFields())) { + throw new InvalidConfigurationException("There is a circular dependency"); + } else { + Object value = getByClass(depClassName); + field.set(object, value); + } + } else { + field.set(object, objByClassName.get(depClassName)); + } + } + } + objByClassName.put(bean.getClassName(), object); + objByName.put(bean.getId(), object); + return object; + } + } + + private boolean isCircularDependency(String className, Field[] declaredFields) { + for (Field field : declaredFields) { + if (field.getType().getName().equals(className)) { + return true; + } + } + return false; } /** * Вернуть объект по имени класса * Например, Car car = (Car) container.getByClass("track.container.beans.Car") */ - public Object getByClass(String className) { - return null; + public Object getByClass(String className) throws ClassNotFoundException, NoSuchFieldException, + InstantiationException, InvalidConfigurationException, IllegalAccessException { + if (objByClassName.containsKey(className)) { + return objByClassName.get(className); + } else { + return getById(beanByClassName.get(className).getId()); + } } } diff --git a/src/main/java/track/container/JsonConfigReader.java b/src/main/java/track/container/JsonConfigReader.java index 76eb69ff..fc37fbb0 100644 --- a/src/main/java/track/container/JsonConfigReader.java +++ b/src/main/java/track/container/JsonConfigReader.java @@ -1,11 +1,16 @@ package track.container; import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; -import track.container.config.Bean; -import track.container.config.ConfigReader; -import track.container.config.InvalidConfigurationException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import track.container.config.*; /** * TODO: Реализовать @@ -14,6 +19,36 @@ public class JsonConfigReader implements ConfigReader { @Override public List parseBeans(File configFile) throws InvalidConfigurationException { - return null; + ObjectMapper mapper = new ObjectMapper(); + List beans = new ArrayList<>(); + try { + JsonNode root = mapper.readTree(configFile).path("beans"); + for (JsonNode currentNode : root) { + String id = currentNode.path("id").asText(); + String className = currentNode.path("className").asText(); + Map properties = createPropertyMap(currentNode.path("properties")); + beans.add(new Bean(id, className, properties)); + } + return beans; + } catch (IOException e) { + throw new InvalidConfigurationException("Invalid configuration"); + } + } + + private Map createPropertyMap(JsonNode jsonNode) throws InvalidConfigurationException { + Map properties = new HashMap<>(); + for (JsonNode currentNode : jsonNode) { + String name = currentNode.path("name").asText(); + Property property = null; + if (currentNode.has("ref")) { + property = new Property(name, currentNode.path("ref").asText(), ValueType.REF); + } else if (currentNode.has("val")) { + property = new Property(name, currentNode.path("val").asText(), ValueType.VAL); + } else { + throw new InvalidConfigurationException("There are not value for " + name); + } + properties.put(name, property); + } + return properties; } } diff --git a/src/main/java/track/container/Main.java b/src/main/java/track/container/Main.java index 8fdc23e6..e1b1869c 100644 --- a/src/main/java/track/container/Main.java +++ b/src/main/java/track/container/Main.java @@ -1,5 +1,13 @@ package track.container; +import track.container.beans.Car; +import track.container.config.Bean; +import track.container.config.ConfigReader; +import track.container.config.InvalidConfigurationException; + +import java.io.File; +import java.util.List; + /** * */ @@ -13,13 +21,20 @@ public static void main(String[] args) { */ -// // При чтении нужно обработать исключение -// ConfigReader reader = new JsonReader(); -// List beans = reader.parseBeans("config.json"); -// Container container = new Container(beans); -// -// Car car = (Car) container.getByClass("track.container.beans.Car"); -// car = (Car) container.getById("carBean"); + ConfigReader reader = new JsonConfigReader(); + try { + File file = new File(JsonConfigReader.class.getClassLoader().getResource("config.json").getFile()); + List beans = reader.parseBeans(file); + System.out.println(beans); + Container container = new Container(beans); + + Car car = (Car) container.getByClass("track.container.beans.Car"); + car = (Car) container.getById("carBean"); + + System.out.println(car); + } catch (Exception e) { + e.printStackTrace(); + } } diff --git a/src/main/java/track/lessons/lesson2/Document.java b/src/main/java/track/lessons/lesson2/Document.java index fa2b2915..b90cee7e 100644 --- a/src/main/java/track/lessons/lesson2/Document.java +++ b/src/main/java/track/lessons/lesson2/Document.java @@ -1,20 +1,26 @@ package track.lessons.lesson2; +import java.util.Arrays; /** * */ + public class Document { String[] tokens; + public Document(String[] tokens) { + this.tokens = tokens; + } + String[] getTokens() { - return null; + return tokens; } int getTokenCount() { - return 0; + return tokens.length; } boolean hasToken(String token) { - return false; + return Arrays.asList(tokens).contains(token); } } diff --git a/src/main/java/track/lessons/lesson2/Parser.java b/src/main/java/track/lessons/lesson2/Parser.java index 7276042d..d2e27152 100644 --- a/src/main/java/track/lessons/lesson2/Parser.java +++ b/src/main/java/track/lessons/lesson2/Parser.java @@ -2,6 +2,7 @@ import java.io.BufferedReader; import java.io.FileReader; +import java.util.Arrays; /** * @@ -9,19 +10,27 @@ public class Parser { Document parse(String data) { - return null; + return new Document(data.split(" ")); } public static void main(String[] args) throws Exception { - String path = "path/to/file"; + String path = "test.txt"; BufferedReader reader = new BufferedReader(new FileReader(path)); + // reader умеет читать по строкам с помощью метода readLine() + StringBuilder stringBuilder = new StringBuilder(); + Parser parser = new Parser(); // Создайте объект Parser + String currentString = reader.readLine(); + while (currentString != null) { + stringBuilder.append(currentString); + currentString = reader.readLine(); + } // Получите объект Document, реализовав метод parse() - - + Document document = parser.parse(stringBuilder.toString()); + System.out.println(Arrays.toString(document.getTokens())); } } diff --git a/src/main/java/track/lessons/lesson3/DynamicList.java b/src/main/java/track/lessons/lesson3/DynamicList.java index 8b30d2c7..ed4c44fa 100644 --- a/src/main/java/track/lessons/lesson3/DynamicList.java +++ b/src/main/java/track/lessons/lesson3/DynamicList.java @@ -1,7 +1,85 @@ package track.lessons.lesson3; +import java.util.Arrays; + /** * */ -public class DynamicList { +public class DynamicList extends List { + + private static final int DEFAULT_CAPACITY = 10; + private int[] elements; + private int size; + + public DynamicList() { + elements = new int[DEFAULT_CAPACITY]; + } + + public DynamicList(int capacity) { + if (capacity >= 0) { + elements = new int[capacity]; + } else { + throw new IllegalArgumentException("Invalid capacity"); + } + } + + @Override + public void add(int item) { + if (size == elements.length) { + resize(2 * elements.length); + } + elements[size++] = item; + } + + private void resize(int capacity) { + int[] copy = new int[capacity]; + System.arraycopy(elements, 0, copy, 0, size); + elements = copy; + } + + @Override + public int remove(int idx) { + if (!isValidId(idx)) { + throw new IndexOutOfBoundsException("Invalid index"); + } + final int item = elements[idx]; + System.arraycopy(elements, idx + 1, elements, idx, (size - 1) - idx); + size--; + if (size > 0 && size == elements.length / 4) { + resize(elements.length / 2); + } + return item; + } + + @Override + public int get(int idx) { + if (!isValidId(idx)) { + throw new IndexOutOfBoundsException("Invalid index"); + } + return elements[idx]; + } + + @Override + public int size() { + return size; + } + + public int capacity() { + return elements.length; + } + + private boolean isValidId(int id) { + return id >= 0 || id < size; + } + + @Override + public String toString() { + int[] elems = new int[size]; + System.arraycopy(elements, 0, elems, 0, size); + return "DynamicList{" + + "elements=" + Arrays.toString(elems) + + ", size=" + size + + ", capacity=" + elements.length + + '}'; + } } diff --git a/src/main/java/track/lessons/lesson3/LinkedList.java b/src/main/java/track/lessons/lesson3/LinkedList.java index 49a5e181..668ea4e2 100644 --- a/src/main/java/track/lessons/lesson3/LinkedList.java +++ b/src/main/java/track/lessons/lesson3/LinkedList.java @@ -1,7 +1,157 @@ package track.lessons.lesson3; +import java.util.Arrays; + /** * */ -public class LinkedList { +public class LinkedList extends List implements Stack, Queue { + + private class Node { + public Node prev; + public Node next; + public int item; + + public Node(int item) { + this.item = item; + } + + public Node(int item, Node prev, Node next) { + this.item = item; + this.prev = prev; + this.next = next; + } + } + + private Node first; + private Node last; + private int size; + + public LinkedList() { + } + + @Override + public void add(int item) { + if (isEmpty()) { + first = last = new Node(item); + } else { + Node oldLast = last; + last = new Node(item, oldLast, null); + oldLast.next = last; + } + size++; + } + + @Override + public int remove(int idx) { + if (idx < 0 || idx >= size) { + throw new IndexOutOfBoundsException("Invalid index"); + } + + if (idx == 0) { + return removeFirst(); + } + + if (idx == size - 1) { + return removeLast(); + } + + Node current = first; + for (int id = 0; id < idx; id++) { + current = current.next; + } + + Node prev = current.prev; + Node next = current.next; + final int item = current.item; + prev.next = next; + next.prev = prev; + size--; + return item; + } + + private int removeLast() { + final int item = last.item; + last = last.prev != null ? last.prev : null; + if (last != null) { + last.next = null; + } + size--; + return item; + } + + private int removeFirst() { + final int item = first.item; + first = first.next != null ? first.next : null; + if (first != null) { + first.prev = null; + } + size--; + return item; + } + + @Override + public int get(int idx) { + if (idx < 0 || idx >= size) { + throw new IndexOutOfBoundsException("Invalid index"); + } + + if (idx == 0) { + return first.item; + } + + if (idx == size - 1) { + return last.item; + } + + Node current = first; + for (int i = 0; i < idx; i++) { + current = current.next; + } + + return current.item; + } + + @Override + public int size() { + return size; + } + + @Override + public void enqueue(int value) { + add(value); + } + + @Override + public int dequeu() { + return remove(0); + } + + @Override + public void push(int value) { + add(value); + } + + @Override + public int pop() { + return remove(size - 1); + } + + private boolean isEmpty() { + return size == 0; + } + + @Override + public String toString() { + int[] elems = new int[size]; + Node current = first; + for (int i = 0; i < size; i++) { + elems[i] = current.item; + current = current.next; + } + return "LinkedList{" + + "size=" + size + + ", elems=" + Arrays.toString(elems) + + '}'; + } } diff --git a/src/main/java/track/lessons/lesson3/List.java b/src/main/java/track/lessons/lesson3/List.java index 49a182d5..528f1917 100644 --- a/src/main/java/track/lessons/lesson3/List.java +++ b/src/main/java/track/lessons/lesson3/List.java @@ -3,5 +3,12 @@ /** * */ -public class List { +public abstract class List { + abstract void add(int item); + + abstract int remove(int idx); + + abstract int get(int idx); + + abstract int size(); } diff --git a/src/main/java/track/lessons/lesson3/ListMain.java b/src/main/java/track/lessons/lesson3/ListMain.java index 5a2e7a3a..6dcd4fd8 100644 --- a/src/main/java/track/lessons/lesson3/ListMain.java +++ b/src/main/java/track/lessons/lesson3/ListMain.java @@ -6,13 +6,60 @@ public class ListMain { public static void main(String[] args) { + LinkedList linkedList = new LinkedList(); + for (int i = 0; i < 5; i++) { + linkedList.add(i); + } -// List list = new DynamicList(); -// list.add(1); -// list.add(2); -// list.add(10); -// int first = list.remove(0); + System.out.println(linkedList); + System.out.println(linkedList.get(0)); + System.out.println(linkedList.get(3)); + System.out.println(linkedList.remove(1)); + System.out.println(linkedList); + System.out.println(linkedList.remove(linkedList.size() - 1)); + System.out.println(linkedList); + System.out.println(linkedList.remove(0)); + System.out.println(linkedList); + System.out.println(linkedList.remove(0)); + System.out.println(linkedList.remove(0)); + System.out.println(linkedList); + for (int i = 0; i < 5; i++) { + linkedList.push(i); + } + System.out.println(linkedList); + System.out.println(linkedList.pop()); + + DynamicList dynamicList = new DynamicList(); + + for (int i = 0; i < 12; i++) { + dynamicList.add(i); + } + + System.out.println(dynamicList); + System.out.println(dynamicList.get(0)); + System.out.println(dynamicList.get(3)); + System.out.println(dynamicList.remove(1)); + System.out.println(dynamicList); + System.out.println(dynamicList.remove(dynamicList.size() - 1)); + System.out.println(dynamicList); + System.out.println(dynamicList.remove(0)); + System.out.println(dynamicList); + System.out.println(dynamicList.remove(0)); + System.out.println(dynamicList.remove(0)); + System.out.println(dynamicList.remove(0)); + System.out.println(dynamicList.remove(0)); + System.out.println(dynamicList.remove(0)); + System.out.println(dynamicList.remove(0)); + System.out.println(dynamicList); + System.out.println(dynamicList.remove(0)); + System.out.println(dynamicList); + System.out.println(dynamicList.remove(0)); + System.out.println(dynamicList); + System.out.println(dynamicList.remove(0)); + System.out.println(dynamicList); + System.out.println(dynamicList.remove(0)); + System.out.println(dynamicList); } } diff --git a/src/main/java/track/lessons/lesson3/Queue.java b/src/main/java/track/lessons/lesson3/Queue.java new file mode 100644 index 00000000..60aa2660 --- /dev/null +++ b/src/main/java/track/lessons/lesson3/Queue.java @@ -0,0 +1,10 @@ +package track.lessons.lesson3; + +/** + * Created by Aynulin on 11.10.2016. + */ +public interface Queue { + void enqueue(int value); + + int dequeu(); +} diff --git a/src/main/java/track/lessons/lesson3/Stack.java b/src/main/java/track/lessons/lesson3/Stack.java new file mode 100644 index 00000000..07d5aa28 --- /dev/null +++ b/src/main/java/track/lessons/lesson3/Stack.java @@ -0,0 +1,10 @@ +package track.lessons.lesson3; + +/** + * Created by Aynulin on 11.10.2016. + */ +public interface Stack { + void push(int value); + + int pop(); +} diff --git a/src/main/resources/config.json b/src/main/resources/config.json index abc47f7c..7c0646b2 100644 --- a/src/main/resources/config.json +++ b/src/main/resources/config.json @@ -8,9 +8,9 @@ "name": "gear", "ref": "gearBean" }, - "power": { - "name": "power", - "ref": "powerBean" + "engine": { + "name": "engine", + "ref": "engineBean" } } }, diff --git a/src/test/java/track/lessons/lesson3/DynamicListTest.java b/src/test/java/track/lessons/lesson3/DynamicListTest.java new file mode 100644 index 00000000..5b0da19f --- /dev/null +++ b/src/test/java/track/lessons/lesson3/DynamicListTest.java @@ -0,0 +1,77 @@ +package track.lessons.lesson3; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Aynulin on 11.10.2016. + */ +public class DynamicListTest { + DynamicList list; + + @Before + public void init() { + list = new DynamicList(); + for (int i = 0; i < 16; i++) { + list.add(i); + } + } + + @Test + public void testSize() { + Assert.assertEquals(16, list.size()); + } + + @Test + public void testGetFirst() { + Assert.assertEquals(0, list.get(0)); + } + + @Test + public void testGetLast() { + Assert.assertEquals(15, list.get(list.size() - 1)); + } + + @Test + public void testGetInside() { + Assert.assertEquals(3, list.get(3)); + } + + + @Test + public void testAdd() { + int oldSize = list.size(); + list.add(15); + Assert.assertEquals(oldSize + 1, list.size()); + Assert.assertEquals(15, list.get(15)); + } + + @Test + public void testRemove() { + int oldSize = list.size(); + int elem = list.remove(7); + Assert.assertEquals(oldSize - 1, list.size()); + Assert.assertEquals(elem, 7); + Assert.assertEquals(8, list.get(7)); + } + + @Test + public void testResizeDec() { + int oldCapacity = list.capacity(); + for (int i = 0; i < 12; i++) { + list.remove(0); + } + Assert.assertEquals(oldCapacity / 2, list.capacity()); + } + + @Test + public void testResizeInc() { + int oldCapacity = list.capacity(); + int size = list.size(); + for (int i = 0; i < 12; i++) { + list.add(size + i); + } + Assert.assertEquals(oldCapacity * 2, list.capacity()); + } +} diff --git a/src/test/java/track/lessons/lesson3/LinkedListTest.java b/src/test/java/track/lessons/lesson3/LinkedListTest.java new file mode 100644 index 00000000..6ae0a9b9 --- /dev/null +++ b/src/test/java/track/lessons/lesson3/LinkedListTest.java @@ -0,0 +1,56 @@ +package track.lessons.lesson3; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class LinkedListTest { + + LinkedList list; + + @Before + public void init() { + list = new LinkedList(); + for (int i = 0; i < 16; i++) { + list.add(i); + } + } + + @Test + public void testSize() { + Assert.assertEquals(16, list.size()); + } + + @Test + public void testGetFirst() { + Assert.assertEquals(0, list.get(0)); + } + + @Test + public void testGetLast() { + Assert.assertEquals(15, list.get(list.size() - 1)); + } + + @Test + public void testGetInside() { + Assert.assertEquals(3, list.get(3)); + } + + + @Test + public void testAdd() { + int oldSize = list.size(); + list.add(15); + Assert.assertEquals(oldSize + 1, list.size()); + Assert.assertEquals(15, list.get(15)); + } + + @Test + public void testRemove() { + int oldSize = list.size(); + int elem = list.remove(7); + Assert.assertEquals(oldSize - 1, list.size()); + Assert.assertEquals(elem, 7); + Assert.assertEquals(8, list.get(7)); + } +}