/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.isis.core.runtime.services; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedSet; import com.google.common.base.Function; import com.google.common.base.Objects; import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; import com.google.common.collect.Sets; class DeweyOrderUtil { public static final <V> Function<Parsed, Map.Entry<String, V>> toMapEntry() { return new Function<Parsed, Map.Entry<String, V>>() { @Override public Map.Entry<String, V> apply(Parsed input) { return input.toMapEntry(); } }; } private DeweyOrderUtil() {} static <V> List<Map.Entry<String, V>> deweySorted(Map<String, V> map) { Set<Map.Entry<String, V>> set = Sets.newLinkedHashSet(); for (Map.Entry<String, V> entry : map.entrySet()) { set.add(entry); } return deweySorted(set); } static <V> List<Map.Entry<String, V>> deweySorted(Set<Map.Entry<String, V>> keys) { if(keys == null) { throw new IllegalArgumentException("Keys cannot be null"); } final Iterable<Parsed<V>> parsedIter = Iterables.transform(keys, new Function<Map.Entry<String,V>, Parsed<V>>() { @Override public Parsed<V> apply(Map.Entry<String,V> input) { return new Parsed(input); } }); final SortedSet<Parsed<V>> parseds = Sets.newTreeSet(parsedIter); final Iterable<Map.Entry<String, V>> transform = Iterables.transform(parseds, DeweyOrderUtil.<V>toMapEntry()); return Lists.newArrayList(transform); } } class Parsed<V> implements Comparable<Parsed<V>> { private static final Function<String, Integer> PARSE = new Function<String, Integer>() { @Override public Integer apply(String input) { try { return Integer.parseInt(input); } catch (NumberFormatException e) { return Integer.MAX_VALUE; } } }; private final List<Integer> parts; private final String key; private final V value; Parsed(Map.Entry<String, V> entry) { key = entry.getKey(); value = entry.getValue(); final Iterable<String> iter = Splitter.on(".").split(entry.getKey()); parts = Lists.newArrayList(Iterators.transform(iter.iterator(),PARSE)); } @Override public int compareTo(Parsed<V> other) { for (int i = 0; i < parts.size(); i++) { Integer p = parts.get(i); if (other.parts.size() < parts.size()) { // run out of parts for other, put it before us return -1; } final Integer q = other.parts.get(i); final int comparison = p.compareTo(q); if(comparison != 0) { return +comparison; } } if(other.parts.size() > parts.size()) { // run out of parts on our side, still more on others; put us before it return +1; } return 0; } public Map.Entry<String, V> toMapEntry() { return new MapEntry<String, V>(key, value){}; } } class MapEntry<K, V> implements Map.Entry<K, V> { private K key; private V value; MapEntry(K key, V value) { this.key = key; this.value = value; } @Override public K getKey() { return key; } @Override public V getValue() { return value; } @Override public V setValue(V value) { throw new UnsupportedOperationException(); } @Override public boolean equals(Object object) { if (object instanceof Map.Entry) { Map.Entry<?, ?> that = (Map.Entry<?, ?>) object; return Objects.equal(this.getKey(), that.getKey()) && Objects.equal(this.getValue(), that.getValue()); } return false; } @Override public int hashCode() { K k = getKey(); V v = getValue(); return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode()); } /** * Returns a string representation of the form {@code {key}={value}}. */ @Override public String toString() { return getKey() + "=" + getValue(); } }