001/*
002 * SonarQube
003 * Copyright (C) 2009-2017 SonarSource SA
004 * mailto:info AT sonarsource DOT com
005 *
006 * This program is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019 */
020package org.sonar.api.utils.dag;
021
022import org.sonar.api.utils.SonarException;
023
024import java.util.ArrayList;
025import java.util.List;
026
027/**
028 * @since 1.10
029 */
030public class Node implements Comparable<Node> {
031
032  private final Object object;
033  private int order = 0;
034  private boolean seen = false;
035  private final List<Node> dependencies = new ArrayList<>();
036
037  public Node(final Object object) {
038    if (object == null) {
039      throw new SonarException("object can not be null");
040    }
041    this.object = object;
042  }
043
044  public void reset() {
045    order = 0;
046    seen = false;
047  }
048
049  public Object getObject() {
050    return object;
051  }
052
053  public void addDependency(Node v) {
054    if (!equals(v) && !dependencies.contains(v)) {
055      dependencies.add(v);
056    }
057  }
058
059  public void resolveOrder() {
060    resolveOrder(toString());
061  }
062
063  private int resolveOrder(String path) {
064    seen = true;
065    try {
066      int highOrder = -1;
067      for (Node dep : dependencies) {
068        if (dep.seen) {
069          throw new CyclicDependenciesException(path + " -> " + dep.toString());
070        }
071        highOrder = Math.max(highOrder, dep.resolveOrder(path + " -> " + dep.toString()));
072
073      }
074
075      order = highOrder + 1;
076      return order;
077
078    } finally {
079      seen = false;
080    }
081  }
082
083  public List<Node> getDependencies() {
084    return dependencies;
085  }
086
087  @Override
088  public int compareTo(final Node other) {
089    int orderInd = 0;
090
091    if (order < other.order) {
092      orderInd = -1;
093    } else if (order > other.order) {
094      orderInd = 1;
095    }
096
097    return orderInd;
098  }
099
100  @Override
101  public String toString() {
102    return object.toString();
103  }
104
105  @Override
106  public boolean equals(Object o) {
107    if (this == o) {
108      return true;
109    }
110    if (!(o instanceof Node)) {
111      return false;
112    }
113    return object.equals(((Node) o).getObject());
114  }
115
116  @Override
117  public int hashCode() {
118    return object.hashCode();
119  }
120}
121