1 /*
   2  * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.xml.internal.bind.v2.runtime;
  27 
  28 import java.util.HashMap;
  29 import java.util.HashSet;
  30 import java.util.Map;
  31 import java.util.Set;
  32 
  33 import javax.xml.namespace.QName;
  34 
  35 import com.sun.xml.internal.bind.v2.util.QNameMap;
  36 
  37 /**
  38  * Creates {@link Name}s and assign index numbers to them.
  39  *
  40  * <p>
  41  * During this process, this class also finds out which namespace URIs
  42  * are statically known to be un-bindable as the default namespace.
  43  * Those are the namespace URIs that are used by attribute names.
  44  *
  45  * @author Kohsuke Kawaguchi
  46  */
  47 @SuppressWarnings({"StringEquality"})
  48 public final class NameBuilder {
  49     private Map<String,Integer> uriIndexMap = new HashMap<String, Integer>();
  50     private Set<String> nonDefaultableNsUris = new HashSet<String>();
  51     private Map<String,Integer> localNameIndexMap = new HashMap<String, Integer>();
  52     private QNameMap<Integer> elementQNameIndexMap = new QNameMap<Integer>();
  53     private QNameMap<Integer> attributeQNameIndexMap = new QNameMap<Integer>();
  54 
  55     public Name createElementName(QName name) {
  56         return createElementName(name.getNamespaceURI(),name.getLocalPart());
  57     }
  58 
  59     public Name createElementName(String nsUri, String localName) {
  60         return createName(nsUri, localName, false, elementQNameIndexMap);
  61     }
  62 
  63     public Name createAttributeName(QName name) {
  64         return createAttributeName(name.getNamespaceURI(),name.getLocalPart());
  65     }
  66 
  67     public Name createAttributeName(String nsUri, String localName) {
  68         assert nsUri.intern()==nsUri;
  69         assert localName.intern()==localName;
  70 
  71         if(nsUri.length()==0)
  72             return new Name(
  73                     allocIndex(attributeQNameIndexMap,"",localName),
  74                     -1,
  75                     nsUri,
  76                     allocIndex(localNameIndexMap,localName),
  77                     localName,
  78                     true);
  79         else {
  80             nonDefaultableNsUris.add(nsUri);
  81             return createName(nsUri,localName, true, attributeQNameIndexMap);
  82         }
  83     }
  84 
  85     private Name createName(String nsUri, String localName, boolean isAttribute, QNameMap<Integer> map) {
  86         assert nsUri.intern()==nsUri;
  87         assert localName.intern()==localName;
  88 
  89         return new Name(
  90                 allocIndex(map,nsUri,localName),
  91                 allocIndex(uriIndexMap,nsUri),
  92                 nsUri,
  93                 allocIndex(localNameIndexMap,localName),
  94                 localName,
  95                 isAttribute );
  96     }
  97 
  98     private int allocIndex(Map<String,Integer> map, String str) {
  99         Integer i = map.get(str);
 100         if(i==null) {
 101             i = map.size();
 102             map.put(str,i);
 103         }
 104         return i;
 105     }
 106 
 107     private int allocIndex(QNameMap<Integer> map, String nsUri, String localName) {
 108         Integer i = map.get(nsUri,localName);
 109         if(i==null) {
 110             i = map.size();
 111             map.put(nsUri,localName,i);
 112         }
 113         return i;
 114     }
 115 
 116     /**
 117      * Wraps up everything and creates {@link NameList}.
 118      */
 119     public NameList conclude() {
 120         boolean[] nsUriCannotBeDefaulted = new boolean[uriIndexMap.size()];
 121         for (Map.Entry<String,Integer> e : uriIndexMap.entrySet()) {
 122             nsUriCannotBeDefaulted[e.getValue()] = nonDefaultableNsUris.contains(e.getKey());
 123         }
 124 
 125         NameList r = new NameList(
 126                 list(uriIndexMap),
 127                 nsUriCannotBeDefaulted,
 128                 list(localNameIndexMap),
 129                 elementQNameIndexMap.size(),
 130                 attributeQNameIndexMap.size() );
 131         // delete them so that the create method can never be called again
 132         uriIndexMap = null;
 133         localNameIndexMap = null;
 134         return r;
 135     }
 136 
 137     private String[] list(Map<String, Integer> map) {
 138         String[] r = new String[map.size()];
 139         for (Map.Entry<String, Integer> e : map.entrySet())
 140             r[e.getValue()] = e.getKey();
 141         return r;
 142     }
 143 }