X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-data-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fdata%2Fimpl%2Fcodec%2Fxml%2FRandomPrefix.java;h=125ac23eb86fd057551e821e76fa757b0f2a36bf;hb=7ba7c6cba54a57c1c299eef1889aa142218ffda7;hp=0251678389a8c29cd3d989fc6e9d0a1a227ba78a;hpb=a84ec52d7bcb57af77a2424755e513cd10bc9c57;p=yangtools.git diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/RandomPrefix.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/RandomPrefix.java index 0251678389..125ac23eb8 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/RandomPrefix.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/RandomPrefix.java @@ -7,43 +7,86 @@ */ package org.opendaylight.yangtools.yang.data.impl.codec.xml; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; + import java.net.URI; -import java.util.HashMap; import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ThreadLocalRandom; -import org.opendaylight.yangtools.yang.common.QName; +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; -final class RandomPrefix { - final Map prefixes = new HashMap<>(); +class RandomPrefix { + // 32 characters, carefully chosen + private static final String LOOKUP = "abcdefghiknoprstABCDEFGHIKNOPRST"; + private static final int MASK = 0x1f; + private static final int SHIFT = 5; - Iterable> getPrefixes() { - return prefixes.entrySet(); + private int counter = 0; + + // BiMap to make values lookup faster + private final BiMap prefixes = HashBiMap.create(); + private final NamespaceContext context; + + RandomPrefix() { + this.context = null; } - String encodeQName(final QName qname) { - return encodePrefix(qname) + ':' + qname.getLocalName(); + RandomPrefix(final NamespaceContext context) { + this.context = Preconditions.checkNotNull(context); } - String encodePrefix(final QName qname) { - String prefix = prefixes.get(qname.getNamespace()); - if (prefix == null) { - prefix = qname.getPrefix(); - if (prefix == null || prefix.isEmpty() || prefixes.containsValue(prefix)) { - final ThreadLocalRandom random = ThreadLocalRandom.current(); - do { - final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 4; i++) { - sb.append((char)('a' + random.nextInt(25))); - } - - prefix = sb.toString(); - } while (prefixes.containsValue(prefix)); - } - - prefixes.put(qname.getNamespace(), prefix); + Iterable> getPrefixes() { + return prefixes.entrySet(); + } + + String encodePrefix(final URI namespace) { + String prefix = prefixes.get(namespace); + if (prefix != null) { + return prefix; } + + do { + prefix = encode(counter); + counter++; + } while (alreadyUsedPrefix(prefix)); + + prefixes.put(namespace, prefix); return prefix; } + + private boolean alreadyUsedPrefix(final String prefix) { + if (context == null) { + return false; + } + + final String str = context.getNamespaceURI(prefix); + return !XMLConstants.NULL_NS_URI.equals(str); + } + + @VisibleForTesting + static int decode(final String str) { + int ret = 0; + for (char c : str.toCharArray()) { + int idx = LOOKUP.indexOf(c); + Preconditions.checkArgument(idx != -1, "Invalid string %s", str); + ret = (ret << SHIFT) + idx; + } + + return ret; + } + + @VisibleForTesting + static String encode(int num) { + final StringBuilder sb = new StringBuilder(); + + do { + sb.append(LOOKUP.charAt(num & MASK)); + num >>>= SHIFT; + } while (num != 0); + + return sb.reverse().toString(); + } }