001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2012 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar 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     * Sonar 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
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    
021    package org.sonar.squid.api;
022    
023    import java.util.HashSet;
024    import java.util.Set;
025    
026    import org.sonar.graph.Edge;
027    
028    public class SourceCodeEdge implements Edge<SourceCode> {
029    
030      private final SourceCode from;
031      private final SourceCode to;
032      private final SourceCodeEdgeUsage usage;
033      private Set<SourceCodeEdge> rootEdges;
034      private Set<SourceCode> rootFromNodes;
035      private Set<SourceCode> rootToNodes;
036      private final int hashcode;
037      private SourceCodeEdge parent;
038    
039      public SourceCodeEdge(SourceCode from, SourceCode to, SourceCodeEdgeUsage link) {
040        this(from, to, link, null);
041      }
042    
043      public SourceCodeEdge(SourceCode from, SourceCode to, SourceCodeEdgeUsage usage, SourceCodeEdge rootEdge) {
044        this.hashcode = from.hashCode() * 31 + to.hashCode() + usage.hashCode(); //NOSONAR even if this basic algorithm could be improved
045        this.from = from;
046        this.to = to;
047        this.usage = usage;
048        addRootEdge(rootEdge);
049      }
050    
051      public SourceCode getFrom() {
052        return from;
053      }
054    
055      public SourceCode getTo() {
056        return to;
057      }
058    
059      public SourceCodeEdgeUsage getUsage() {
060        return usage;
061      }
062    
063      private boolean noRoots() {
064        return rootEdges == null;
065      }
066    
067      public boolean hasAnEdgeFromRootNode(SourceCode rootFromNode) {
068        if (noRoots()) {
069          return false;
070        }
071        return rootFromNodes.contains(rootFromNode);
072      }
073    
074      public boolean hasAnEdgeToRootNode(SourceCode rootToNode) {
075        if (noRoots()) {
076          return false;
077        }
078        return rootToNodes.contains(rootToNode);
079      }
080    
081      public Set<SourceCodeEdge> getRootEdges() {
082        return rootEdges;
083      }
084    
085      public int getNumberOfRootFromNodes() {
086        if (noRoots()) {
087          return 0;
088        }
089        return rootFromNodes.size();
090      }
091    
092      public final void addRootEdge(SourceCodeEdge rootRelationShip) {
093        if (noRoots()) {
094          rootEdges = new HashSet<SourceCodeEdge>();
095          rootFromNodes = new HashSet<SourceCode>();
096          rootToNodes = new HashSet<SourceCode>();
097        }
098        if (rootRelationShip != null) {
099          rootEdges.add(rootRelationShip);
100          rootFromNodes.add(rootRelationShip.getFrom());
101          rootToNodes.add(rootRelationShip.getTo());
102          rootRelationShip.setParent(this);
103        }
104      }
105    
106      public int getWeight() {
107        if (noRoots()) {
108          return 0;
109        }
110        return rootEdges.size();
111      }
112    
113      public SourceCodeEdge getParent() {
114        return parent;
115      }
116    
117      public SourceCodeEdge setParent(SourceCodeEdge parent) {
118        this.parent = parent;
119        return this;
120      }
121    
122      @Override
123      public boolean equals(Object obj) {
124        if ( !(obj instanceof SourceCodeEdge) || this.hashCode() != obj.hashCode()) {
125          return false;
126        }
127        SourceCodeEdge edge = (SourceCodeEdge) obj;
128        return from.equals(edge.from) && to.equals(edge.to);
129      }
130    
131      @Override
132      public int hashCode() {
133        return hashcode;
134      }
135    
136      @Override
137      public String toString() {
138        return "from : " + from + ", to : " + to;
139      }
140    }