001/** 002 * Copyright 2010-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.common.util.metainf.model; 017 018import com.google.common.collect.ImmutableList; 019import com.google.common.collect.Ordering; 020import org.apache.commons.lang3.EnumUtils; 021import org.apache.commons.lang3.StringUtils; 022import org.kuali.common.util.metainf.spring.MetaInfDataLocation; 023import org.kuali.common.util.metainf.spring.MetaInfDataType; 024import org.springframework.util.CollectionUtils; 025 026import java.util.Collections; 027import java.util.List; 028 029/** 030 * <p> 031 * Sort first by the data passed into the configurable comparator, then sort lexicographically by directory structure, 032 * then filename 033 * </p> 034 * 035 * For example: 036 * 037 * <pre> 038 * 2 - server/demo/a/foo2.txt 1 - client/bootstrap/a/foo1.txt 039 * 3 - server/demo/a/b/foo.txt 2 - server/demo/a/foo2.txt 040 * 1 - client/bootstrap/a/foo1.txt 3 - server/demo/a/b/foo.txt 041 * </pre> 042 * 043 */ 044public class ConfigurablePathComparator extends PathComparator { 045 046 private List<String> qualifierOrder = Collections.emptyList(); 047 private List<MetaInfDataLocation> locationOrder = Collections.emptyList(); 048 private List<MetaInfDataType> typeOrder = Collections.emptyList(); 049 050 @Override 051 protected int compare(int index, String[] tokens1, String[] tokens2) { 052 String string1 = tokens1[index]; 053 String string2 = tokens2[index]; 054 055 if (!CollectionUtils.isEmpty(qualifierOrder)) { 056 if (qualifierOrder.contains(string1) && qualifierOrder.contains(string2)) { 057 int compare = Ordering.explicit(qualifierOrder).compare(string1, string2); 058 059 // If the comparison comes back as anything but zero, we are done 060 if (compare != 0) { 061 return compare; 062 } 063 } 064 } 065 066 if (!CollectionUtils.isEmpty(locationOrder)) { 067 if (isLocation(string1) && isLocation(string2)) { 068 MetaInfDataLocation location1 = MetaInfDataLocation.valueOf(StringUtils.upperCase(string1)); 069 MetaInfDataLocation location2 = MetaInfDataLocation.valueOf(StringUtils.upperCase(string2)); 070 071 int compare = Ordering.explicit(locationOrder).compare(location1, location2); 072 073 // If the comparison comes back as anything but zero, we are done 074 if (compare != 0) { 075 return compare; 076 } 077 } 078 } 079 080 if (!CollectionUtils.isEmpty(typeOrder)) { 081 if (isType(string1) && isType(string2)) { 082 MetaInfDataType type1 = MetaInfDataType.valueOf(StringUtils.upperCase(string1)); 083 MetaInfDataType type2 = MetaInfDataType.valueOf(StringUtils.upperCase(string2)); 084 085 int compare = Ordering.explicit(typeOrder).compare(type1, type2); 086 087 // If the comparison comes back as anything but zero, we are done 088 if (compare != 0) { 089 return compare; 090 } 091 } 092 } 093 094 return super.compare(index, tokens1, tokens2); 095 } 096 097 protected boolean isLocation(String token) { 098 return EnumUtils.isValidEnum(MetaInfDataLocation.class, StringUtils.upperCase(token)); 099 } 100 101 protected boolean isType(String token) { 102 return EnumUtils.isValidEnum(MetaInfDataType.class, StringUtils.upperCase(token)); 103 } 104 105 public static Builder builder() { 106 return new Builder(); 107 } 108 109 public static class Builder { 110 111 // Optional 112 private List<String> qualifierOrder = Collections.emptyList(); 113 private List<MetaInfDataLocation> locationOrder = Collections.emptyList(); 114 private List<MetaInfDataType> typeOrder = Collections.emptyList(); 115 116 public Builder qualifierOrder(List<String> qualifierOrder) { 117 this.qualifierOrder = qualifierOrder; 118 return this; 119 } 120 121 public Builder locationOrder(List<MetaInfDataLocation> locationOrder) { 122 this.locationOrder = locationOrder; 123 return this; 124 } 125 126 public Builder typeOrder(List<MetaInfDataType> typeOrder) { 127 this.typeOrder = typeOrder; 128 return this; 129 } 130 131 public ConfigurablePathComparator build() { 132 this.qualifierOrder = ImmutableList.copyOf(qualifierOrder); 133 this.locationOrder = ImmutableList.copyOf(locationOrder); 134 this.typeOrder = ImmutableList.copyOf(typeOrder); 135 return new ConfigurablePathComparator(this); 136 } 137 138 } 139 140 private ConfigurablePathComparator(Builder builder) { 141 this.qualifierOrder = builder.qualifierOrder; 142 this.locationOrder = builder.locationOrder; 143 this.typeOrder = builder.typeOrder; 144 } 145 146}