Coverage Report - org.simpleframework.xml.stream.PrefixResolver
 
Classes in this File Line Coverage Branch Coverage Complexity
PrefixResolver
97%
33/34
90%
18/20
2.667
 
 1  
 /*
 2  
  * PrefixResolver.java July 2008
 3  
  *
 4  
  * Copyright (C) 2008, Niall Gallagher <niallg@users.sf.net>
 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 
 15  
  * implied. See the License for the specific language governing 
 16  
  * permissions and limitations under the License.
 17  
  */
 18  
 
 19  
 package org.simpleframework.xml.stream;
 20  
 
 21  
 import java.util.Iterator;
 22  
 import java.util.LinkedHashMap;
 23  
 
 24  
 /**
 25  
  * The <code>PrefixResolver</code> object will store the namespaces
 26  
  * for an element. Each namespace added to this map can be added
 27  
  * with a prefix. A prefix is added only if the associated reference
 28  
  * has not been added to a parent element. If a parent element has
 29  
  * the associated reference, then the parents prefix is the one that
 30  
  * will be returned when requested from this map. 
 31  
  * 
 32  
  * @author Niall Gallagher
 33  
  *
 34  
  * @see org.simpleframework.xml.stream.OutputElement
 35  
  */
 36  
 class PrefixResolver extends LinkedHashMap<String, String> implements NamespaceMap {
 37  
 
 38  
    /**
 39  
     * Represents the actual XML element this is associated with.
 40  
     */ 
 41  
    private final OutputNode source;
 42  
    
 43  
    /**
 44  
     * Constructor for the <code>PrefixResolver</code> object. This
 45  
     * is used to create a resolver for namespace prefixes using 
 46  
     * the hierarchy of elements. Resolving the prefix in this way
 47  
     * avoids having to redeclare the same namespace with another
 48  
     * prefix in a child element if it has already been declared.
 49  
     *
 50  
     * @param source this is the XML element this is associated to
 51  
     */ 
 52  562116
    public PrefixResolver(OutputNode source) {
 53  562116
       this.source = source;
 54  562116
    }
 55  
 
 56  
    /**
 57  
     * This is the prefix that is associated with the source element.
 58  
     * If the source element does not contain a namespace reference
 59  
     * then this will return its parents namespace. This ensures 
 60  
     * that if a namespace has been declared its child elements will
 61  
     * inherit its prefix.
 62  
     * 
 63  
     * @return this returns the prefix that is currently in scope
 64  
     */
 65  
    public String getPrefix() {
 66  0
       return source.getPrefix();
 67  
    }
 68  
    
 69  
    /**
 70  
     * This is used to add the namespace reference to the namespace
 71  
     * map. If the namespace has been added to a parent node then
 72  
     * this will not add the reference. The prefix added to the map
 73  
     * will be the default namespace, which is an empty prefix.
 74  
     * 
 75  
     * @param reference this is the reference to be added 
 76  
     * 
 77  
     * @return this returns the prefix that has been replaced
 78  
     */
 79  
    public String setReference(String reference) {
 80  3
       return setReference(reference, "");
 81  
    }
 82  
    
 83  
    /**
 84  
     * This is used to add the namespace reference to the namespace
 85  
     * map. If the namespace has been added to a parent node then
 86  
     * this will not add the reference. 
 87  
     * 
 88  
     * @param reference this is the reference to be added 
 89  
     * @param prefix this is the prefix to be added to the reference
 90  
     * 
 91  
     * @return this returns the prefix that has been replaced
 92  
     */
 93  
    public String setReference(String reference, String prefix) {
 94  665
       String parent = resolvePrefix(reference);
 95  
       
 96  665
       if(parent != null) {
 97  187
          return null;
 98  
       }
 99  478
       return put(reference, prefix);
 100  
    }
 101  
 
 102  
    /**
 103  
     * This acquires the prefix for the specified namespace reference.
 104  
     * If the namespace reference has been set on this node with a
 105  
     * given prefix then that prefix is returned, however if it has
 106  
     * not been set this will search the parent elements to find the
 107  
     * prefix that is in scope for the specified reference.
 108  
     * 
 109  
     * @param reference the reference to find a matching prefix for
 110  
     * 
 111  
     * @return this will return the prefix that is is scope
 112  
     */
 113  
    public String getPrefix(String reference) {
 114  4178083
       int size = size();
 115  
       
 116  4178083
       if(size > 0) {
 117  4418
          String prefix = get(reference); 
 118  
    
 119  4418
          if(prefix != null) {
 120  1307
             return prefix;
 121  
          }    
 122  
       }
 123  4176776
       return resolvePrefix(reference);
 124  
    }
 125  
    
 126  
    /**
 127  
     * This acquires the namespace reference for the specified prefix.
 128  
     * If the provided prefix has been set on this node with a given
 129  
     * reference then that reference is returned, however if it has
 130  
     * not been set this will search the parent elements to find the
 131  
     * reference that is in scope for the specified reference.
 132  
     * 
 133  
     * @param prefix the prefix to find a matching reference for
 134  
     * 
 135  
     * @return this will return the reference that is is scope
 136  
     */
 137  
    public String getReference(String prefix) {
 138  162
       if(containsValue(prefix)) {
 139  58
          for(String reference : this) {
 140  63
             String value = get(reference);
 141  
             
 142  63
             if(value != null) {
 143  63
                if(value.equals(prefix)) {
 144  58
                   return reference;
 145  
                }
 146  
             }
 147  5
          }
 148  
       }
 149  104
       return resolveReference(prefix);
 150  
    }
 151  
    
 152  
    /**
 153  
     * This method will resolve the reference or the specified prefix
 154  
     * by searching the parent nodes in order. This allows the prefix
 155  
     * that is currently in scope for the reference to be acquired.
 156  
     *
 157  
     * @param prefix the prefix to find a matching reference for
 158  
     * 
 159  
     * @return this will return the reference that is is scope
 160  
     */ 
 161  
    private String resolveReference(String prefix) {
 162  104
       NamespaceMap parent = source.getNamespaces();
 163  
       
 164  104
       if(parent != null) {
 165  103
          return parent.getReference(prefix);
 166  
       }
 167  1
       return null;
 168  
    }
 169  
    
 170  
    /**
 171  
     * This method will resolve the prefix or the specified reference
 172  
     * by searching the parent nodes in order. This allows the prefix
 173  
     * that is currently in scope for the reference to be acquired.
 174  
     *
 175  
     * @param reference the reference to find a matching prefix for
 176  
     * 
 177  
     * @return this will return the prefix that is is scope
 178  
     */ 
 179  
    private String resolvePrefix(String reference) {
 180  4177441
       NamespaceMap parent = source.getNamespaces();
 181  
       
 182  4177441
       if(parent != null) {
 183  2783203
          String prefix = parent.getPrefix(reference);
 184  
          
 185  2783203
          if(!containsValue(prefix)) {
 186  2783194
             return prefix;
 187  
          }
 188  
       }
 189  1394247
       return null;
 190  
    }
 191  
    
 192  
    /**
 193  
     * This returns an iterator for the namespace of all the nodes 
 194  
     * in this <code>NamespaceMap</code>. This allows the namespaces 
 195  
     * to be iterated within a for each loop in order to extract the
 196  
     * prefix values associated with the map.
 197  
     *
 198  
     * @return this returns the namespaces contained in this map
 199  
     */ 
 200  
    public Iterator<String> iterator() {
 201  561749
       return keySet().iterator();
 202  
    }
 203  
 }