Coverage Report - org.codehaus.plexus.util.xml.pull.EntityReplacementMap
 
Classes in this File Line Coverage Branch Coverage Complexity
EntityReplacementMap
88%
30/34
70%
14/20
3.75
 
 1  
 package org.codehaus.plexus.util.xml.pull;
 2  
 
 3  
 /*
 4  
  * Copyright The Codehaus Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License");
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 public class EntityReplacementMap
 19  
 {
 20  
     final String entityName[];
 21  
 
 22  
     final char[] entityNameBuf[];
 23  
 
 24  
     final String entityReplacement[];
 25  
 
 26  
     final char[] entityReplacementBuf[];
 27  
 
 28  
     int entityEnd;
 29  
 
 30  
     final int entityNameHash[];
 31  
 
 32  
     public EntityReplacementMap( String[][] replacements )
 33  2
     {
 34  2
         int length = replacements.length;
 35  2
         entityName = new String[length];
 36  2
         entityNameBuf = new char[length][];
 37  2
         entityReplacement = new String[length];
 38  2
         entityReplacementBuf = new char[length][];
 39  2
         entityNameHash = new int[length];
 40  
 
 41  252
         for ( String[] replacement : replacements )
 42  
         {
 43  250
             defineEntityReplacementText( replacement[0], replacement[1] );
 44  
         }
 45  2
     }
 46  
 
 47  
     private void defineEntityReplacementText( String entityName, String replacementText )
 48  
     {
 49  250
         if ( !replacementText.startsWith( "&#" ) && this.entityName != null && replacementText.length() > 1 )
 50  
         {
 51  2
             String tmp = replacementText.substring( 1, replacementText.length() - 1 );
 52  6
             for ( int i = 0; i < this.entityName.length; i++ )
 53  
             {
 54  4
                 if ( this.entityName[i] != null && this.entityName[i].equals( tmp ) )
 55  
                 {
 56  0
                     replacementText = this.entityReplacement[i];
 57  
                 }
 58  
             }
 59  
         }
 60  
 
 61  
         // this is to make sure that if interning works we will take advantage of it ...
 62  250
         char[] entityNameCharData = entityName.toCharArray();
 63  
         // noinspection ConstantConditions
 64  250
         this.entityName[entityEnd] = newString( entityNameCharData, 0, entityName.length() );
 65  250
         entityNameBuf[entityEnd] = entityNameCharData;
 66  
 
 67  250
         entityReplacement[entityEnd] = replacementText;
 68  250
         entityReplacementBuf[entityEnd] = replacementText.toCharArray();
 69  250
         entityNameHash[entityEnd] = fastHash( entityNameBuf[entityEnd], 0, entityNameBuf[entityEnd].length );
 70  250
         ++entityEnd;
 71  
         // TODO disallow < or & in entity replacement text (or ]]>???)
 72  
         // TODO keepEntityNormalizedForAttributeValue cached as well ...
 73  250
     }
 74  
 
 75  
     private String newString( char[] cbuf, int off, int len )
 76  
     {
 77  250
         return new String( cbuf, off, len );
 78  
     }
 79  
 
 80  
     /**
 81  
      * simplistic implementation of hash function that has <b>constant</b> time to compute - so it also means
 82  
      * diminishing hash quality for long strings but for XML parsing it should be good enough ...
 83  
      */
 84  
     private static int fastHash( char ch[], int off, int len )
 85  
     {
 86  250
         if ( len == 0 )
 87  0
             return 0;
 88  
         // assert len >0
 89  250
         int hash = ch[off]; // hash at beginning
 90  
         // try {
 91  250
         hash = ( hash << 7 ) + ch[off + len - 1]; // hash at the end
 92  
         // } catch(ArrayIndexOutOfBoundsException aie) {
 93  
         // aie.printStackTrace(); //should never happen ...
 94  
         // throw new RuntimeException("this is violation of pre-condition");
 95  
         // }
 96  250
         if ( len > 16 )
 97  0
             hash = ( hash << 7 ) + ch[off + ( len / 4 )]; // 1/4 from beginning
 98  250
         if ( len > 8 )
 99  0
             hash = ( hash << 7 ) + ch[off + ( len / 2 )]; // 1/2 of string size ...
 100  
         // notice that hash is at most done 3 times <<7 so shifted by 21 bits 8 bit value
 101  
         // so max result == 29 bits so it is quite just below 31 bits for long (2^32) ...
 102  
         // assert hash >= 0;
 103  250
         return hash;
 104  
     }
 105  
 
 106  1
     public static final EntityReplacementMap defaultEntityReplacementMap = new EntityReplacementMap( new String[][] {
 107  
         { "nbsp", "\u00a0" }, { "iexcl", "\u00a1" }, { "cent", "\u00a2" }, { "pound", "\u00a3" },
 108  
         { "curren", "\u00a4" }, { "yen", "\u00a5" }, { "brvbar", "\u00a6" }, { "sect", "\u00a7" }, { "uml", "\u00a8" },
 109  
         { "copy", "\u00a9" }, { "ordf", "\u00aa" }, { "laquo", "\u00ab" }, { "not", "\u00ac" }, { "shy", "\u00ad" },
 110  
         { "reg", "\u00ae" }, { "macr", "\u00af" }, { "deg", "\u00b0" }, { "plusmn", "\u00b1" }, { "sup2", "\u00b2" },
 111  
         { "sup3", "\u00b3" }, { "acute", "\u00b4" }, { "micro", "\u00b5" }, { "para", "\u00b6" },
 112  
         { "middot", "\u00b7" }, { "cedil", "\u00b8" }, { "sup1", "\u00b9" }, { "ordm", "\u00ba" },
 113  
         { "raquo", "\u00bb" }, { "frac14", "\u00bc" }, { "frac12", "\u00bd" }, { "frac34", "\u00be" },
 114  
         { "iquest", "\u00bf" }, { "Agrave", "\u00c0" }, { "Aacute", "\u00c1" }, { "Acirc", "\u00c2" },
 115  
         { "Atilde", "\u00c3" }, { "Auml", "\u00c4" }, { "Aring", "\u00c5" }, { "AElig", "\u00c6" },
 116  
         { "Ccedil", "\u00c7" }, { "Egrave", "\u00c8" }, { "Eacute", "\u00c9" }, { "Ecirc", "\u00ca" },
 117  
         { "Euml", "\u00cb" }, { "Igrave", "\u00cc" }, { "Iacute", "\u00cd" }, { "Icirc", "\u00ce" },
 118  
         { "Iuml", "\u00cf" }, { "ETH", "\u00d0" }, { "Ntilde", "\u00d1" }, { "Ograve", "\u00d2" },
 119  
         { "Oacute", "\u00d3" }, { "Ocirc", "\u00d4" }, { "Otilde", "\u00d5" }, { "Ouml", "\u00d6" },
 120  
         { "times", "\u00d7" }, { "Oslash", "\u00d8" }, { "Ugrave", "\u00d9" }, { "Uacute", "\u00da" },
 121  
         { "Ucirc", "\u00db" }, { "Uuml", "\u00dc" }, { "Yacute", "\u00dd" }, { "THORN", "\u00de" },
 122  
         { "szlig", "\u00df" }, { "agrave", "\u00e0" }, { "aacute", "\u00e1" }, { "acirc", "\u00e2" },
 123  
         { "atilde", "\u00e3" }, { "auml", "\u00e4" }, { "aring", "\u00e5" }, { "aelig", "\u00e6" },
 124  
         { "ccedil", "\u00e7" }, { "egrave", "\u00e8" }, { "eacute", "\u00e9" }, { "ecirc", "\u00ea" },
 125  
         { "euml", "\u00eb" }, { "igrave", "\u00ec" }, { "iacute", "\u00ed" }, { "icirc", "\u00ee" },
 126  
         { "iuml", "\u00ef" }, { "eth", "\u00f0" }, { "ntilde", "\u00f1" }, { "ograve", "\u00f2" },
 127  
         { "oacute", "\u00f3" }, { "ocirc", "\u00f4" }, { "otilde", "\u00f5" }, { "ouml", "\u00f6" },
 128  
         { "divide", "\u00f7" }, { "oslash", "\u00f8" }, { "ugrave", "\u00f9" }, { "uacute", "\u00fa" },
 129  
         { "ucirc", "\u00fb" }, { "uuml", "\u00fc" }, { "yacute", "\u00fd" }, { "thorn", "\u00fe" },
 130  
         { "yuml", "\u00ff" },
 131  
 
 132  
         // ----------------------------------------------------------------------
 133  
         // Special entities
 134  
         // ----------------------------------------------------------------------
 135  
 
 136  
         { "OElig", "\u0152" }, { "oelig", "\u0153" }, { "Scaron", "\u0160" }, { "scaron", "\u0161" },
 137  
         { "Yuml", "\u0178" }, { "circ", "\u02c6" }, { "tilde", "\u02dc" }, { "ensp", "\u2002" }, { "emsp", "\u2003" },
 138  
         { "thinsp", "\u2009" }, { "zwnj", "\u200c" }, { "zwj", "\u200d" }, { "lrm", "\u200e" }, { "rlm", "\u200f" },
 139  
         { "ndash", "\u2013" }, { "mdash", "\u2014" }, { "lsquo", "\u2018" }, { "rsquo", "\u2019" },
 140  
         { "sbquo", "\u201a" }, { "ldquo", "\u201c" }, { "rdquo", "\u201d" }, { "bdquo", "\u201e" },
 141  
         { "dagger", "\u2020" }, { "Dagger", "\u2021" }, { "permil", "\u2030" }, { "lsaquo", "\u2039" },
 142  
         { "rsaquo", "\u203a" }, { "euro", "\u20ac" },
 143  
 
 144  
         // ----------------------------------------------------------------------
 145  
         // Symbol entities
 146  
         // ----------------------------------------------------------------------
 147  
 
 148  
         { "fnof", "\u0192" }, { "Alpha", "\u0391" }, { "Beta", "\u0392" }, { "Gamma", "\u0393" }, { "Delta", "\u0394" },
 149  
         { "Epsilon", "\u0395" }, { "Zeta", "\u0396" }, { "Eta", "\u0397" }, { "Theta", "\u0398" }, { "Iota", "\u0399" },
 150  
         { "Kappa", "\u039a" }, { "Lambda", "\u039b" }, { "Mu", "\u039c" }, { "Nu", "\u039d" }, { "Xi", "\u039e" },
 151  
         { "Omicron", "\u039f" }, { "Pi", "\u03a0" }, { "Rho", "\u03a1" }, { "Sigma", "\u03a3" }, { "Tau", "\u03a4" },
 152  
         { "Upsilon", "\u03a5" }, { "Phi", "\u03a6" }, { "Chi", "\u03a7" }, { "Psi", "\u03a8" }, { "Omega", "\u03a9" },
 153  
         { "alpha", "\u03b1" }, { "beta", "\u03b2" }, { "gamma", "\u03b3" }, { "delta", "\u03b4" },
 154  
         { "epsilon", "\u03b5" }, { "zeta", "\u03b6" }, { "eta", "\u03b7" }, { "theta", "\u03b8" }, { "iota", "\u03b9" },
 155  
         { "kappa", "\u03ba" }, { "lambda", "\u03bb" }, { "mu", "\u03bc" }, { "nu", "\u03bd" }, { "xi", "\u03be" },
 156  
         { "omicron", "\u03bf" }, { "pi", "\u03c0" }, { "rho", "\u03c1" }, { "sigmaf", "\u03c2" }, { "sigma", "\u03c3" },
 157  
         { "tau", "\u03c4" }, { "upsilon", "\u03c5" }, { "phi", "\u03c6" }, { "chi", "\u03c7" }, { "psi", "\u03c8" },
 158  
         { "omega", "\u03c9" }, { "thetasym", "\u03d1" }, { "upsih", "\u03d2" }, { "piv", "\u03d6" },
 159  
         { "bull", "\u2022" }, { "hellip", "\u2026" }, { "prime", "\u2032" }, { "Prime", "\u2033" },
 160  
         { "oline", "\u203e" }, { "frasl", "\u2044" }, { "weierp", "\u2118" }, { "image", "\u2111" },
 161  
         { "real", "\u211c" }, { "trade", "\u2122" }, { "alefsym", "\u2135" }, { "larr", "\u2190" },
 162  
         { "uarr", "\u2191" }, { "rarr", "\u2192" }, { "darr", "\u2193" }, { "harr", "\u2194" }, { "crarr", "\u21b5" },
 163  
         { "lArr", "\u21d0" }, { "uArr", "\u21d1" }, { "rArr", "\u21d2" }, { "dArr", "\u21d3" }, { "hArr", "\u21d4" },
 164  
         { "forall", "\u2200" }, { "part", "\u2202" }, { "exist", "\u2203" }, { "empty", "\u2205" },
 165  
         { "nabla", "\u2207" }, { "isin", "\u2208" }, { "notin", "\u2209" }, { "ni", "\u220b" }, { "prod", "\u220f" },
 166  
         { "sum", "\u2211" }, { "minus", "\u2212" }, { "lowast", "\u2217" }, { "radic", "\u221a" }, { "prop", "\u221d" },
 167  
         { "infin", "\u221e" }, { "ang", "\u2220" }, { "and", "\u2227" }, { "or", "\u2228" }, { "cap", "\u2229" },
 168  
         { "cup", "\u222a" }, { "int", "\u222b" }, { "there4", "\u2234" }, { "sim", "\u223c" }, { "cong", "\u2245" },
 169  
         { "asymp", "\u2248" }, { "ne", "\u2260" }, { "equiv", "\u2261" }, { "le", "\u2264" }, { "ge", "\u2265" },
 170  
         { "sub", "\u2282" }, { "sup", "\u2283" }, { "nsub", "\u2284" }, { "sube", "\u2286" }, { "supe", "\u2287" },
 171  
         { "oplus", "\u2295" }, { "otimes", "\u2297" }, { "perp", "\u22a5" }, { "sdot", "\u22c5" },
 172  
         { "lceil", "\u2308" }, { "rceil", "\u2309" }, { "lfloor", "\u230a" }, { "rfloor", "\u230b" },
 173  
         { "lang", "\u2329" }, { "rang", "\u232a" }, { "loz", "\u25ca" }, { "spades", "\u2660" }, { "clubs", "\u2663" },
 174  
         { "hearts", "\u2665" }, { "diams", "\u2666" } } );
 175  
 
 176  
 }