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    }