archesproject / arches

Arches is a web platform for creating, managing, & visualizing geospatial data. Arches was inspired by the needs of the Cultural Heritage community, particularly the widespread need of organizations to build & manage cultural heritage inventories
GNU Affero General Public License v3.0
212 stars 143 forks source link

Make root nodes of (cloned) graphs editable #3653

Open azaroth42 opened 6 years ago

azaroth42 commented 6 years ago

Is your feature request related to a problem? Please describe.

When cloning a branch, if the root node has related nodes, then the root node's class is not able to be changed. I want to have a baseline branch with (e.g.) Type and label pre-configured on it, then start from there for all of my new branches. Currently I have to start from zero and create the same structure over and over again.

Describe the solution you'd like

Make the class of the root node of a branch with relationships editable :) It should check the ontology to determine which classes are available.

azaroth42 commented 5 years ago

Running into this again, in rebuilding from a new version of CIDOC CRM. For example, I can create a generic activity branch and clone it, but want to be able to then say that the clone is actually a Production or a Destruction or an Acquisition or ...

Limiting to subclasses of the cloned node would be fine, ensuring that the model remains valid without necessarily checking everything.

azaroth42 commented 5 years ago

If you also have this, here's some code to do it offline and reimport...

Export the source branch and make the top node of the new branch and export it. Then run the script below, which will generate new_branch-merged.json. Then just import the -merged file.

import json
import sys
import uuid

input = sys.argv[1]
output = sys.argv[2]

print "Merging %s to %s" % (input, output)

fh = open(input)
data = fh.read()
fh.close()
in_data = json.loads(data)

fh = open(output)
data = fh.read()
fh.close()
out_data = json.loads(data)

# empty out_data
out_graph = out_data['graph'][0]
out_graph['cards'] = []
out_graph['nodegroups'] = []
out_graph['nodes'] = []
out_graph['edges'] = []
out_graph_id = out_graph['graphid']
out_graph_root_id = out_graph['root']['nodeid']

in_graph = in_data['graph'][0]
in_graph_id = in_graph['graphid']
in_graph_root_id = in_graph['root']['nodeid']

in_out_map = {in_graph_id : out_graph_id, in_graph_root_id : out_graph_root_id}

def subst(val):
    if val in in_out_map:
        return in_out_map[val]
    else:
        # mint a new one
        nval = str(uuid.uuid4())
        in_out_map[val] = nval
        return nval

for n in in_graph['nodes']:
    repl = n.copy()
    for p in ['graph_id', 'nodegroup_id', 'nodeid']:
        repl[p] = subst(repl[p])
    out_graph['nodes'].append(repl)

for n in in_graph['nodegroups']:
    repl = n.copy()
    repl['nodegroupid'] = subst(repl['nodegroupid'])
    out_graph['nodegroups'].append(repl)

for c in in_graph['cards']:
    repl = c.copy()
    for p in ['cardid', 'graph_id', 'nodegroup_id']:
        repl[p] = subst(repl[p])
    out_graph['cards'].append(repl)

for e in in_graph['edges']:
    repl = e.copy()
    for p in ['domainnode_id', 'edgeid', 'graph_id', 'rangenode_id']:
        repl[p] = subst(repl[p])
    out_graph['edges'].append(repl)

# Now write out the merged branch

out_data['graph'] = [out_graph]

outfn = output.replace(".json", '-merged.json')
outstr = json.dumps(out_data, indent=2)
fh = open(outfn, 'w')
fh.write(outstr)
fh.close()
azaroth42 commented 4 years ago

Triage: Still valid, with above workaround.