1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2001, 2002,2004 The Apache Software Foundation.
   7  *
   8  * Licensed under the Apache License, Version 2.0 (the "License");
   9  * you may not use this file except in compliance with the License.
  10  * You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xerces.internal.util;
  22 
  23 import java.util.Arrays;
  24 import java.util.HashMap;
  25 import java.util.HashSet;
  26 import java.util.Map;
  27 import java.util.Set;
  28 
  29 import com.sun.org.apache.xerces.internal.impl.Constants;
  30 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  31 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  32 
  33 /**
  34  * This class implements the basic operations for managing parser
  35  * configuration features and properties. This utility class can
  36  * be used as a base class for parser configurations or separately
  37  * to encapsulate a number of parser settings as a component
  38  * manager.
  39  * <p>
  40  * This class can be constructed with a "parent" settings object
  41  * (in the form of an <code>XMLComponentManager</code>) that allows
  42  * parser configuration settings to be "chained" together.
  43  *
  44  * @author Andy Clark, IBM
  45  *
  46  * @version $Id: ParserConfigurationSettings.java,v 1.6 2010-11-01 04:40:14 joehw Exp $
  47  */
  48 public class ParserConfigurationSettings
  49     implements XMLComponentManager {
  50 
  51         protected static final String PARSER_SETTINGS =
  52                         Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
  53 
  54     //
  55     // Data
  56     //
  57 
  58     // data
  59 
  60     /** Recognized properties. */
  61     protected Set<String> fRecognizedProperties;
  62 
  63     /** Properties. */
  64     protected Map<String, Object> fProperties;
  65 
  66     /** Recognized features. */
  67     protected Set<String> fRecognizedFeatures;
  68 
  69     /** Features. */
  70     protected Map<String, Boolean> fFeatures;
  71 
  72     /** Parent parser configuration settings. */
  73     protected XMLComponentManager fParentSettings;
  74 
  75     //
  76     // Constructors
  77     //
  78 
  79     /** Default Constructor. */
  80     public ParserConfigurationSettings() {
  81         this(null);
  82     } // <init>()
  83 
  84     /**
  85      * Constructs a parser configuration settings object with a
  86      * parent settings object.
  87      */
  88     public ParserConfigurationSettings(XMLComponentManager parent) {
  89 
  90         // create storage for recognized features and properties
  91         fRecognizedFeatures = new HashSet<String>();
  92         fRecognizedProperties = new HashSet<String>();
  93 
  94         // create table for features and properties
  95         fFeatures = new HashMap<String, Boolean>();
  96         fProperties = new HashMap<String, Object>();
  97 
  98         // save parent
  99         fParentSettings = parent;
 100 
 101     } // <init>(XMLComponentManager)
 102 
 103     //
 104     // XMLParserConfiguration methods
 105     //
 106 
 107     /**
 108      * Allows a parser to add parser specific features to be recognized
 109      * and managed by the parser configuration.
 110      *
 111      * @param featureIds An array of the additional feature identifiers
 112      *                   to be recognized.
 113      */
 114     public void addRecognizedFeatures(String[] featureIds) {
 115 
 116         // add recognized features
 117         int featureIdsCount = featureIds != null ? featureIds.length : 0;
 118         for (int i = 0; i < featureIdsCount; i++) {
 119             String featureId = featureIds[i];
 120             if (!fRecognizedFeatures.contains(featureId)) {
 121                 fRecognizedFeatures.add(featureId);
 122             }
 123         }
 124 
 125     } // addRecognizedFeatures(String[])
 126 
 127     /**
 128      * Set the state of a feature.
 129      *
 130      * Set the state of any feature in a SAX2 parser.  The parser
 131      * might not recognize the feature, and if it does recognize
 132      * it, it might not be able to fulfill the request.
 133      *
 134      * @param featureId The unique identifier (URI) of the feature.
 135      * @param state The requested state of the feature (true or false).
 136      *
 137      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
 138      *            requested feature is not known.
 139      */
 140     public void setFeature(String featureId, boolean state)
 141         throws XMLConfigurationException {
 142 
 143         // check and store
 144         FeatureState checkState = checkFeature(featureId);
 145         if (checkState.isExceptional()) {
 146             throw new XMLConfigurationException(checkState.status, featureId);
 147         }
 148 
 149         fFeatures.put(featureId, state);
 150     } // setFeature(String,boolean)
 151 
 152     /**
 153      * Allows a parser to add parser specific properties to be recognized
 154      * and managed by the parser configuration.
 155      *
 156      * @param propertyIds An array of the additional property identifiers
 157      *                    to be recognized.
 158      */
 159     public void addRecognizedProperties(String[] propertyIds) {
 160         fRecognizedProperties.addAll(Arrays.asList(propertyIds));
 161     } // addRecognizedProperties(String[])
 162 
 163     /**
 164      * setProperty
 165      *
 166      * @param propertyId
 167      * @param value
 168      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
 169      *            requested feature is not known.
 170      */
 171     public void setProperty(String propertyId, Object value)
 172         throws XMLConfigurationException {
 173 
 174         // check and store
 175         PropertyState checkState = checkProperty(propertyId);
 176         if (checkState.isExceptional()) {
 177             throw new XMLConfigurationException(checkState.status, propertyId);
 178         }
 179         fProperties.put(propertyId, value);
 180 
 181     } // setProperty(String,Object)
 182 
 183     //
 184     // XMLComponentManager methods
 185     //
 186 
 187     /**
 188      * Returns the state of a feature.
 189      *
 190      * @param featureId The feature identifier.
 191                  * @return true if the feature is supported
 192      *
 193      * @throws XMLConfigurationException Thrown for configuration error.
 194      *                                   In general, components should
 195      *                                   only throw this exception if
 196      *                                   it is <strong>really</strong>
 197      *                                   a critical error.
 198      */
 199     public final boolean getFeature(String featureId)
 200         throws XMLConfigurationException {
 201 
 202         FeatureState state = getFeatureState(featureId);
 203         if (state.isExceptional()) {
 204             throw new XMLConfigurationException(state.status, featureId);
 205         }
 206         return state.state;
 207     } // getFeature(String):boolean
 208 
 209     public final boolean getFeature(String featureId, boolean defaultValue) {
 210         FeatureState state = getFeatureState(featureId);
 211         if (state.isExceptional()) {
 212             return defaultValue;
 213         }
 214         return state.state;
 215     }
 216 
 217     public FeatureState getFeatureState(String featureId) {
 218         Boolean state = (Boolean) fFeatures.get(featureId);
 219 
 220         if (state == null) {
 221             FeatureState checkState = checkFeature(featureId);
 222             if (checkState.isExceptional()) {
 223                 return checkState;
 224             }
 225             return FeatureState.is(false);
 226         }
 227         return FeatureState.is(state);
 228     }
 229 
 230     /**
 231      * Returns the value of a property.
 232      *
 233      * @param propertyId The property identifier.
 234                  * @return the value of the property
 235      *
 236      * @throws XMLConfigurationException Thrown for configuration error.
 237      *                                   In general, components should
 238      *                                   only throw this exception if
 239      *                                   it is <strong>really</strong>
 240      *                                   a critical error.
 241      */
 242     public final Object getProperty(String propertyId)
 243         throws XMLConfigurationException {
 244 
 245         PropertyState state = getPropertyState(propertyId);
 246         if (state.isExceptional()) {
 247             throw new XMLConfigurationException(state.status, propertyId);
 248         }
 249 
 250         return state.state;
 251     } // getProperty(String):Object
 252 
 253     public final Object getProperty(String propertyId, Object defaultValue) {
 254         PropertyState state = getPropertyState(propertyId);
 255         if (state.isExceptional()) {
 256             return defaultValue;
 257         }
 258 
 259         return state.state;
 260     }
 261 
 262     public PropertyState getPropertyState(String propertyId) {
 263         Object propertyValue = fProperties.get(propertyId);
 264 
 265         if (propertyValue == null) {
 266             PropertyState state = checkProperty(propertyId);
 267             if (state.isExceptional()) {
 268                 return state;
 269             }
 270         }
 271 
 272         return PropertyState.is(propertyValue);
 273     }
 274 
 275     //
 276     // Protected methods
 277     //
 278 
 279     /**
 280      * Check a feature. If feature is known and supported, this method simply
 281      * returns. Otherwise, the appropriate exception is thrown.
 282      *
 283      * @param featureId The unique identifier (URI) of the feature.
 284      *
 285      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
 286      *            requested feature is not known.
 287      */
 288     protected FeatureState checkFeature(String featureId)
 289         throws XMLConfigurationException {
 290 
 291         // check feature
 292         if (!fRecognizedFeatures.contains(featureId)) {
 293             if (fParentSettings != null) {
 294                 return fParentSettings.getFeatureState(featureId);
 295             }
 296             else {
 297                 return FeatureState.NOT_RECOGNIZED;
 298             }
 299         }
 300 
 301         // TODO: reasonable default?
 302         return FeatureState.RECOGNIZED;
 303     } // checkFeature(String)
 304 
 305     /**
 306      * Check a property. If the property is known and supported, this method
 307      * simply returns. Otherwise, the appropriate exception is thrown.
 308      *
 309      * @param propertyId The unique identifier (URI) of the property
 310      *                   being set.
 311      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
 312      *            requested feature is not known.
 313      */
 314     protected PropertyState checkProperty(String propertyId)
 315         throws XMLConfigurationException {
 316 
 317         // check property
 318         if (!fRecognizedProperties.contains(propertyId)) {
 319             if (fParentSettings != null) {
 320                 PropertyState state = fParentSettings.getPropertyState(propertyId);
 321                 if (state.isExceptional()) {
 322                     return state;
 323                 }
 324             }
 325             else {
 326                 return PropertyState.NOT_RECOGNIZED;
 327             }
 328         }
 329         return PropertyState.RECOGNIZED;
 330     } // checkProperty(String)
 331 
 332 } // class ParserConfigurationSettings