def _update_workflow_nodes_json(workflow, json_nodes, id_map, user):
  """Ideally would get objects from form validation instead."""
  nodes = []

  for json_node in json_nodes:
    node = get_or_create_node(workflow, json_node, save=False)

    if node.node_type == 'subworkflow':
      try:
        node.sub_workflow = Workflow.objects.get(id=int(json_node['sub_workflow']))
      except __HOLE__:
        # sub_workflow is None
        node.sub_workflow = None
      except Workflow.DoesNotExist:
        raise StructuredException(code="INVALID_REQUEST_ERROR", message=_('Error saving workflow'), data={'errors': 'Chosen subworkflow does not exist.'}, error_code=400)
    elif node.node_type == 'fork' and json_node['node_type'] == 'decision':
      node.save() # Need to save in case database throws error when performing delete.
      node = node.convert_to_decision()
    node.save()

    id_map[str(json_node['id'])] = node.id

    for key in json_node:
      if key == 'data':
        if isinstance(json_node[key], basestring):
          node.data = json_node[key]
        else:
          node.data = json.dumps(json_node[key])
      elif key not in ('node_ptr', 'child_nodes', 'workflow', 'id', 'sub_workflow'):
        setattr(node, key, format_field_value(key, json_node[key]))

    node.workflow = workflow
    node.save()

    # Keep track of nodes in order of received list
    # so that we may iterate over them again in the same order
    # when we handle links
    nodes.append(node)

  # Delete unused nodes from workflow
  old_nodes = Node.objects.filter(workflow=workflow).exclude(id__in=map(lambda x: x.id, nodes))
  for node in old_nodes:
    node.get_full_node().delete()

  return nodes
dataset/ETHPy150Open cloudera/hue/apps/oozie/src/oozie/views/api.py/_update_workflow_nodes_json