View Javadoc
1   package org.kuali.common.util.metainf.model;
2   
3   import com.google.common.collect.ImmutableList;
4   import com.google.common.collect.Ordering;
5   import org.apache.commons.lang3.EnumUtils;
6   import org.apache.commons.lang3.StringUtils;
7   import org.kuali.common.util.metainf.spring.MetaInfDataLocation;
8   import org.kuali.common.util.metainf.spring.MetaInfDataType;
9   import org.springframework.util.CollectionUtils;
10  
11  import java.util.Collections;
12  import java.util.List;
13  
14  /**
15   * <p>
16   * Sort first by the data passed into the configurable comparator, then sort lexicographically by directory structure,
17   * then filename
18   * </p>
19   *
20   * For example:
21   *
22   * <pre>
23   *   2 - server/demo/a/foo2.txt         1 - client/bootstrap/a/foo1.txt
24   *   3 - server/demo/a/b/foo.txt        2 - server/demo/a/foo2.txt
25   *   1 - client/bootstrap/a/foo1.txt    3 - server/demo/a/b/foo.txt
26   * </pre>
27   *
28   */
29  public class ConfigurablePathComparator extends PathComparator {
30  
31      private List<String> qualifierOrder = Collections.emptyList();
32      private List<MetaInfDataLocation> locationOrder = Collections.emptyList();
33      private List<MetaInfDataType> typeOrder = Collections.emptyList();
34  
35      @Override
36      protected int compare(int index, String[] tokens1, String[] tokens2) {
37          String string1 = tokens1[index];
38          String string2 = tokens2[index];
39  
40          if (!CollectionUtils.isEmpty(qualifierOrder)) {
41              if (qualifierOrder.contains(string1) && qualifierOrder.contains(string2)) {
42                  int compare = Ordering.explicit(qualifierOrder).compare(string1, string2);
43  
44                  // If the comparison comes back as anything but zero, we are done
45                  if (compare != 0) {
46                      return compare;
47                  }
48              }
49          }
50  
51          if (!CollectionUtils.isEmpty(locationOrder)) {
52              if (isLocation(string1) && isLocation(string2)) {
53                  MetaInfDataLocation location1 = MetaInfDataLocation.valueOf(StringUtils.upperCase(string1));
54                  MetaInfDataLocation location2 = MetaInfDataLocation.valueOf(StringUtils.upperCase(string2));
55  
56                  int compare = Ordering.explicit(locationOrder).compare(location1, location2);
57  
58                  // If the comparison comes back as anything but zero, we are done
59                  if (compare != 0) {
60                      return compare;
61                  }
62              }
63          }
64  
65          if (!CollectionUtils.isEmpty(typeOrder)) {
66              if (isType(string1) && isType(string2)) {
67                  MetaInfDataType type1 = MetaInfDataType.valueOf(StringUtils.upperCase(string1));
68                  MetaInfDataType type2 = MetaInfDataType.valueOf(StringUtils.upperCase(string2));
69  
70                  int compare = Ordering.explicit(typeOrder).compare(type1, type2);
71  
72                  // If the comparison comes back as anything but zero, we are done
73                  if (compare != 0) {
74                      return compare;
75                  }
76              }
77          }
78  
79          return super.compare(index, tokens1, tokens2);
80      }
81  
82      protected boolean isLocation(String token) {
83          return EnumUtils.isValidEnum(MetaInfDataLocation.class, StringUtils.upperCase(token));
84      }
85  
86      protected boolean isType(String token) {
87          return EnumUtils.isValidEnum(MetaInfDataType.class, StringUtils.upperCase(token));
88      }
89  
90      public static Builder builder() {
91          return new Builder();
92      }
93  
94      public static class Builder {
95  
96          // Optional
97          private List<String> qualifierOrder = Collections.emptyList();
98          private List<MetaInfDataLocation> locationOrder = Collections.emptyList();
99          private List<MetaInfDataType> typeOrder = Collections.emptyList();
100 
101         public Builder qualifierOrder(List<String> qualifierOrder) {
102             this.qualifierOrder = qualifierOrder;
103             return this;
104         }
105 
106         public Builder locationOrder(List<MetaInfDataLocation> locationOrder) {
107             this.locationOrder = locationOrder;
108             return this;
109         }
110 
111         public Builder typeOrder(List<MetaInfDataType> typeOrder) {
112             this.typeOrder = typeOrder;
113             return this;
114         }
115 
116         public ConfigurablePathComparator build() {
117             this.qualifierOrder = ImmutableList.copyOf(qualifierOrder);
118             this.locationOrder = ImmutableList.copyOf(locationOrder);
119             this.typeOrder = ImmutableList.copyOf(typeOrder);
120             return new ConfigurablePathComparator(this);
121         }
122 
123     }
124 
125     private ConfigurablePathComparator(Builder builder) {
126         this.qualifierOrder = builder.qualifierOrder;
127         this.locationOrder = builder.locationOrder;
128         this.typeOrder = builder.typeOrder;
129     }
130 
131 }