Bug 1441: Bug fixes, clean-up and test migration
[yangtools.git] / yang / yang-data-codec-xml / src / main / java / org / opendaylight / yangtools / yang / data / codec / xml / RandomPrefix.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.data.codec.xml;
9
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.BiMap;
13 import com.google.common.collect.HashBiMap;
14 import java.net.URI;
15 import java.util.Map.Entry;
16 import javax.xml.XMLConstants;
17 import javax.xml.namespace.NamespaceContext;
18
19 class RandomPrefix {
20     // 32 characters, carefully chosen
21     private static final String LOOKUP = "abcdefghiknoprstABCDEFGHIKNOPRST";
22     private static final int MASK = 0x1f;
23     private static final int SHIFT = 5;
24
25     private int counter = 0;
26
27     // BiMap to make values lookup faster
28     private final BiMap<URI, String> prefixes = HashBiMap.create();
29     private final NamespaceContext context;
30
31     RandomPrefix() {
32         this.context = null;
33     }
34
35     RandomPrefix(final NamespaceContext context) {
36         this.context = Preconditions.checkNotNull(context);
37     }
38
39     Iterable<Entry<URI, String>> getPrefixes() {
40         return prefixes.entrySet();
41     }
42
43     String encodePrefix(final URI namespace) {
44         String prefix = prefixes.get(namespace);
45         if (prefix != null) {
46             return prefix;
47         }
48
49         do {
50             prefix = encode(counter);
51             counter++;
52         } while (alreadyUsedPrefix(prefix));
53
54         prefixes.put(namespace, prefix);
55         return prefix;
56     }
57
58     private boolean alreadyUsedPrefix(final String prefix) {
59         if (context == null) {
60             return false;
61         }
62
63         final String str = context.getNamespaceURI(prefix);
64         return !XMLConstants.NULL_NS_URI.equals(str);
65     }
66
67     @VisibleForTesting
68     static int decode(final String str) {
69         int ret = 0;
70         for (char c : str.toCharArray()) {
71             int idx = LOOKUP.indexOf(c);
72             Preconditions.checkArgument(idx != -1, "Invalid string %s", str);
73             ret = (ret << SHIFT) + idx;
74         }
75
76         return ret;
77     }
78
79     @VisibleForTesting
80     static String encode(int num) {
81         final StringBuilder sb = new StringBuilder();
82
83         do {
84             sb.append(LOOKUP.charAt(num & MASK));
85             num >>>= SHIFT;
86         } while (num != 0);
87
88         return sb.reverse().toString();
89     }
90 }