lang-api
[idea/community.git] / platform / lang-api / src / com / intellij / psi / WeighingComparable.java
1 /*
2  * Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
3  * Use is subject to license terms.
4  */
5 package com.intellij.psi;
6
7 import org.jetbrains.annotations.Nullable;
8
9 /**
10  * @author peter
11 */
12 public class WeighingComparable<T,Loc> implements Comparable<WeighingComparable<T,Loc>> {
13   private static final Comparable NULL = new Comparable() {
14     public int compareTo(final Object o) {
15       throw new UnsupportedOperationException("Method compareTo is not yet implemented in " + getClass().getName());
16     }
17   };
18   private Comparable[] myComputedWeighs;
19   private final T myElement;
20   private final Loc myLocation;
21   private final Weigher<T,Loc>[] myWeighers;
22
23   public WeighingComparable(final T element, final Loc location, final Weigher<T,Loc>[] weighers) {
24     myElement = element;
25     myLocation = location;
26     myWeighers = weighers;
27     myComputedWeighs = new Comparable[weighers.length];
28   }
29
30   public int compareTo(final WeighingComparable<T,Loc> comparable) {
31     if (myComputedWeighs == comparable.myComputedWeighs) return 0;
32
33     for (int i = 0; i < myComputedWeighs.length; i++) {
34       final Comparable weight1 = getWeight(i);
35       final Comparable weight2 = comparable.getWeight(i);
36       if (weight1 == null ^ weight2 == null) {
37         return weight1 == null ? -1 : 1;
38       }
39
40       if (weight1 != null) {
41         final int result = weight1.compareTo(weight2);
42         if (result != 0) return result;
43       }
44     }
45     myComputedWeighs = comparable.myComputedWeighs;
46     return 0;
47   }
48
49   @Nullable
50   private Comparable getWeight(final int index) {
51     Comparable weight = myComputedWeighs[index];
52     if (weight == null) {
53       weight = myWeighers[index].weigh(myElement, myLocation);
54       if (weight == null) weight = NULL;
55       myComputedWeighs[index] = weight;
56     }
57     return weight == NULL ? null : weight;
58   }
59
60   public String toString() {
61     final StringBuilder builder = new StringBuilder("[");
62     for (int i = 0; i < myComputedWeighs.length; i++) {
63       if (i != 0) builder.append(", ");
64       builder.append(myWeighers[i]);
65       builder.append("=");
66       builder.append(getWeight(i));
67     }
68     return builder.append("]").toString();
69   }
70 }