Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
aeva
graph
Commits
fc7d5387
Commit
fc7d5387
authored
Mar 24, 2022
by
David Thompson
Browse files
WIP: Broken progress on Read.
parent
4ad6c3d8
Changes
6
Hide whitespace changes
Inline
Side-by-side
smtk/markup/Component.cxx
View file @
fc7d5387
...
...
@@ -31,10 +31,11 @@ Component::~Component() = default;
void
Component
::
initialize
(
const
nlohmann
::
json
&
data
,
json
::
Helper
&
helper
)
{
(
void
)
helper
;
std
::
cout
<<
"init comp "
<<
this
<<
" with "
<<
data
.
dump
(
2
)
<<
"
\n
"
;
auto
it
=
data
.
find
(
"name"
);
if
(
it
!=
data
.
end
())
{
m_name
=
it
->
get
<
std
::
string
>
();
this
->
setName
(
it
->
get
<
std
::
string
>
()
)
;
}
}
...
...
smtk/markup/DomainMap.h
View file @
fc7d5387
...
...
@@ -26,8 +26,8 @@ class SMTKMARKUP_EXPORT DomainMap
public:
DomainMap
()
=
default
;
~
DomainMap
()
=
default
;
DomainMap
(
const
DomainMap
&
)
=
de
lete
;
void
operator
=
(
const
DomainMap
&
)
=
de
lete
;
DomainMap
(
const
DomainMap
&
)
=
de
fault
;
DomainMap
&
operator
=
(
const
DomainMap
&
)
=
de
fault
;
/// Return true if the \a space exists in this map.
bool
contains
(
const
smtk
::
string
::
Token
&
space
)
const
;
...
...
smtk/markup/Resource.h
View file @
fc7d5387
...
...
@@ -14,6 +14,8 @@
#include
"smtk/markup/Exports.h"
#include
"nlohmann/json.hpp"
namespace
smtk
{
/// Markup resource
...
...
@@ -49,10 +51,10 @@ public:
virtual
~
Resource
()
=
default
;
// Wrap this method (instead of create()) to avoid name conflict in MSVC.
template
<
typename
componentT
>
smtk
::
shared_ptr
<
componentT
>
createNode
()
template
<
typename
componentT
,
typename
...
Args
>
smtk
::
shared_ptr
<
componentT
>
createNode
(
Args
&&
...
args
)
{
return
GraphResource
::
create
<
componentT
>
();
return
GraphResource
::
create
<
componentT
>
(
std
::
forward
<
Args
>
(
args
)...
);
}
/// Return a boolean functor that classifies components according to \a query.
...
...
@@ -79,6 +81,7 @@ public:
protected:
friend
class
Component
;
friend
void
from_json
(
const
nlohmann
::
json
&
j
,
Ptr
&
resource
);
Resource
(
const
smtk
::
common
::
UUID
&
,
smtk
::
resource
::
Manager
::
Ptr
manager
=
nullptr
);
Resource
(
smtk
::
resource
::
Manager
::
Ptr
manager
=
nullptr
);
...
...
smtk/markup/json/jsonResource.cxx
View file @
fc7d5387
...
...
@@ -17,45 +17,7 @@
#include
"smtk/string/json/jsonManager.h"
#include
"smtk/string/json/jsonToken.h"
#if 0
namespace nlohmann
{
template<typename Src, typename Dst, typename ArcType>
struct adl_serializer<smtk::graph::Arcs<Src, Dst, ArcType>>
{
static smtk::graph::Arcs<Src, Dst, ArcType> from_json(const json& j)
{
auto resource = smtk::markup::json::Helper::instance().resource();
auto fromNode = std::dynamic_pointer_cast<Src>(
resource->find(j.at("from").get<smtk::common::UUID>()));
smtk::graph::Arcs<Src, Dst, ArcType> result(fromNode);
for (const auto& jTo : j.at("to"))
{
auto toNode = std::dynamic_pointer_cast<Dst>(resource->find(jTo.get<smtk::common::UUID>()));
if (toNode)
{
result.to().insert(toNode);
}
}
return result;
}
static void to_json(json& j, const smtk::graph::Arcs<Src, Dst, ArcType>& arcs)
{
j["from"] = arcs.from().id();
std::vector<smtk::common::UUID> toIds;
toIds.reserve(arcs.to().size());
for (const auto& to : arcs.to())
{
toIds.push_back(to);
}
j["to"] = toIds;
}
};
} // namespace nlohmann
#endif
using
ArcMap
=
smtk
::
graph
::
ArcMap
;
namespace
smtk
{
...
...
@@ -80,6 +42,130 @@ void to_json(nlohmann::json& j, const smtk::graph::Arcs<Src, Dst, ArcType>& arcs
}
}
template
<
typename
Src
,
typename
Dst
,
typename
ArcType
>
void
from_json
(
const
nlohmann
::
json
&
j
,
smtk
::
graph
::
Arc
<
Src
,
Dst
,
ArcType
>&
arc
)
{
auto
resource
=
json
::
Helper
::
instance
().
resource
();
auto
from
=
std
::
dynamic_pointer_cast
<
Src
>
(
resource
->
find
(
j
.
at
(
"from"
).
get
<
smtk
::
common
::
UUID
>
()));
auto
to
=
std
::
dynamic_pointer_cast
<
Dst
>
(
resource
->
find
(
j
.
at
(
"to"
).
get
<
smtk
::
common
::
UUID
>
()));
arc
=
ArcType
(
from
,
to
);
}
template
<
typename
Src
,
typename
Dst
,
typename
ArcType
>
void
from_json
(
const
nlohmann
::
json
&
j
,
smtk
::
graph
::
Arcs
<
Src
,
Dst
,
ArcType
>&
arcs
)
{
auto
resource
=
json
::
Helper
::
instance
().
resource
();
auto
from
=
std
::
dynamic_pointer_cast
<
Src
>
(
resource
->
find
(
j
.
at
(
"from"
).
get
<
smtk
::
common
::
UUID
>
()));
arcs
=
ArcType
(
from
);
for
(
const
auto
&
jto
:
j
.
at
(
"to"
))
{
auto
to
=
std
::
dynamic_pointer_cast
<
Dst
>
(
resource
->
find
(
jto
.
get
<
smtk
::
common
::
UUID
>
()));
arcs
.
insert
(
to
);
}
}
template
<
typename
Src
,
typename
Dst
,
typename
ArcType
>
void
from_json
(
const
nlohmann
::
json
&
j
,
smtk
::
graph
::
OrderedArcs
<
Src
,
Dst
,
ArcType
>&
arcs
)
{
auto
resource
=
json
::
Helper
::
instance
().
resource
();
auto
from
=
std
::
dynamic_pointer_cast
<
Src
>
(
resource
->
find
(
j
.
at
(
"from"
).
get
<
smtk
::
common
::
UUID
>
()));
arcs
=
ArcType
(
from
);
const
auto
&
jAllTo
=
j
.
at
(
"to"
);
arcs
.
to
().
reserve
(
jAllTo
.
size
());
for
(
const
auto
&
jto
:
jAllTo
)
{
auto
to
=
std
::
dynamic_pointer_cast
<
Dst
>
(
resource
->
find
(
jto
.
get
<
smtk
::
common
::
UUID
>
()));
arcs
.
insert
(
to
);
}
}
template
<
std
::
size_t
I
,
typename
Tuple
,
typename
ResourceType
>
inline
typename
std
::
enable_if
<
I
!=
std
::
tuple_size
<
Tuple
>::
value
,
void
>::
type
deserializeArcsOfType
(
const
nlohmann
::
json
&
jj
,
const
std
::
shared_ptr
<
ResourceType
>&
resource
,
ArcMap
&
arcMap
)
{
using
ArcType
=
typename
std
::
tuple_element
<
I
,
Tuple
>::
type
;
auto
arcType
=
smtk
::
common
::
typeName
<
ArcType
>
();
auto
it
=
jj
.
find
(
arcType
);
if
(
it
!=
jj
.
end
())
{
/*
if (!resource->arcs().template contains<ArcType>(arcType))
{
// FIXME: URHERE Cannot construct ArcType without a from node? But I want to insert a TypeMapEntry<UUID, ArcType>?
resource->arcs().template insert<ArcType>(arcType, ArcType{});
}
auto& arcEntry(resource->arcs().template get<ArcType>());
*/
std
::
vector
<
smtk
::
WeakReferenceWrapper
<
typename
ArcType
::
ToType
>>
toNodes
;
for
(
const
auto
jarc
:
*
it
)
{
toNodes
.
clear
();
smtk
::
common
::
UUID
fromId
=
jarc
.
at
(
"from"
).
template
get
<
smtk
::
common
::
UUID
>();
auto
fromNode
=
std
::
dynamic_pointer_cast
<
typename
ArcType
::
FromType
>
(
resource
->
find
(
fromId
));
if
(
fromNode
)
{
toNodes
.
reserve
(
jarc
.
size
());
for
(
const
auto
jto
:
jarc
.
at
(
"to"
))
{
smtk
::
common
::
UUID
toId
=
jto
;
auto
toNode
=
std
::
dynamic_pointer_cast
<
typename
ArcType
::
ToType
>
(
resource
->
find
(
toId
));
if
(
toNode
)
{
std
::
weak_ptr
<
typename
ArcType
::
ToType
>
weakRef
(
toNode
);
toNodes
.
push_back
(
weakRef
);
}
}
fromNode
->
template
set
<
ArcType
>(
toNodes
.
begin
(),
toNodes
.
end
());
// std::cout << "Extract arc of type " << arcType << " from " << fromId << "\n";
// ArcType value(fromId);
// from_json(jarc, value);
// arcEntry.emplace(value.from(), value);
}
else
{
smtkErrorMacro
(
smtk
::
io
::
Logger
::
instance
(),
"Could not find node "
<<
fromId
<<
". Skipping."
);
}
}
}
// Now process the next entry in the tuple:
deserializeArcsOfType
<
I
+
1
,
Tuple
>
(
jj
,
resource
,
arcMap
);
}
template
<
std
::
size_t
I
,
typename
Tuple
,
typename
ResourceType
>
inline
typename
std
::
enable_if
<
I
==
std
::
tuple_size
<
Tuple
>::
value
,
void
>::
type
deserializeArcsOfType
(
const
nlohmann
::
json
&
jj
,
const
std
::
shared_ptr
<
ResourceType
>&
resource
,
ArcMap
&
arcMap
)
{
(
void
)
jj
;
(
void
)
resource
;
(
void
)
arcMap
;
}
template
<
typename
ResourceType
>
void
deserializeArcs
(
const
nlohmann
::
json
&
jj
,
const
std
::
shared_ptr
<
ResourceType
>&
resource
,
ArcMap
&
arcMap
)
{
deserializeArcsOfType
<
0
,
typename
ResourceType
::
TypeTraits
::
ArcTypes
>
(
jj
,
resource
,
arcMap
);
}
void
from_json
(
const
nlohmann
::
json
&
jj
,
ArcMap
&
arcMap
)
{
// Erase all pre-existing arcs
arcMap
.
data
().
clear
();
// Keep track of visited arc types. At the end, we'll signal an error if there
// were arc types present in the JSON that this resource's traits do not handle.
std
::
set
<
std
::
string
>
visitedArcTypes
;
auto
resource
=
json
::
Helper
::
instance
().
resource
();
deserializeArcs
(
jj
,
resource
,
arcMap
);
}
template
<
std
::
size_t
I
,
typename
Tuple
,
typename
ResourceType
>
inline
typename
std
::
enable_if
<
I
!=
std
::
tuple_size
<
Tuple
>::
value
,
void
>::
type
serializeArcsOfType
(
const
std
::
shared_ptr
<
ResourceType
>&
resource
,
nlohmann
::
json
&
arcs
)
...
...
@@ -164,20 +250,35 @@ void to_json(nlohmann::json& j, const smtk::markup::Resource::Ptr& resource)
void
from_json
(
const
nlohmann
::
json
&
j
,
smtk
::
markup
::
Resource
::
Ptr
&
resource
)
{
if
(
!
resource
)
{
resource
=
smtk
::
markup
::
Resource
::
create
();
}
auto
tmp
=
std
::
static_pointer_cast
<
smtk
::
resource
::
Resource
>
(
resource
);
smtk
::
resource
::
from_json
(
j
,
tmp
);
// resource->m_domains = j.at("domains")
// resource->arcs() = j.at("arcs");
// Insert nodes, then initialize them (so they can freely assume
// other nodes are present when configuring themselves).
resource
->
m_domains
=
j
.
at
(
"domains"
);
// I. Insert nodes. Initialize them later (so they can freely
// assume other nodes are present when configuring themselves).
for
(
const
auto
&
jnode
:
j
.
at
(
"nodes"
))
{
auto
node
=
resource
->
nodeFactory
().
makeFromName
(
jnode
.
at
(
"type"
).
get
<
std
::
string
>
(),
resource
,
jnode
.
at
(
"id"
).
get
<
smtk
::
common
::
UUID
>
());
resource
->
add
(
node
);
auto
nodeType
=
jnode
.
at
(
"type"
).
get
<
std
::
string
>
();
auto
nodeId
=
jnode
.
at
(
"id"
).
get
<
smtk
::
common
::
UUID
>
();
// std::cout << " Create " << nodeType << " " << (smtk::markup::Resource::nodeFactory().contains(nodeType) ? "Y" : "N") << "\n";
auto
node
=
smtk
::
markup
::
Resource
::
nodeFactory
().
makeFromName
(
nodeType
,
resource
,
nodeId
);
std
::
cout
<<
"Create "
<<
nodeType
<<
" id "
<<
nodeId
<<
" "
<<
node
<<
"
\n
"
;
if
(
node
)
{
resource
->
add
(
node
);
}
}
// II. Insert arcs. Arcs should be added before initializing nodes.
smtk
::
markup
::
from_json
(
j
.
at
(
"arcs"
),
resource
->
arcs
());
// III. Initialize nodes.
// Initializers can assume that other nodes in the resource exist
// and that arcs are in a valid state (making it possible to
// find pointers to relevant nodes by following arcs).
auto
&
helper
=
json
::
Helper
::
instance
();
for
(
const
auto
&
jnode
:
j
.
at
(
"nodes"
))
{
...
...
smtk/markup/operators/Read.cxx
View file @
fc7d5387
...
...
@@ -74,15 +74,13 @@ Read::Result Read::operateInternal()
resource
->
setLocation
(
filename
);
// Deserialize resource from a set of JSON records:
json
::
Helper
::
pushInstance
(
resource
);
resource
=
jj
;
/*
smtk::common::UUID resourceId = j.at("id").get<smtk::common::UUID>();
resource->setId(resourceId);
*/
smtk
::
markup
::
from_json
(
jj
,
resource
);
// std::string fileDirectory = smtk::common::Paths::directory(rsrc->location()) + "/";
return
this
->
createResult
(
smtk
::
operation
::
Operation
::
Outcome
::
SUCCEEDED
);
auto
result
=
this
->
createResult
(
smtk
::
operation
::
Operation
::
Outcome
::
SUCCEEDED
);
result
->
findResource
(
"resource"
)
->
appendValue
(
resource
);
return
result
;
}
const
char
*
Read
::
xmlDescription
()
const
...
...
@@ -90,15 +88,22 @@ const char* Read::xmlDescription() const
return
Read_xml
;
}
void
Read
::
markModifiedResources
(
Read
::
Result
&
/*unused*/
)
void
Read
::
markModifiedResources
(
Read
::
Result
&
result
)
{
auto
resourceItem
=
this
->
parameters
()
->
associations
(
);
for
(
auto
rit
=
resourceItem
->
begin
();
rit
!=
resourceItem
->
end
();
++
rit
)
auto
resourceItem
=
result
->
findResource
(
"resource"
);
for
(
std
::
size_t
ii
=
0
;
ii
<
resourceItem
->
numberOfValues
();
++
ii
)
{
auto
resource
=
std
::
dynamic_pointer_cast
<
smtk
::
resource
::
Resource
>
(
*
rit
);
if
(
!
resourceItem
->
isSet
(
ii
))
{
continue
;
}
auto
resource
=
std
::
dynamic_pointer_cast
<
smtk
::
markup
::
Resource
>
(
resourceItem
->
value
(
ii
));
// Set the resource as unmodified from its persistent (i.e. on-disk) state
resource
->
setClean
(
true
);
if
(
resource
)
{
resource
->
setClean
(
true
);
}
}
}
...
...
smtk/markup/testing/cxx/TestResource.cxx
View file @
fc7d5387
...
...
@@ -2,29 +2,70 @@
#include
"smtk/markup/Component.h"
#include
"smtk/markup/Label.h"
#include
"smtk/markup/Group.h"
#include
"smtk/markup/Registrar.h"
#include
"smtk/markup/Resource.h"
#include
"smtk/markup/operators/Read.h"
#include
"smtk/markup/operators/Write.h"
#include
"smtk/plugin/Registry.h"
#include
"smtk/operation/Manager.h"
#include
"smtk/attribute/Attribute.h"
#include
"smtk/attribute/FileItem.h"
#include
"smtk/attribute/IntItem.h"
#include
"smtk/attribute/ReferenceItem.h"
#include
"smtk/attribute/ResourceItem.h"
#include
"smtk/resource/Manager.h"
#include
"smtk/common/Managers.h"
#include
"smtk/common/UUID.h"
#include
"smtk/common/testing/cxx/helpers.h"
#include
"nlohmann/json.hpp"
#include
<cstdio>
#include
<iostream>
#include
<sstream>
using
namespace
smtk
::
markup
;
using
namespace
json
;
int
TestResource
(
int
argc
,
char
**
argv
)
namespace
{
smtk
::
common
::
Managers
::
Ptr
testRegistrar
()
{
auto
managers
=
smtk
::
common
::
Managers
::
create
();
auto
resourceManager
=
smtk
::
resource
::
Manager
::
create
();
auto
operationManager
=
smtk
::
operation
::
Manager
::
create
();
managers
->
insert_or_assign
(
resourceManager
);
managers
->
insert_or_assign
(
operationManager
);
auto
markupRegistry
=
smtk
::
plugin
::
addToManagers
<
smtk
::
markup
::
Registrar
>
(
resourceManager
,
operationManager
);
// Register the resource manager to the operation manager (newly created
// resources will be automatically registered to the resource manager).
operationManager
->
registerResourceManager
(
resourceManager
);
return
managers
;
}
std
::
string
testCreateAndWrite
()
{
auto
resource
=
smtk
::
markup
::
Resource
::
create
();
resource
->
setLocation
(
"/tmp/markup.smtk"
);
std
::
ostringstream
filename
;
filename
<<
tmpnam
(
nullptr
)
<<
".smtk"
;
resource
->
setLocation
(
filename
.
str
());
auto
label
=
resource
->
createNode
<
Label
>
();
label
->
setName
(
"foo"
);
auto
group
=
std
::
make_shared
<
Group
>
(
resource
,
smtk
::
common
::
UUID
::
random
());
group
->
setName
(
"barf"
);
resource
->
add
(
group
);
group
->
setName
(
"barf"
);
/*
auto group = resource->createNode<Group>();
group->setName("barf");
...
...
@@ -42,8 +83,13 @@ int TestResource(int argc, char** argv)
nn
=
components
.
size
();
std
::
cout
<<
"Found "
<<
nn
<<
" labels
\n
"
;
// resource->connect<LabelSubject>(*label, *group);
auto
anotherLabel
=
resource
->
createNode
<
Label
>
(
R"({"name": "This is a really long descriptive label with no purpose."})"
_json
);
auto
anotherGroup
=
resource
->
createNode
<
Group
>
(
R"({"name": "baz"})"
_json
);
label
->
get
<
LabelSubject
>
().
insert
(
*
group
);
resource
->
connect
<
LabelSubject
>
(
*
anotherLabel
,
*
anotherGroup
);
// group->get<Labels>().insert(*label);
// Verify that both arcs (Labels and LabelSubject) were created.
...
...
@@ -51,9 +97,60 @@ int TestResource(int argc, char** argv)
test
(
group
->
get
<
Labels
>
().
count
()
==
1
,
"Group has no label or multiple labels."
);
test
(
group
->
get
<
Labels
>
().
to
().
find
(
*
label
)
!=
group
->
get
<
Labels
>
().
to
().
end
(),
"Group does not have label."
);
test
(
anotherLabel
->
get
<
LabelSubject
>
().
to
().
id
()
==
anotherGroup
->
id
(),
"AnotherLabel has no subject."
);
test
(
anotherGroup
->
get
<
Labels
>
().
count
()
==
1
,
"AnotherGroup has no label or multiple labels."
);
test
(
anotherGroup
->
get
<
Labels
>
().
to
().
find
(
*
anotherLabel
)
!=
anotherGroup
->
get
<
Labels
>
().
to
().
end
(),
"AnotherGroup does not have label."
);
std
::
cout
<<
"Writing "
<<
filename
.
str
()
<<
"
\n
"
;
auto
write
=
smtk
::
markup
::
Write
::
create
();
write
->
parameters
()
->
associations
()
->
appendValue
(
resource
);
write
->
operate
();
return
filename
.
str
();
// or resource->location();
}
std
::
string
testReadAndWrite
(
const
std
::
string
&
filename1
)
{
bool
ok
=
true
;
auto
read
=
smtk
::
markup
::
Read
::
create
();
ok
=
read
->
parameters
()
->
findFile
(
"filename"
)
->
setValue
(
filename1
);
test
(
ok
,
"Could not set filename."
);
std
::
cout
<<
"Reading "
<<
read
->
parameters
()
->
findFile
(
"filename"
)
->
value
()
<<
"
\n
"
;
auto
result
=
read
->
operate
();
auto
resource
=
result
->
findResource
(
"resource"
)
->
valueAs
<
smtk
::
markup
::
Resource
>
();
std
::
cout
<<
"Read "
<<
result
->
findInt
(
"outcome"
)
->
value
()
<<
" "
<<
resource
<<
"
\n
"
;
// Rename the file we just read to make room for the second generation copy.
std
::
ostringstream
filename2
;
filename2
<<
tmpnam
(
nullptr
)
<<
".smtk"
;
std
::
cout
<<
"Rename "
<<
filename2
.
str
()
<<
"
\n
"
;
std
::
rename
(
filename1
.
c_str
(),
filename2
.
str
().
c_str
());
// Write our resource back to filename1.
auto
write
=
smtk
::
markup
::
Write
::
create
();
write
->
parameters
()
->
associations
()
->
appendValue
(
resource
);
result
=
write
->
operate
();
std
::
cout
<<
"Wrote "
<<
result
->
findInt
(
"outcome"
)
->
value
()
<<
" "
<<
resource
<<
"
\n
"
;
// std::cout << "Wrote " << resource->location() << "? " << result->findInt("outcome")->value() << "\n";
return
0
;
return
filename2
.
str
();
}
bool
testFileContentsMatch
(
const
std
::
string
&
filename1
,
const
std
::
string
&
filename2
)
{
return
true
;
}
}
// anonymous namespace
int
TestResource
(
int
argc
,
char
**
argv
)
{
auto
managers
=
testRegistrar
();
std
::
string
filename1
=
testCreateAndWrite
();
std
::
string
filename2
=
testReadAndWrite
(
filename1
);
bool
ok
=
testFileContentsMatch
(
filename1
,
filename2
);
return
ok
?
0
:
1
;
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment