correct find elements recursion + test

This commit is contained in:
Alexey Fedoseev
2024-05-10 19:00:35 +03:00
parent 7f861c9fd3
commit 02fbc97101
4 changed files with 227 additions and 4 deletions

View File

@@ -633,7 +633,8 @@ ConstElementList ElementCollection::find_elements_by_type(ElementType _type) con
const Element* e = *i; const Element* e = *i;
if (e->get_type() == _type) { if (e->get_type() == _type) {
result.push_back(e); result.push_back(e);
} else if (e->has_children()) { }
if (e->has_children()) {
const ElementCollection* c = static_cast<const ElementCollection*>(e); const ElementCollection* c = static_cast<const ElementCollection*>(e);
ConstElementList r = c->find_elements_by_type(_type); ConstElementList r = c->find_elements_by_type(_type);
result.insert(result.end(), r.begin(), r.end()); result.insert(result.end(), r.begin(), r.end());
@@ -649,7 +650,8 @@ ConstElementList ElementCollection::find_elements_by_types(const ElementTypes& t
const Element* e = *i; const Element* e = *i;
if (std::find(types.begin(), types.end(), e->get_type()) != types.end()) { if (std::find(types.begin(), types.end(), e->get_type()) != types.end()) {
result.push_back(e); result.push_back(e);
} else if (e->has_children()) { }
if (e->has_children()) {
const ElementCollection* c = static_cast<const ElementCollection*>(e); const ElementCollection* c = static_cast<const ElementCollection*>(e);
ConstElementList r = c->find_elements_by_types(types); ConstElementList r = c->find_elements_by_types(types);
result.insert(result.end(), r.begin(), r.end()); result.insert(result.end(), r.begin(), r.end());
@@ -665,7 +667,8 @@ ElementList ElementCollection::find_elements_by_type(ElementType _type)
Element* e = *i; Element* e = *i;
if (e->get_type() == _type) { if (e->get_type() == _type) {
result.push_back(e); result.push_back(e);
} else if (e->has_children()) { }
if (e->has_children()) {
ElementCollection* c = static_cast<ElementCollection*>(e); ElementCollection* c = static_cast<ElementCollection*>(e);
ElementList r = c->find_elements_by_type(_type); ElementList r = c->find_elements_by_type(_type);
result.insert(result.end(), r.begin(), r.end()); result.insert(result.end(), r.begin(), r.end());
@@ -681,7 +684,8 @@ ElementList ElementCollection::find_elements_by_types(const ElementTypes& types)
Element* e = *i; Element* e = *i;
if (std::find(types.begin(), types.end(), e->get_type()) != types.end()) { if (std::find(types.begin(), types.end(), e->get_type()) != types.end()) {
result.push_back(e); result.push_back(e);
} else if (e->has_children()) { }
if (e->has_children()) {
ElementCollection* c = static_cast<ElementCollection*>(e); ElementCollection* c = static_cast<ElementCollection*>(e);
ElementList r = c->find_elements_by_types(types); ElementList r = c->find_elements_by_types(types);
result.insert(result.end(), r.begin(), r.end()); result.insert(result.end(), r.begin(), r.end());

View File

@@ -0,0 +1,48 @@
/* -----------------------------------------------------------------------------
* The Cyberiada GraphML C++ library implemention
*
* The test
*
* Copyright (C) 2024 Alexey Fedoseev <aleksey@fedoseev.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/
* ----------------------------------------------------------------------------- */
#include <iostream>
#include "cyberiadamlpp.h"
using namespace Cyberiada;
using namespace std;
int main(int argc, char** argv)
{
Document d;
try {
d.load(string(argv[0]) + "-input.graphml", formatLegacyYED);
const StateMachine* sm = d.get_state_machines().front();
ConstElementList list = sm->find_elements_by_types({Cyberiada::elementSimpleState,
Cyberiada::elementCompositeState,
Cyberiada::elementInitial,
Cyberiada::elementFinal,
Cyberiada::elementChoice,
Cyberiada::elementTerminate});
for (ConstElementList::const_iterator i = list.begin(); i != list.end(); i++) {
cout << (*i)->dump_to_str() << endl;
}
} catch (const Cyberiada::Exception& e) {
cerr << e.str() << endl;
return 1;
}
return 0;
}

View File

@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="utf-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" yed:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd" SchemeName="Автобортник" entryPosition="-1573,862 1002,069">
<key attr.name="Description" attr.type="string" for="graph" id="d0" />
<key for="port" id="d1" yfiles.type="portgraphics" />
<key for="port" id="d2" yfiles.type="portgeometry" />
<key for="port" id="d3" yfiles.type="portuserdata" />
<key attr.name="url" attr.type="string" for="node" id="d4" />
<key attr.name="description" attr.type="string" for="node" id="d5" />
<key for="node" id="d6" yfiles.type="nodegraphics" />
<key for="graphml" id="d7" yfiles.type="resources" />
<key attr.name="url" attr.type="string" for="edge" id="d8" />
<key attr.name="description" attr.type="string" for="edge" id="d9" />
<key for="edge" id="d10" yfiles.type="edgegraphics" />
<graph edgedefault="directed" id="G">
<data key="d0" xml:space="preserve" />
<node id="">
<data key="d6">
<y:GenericNode configuration="com.yworks.bpmn.Event.withShadow">
<y:Geometry x="-1628" y="748" width="10" height="10" />
<y:Fill color="#333333" color2="#000000" transparent="false" />
<y:BorderStyle color="#000000" type="line" width="1.0" />
<y:NodeLabel />
</y:GenericNode>
</data>
</node>
<node id="n0" yfiles.foldertype="group">
<data key="d4" xml:space="preserve" />
<data key="d6">
<y:ProxyAutoBoundsNode>
<y:Realizers active="0">
<y:GroupNode>
<y:Geometry x="-786" y="492" width="517" height="770" />
<y:Fill color="#F5F5F5" transparent="false" />
<y:BorderStyle color="#000000" type="line" width="1.0" />
<y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="bold" hasLineColor="false" height="22" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="517" x="0" xml:space="preserve" y="0">Бой</y:NodeLabel>
<y:NodeLabel alignment="left" autoSizePolicy="node_size" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="770" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="517" x="0" xml:space="preserve" y="0">entry/
exit/
</y:NodeLabel>
<y:Shape type="roundrectangle" />
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false" />
<y:NodeBounds considerNodeLabelSize="true" />
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0" />
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0" />
</y:GroupNode>
</y:Realizers>
</y:ProxyAutoBoundsNode>
</data>
<graph edgedefault="directed" id="n0:">
<node id="n0::n1">
<data key="d6">
<y:GenericNode>
<y:Geometry x="-788" y="645" width="413" height="208" />
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false" />
<y:BorderStyle color="#000000" type="line" width="1.0" />
<y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="#B7C9E3" configuration="com.yworks.entityRelationship.label.name" fontFamily="Dialog" fontSize="15" fontStyle="bold" hasLineColor="false" height="22" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="413" x="0" xml:space="preserve" y="0">Сближение</y:NodeLabel>
<y:NodeLabel alignment="left" autoSizePolicy="content" configuration="com.yworks.entityRelationship.label.name" fontFamily="Consolas" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="208" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="413" x="0" xml:space="preserve" y="0">entry/
МодульДвижения.ДвигатьсяКЦели()
exit/
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n0::n2">
<data key="d6">
<y:GenericNode>
<y:Geometry x="-784" y="311" width="413" height="208" />
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false" />
<y:BorderStyle color="#000000" type="line" width="1.0" />
<y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="#B7C9E3" configuration="com.yworks.entityRelationship.label.name" fontFamily="Dialog" fontSize="15" fontStyle="bold" hasLineColor="false" height="22" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="413" x="0" xml:space="preserve" y="0">Атака</y:NodeLabel>
<y:NodeLabel alignment="left" autoSizePolicy="content" configuration="com.yworks.entityRelationship.label.name" fontFamily="Consolas" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="208" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="413" x="0" xml:space="preserve" y="0">entry/
ОружиеЦелевое.АтаковатьЦель()
exit/
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
</graph>
</node>
<node id="n3">
<data key="d6">
<y:GenericNode>
<y:Geometry x="-1573" y="738" width="413" height="288" />
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false" />
<y:BorderStyle color="#000000" type="line" width="1.0" />
<y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="#B7C9E3" configuration="com.yworks.entityRelationship.label.name" fontFamily="Dialog" fontSize="15" fontStyle="bold" hasLineColor="false" height="22" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="413" x="0" xml:space="preserve" y="0">Скан</y:NodeLabel>
<y:NodeLabel alignment="left" autoSizePolicy="content" configuration="com.yworks.entityRelationship.label.name" fontFamily="Consolas" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="288" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="413" x="0" xml:space="preserve" y="0">entry/
Сенсор.ПоискВрагаПоДистанции(мин)
exit/
Сенсор.ОстановкаПоиска()
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<edge source="n0" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0" sy="0" tx="0" ty="0" />
<y:LineStyle color="#000000" type="line" width="1.0" />
<y:Arrows source="none" target="standard" />
<y:EdgeLabel alignment="center" backgroundColor="#F5F5F5" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" horizontalTextPosition="center" iconTextGap="4" modelName="centered" modelPosition="center" preferredPlacement="center_on_edge" ratio="5.0" textColor="#000000" verticalTextPosition="bottom" visible="true" xml:space="preserve">АнализаторЦели.ЦельПотеряна/
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" placement="center" side="on_edge" sideReference="relative_to_edge_flow" /></y:EdgeLabel>
</y:PolyLineEdge>
</data>
</edge>
<edge source="n0" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0" sy="0" tx="0" ty="0" />
<y:LineStyle color="#000000" type="line" width="1.0" />
<y:Arrows source="none" target="standard" />
<y:EdgeLabel alignment="center" backgroundColor="#F5F5F5" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" horizontalTextPosition="center" iconTextGap="4" modelName="centered" modelPosition="center" preferredPlacement="center_on_edge" ratio="5.0" textColor="#000000" verticalTextPosition="bottom" visible="true" xml:space="preserve">АнализаторЦели.ЦельУничтожена/
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" placement="center" side="on_edge" sideReference="relative_to_edge_flow" /></y:EdgeLabel>
</y:PolyLineEdge>
</data>
</edge>
<edge source="n3" target="n0::n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0" sy="0" tx="0" ty="0" />
<y:LineStyle color="#000000" type="line" width="1.0" />
<y:Arrows source="none" target="standard" />
<y:EdgeLabel alignment="center" backgroundColor="#F5F5F5" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" horizontalTextPosition="center" iconTextGap="4" modelName="centered" modelPosition="center" preferredPlacement="center_on_edge" ratio="5.0" textColor="#000000" verticalTextPosition="bottom" visible="true" xml:space="preserve">Сенсор.ЦельПолучена/
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" placement="center" side="on_edge" sideReference="relative_to_edge_flow" /></y:EdgeLabel>
</y:PolyLineEdge>
</data>
</edge>
<edge source="n0::n1" target="n0::n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0" sy="0" tx="0" ty="0" />
<y:LineStyle color="#000000" type="line" width="1.0" />
<y:Arrows source="none" target="standard" />
<y:EdgeLabel alignment="center" backgroundColor="#F5F5F5" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" horizontalTextPosition="center" iconTextGap="4" modelName="centered" modelPosition="center" preferredPlacement="center_on_edge" ratio="5.0" textColor="#000000" verticalTextPosition="bottom" visible="true" xml:space="preserve">ОружиеЦелевое.ЦельВошлаВЗонуАтаки/
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" placement="center" side="on_edge" sideReference="relative_to_edge_flow" /></y:EdgeLabel>
</y:PolyLineEdge>
</data>
</edge>
<edge source="n0::n2" target="n0::n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0" sy="0" tx="0" ty="0" />
<y:LineStyle color="#000000" type="line" width="1.0" />
<y:Arrows source="none" target="standard" />
<y:EdgeLabel alignment="center" backgroundColor="#F5F5F5" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" horizontalTextPosition="center" iconTextGap="4" modelName="centered" modelPosition="center" preferredPlacement="center_on_edge" ratio="5.0" textColor="#000000" verticalTextPosition="bottom" visible="true" xml:space="preserve">ОружиеЦелевое.ЦельВышлаИзЗоныАтаки/
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" placement="center" side="on_edge" sideReference="relative_to_edge_flow" /></y:EdgeLabel>
</y:PolyLineEdge>
</data>
</edge>
<edge source="" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0" sy="0" tx="0" ty="0" />
<y:LineStyle color="#000000" type="line" width="1.0" />
<y:Arrows source="none" target="standard" />
<y:EdgeLabel alignment="center" backgroundColor="#F5F5F5" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" horizontalTextPosition="center" iconTextGap="4" modelName="centered" modelPosition="center" preferredPlacement="center_on_edge" ratio="5.0" textColor="#000000" verticalTextPosition="bottom" visible="false" xml:space="preserve">
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" placement="center" side="on_edge" sideReference="relative_to_edge_flow" />
</y:EdgeLabel>
</y:PolyLineEdge>
</data>
</edge>
</graph>
</graphml>

5
tests/21-output.txt Normal file
View File

@@ -0,0 +1,5 @@
Initial: {id: 'n1', name: '', geometry: (-1623; 753)}
Composite State: {id: 'n0', name: 'Бой', actions: {a {entry}, a {exit}}, geometry: (-786; 492; 517; 770), elements: {Simple State: {id: 'n0::n1', name: 'Сближение', actions: {a {entry, behavior: 'МодульДвижения.ДвигатьсяКЦели()'}, a {exit}}, geometry: (-2; 153; 413; 208)}, Simple State: {id: 'n0::n2', name: 'Атака', actions: {a {entry, behavior: 'ОружиеЦелевое.АтаковатьЦель()'}, a {exit}}, geometry: (2; -181; 413; 208)}}}
Simple State: {id: 'n0::n1', name: 'Сближение', actions: {a {entry, behavior: 'МодульДвижения.ДвигатьсяКЦели()'}, a {exit}}, geometry: (-2; 153; 413; 208)}
Simple State: {id: 'n0::n2', name: 'Атака', actions: {a {entry, behavior: 'ОружиеЦелевое.АтаковатьЦель()'}, a {exit}}, geometry: (2; -181; 413; 208)}
Simple State: {id: 'n3', name: 'Скан', actions: {a {entry, behavior: 'Сенсор.ПоискВрагаПоДистанции(мин)'}, a {exit, behavior: 'Сенсор.ОстановкаПоиска()'}}, geometry: (-1573; 738; 413; 288)}