001 /*
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 *
006 * http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * Unless required by applicable law or agreed to in writing, software
009 * distributed under the License is distributed on an "AS IS" BASIS,
010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011 * See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014 package org.apache.commons.classscan.util;
015
016 import java.lang.reflect.Array;
017 import java.util.Arrays;
018 import java.util.Collection;
019 import java.util.Comparator;
020
021 import org.apache.commons.classscan.HasName;
022 import org.apache.commons.classscan.spi.model.HasResolve;
023
024 public class NameSet<V extends HasName & HasResolve> extends ResolveSet<V> {
025
026 private final static Comparator<HasName> REVERSE_COMPARE = new Comparator<HasName>() {
027 @Override
028 public int compare(HasName l, HasName r) {
029 String left = l.getName();
030 String right = r.getName();
031
032 // "quick" compare
033 int diff = left.length() - right.length();
034 if (diff != 0) {
035 return diff;
036 }
037 // compare from end of strings - the names probably have long equivalent prefixes
038 for (int i = left.length(); --i > 0;) {
039 int d = left.charAt(i) - right.charAt(i);
040 if (d != 0) {
041 return d;
042 }
043 }
044 return 0;
045 }
046 };
047
048 public NameSet(V[] values) {
049 super(values);
050 if(values!=null && values.length>0) {
051 Arrays.sort(values, REVERSE_COMPARE);
052 }
053 }
054
055 public NameSet(Class<V> clss, Collection<? extends V> workValues) {
056 this(collectionToArray(clss, workValues));
057 }
058
059 private static <D extends HasName> D[] collectionToArray(Class<D> collectionType, Collection<? extends D> workValues) {
060 if(workValues.isEmpty()) {
061 return null;
062 }
063 @SuppressWarnings("unchecked")
064 D[] newInstance = (D[]) Array.newInstance(collectionType, workValues.size());
065 return workValues.toArray(newInstance);
066 }
067
068 public V getValue(final String name) {
069 int idx= Arrays.binarySearch(values, new HasName() {
070 @Override
071 public String getName() {
072 return name;
073 }
074 }, REVERSE_COMPARE);
075 return idx<0 ? null : values[idx];
076 }
077
078 private static interface NameResolve extends HasName, HasResolve {};
079 private static NameSet<NameResolve> EMPTY_SET = new NameSet<NameResolve>(new NameResolve[0]);
080
081 public static <V extends HasName & HasResolve> NameSet<V> emptyNameSet() {
082 NameSet<?> qrc = (NameSet<?>) EMPTY_SET;
083 @SuppressWarnings("unchecked")
084 NameSet<V> rc = (NameSet<V>) qrc;
085 return rc;
086 }
087 }