-
Notifications
You must be signed in to change notification settings - Fork 53
Maksutovaynur class container #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Максутов Айнур Мухарамович |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,63 +1,171 @@ | ||
| package arhangel.dim.container; | ||
|
|
||
| import arhangel.dim.container.dag.Graph; | ||
| import arhangel.dim.container.dag.Vertex; | ||
|
|
||
| import java.lang.reflect.Field; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.TreeMap; | ||
| import java.util.LinkedList; | ||
| import java.util.StringJoiner; | ||
|
|
||
|
|
||
| /** | ||
| * Используйте ваш xml reader чтобы прочитать конфиг и получить список бинов | ||
| */ | ||
| public class Container { | ||
| private List<Bean> beans; | ||
| private Map<String, Object> objByName; | ||
| private Map<String, Object> objByClass; | ||
|
|
||
| /** | ||
| * Если не получается считать конфиг, то бросьте исключение | ||
| * @throws InvalidConfigurationException неверный конфиг | ||
| */ | ||
| public Container(String pathToConfig) throws InvalidConfigurationException { | ||
|
|
||
| // вызываем BeanXmlReader | ||
| BeanXmlReader reader = new BeanXmlReader(); | ||
|
|
||
| List<Bean> beanList = reader.parseBeans(pathToConfig); | ||
| List<Vertex<Bean>> vertexList = new ArrayList<>(); | ||
| Graph<Bean> graph = new Graph<>(); | ||
| Map<String, Vertex<Bean>> vertexById = new TreeMap<>(); | ||
|
|
||
| for ( int i = 0; i < beanList.size(); i++ ) { | ||
| Bean bean = beanList.get(i); | ||
| Vertex<Bean> vertex = graph.addVertex(bean); | ||
| vertexById.put(bean.getName(), vertex); | ||
| vertexList.add(vertex); | ||
| } | ||
|
|
||
| for ( int i = 0; i < vertexList.size(); i++ ) { | ||
| Vertex<Bean> vertex = vertexList.get(i); | ||
| Map<String, Property> mp = vertex.getValue().getProperties(); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rename mp -> propertyMap |
||
| for ( Map.Entry<String, Property> entry : mp.entrySet()) { | ||
| if ( entry.getValue().getType() == ValueType.REF ) { | ||
| String ref = entry.getValue().getValue(); | ||
| System.out.print(ref + "\n"); | ||
| graph.addEdge(vertex, vertexById.get(ref), true); | ||
| } | ||
| } | ||
| } | ||
| vertexList = graph.toposort(); | ||
| beans = new LinkedList<>(); | ||
| for ( int i = 0; i < vertexList.size(); i++ ) { | ||
| Bean bean = vertexList.get(i).getValue(); | ||
| System.out.print("\nObject: \n" + bean.toString() + "\n\n"); | ||
| beans.add(bean); | ||
| } | ||
| objByClass = new TreeMap<>(); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А почему выбрали TreeMap?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. В TreeMap(как я понял) предполагается хранение различных объектов, ну а в нашей задаче объекты различны все.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А почему не HashMap? |
||
| objByName = new TreeMap<>(); | ||
| try { | ||
| if (graph.hasCycle()) { | ||
| throw new CycleReferenceException("Here is a cicle"); | ||
| } else { | ||
| for (Bean b : beans) { | ||
| preInstantiateBean(b); | ||
| } | ||
| for (Bean b : beans) { | ||
| instantiateBean(b); | ||
| } | ||
| } | ||
| } catch ( CycleReferenceException e) { | ||
| System.out.print(e.toString()); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Вернуть объект по имени бина из конфига | ||
| * Например, Car car = (Car) container.getByName("carBean") | ||
| */ | ||
| public Object getByName(String name) { | ||
| return null; | ||
| return objByName.get(name); | ||
| } | ||
|
|
||
| /** | ||
| * Вернуть объект по имени класса | ||
| * Например, Car car = (Car) container.getByClass("arhangel.dim.container.Car") | ||
| */ | ||
| public Object getByClass(String className) { | ||
| return null; | ||
| return objByClass.get(className); | ||
| } | ||
|
|
||
| private void instantiateBean(Bean bean) { | ||
|
|
||
| /* | ||
| // Примерный ход работы | ||
| String className = bean.getClassName(); | ||
| Class clazz = Class.forName(className); | ||
| // ищем дефолтный конструктор | ||
| Object ob = clazz.newInstance(); | ||
| public String toString() { | ||
| StringJoiner str = new StringJoiner("\n"); | ||
| for (Map.Entry e : objByName.entrySet()) { | ||
| str.add("\nObject:" + e.getKey() + " \n" + e.getValue()); | ||
| } | ||
| return str.toString(); | ||
| } | ||
|
|
||
| for (String name : bean.getProperties().keySet()) { | ||
| // ищем поле с таким именен внутри класса | ||
| // учитывая приватные | ||
| Field field = clazz.getDeclaredField(name); | ||
| // проверяем, если такого поля нет, то кидаем InvalidConfigurationException с описание ошибки | ||
| private Object fromString(String typeName, String data) throws Exception { | ||
| switch (typeName) { | ||
| case "double": | ||
| case "Double": | ||
| return Double.valueOf(data); | ||
| case "int": | ||
| case "Integer": | ||
| return Integer.valueOf(data); | ||
| case "boolean": | ||
| case "Boolean": | ||
| return Boolean.valueOf(data); | ||
| default: | ||
| throw new InvalidConfigurationException("type name = " + typeName); | ||
| } | ||
| } | ||
|
|
||
| // Делаем приватные поля доступными | ||
| field.setAccessible(true); | ||
| private void preInstantiateBean(Bean bean) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Зачем эта процедура? Что она улучшает?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Проблема в том, что хотя в выходном листе все классы в нормальном порядке, в порядке инициализации, почему-то , когда я прохожу его с помощью foreach, они инициализуются в другом порядке. Пришлось, чтобы не было ссылок на несуществующие объекты, сначала инициализировать все объекты без ссылок, а затем уже эти ссылки присвоить.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. То есть на самом деле, проблема в том, что бины инициализируются в неверном порядке? Может лучше решить проблему? |
||
| try { | ||
| String className = bean.getClassName(); | ||
| Class clazz = Class.forName(className); | ||
| Object ob = clazz.newInstance(); | ||
| objByName.put(bean.getName(), ob); | ||
| objByClass.put(bean.getClassName(), ob); | ||
| } catch (ClassNotFoundException e) { | ||
| System.out.print(e.getLocalizedMessage()); | ||
| } catch (InstantiationException e) { | ||
| System.out.print(e.getLocalizedMessage()); | ||
| } catch (IllegalAccessException e) { | ||
| System.out.print(e.getLocalizedMessage()); | ||
| } catch (Exception e) { | ||
| System.out.print(e.getLocalizedMessage()); | ||
| } | ||
| } | ||
|
|
||
| // Далее определяем тип поля и заполняем его | ||
| // Если поле - примитив, то все просто | ||
| // Если поле ссылка, то эта ссылка должа была быть инициализирована ранее | ||
| private void instantiateBean(Bean bean) { | ||
|
|
||
| */ | ||
| try { | ||
| String beanName = bean.getName(); | ||
| Object ob = getByName(beanName); | ||
| Class clazz = ob.getClass(); | ||
| String className = bean.getClassName(); | ||
| for (String name : bean.getProperties().keySet()) { | ||
| Field field = clazz.getDeclaredField(name); | ||
| if (field == null) { | ||
| throw new InvalidConfigurationException("Failed to set field [" + name + "] for class " + clazz.getName()); | ||
| } | ||
| field.setAccessible(true); | ||
| Property prop = bean.getProperties().get(name); | ||
| if (prop.getType() == ValueType.VAL) { | ||
| field.set(ob, fromString(field.getType().getTypeName(), prop.getValue())); | ||
| } else if (prop.getType() == ValueType.REF) { | ||
| if (objByName.containsKey(prop.getValue())) { | ||
| field.set(ob, getByName(prop.getValue())); | ||
| } else { | ||
| throw new InvalidConfigurationException("Failed to instantiate bean. Field " + | ||
| name + ", object: " + className + "\n"); | ||
| } | ||
| } | ||
| } | ||
| } catch (ClassNotFoundException e) { | ||
| System.out.print(e.getLocalizedMessage()); | ||
| } catch (InstantiationException e) { | ||
| System.out.print(e.getLocalizedMessage()); | ||
| } catch (NoSuchFieldException e) { | ||
| System.out.print(e.getLocalizedMessage()); | ||
| } catch (IllegalAccessException e) { | ||
| System.out.print(e.getLocalizedMessage()); | ||
| } catch (Exception e) { | ||
| System.out.print(e.getLocalizedMessage()); | ||
| } | ||
|
|
||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,35 +1,18 @@ | ||
| package arhangel.dim.container.dag; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import arhangel.dim.container.Container; | ||
| import arhangel.dim.container.beans.Car; | ||
|
|
||
| /** | ||
| * | ||
| */ | ||
| public class Main { | ||
|
|
||
| public static void main(String[] args) throws Exception { | ||
| Graph<Integer> graph = new Graph<>(); | ||
| Vertex<Integer> v1 = graph.addVertex(1); | ||
| Vertex v2 = graph.addVertex(2); | ||
| Vertex v3 = graph.addVertex(3); | ||
| Vertex v4 = graph.addVertex(4); | ||
| Vertex v5 = graph.addVertex(5); | ||
|
|
||
| Vertex v6 = graph.addVertex(6); | ||
| Vertex v7 = graph.addVertex(7); | ||
|
|
||
|
|
||
| graph.addEdge(v1, v2, true); | ||
| graph.addEdge(v1, v3, true); | ||
| graph.addEdge(v2, v3, true); | ||
| graph.addEdge(v2, v4, true); | ||
| graph.addEdge(v3, v5, true); | ||
| graph.addEdge(v4, v5, true); | ||
|
|
||
| graph.addEdge(v6, v7, true); | ||
|
|
||
| List<Vertex<Integer>> sorted = graph.toposort(); | ||
|
|
||
| Container container = new Container("./config.xml"); | ||
| System.out.print(container.toString()); | ||
| System.out.print("\ncarBean->gear->count = " + ((Car)container.getByName("carBean")).getGear().getCount()); | ||
| } | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
foreach будет читабельнее
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
У меня появились проблемы с порядком обходя foreach, поэтому пришлось воспользоваться более явным указанием порядка