001/*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2013 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube 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 * SonarQube 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<Node>();
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  public int compareTo(final Node other) {
088    int orderInd = 0;
089
090    if (order < other.order) {
091      orderInd = -1;
092    } else if (order > other.order) {
093      orderInd = 1;
094    }
095
096    return orderInd;
097  }
098
099  @Override
100  public String toString() {
101    return object.toString();
102  }
103
104  @Override
105  public boolean equals(Object o) {
106    if (this == o) {
107      return true;
108    }
109    if (!(o instanceof Node)) {
110      return false;
111    }
112    return object.equals(((Node) o).getObject());
113  }
114
115  @Override
116  public int hashCode() {
117    return object.hashCode();
118  }
119}
120