From 7785d5fdf183951b15c806397c61e18f999a9523 Mon Sep 17 00:00:00 2001 From: marvin <marvin@marvin-TERRA-MOBILE-1529H> Date: Wed, 29 Jan 2020 23:38:54 +0100 Subject: [PATCH] gitignore change --- .../FeatureModelConfigurator/src/.gitignore | 5 + .../FeatureModelConfigurator/src/Adapter.java | 280 ++++++++++++++++++ .../src/Configurator.java | 160 ++++++++++ 3 files changed, 445 insertions(+) create mode 100644 Varianten/FeatureModelConfigurator/src/.gitignore create mode 100644 Varianten/FeatureModelConfigurator/src/Adapter.java create mode 100644 Varianten/FeatureModelConfigurator/src/Configurator.java diff --git a/Varianten/FeatureModelConfigurator/src/.gitignore b/Varianten/FeatureModelConfigurator/src/.gitignore new file mode 100644 index 0000000..7e3573c --- /dev/null +++ b/Varianten/FeatureModelConfigurator/src/.gitignore @@ -0,0 +1,5 @@ +#Woher kommt das?? +#/Adapter.java +#/Configurator.jak +#/.gitignore +#/Configurator.java diff --git a/Varianten/FeatureModelConfigurator/src/Adapter.java b/Varianten/FeatureModelConfigurator/src/Adapter.java new file mode 100644 index 0000000..360929d --- /dev/null +++ b/Varianten/FeatureModelConfigurator/src/Adapter.java @@ -0,0 +1,280 @@ +import java.io.*; +import java.util.*; + +import org.jdom2.*; +import org.jdom2.filter.Filters; +import org.jdom2.input.SAXBuilder; +import org.jdom2.output.XMLOutputter; +import org.jdom2.xpath.*; + + + +/** + * Takes a featuremodel.xml file generated using FeatureModelConfigurator and a given + * ROS/ Gazebo .gazebo.xacro file. + * The .gazebo.xacro file is modified to support the features specified in the + * featuremodel.xml file. + */ +public class Adapter { + + /** + * Reads an .xml file from file path and returns a JDOM document. + * + * @param src The .xml file path + * @return JDOM document + * @throws JDOMException + * @throws IOException + */ + public static Document readXml(String src) throws JDOMException, IOException { + File file = new File(src); + SAXBuilder saxBuilder = new SAXBuilder(); + Document doc = saxBuilder.build(file); + + return doc; + } + + /** + * Saves the given Document as XML to the given path. + * + * @param oDoc The JDOM document + * @param sPath The output path + * @throws IOException + */ + public static void saveAsXml(Document oDoc, String sPath) throws IOException { + FileOutputStream dest = new FileOutputStream(sPath); + XMLOutputter xmlOutput = new XMLOutputter(); + xmlOutput.output(oDoc, dest); + } + + /** + * Executes given XPath expression for elements with JDOM Document as source. + * + * @param doc The JDOM Document + * @param xPath XPath expression + * @return List with all elements found or empty list if no match found + */ + public static List<Element> xQueryElements(Document doc, String xPath) { + XPathFactory xFactory = XPathFactory.instance(); + XPathExpression<Element> expr = xFactory.compile(xPath, Filters.element()); + List<Element> result = expr.evaluate(doc); + + return result; + } + + /** + * Executes given XPath expression for elements with Element as source. + * + * @param elem The Element + * @param xPath XPath expression + * @return List with all elements found or empty list if no match found + */ + public static List<Element> xQueryElements(Element elem, String xPath) { + XPathFactory xFactory = XPathFactory.instance(); + XPathExpression<Element> expr = xFactory.compile(xPath, Filters.element()); + List<Element> result = expr.evaluate(elem); + + return result; + } + + /** + * Executes given XPath expression for attributes. + * + * @param doc The JDOM Document + * @param xPath XPath expression + * @return List with all attributes found or empty list if no match found + */ + public static List<Attribute> xQueryAttributes(Document doc, String xPath) { + XPathFactory xFactory = XPathFactory.instance(); + XPathExpression<Attribute> expr = xFactory.compile(xPath, Filters.attribute()); + List<Attribute> result = expr.evaluate(doc); + + return result; + } + + /** + * Searches a document for the first occurrence of an xml tag. + * + * @param doc The JDOM Document + * @param elementName Name of the xml tag + * @return First element found or NULL if no match found + */ + public static Element searchFirstElement(Document doc, String elementName) { + //XPath index starts with 1; [] has a higher precedence than // + List<Element> query= xQueryElements(doc, "(//"+elementName+")[1]"); + + if(query.isEmpty()) return null; + return query.get(0); + } + + /** + * Searches a document for all occurrences of an xml tag. + * + * @param doc The JDOM Document + * @param elementName Name of the xml tag + * @return List with all elements found or empty list if no match found + */ + public static List<Element> searchAllElements(Document doc, String elementName) { + return xQueryElements(doc, "//"+elementName); + } + + /** + * Checks whether two elements have an equal xml tag. + * (Name of the xml tag and all attributes including their order must be equal) + * + * @param element1 Element1 + * @param element2 Element2 + * @return true if of equal tag or false if not + */ + public static boolean equalTag(Element element1, Element element2) { + List<Attribute> attributeList1 = element1.getAttributes(); + List<Attribute> attributeList2 = element2.getAttributes(); + + if(!element1.getName().equals(element2.getName())) return false; + if(attributeList1.size()!=attributeList2.size()) return false; + for(int i=0; i<attributeList1.size(); i++) { + if(!attributeList1.get(i).getName().equals(attributeList2.get(i).getName())) return false; + if(!attributeList1.get(i).getValue().equals(attributeList2.get(i).getValue())) return false; + } + + return true; + } + + /** + * Recursive replacement of all text values in destElements with their corresponding + * new ones from srcElements. + * (srcElements and destElements must be matching tags!) + * + * TODO maybe add tags that are in srcElements but not yet in destElements + * + * @param srcElements Element list with new values + * @param destElements Element list with values to be replaced + * @return true if reached deepest Element or false if not + */ + public static boolean replace(List<Element> srcElements, List<Element> destElements) { + if(srcElements.isEmpty()&&destElements.isEmpty()) return true; + if(srcElements.isEmpty()^destElements.isEmpty()) { + System.out.println("Error during value replacement: Sensor xml trees have mismatching deph (maybe tags with no value)"); + System.exit(-1); + } + for(Element src : srcElements) { + for(Element dest : destElements) { + if(equalTag(src, dest)) { + boolean deadEnd = replace(src.getChildren(), dest.getChildren()); + if(deadEnd) dest.setText(src.getText()); + break; + } + } + } + return false; + } + + /** + * @param args + */ + public static void main(String[] args) { + try { + //TODO##### Input ############################### + Document featureModel = readXml("resources/output/featuremodel.xml"); + Document sensorConfig = readXml("resources/input/sensorconfig.xml"); + Document gazeboModel = null; + + //CustomBot not supported for now + List<Attribute> botList = xQueryAttributes(featureModel, "//module[@types='TurtleBot']/@name"); + String botName = ""; + String fileName = ""; + + switch(botList.size()) { + case 0: + System.out.println("Invalid input: No bot selected"); + System.exit(-1); + break; + case 1: + botName = botList.get(0).getValue(); + break; + default: + System.out.println("Invalid input: Multiple bots selected"); + System.exit(-1); + } + switch(botName) { + case "Burger": + fileName = "turtlebot3_burger.gazebo.xacro"; + break; + case "Waffle": + fileName = "turtlebot3_waffle.gazebo.xacro"; + break; + case "WafflePi": + fileName = "turtlebot3_waffle_pi.gazebo.xacro"; + break; + default: + System.out.println("Cannot handle \'"+botName+"\': No input file known."); + System.exit(-1); + } + gazeboModel = readXml("resources/input/turtlebot3-master/turtlebot3_description/urdf/"+fileName); + //############################################### + + + //TODO##### Operate on .gazebo.xacro ############ + List<Element> cSensorList = xQueryElements(sensorConfig, "//sensor"); + List<Element> gSensorList = xQueryElements(gazeboModel, "//sensor"); + + if(cSensorList.isEmpty()) { + System.out.println("No new sensor values in sensorconfig.xml"); + System.exit(-1); + } + if(gSensorList.isEmpty()) { + System.out.println("No sensors found in "+fileName); + System.exit(-1); + } + + for(Element cSensor : cSensorList) { + for(Element gSensor : gSensorList) { + if(equalTag(cSensor, gSensor)) { + replace(cSensor.getChildren(),gSensor.getChildren()); + } + } + } + + //hard-coded and only for demo purposes +// List<Element> cSensorList = xQueryElements(sensorConfig, "//sensor[@type='ray' and @name='lds_lfcd_sensor']"); +// Element cSensor = cSensorList.get(0); +// +// List<Element> gSensorList = xQueryElements(gazeboModel, "//sensor[@type='ray' and @name='lds_lfcd_sensor']"); +// Element gSensor = gSensorList.get(0); +// +// String new_min = cSensor.getChild("range").getChild("min").getText(); +// String new_max = cSensor.getChild("range").getChild("max").getText(); +// +// gSensor.getChild("ray").getChild("range").getChild("min").setText(new_min); +// gSensor.getChild("ray").getChild("range").getChild("max").setText(new_max); + //############################################### + + + //######### Output result ####################### + saveAsXml(gazeboModel, "resources/output/"+fileName); + //############################################### + + + //XPathExamples +// XPathFactory xFactory = XPathFactory.instance(); +// XPathExpression<Element> xExpr = xFactory.compile("robot/gazebo/sensor/ray/range/min", Filters.element()); +// Element test = xExpr.evaluateFirst(gazeboModel); +// List<Element> test2 = searchAllElements(gazeboModel, "min"); +// List<Element> test3 = searchAllElements(gazeboModel, "max"); +// Element test4 = searchFirstElement(gazeboModel, "plugin"); +// List<Attribute> test5 = xQueryAttributes(gazeboModel, "(//plugin)[1]/@*"); +// +// if(test != null) xmlOutput.output(test, System.out); +// System.out.println("\n"); +// xmlOutput.output(test2, System.out); +// System.out.println("\n"); +// xmlOutput.output(test3, System.out); +// System.out.println("\n"); +// if(test4 != null) xmlOutput.output(test4, System.out); +// System.out.println("\n"); +// for(Attribute a : test5) System.out.println(a.getName()+"="+a.getValue()); + + } catch (JDOMException | IOException e) { + e.printStackTrace(); + } + } +} diff --git a/Varianten/FeatureModelConfigurator/src/Configurator.java b/Varianten/FeatureModelConfigurator/src/Configurator.java new file mode 100644 index 0000000..770a885 --- /dev/null +++ b/Varianten/FeatureModelConfigurator/src/Configurator.java @@ -0,0 +1,160 @@ + +import java.util.List; +import java.util.ArrayList; +import java.io.IOException; + +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.JDOMException; + + + +/** + * Main class for the car configurator. + * Is refined by modules, which add selected components to component list. + * This class has to save a file containing the configuration + * and launch the test seletion application afterwards. + * + * + * Naming conventions: + * m_: Member variable + * s: String + * n: Integer number (int, long,...) + * f: Floating point number (float, double,...) + * o: Object + * a: Collection (List, Array,...) + * + */ + +abstract class Configurator$$ConfiguratorMain { + //module list + private List m_aModuleList; + //output path + private String m_sOutputPath = "resources/output/featuremodel.xml"; + //TODO: set this + //path for test case selector, which has to be launched from this application + private String m_sTestCaseSelectorPath; + //path to the feature model xml + private String m_sFeatureModelPath = "model.xml"; + //document representation of the feature model + private Document m_oFeatureModelDoc; + //representation of a single module with all of its types + class Module { + String sModuleName; + ArrayList aModuleTypes; + } + + + public static void main(String[] args) { + new Configurator().save(); + } + + public void save() { + //create empty xml + Element oStruct = new Element("specification"); + Document oDoc = new Document(oStruct); + + //if the module list was initialized + if(m_aModuleList!=null) { + for(int i=0; i<m_aModuleList.size(); i++) { + //Add module and tag to Document + Element oModuleElement = new Element("module"); + //Add name + Module oModule = (Module)m_aModuleList.get(i); + oModuleElement.setAttribute("name", oModule.sModuleName); + //Create type String + ArrayList<String> aTypes = oModule.aModuleTypes; + String sTypesString = ""; + //concat String + for(int j=0; j<aTypes.size(); j++) { + sTypesString += aTypes.get(j); + //add comma if it's not the last Type + if(j<aTypes.size()-1) + sTypesString += ", "; + } + oModuleElement.setAttribute("types", sTypesString); + oStruct.addContent(oModuleElement); + } + } + + //generate xml String and save it to a file + try { + Adapter.saveAsXml(oDoc, m_sOutputPath); + } + catch (Exception oEx) { + System.out.println(oEx); + return; + } + + //create and launch Adapter + new Adapter(); + } + + //get all parents of a given module from the Feature Model file + private Module GetModuleParents(String sModuleName) throws IOException, JDOMException { + Module oModule = new Module(); + //set name + oModule.sModuleName = sModuleName; + //init Doc if not done + if(m_oFeatureModelDoc==null) { + m_oFeatureModelDoc = Adapter.readXml(m_sFeatureModelPath); + System.out.println(m_oFeatureModelDoc.toString()); + } + //get element + String sQuery = "//*[@name= '"+sModuleName+"']"; + List<Element> aModules = Adapter.xQueryElements(m_oFeatureModelDoc, sQuery); + Element oModuleElement; + try { + oModuleElement = aModules.get(0); + } + catch (Exception oEx) { + System.out.println(oEx.toString() + "\nList empty for query "+ sQuery); + return null; + } + //get all anchestors + Element oParent = oModuleElement.getParentElement(); + ArrayList<String> aTypes = new ArrayList(); + //itterate through parents of module + while(true) { + String sElementName = oParent.getAttribute("name").getValue(); + //break if we reach the Main class, as there are no types further up + if(sElementName.equals("ConfiguratorMain")) { + break; + } + aTypes.add(sElementName); + //iterate further trough List + oModuleElement = oParent; + oParent = oModuleElement.getParentElement(); + } + oModule.aModuleTypes = aTypes; + return oModule; + } + + //add a module name and module type to the feature list. Init list, if not already done + public void addToModuleList(String sModuleName) { + //init List, if not already done + if(m_aModuleList==null) { + m_aModuleList = new ArrayList(); + } + //get the module types + Module oModule; + try { + oModule = GetModuleParents(sModuleName); + } + catch (Exception oEx) { + System.out.print(oEx); + return; + } + m_aModuleList.add(oModule); + } +} + +/** + * TODO description + */ +public class Configurator extends Configurator$$ConfiguratorMain { + public void save() { + super.addToModuleList("Waffle"); + super.save(); + } +} \ No newline at end of file -- GitLab