<commit_before>// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var Registry = RegistryModule($);

var Modal = ModalModule($, ko);

var Node = NodeModule($, IdGeneratorTable, NodeFields);

var SubworkflowNode = NodeModule($, IdGeneratorTable, NodeFields);
$.extend(SubworkflowNode.prototype, Node.prototype, {
  'initialize': function(workflow, model, registry) {
    var self = this;

    if (self.sub_workflow()) {
      self.sub_workflow(self.sub_workflow().toString());
    }
  }
});

var StartNode = NodeModule($, IdGeneratorTable, NodeFields);
$.extend(StartNode.prototype, Node.prototype, {
  /**
   * Same as addChild for nodes, except if we reach the end,
   * we add the end node to our child_links in the form of a
   * 'related' link and 'start' link.
   * We should always have a start link in an empty workflow!
   */
  replaceChild: function(child, replacement) {
    var self = this;
    var index = -1;

    $.each(self.non_error_links(), function(i, link) {
      if (link.child() == child.id()) {
        index = i;
      }
    });

    if (index > -1) {
      self.child_links.splice(index, 1);
      var links = self.child_links.splice(index);
      var link = {
        parent: ko.observable(self.id()),
        child: ko.observable(replacement.id()),
        name: ko.observable('to'),
        comment: ko.observable('')
      };
      self.child_links.push(link);

      $.each(links, function(index, link) {
        self.child_links.push(link);
      });
    }

    return index != -1;
  }
});

var ForkNode = NodeModule($, IdGeneratorTable, NodeFields);
$.extend(ForkNode.prototype, Node.prototype, {
  // Join nodes are connected through 'related' links
  join: function() {
    var self = this;

    var join = null;
    $.each(self.child_links(), function(index, link) {
      if (link.name() == 'related') {
        join = self.registry.get(link.child());
      }
    });
    return join;
  },

  /**
   * Append a node to the current fork
   * Also adds join node to node.
   * When adding the join node, append will remove all the children from the join!
   * We need to make sure the join remembers its children since append will replace them.
   * NOTE: Cannot append a fork or decision! Use addChild or replaceChild instead!
   */
  append: function(node) {
    var self = this;

    if (node.node_type() != 'decision' && node.node_type() != 'fork') {
      var join = self.join();
      if (join.id() != node.id()) {
        var children = join.findChildren();

        self.addChild(node);
        node.append(join);

        // remember children
        $.each(children, function(index, child) {
          join.addChild(child);
        });
      }
    }
  },

  /**
   * Replace child node with another node
   * 1. Remove child if the replacement is related join
   * 2. Apply Node.replaceChild for all other causes
   * NOTE: can assume the only join this fork will ever see is the related join!
   * This is because the related will always be the closest join for children.
   * Also, the operations allowed that would make this all possible: detach, append;
   * are inherently going to remove any other joins if they exist.
   * This is also easier given nodes are contained within Forks!
   */
  replaceChild: function(child, replacement) {
    var self = this;

    var ret = true;
    if (self.join().id() == replacement.id()) {
      ret = self.removeChild(child);
    } else {
      ret = Node.prototype.replaceChild.apply(self, arguments);
    }

    var links = self.links().filter(function(element, index, arr) {
      return self.registry.get(element.child()).node_type() != 'join';
    });

    if (links.length < 2) {
      self.detach();
      self.join().detach();

      self.erase();
      self.join().erase();
    }

    return ret;
  },

  /**
   * Converts fork node into decision node in the following way:
   * 1. Copies contents of current fork node into a new decision node
   * 2. Detach fork node
   * 3. Erase fork node
   * 4. Append decision node to parent
   */
  convertToDecision: function() {
    var self = this;

    var join = self.join();
    var end = null;
    var child = join.findChildren()[0];

    // Replace join with decision end
    var decision_end_model = new NodeModel({
      id: IdGeneratorTable['decisionend'].nextId(),
      node_type: 'decisionend',
      workflow: self.workflow(),
      child_links: ko.mapping.toJS(join.child_links())
    });
    $.each(decision_end_model.child_links, function(index, link) {
      link.parent = decision_end_model.id;
    });
    var decision_end_node = new Node(self._workflow, decision_end_model, self.registry);
    var parents = join.findParents();
    $.each(parents, function(index, parent) {
      parent.replaceChild(join, decision_end_node);
    });

    // Replace fork with decision node
    var decision_model = new DecisionModel({
      id: IdGeneratorTable['decision'].nextId(),
      name: self.name(),
      description: self.description(),
      node_type: 'decision',
      workflow: self.workflow(),
      child_links: self.model.child_links
    });
    var default_link = {
      parent: decision_model.id,
      child: self._workflow.end(),
      name: 'default',
      comment: ''
    };

    decision_model.child_links.push(default_link);

    $.each(decision_model.child_links, function(index, link) {
      link.parent = decision_model.id;
    });

    var parents = self.findParents();
    var decision_node = new DecisionNode(self._workflow, decision_model, self.registry);
    decision_node.removeChild(join);
    decision_node.addChild(decision_end_node);

    $.each(parents, function(index, parent) {
      parent.replaceChild(self, decision_node);
    });

    // Get rid of fork and join in registry
    join.erase();
    self.erase();
<commit_msg>HUE-1943 [oozie] Convert to descision node can lose all the nodes<commit_after>// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var Registry = RegistryModule($);

var Modal = ModalModule($, ko);

var Node = NodeModule($, IdGeneratorTable, NodeFields);

var SubworkflowNode = NodeModule($, IdGeneratorTable, NodeFields);
$.extend(SubworkflowNode.prototype, Node.prototype, {
  'initialize': function(workflow, model, registry) {
    var self = this;

    if (self.sub_workflow()) {
      self.sub_workflow(self.sub_workflow().toString());
    }
  }
});

var StartNode = NodeModule($, IdGeneratorTable, NodeFields);
$.extend(StartNode.prototype, Node.prototype, {
  /**
   * Same as addChild for nodes, except if we reach the end,
   * we add the end node to our child_links in the form of a
   * 'related' link and 'start' link.
   * We should always have a start link in an empty workflow!
   */
  replaceChild: function(child, replacement) {
    var self = this;
    var index = -1;

    $.each(self.non_error_links(), function(i, link) {
      if (link.child() == child.id()) {
        index = i;
      }
    });

    if (index > -1) {
      self.child_links.splice(index, 1);
      var links = self.child_links.splice(index);
      var link = {
        parent: ko.observable(self.id()),
        child: ko.observable(replacement.id()),
        name: ko.observable('to'),
        comment: ko.observable('')
      };
      self.child_links.push(link);

      $.each(links, function(index, link) {
        self.child_links.push(link);
      });
    }

    return index != -1;
  }
});

var ForkNode = NodeModule($, IdGeneratorTable, NodeFields);
$.extend(ForkNode.prototype, Node.prototype, {
  // Join nodes are connected through 'related' links
  join: function() {
    var self = this;

    var join = null;
    $.each(self.child_links(), function(index, link) {
      if (link.name() == 'related') {
        join = self.registry.get(link.child());
      }
    });
    return join;
  },

  /**
   * Append a node to the current fork
   * Also adds join node to node.
   * When adding the join node, append will remove all the children from the join!
   * We need to make sure the join remembers its children since append will replace them.
   * NOTE: Cannot append a fork or decision! Use addChild or replaceChild instead!
   */
  append: function(node) {
    var self = this;

    if (node.node_type() != 'decision' && node.node_type() != 'fork') {
      var join = self.join();
      if (join.id() != node.id()) {
        var children = join.findChildren();

        self.addChild(node);
        node.append(join);

        // remember children
        $.each(children, function(index, child) {
          join.addChild(child);
        });
      }
    }
  },

  /**
   * Replace child node with another node
   * 1. Remove child if the replacement is related join
   * 2. Apply Node.replaceChild for all other causes
   * NOTE: can assume the only join this fork will ever see is the related join!
   * This is because the related will always be the closest join for children.
   * Also, the operations allowed that would make this all possible: detach, append;
   * are inherently going to remove any other joins if they exist.
   * This is also easier given nodes are contained within Forks!
   */
  replaceChild: function(child, replacement) {
    var self = this;

    var ret = true;
    if (self.join().id() == replacement.id()) {
      ret = self.removeChild(child);
    } else {
      ret = Node.prototype.replaceChild.apply(self, arguments);
    }

    var links = self.links().filter(function(element, index, arr) {
      return self.registry.get(element.child()).node_type() != 'join';
    });

    if (links.length < 2) {
      self.detach();
      self.join().detach();

      self.erase();
      self.join().erase();
    }

    return ret;
  },

  /**
   * Converts fork node into decision node in the following way:
   * 1. Copies contents of current fork node into a new decision node
   * 2. Detach fork node
   * 3. Erase fork node
   * 4. Append decision node to parent
   */
  convertToDecision: function() {
    var self = this;

    var join = self.join();
    var end = null;
    var child = join.findChildren()[0];

    // Replace join with decision end
    var decision_end_model = new NodeModel({
      id: IdGeneratorTable['decisionend'].nextId(),
      node_type: 'decisionend',
      workflow: self.workflow(),
      child_links: ko.mapping.toJS(join.child_links())
    });
    $.each(decision_end_model.child_links, function(index, link) {
      link.parent = decision_end_model.id;
    });
    var decision_end_node = new Node(self._workflow, decision_end_model, self.registry);
    var parents = join.findParents();
    $.each(parents, function(index, parent) {
      parent.replaceChild(join, decision_end_node);
    });

    // Replace fork with decision node
    var decision_model = new DecisionModel({
      id: IdGeneratorTable['decision'].nextId(),
      name: self.name(),
      description: self.description(),
      node_type: 'decision',
      workflow: self.workflow(),
      child_links: ko.mapping.toJS(self.child_links())
    });
    var default_link = {
      parent: decision_model.id,
      child: self._workflow.end(),
      name: 'default',
      comment: ''
    };

    decision_model.child_links.push(default_link);

    $.each(decision_model.child_links, function(index, link) {
      link.parent = decision_model.id;
    });

    var parents = self.findParents();
    var decision_node = new DecisionNode(self._workflow, decision_model, self.registry);
    decision_node.removeChild(join);
    decision_node.addChild(decision_end_node);

    $.each(parents, function(index, parent) {
      parent.replaceChild(self, decision_node);
    });

    // Get rid of fork and join in registry
    join.erase();
    self.erase();

{'fraction_non_alphanumeric': 0.12183820736802127, 'fraction_numerical': 0.002734523357387011, 'mean_word_length': 2.894114167406093, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3081159', 'n_tokens_mistral': 3909, 'n_tokens_neox': 3803, 'n_words': 1228}