diff options
author | nirmal070125 <nirmal070125@13f79535-47bb-0310-9956-ffa450edef68> | 2011-06-10 20:29:43 +0000 |
---|---|---|
committer | nirmal070125 <nirmal070125@13f79535-47bb-0310-9956-ffa450edef68> | 2011-06-10 20:29:43 +0000 |
commit | 55ca4b66c5f46bc17e248bcd120530be5cccab57 (patch) | |
tree | 88bc0eae9ba0d30b00fecddce3eb64347e384318 /collaboration | |
parent | 1831c66fa90abb198249d73197aec8044bff9a04 (diff) |
start on layout
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1134433 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'collaboration')
8 files changed, 414 insertions, 78 deletions
diff --git a/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/input/composite.xml b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/input/composite.xml new file mode 100755 index 0000000000..345b9065a9 --- /dev/null +++ b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/input/composite.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + targetNamespace="http://sample" + xmlns:sample="http://sample" + name="Calculator"> + + <component name="CalculatorServiceComponent"> + <implementation.java class="calculator.CalculatorServiceImpl"/> + <reference name="addService" target="AddServiceComponent" /> + <reference name="subtractService" target="SubtractServiceComponent" /> + <reference name="multiplyService" target="MultiplyServiceComponent" /> + <reference name="divideService" target="DivideServiceComponent" /> + </component> + + <component name="AddServiceComponent"> + <implementation.java class="calculator.AddServiceImpl"/> + </component> + + <component name="SubtractServiceComponent"> + <implementation.java class="calculator.SubtractServiceImpl"/> + </component> + + <component name="MultiplyServiceComponent"> + <implementation.java class="calculator.MultiplyServiceImpl"/> + </component> + + <component name="DivideServiceComponent"> + <implementation.java class="calculator.DivideServiceImpl"/> + </component> + +</composite>
\ No newline at end of file diff --git a/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/input/composite1.xml b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/input/composite1.xml new file mode 100755 index 0000000000..b88a83120e --- /dev/null +++ b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/input/composite1.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + targetNamespace="http://supplychain" + xmlns:sp="http://supplychain" + name="supplychain"> + + <component name="CustomerComponent"> + <implementation.java class="supplychain.CustomerComponentImpl" /> + <reference name="retailer" target="RetailerComponent"/> + </component> + + <component name="RetailerComponent"> + <implementation.java class="supplychain.RetailerComponentImpl" /> + <reference name="warehouse" target="WarehouseComponent"/> + </component> + + <component name="WarehouseComponent"> + <implementation.java class="supplychain.WarehouseComponentImpl" /> + <reference name="shipper" target="ShipperComponent"/> + </component> + + <component name="ShipperComponent"> + <implementation.java class="supplychain.ShipperComponentImpl" /> + <reference name="customer" target="CustomerComponent"/> + </component> + +</composite>
\ No newline at end of file diff --git a/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/input/composite2.xml b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/input/composite2.xml new file mode 100755 index 0000000000..fc32186344 --- /dev/null +++ b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/input/composite2.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:t="http://tuscany.apache.org/xmlns/sca/1.0" + targetNamespace="http://store" + name="store"> + + <component name="Store"> + <t:implementation.widget location="uiservices/store.html"/> + <service name="Widget"> + <t:binding.http uri="/store"/> + </service> + <reference name="catalog" target="Catalog"> + <t:binding.jsonrpc/> + </reference> + <reference name="shoppingCart" target="ShoppingCart/Cart"> + <t:binding.atom/> + </reference> + <reference name="shoppingTotal" target="ShoppingCart/Total"> + <t:binding.jsonrpc/> + </reference> + </component> + + <component name="Catalog"> + <implementation.java class="services.FruitsCatalogImpl"/> + <property name="currencyCode">USD</property> + <service name="Catalog"> + <t:binding.jsonrpc/> + </service> + <reference name="currencyConverter" target="CurrencyConverter"/> + </component> + + <component name="ShoppingCart"> + <implementation.java class="services.ShoppingCartImpl"/> + <service name="Cart"> + <t:binding.atom uri="/ShoppingCart/Cart"/> + </service> + <service name="Total"> + <t:binding.jsonrpc/> + </service> + </component> + + <component name="CurrencyConverter"> + <implementation.java class="services.CurrencyConverterImpl"/> + </component> + +</composite>
\ No newline at end of file diff --git a/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/diagram/DiagramGenerator.java b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/diagram/DiagramGenerator.java new file mode 100755 index 0000000000..b4f425aeed --- /dev/null +++ b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/diagram/DiagramGenerator.java @@ -0,0 +1,17 @@ +package org.apache.tuscany.sca.impl.diagram; + +import org.apache.tuscany.sca.impl.layout.Entity; + +public class DiagramGenerator { + + Entity[] entities; + + public DiagramGenerator(Entity[] entities) { + this.entities = entities; + } + + + + + +} diff --git a/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/layout/Entity.java b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/layout/Entity.java index 34c750bbce..a9716146bb 100755 --- a/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/layout/Entity.java +++ b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/layout/Entity.java @@ -18,7 +18,7 @@ import org.apache.tuscany.sca.impl.artifacts.Service; public class Entity { private String componentName; - private int X, Y, level, lane, refHeight, serHeight, propLength; + private int X, Y, level=-1, lane=-1, refHeight, serHeight, propLength; public static final int defaultNoOfSers= Component.DEFAULT_HEIGHT / (Service.MAXIMUM_HEIGHT+Service.SPACING); public static final int defaultNoOfRefs= Component.DEFAULT_HEIGHT / (Reference.MAXIMUM_HEIGHT+Reference.SPACING); //same value for defaultNoOfSers @@ -36,6 +36,7 @@ public class Entity { private ArrayList<String> propProperties = new ArrayList<String>(); private HashSet<String> adjacentEntities = new HashSet<String>(); + private HashSet<String> connectedEntities = new HashSet<String>(); public Entity(){ @@ -94,8 +95,8 @@ public class Entity { */ //assumption there can not be two services for the same reference public boolean addToRefToSerMap(String ref, String ser){ - ref = ref.toLowerCase(); - ser = ser.toLowerCase(); + //ref = ref.toLowerCase(); + //ser = ser.toLowerCase(); if (referenceToServiceMap.containsKey(ref)) return false; @@ -110,7 +111,7 @@ public class Entity { * @return service name */ public String getSerOfRef(String ref){ - ref = ref.toLowerCase(); + //ref = ref.toLowerCase(); if (!referenceToServiceMap.containsKey(ref)) return null; @@ -119,25 +120,31 @@ public class Entity { } public void addAService(String serName){ - serName = serName.toLowerCase(); + //serName = serName.toLowerCase(); services.add(serName); } public void addAReference(String refName){ - refName = refName.toLowerCase(); + //refName = refName.toLowerCase(); references.add(refName); } public void addAProperty(String propName){ - propName = propName.toLowerCase(); + //propName = propName.toLowerCase(); properties.add(propName); } public void addAnAdjacentEntity(String x){ +// System.out.println("eee "+x); + adjacentEntities.add(x); + + } + public void addAnConnectedEntity(String x){ +// System.out.println("eee "+x); adjacentEntities.add(x); } @@ -243,4 +250,12 @@ public class Entity { return propLength; } + public void setConnectedEntities(HashSet<String> connectedEntities) { + this.connectedEntities = connectedEntities; + } + + public HashSet<String> getConnectedEntities() { + return connectedEntities; + } + } diff --git a/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/layout/EntityBuilder.java b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/layout/EntityBuilder.java index dad3518b90..75dd21f5c3 100755 --- a/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/layout/EntityBuilder.java +++ b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/layout/EntityBuilder.java @@ -1,6 +1,8 @@ package org.apache.tuscany.sca.impl.layout; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import org.apache.tuscany.sca.impl.artifacts.Component; import org.w3c.dom.Document; @@ -9,128 +11,250 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class EntityBuilder { - + private Document dom; private final int initPoint = 100; private final int spaceX = Component.DEFAULT_WIDTH*2; private final int spaceY = Component.DEFAULT_HEIGHT*2; - private ArrayList<Integer> levelCount = new ArrayList<Integer>(); + private ArrayList<Integer> levelCount = new ArrayList<Integer>();//keeps track of levels used in lanes + private HashMap<String, ArrayList<String>> connectedEntities = new HashMap<String, ArrayList<String>>(); + public final int totalLength=0, totalHeight=0; public EntityBuilder(Document aDom){ dom = aDom; } - + public Entity[] buildEntities(){ Entity[] elts = null; //get the root element Element docEle = dom.getDocumentElement(); //get a nodelist of elements - NodeList nl = docEle.getElementsByTagName("sca:component"); + NodeList nl = docEle.getElementsByTagName("component"); if(nl != null && nl.getLength() > 0 ) { elts = new Entity[nl.getLength()]; for(int i = 0 ; i < nl.getLength();i++) { + elts[i] = new Entity(); Element nVal = (Element)nl.item(i); + //System.out.println(nVal.hasAttribute("name")); elts[i].setComponentName(nVal.getAttribute("name")); - setReferences(nVal, elts[i]); setServices(nVal, elts[i]); + setReferences(nVal, elts[i]); setProperties(nVal, elts[i]); elts[i].referenceHeight(); elts[i].serviceHeight(); elts[i].propertyLength(); } } - - //get a nodelist of elements - NodeList nl2 = docEle.getElementsByTagName("sca:wire"); - if(nl2 != null && nl2.getLength() > 0 ) { - - for(int i = 0 ; i < nl2.getLength();i++) { - Element nVal = (Element)nl2.item(i); - String[] source = splitValues(nVal.getAttribute("source")); - String[] target = splitValues(nVal.getAttribute("target")); - - for(Entity ent: elts){ - if(ent.getComponentName().equalsIgnoreCase(source[0])){ - ent.addAnAdjacentEntity(target[0]); - ent.addToRefToSerMap(source[1], target[1]); - break; - } - } - } - } - + + // //get a nodelist of elements + // NodeList nl2 = docEle.getElementsByTagName("wire"); + // if(nl2 != null && nl2.getLength() > 0 ) { + // + // for(int i = 0 ; i < nl2.getLength();i++) { + // Element nVal = (Element)nl2.item(i); + // String[] source = splitValues(nVal.getAttribute("source")); + // String[] target = splitValues(nVal.getAttribute("target")); + // + // for(Entity ent: elts){ + // if(ent.getComponentName().equalsIgnoreCase(source[0])){ + // ent.addAnAdjacentEntity(target[0]); + // ent.addToRefToSerMap(source[1], target[1]); + // break; + // } + // } + // } + // } + + //correctMap(elts); + positionEntities(elts); - + + print(elts); + return elts; - + } - + + // private void correctMap(Entity[] elts) { + // + // for(Entity ent: elts){ + // for(Iterator it=ent.getReferenceToServiceMap().values().iterator();it.hasNext();){ + // String target = (String)it.next(); + // if(target.startsWith("#")){ + // for(Entity e: elts){ + // if(e.getComponentName().equals(target.substring(1))){ + // + // } + // } + // } + // } + // } + // } + + private void print(Entity[] elts) { + + for(Entity ent: elts){ + System.out.println(ent.getComponentName()+" : "+ent.getLevel()+" : " + +ent.getLane()+" : "+ent.getX()+" : "+ent.getY()); + } + } + private void positionEntities(Entity[] ents){ Entity startEnt = null; for(Entity ent: ents){ - if(ent.getAdjacentEntities().size() != 0){ + if(ent.getAdjacentEntities().size() != 0 || ents.length==1){ setPosition(ent, initPoint, initPoint, 0, 0); levelCount.add(0, 1); startEnt = ent; + System.err.println(ent.getComponentName()); break; } } +// for(Entity ent: ents){ +// if(ent != startEnt){ +// assignPosition(ent, ents); +// } +// } + if(startEnt != null) assignPositions(ents, startEnt); + + } + + private void assignPosition(Entity ent, Entity[] ents) { + } - + private void assignPositions(Entity[] ents, Entity ent){ int i=0; - for(String name: ent.getAdjacentEntities()){ - for(Entity aEnt: ents){ - if(name.equalsIgnoreCase(aEnt.getComponentName())){ - int lane = ent.getLane()+1; - if(levelCount.get(lane) != null){ - levelCount.add(lane, 1); - setPosition(aEnt, ent.getX()+spaceX, ent.getY(), 0, lane); - } - else{ - int level = levelCount.get(lane); - levelCount.add(lane, level+1); - setPosition(aEnt, ent.getX()+spaceX, ent.getY()+spaceY*level, level, lane); + + //for(Entity ent: ents){ + + if(ent.getAdjacentEntities().size()>0){ + System.out.println(ent.getComponentName()); + for(String name: ent.getAdjacentEntities()){ + System.out.println("eee "+name); + for(Entity aEnt: ents){ + i++; + if(name.equalsIgnoreCase(aEnt.getComponentName())){ + int lane = ent.getLane()+1; + if(levelCount.size()<= lane){ + levelCount.add(lane, 1); + setPosition(aEnt, ent.getX()+spaceX, ent.getY(), 0, lane); + } + else{ + int level = levelCount.get(lane); + levelCount.add(lane, level+1); + setPosition(aEnt, ent.getX()+spaceX, ent.getY()+spaceY*level, level, lane); + } + if(i<ents.length) + assignPositions(ents, aEnt); + break; } - assignPositions(ents, aEnt); - break; + } } - i++; } - } + + //} + else{ + ArrayList<String> conns = connectedEntities.get(ent.getComponentName()); + System.err.println(conns.size()); + if(conns.size()>0){ + + for(String conn: conns){ + System.err.println("conn "+conn +" : "+ent.getComponentName()); + for(Entity e: ents){ + if(e.getLane() == -1 && e.getComponentName().equals(conn)){ + + int lane = ent.getLane()-1; + System.err.println(lane); + int level = levelCount.get(lane); + levelCount.add(lane, level+1); + setPosition(e, ent.getX()-spaceX, ent.getY()+spaceY*level, level, lane); + +// if(levelCount.size()<= lane){ +// levelCount.add(lane, 1); +// setPosition(aEnt, ent.getX()+spaceX, ent.getY(), 0, lane); +// } +// else{ +// int level = levelCount.get(lane); +// levelCount.add(lane, level+1); +// setPosition(aEnt, ent.getX()+spaceX, ent.getY()+spaceY*level, level, lane); +// } +// System.err.println(e.getComponentName()); +// assignPositions(ents, e); + break; + } + } + } + } + } + } + private void setPosition(Entity ent, int x, int y, int level, int lane){ ent.setX(x); ent.setY(y); ent.setLevel(level); ent.setLane(lane); } - - + + private String[] splitValues(String str){ return str.split("/"); } private void setReferences(Element nVal, Entity ent) { - NodeList nl = nVal.getElementsByTagName("sca:reference"); + NodeList nl = nVal.getElementsByTagName("reference"); if(nl != null && nl.getLength() > 0 ) { for(int i = 0 ; i < nl.getLength();i++) { Element elt = (Element)nl.item(i); - ent.addAReference(elt.getAttribute("name")); + String target = elt.getAttribute("target"); + String ref = elt.getAttribute("name"); + if(target.contains("/")){ + ent.addToRefToSerMap(ref, target.split("/")[1]); + ent.addAnAdjacentEntity(target.split("/")[0]); + addToConnectedEntities(ent.getComponentName(), target.split("/")[0]); + addToConnectedEntities(target.split("/")[0], ent.getComponentName()); + } + else if(!target.equals("")){ + //adding a #, since this is not the name of the service + //but the component which has only one service + ent.addToRefToSerMap(ref, "#"+target); + ent.addAnAdjacentEntity(target); + addToConnectedEntities(ent.getComponentName(), target); + addToConnectedEntities(target, ent.getComponentName()); + } + + ent.addAReference(ref); + } } } - + + private void addToConnectedEntities(String ent1, String ent2) { + System.err.println(ent1+" : "+ent2); + ArrayList<String> list; + if(connectedEntities.containsKey(ent1)){ + list = connectedEntities.get(ent1); + + } + else{ + list =new ArrayList<String>(); + + } + list.add(ent2); + connectedEntities.put(ent1, list); + } + private void setServices(Element nVal, Entity ent) { - NodeList nl = nVal.getElementsByTagName("sca:service"); + NodeList nl = nVal.getElementsByTagName("service"); if(nl != null && nl.getLength() > 0 ) { for(int i = 0 ; i < nl.getLength();i++) { Element elt = (Element)nl.item(i); @@ -138,10 +262,10 @@ public class EntityBuilder { } } } - + private void setProperties(Element nVal, Entity ent) { - NodeList nl = nVal.getElementsByTagName("sca:property"); + NodeList nl = nVal.getElementsByTagName("property"); if(nl != null && nl.getLength() > 0 ) { for(int i = 0 ; i < nl.getLength();i++) { Element elt = (Element)nl.item(i); @@ -149,7 +273,7 @@ public class EntityBuilder { } } } - - + + } diff --git a/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/layout/PropertyAllocator.java b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/layout/PropertyAllocator.java index 1574d1247f..a05951f3ac 100755 --- a/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/layout/PropertyAllocator.java +++ b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/impl/layout/PropertyAllocator.java @@ -6,21 +6,21 @@ import org.apache.tuscany.sca.impl.artifacts.Component; import org.apache.tuscany.sca.impl.artifacts.Reference; public class PropertyAllocator { - Entity entity; - - public PropertyAllocator(Entity e) { - entity = e; - } - - public void allocatePropertiesOfRefs(){ - int height=0; - - - for(Iterator it=entity.getReferenceToServiceMap().keySet().iterator();it.hasNext();){ - String ref = it.next(); - - } - } +// Entity entity; +// +// public PropertyAllocator(Entity e) { +// entity = e; +// } +// +// public void allocatePropertiesOfRefs(){ +// int height=0; +// +// +// for(Iterator it=entity.getReferenceToServiceMap().keySet().iterator();it.hasNext();){ +// String ref = it.next(); +// +// } +// } } diff --git a/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/main/Main.java b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/main/Main.java new file mode 100755 index 0000000000..24ec643779 --- /dev/null +++ b/collaboration/GSoC-2011-Nirmal/CompositeDiagramGeneratorUsingBatik/src/main/java/org/apache/tuscany/sca/main/Main.java @@ -0,0 +1,22 @@ +package org.apache.tuscany.sca.main; + +import org.apache.tuscany.sca.impl.io.XMLReader; +import org.apache.tuscany.sca.impl.layout.EntityBuilder; +import org.w3c.dom.Document; + +public class Main { + + /** + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + + XMLReader reader = new XMLReader(); + Document doc =reader.parseXMLFile(System.getProperty("user.dir")+"/input/composite2.xml"); + EntityBuilder eb = new EntityBuilder(doc); + eb.buildEntities(); + + } + +} |