| /* |
| * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
| */ |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.sun.org.apache.xerces.internal.impl.xs; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Vector; |
| |
| /** |
| * A class used to hold the internal schema grammar set for the current instance |
| * |
| * @xerces.internal |
| * |
| * @author Sandy Gao, IBM |
| * @version $Id: XSGrammarBucket.java,v 1.7 2010-11-01 04:39:55 joehw Exp $ |
| */ |
| public class XSGrammarBucket { |
| |
| // Data |
| |
| /** |
| * Map that maps between Namespace and a Grammar |
| */ |
| Map<String, SchemaGrammar> fGrammarRegistry = new HashMap(); |
| SchemaGrammar fNoNSGrammar = null; |
| |
| /** |
| * Get the schema grammar for the specified namespace |
| * |
| * @param namespace |
| * @return SchemaGrammar associated with the namespace |
| */ |
| public SchemaGrammar getGrammar(String namespace) { |
| if (namespace == null) |
| return fNoNSGrammar; |
| return (SchemaGrammar)fGrammarRegistry.get(namespace); |
| } |
| |
| /** |
| * Put a schema grammar into the registry |
| * This method is for internal use only: it assumes that a grammar with |
| * the same target namespace is not already in the bucket. |
| * |
| * @param grammar the grammar to put in the registry |
| */ |
| public void putGrammar(SchemaGrammar grammar) { |
| if (grammar.getTargetNamespace() == null) |
| fNoNSGrammar = grammar; |
| else |
| fGrammarRegistry.put(grammar.getTargetNamespace(), grammar); |
| } |
| |
| /** |
| * put a schema grammar and any grammars imported by it (directly or |
| * inderectly) into the registry. when a grammar with the same target |
| * namespace is already in the bucket, and different from the one being |
| * added, it's an error, and no grammar will be added into the bucket. |
| * |
| * @param grammar the grammar to put in the registry |
| * @param deep whether to add imported grammars |
| * @return whether the process succeeded |
| */ |
| public boolean putGrammar(SchemaGrammar grammar, boolean deep) { |
| // whether there is one with the same tns |
| SchemaGrammar sg = getGrammar(grammar.fTargetNamespace); |
| if (sg != null) { |
| // if the one we have is different from the one passed, it's an error |
| return sg == grammar; |
| } |
| // not deep import, then just add this one grammar |
| if (!deep) { |
| putGrammar(grammar); |
| return true; |
| } |
| |
| // get all imported grammars, and make a copy of the Vector, so that |
| // we can recursively process the grammars, and add distinct ones |
| // to the same vector |
| Vector currGrammars = (Vector)grammar.getImportedGrammars(); |
| if (currGrammars == null) { |
| putGrammar(grammar); |
| return true; |
| } |
| |
| Vector grammars = ((Vector)currGrammars.clone()); |
| SchemaGrammar sg1, sg2; |
| Vector gs; |
| // for all (recursively) imported grammars |
| for (int i = 0; i < grammars.size(); i++) { |
| // get the grammar |
| sg1 = (SchemaGrammar)grammars.elementAt(i); |
| // check whether the bucket has one with the same tns |
| sg2 = getGrammar(sg1.fTargetNamespace); |
| if (sg2 == null) { |
| // we need to add grammars imported by sg1 too |
| gs = sg1.getImportedGrammars(); |
| // for all grammars imported by sg2, but not in the vector |
| // we add them to the vector |
| if(gs == null) continue; |
| for (int j = gs.size() - 1; j >= 0; j--) { |
| sg2 = (SchemaGrammar)gs.elementAt(j); |
| if (!grammars.contains(sg2)) |
| grammars.addElement(sg2); |
| } |
| } |
| // we found one with the same target namespace |
| // if the two grammars are not the same object, then it's an error |
| else if (sg2 != sg1) { |
| return false; |
| } |
| } |
| |
| // now we have all imported grammars stored in the vector. add them |
| putGrammar(grammar); |
| for (int i = grammars.size() - 1; i >= 0; i--) |
| putGrammar((SchemaGrammar)grammars.elementAt(i)); |
| |
| return true; |
| } |
| |
| /** |
| * put a schema grammar and any grammars imported by it (directly or |
| * inderectly) into the registry. when a grammar with the same target |
| * namespace is already in the bucket, and different from the one being |
| * added, no grammar will be added into the bucket. |
| * |
| * @param grammar the grammar to put in the registry |
| * @param deep whether to add imported grammars |
| * @param ignoreConflict whether to ignore grammars that already exist in the grammar |
| * bucket or not - including 'grammar' parameter. |
| * @return whether the process succeeded |
| */ |
| public boolean putGrammar(SchemaGrammar grammar, boolean deep, boolean ignoreConflict) { |
| if (!ignoreConflict) { |
| return putGrammar(grammar, deep); |
| } |
| |
| // if grammar already exist in the bucket, we ignore the request |
| SchemaGrammar sg = getGrammar(grammar.fTargetNamespace); |
| if (sg == null) { |
| putGrammar(grammar); |
| } |
| |
| // not adding the imported grammars |
| if (!deep) { |
| return true; |
| } |
| |
| // get all imported grammars, and make a copy of the Vector, so that |
| // we can recursively process the grammars, and add distinct ones |
| // to the same vector |
| Vector currGrammars = (Vector)grammar.getImportedGrammars(); |
| if (currGrammars == null) { |
| return true; |
| } |
| |
| Vector grammars = ((Vector)currGrammars.clone()); |
| SchemaGrammar sg1, sg2; |
| Vector gs; |
| // for all (recursively) imported grammars |
| for (int i = 0; i < grammars.size(); i++) { |
| // get the grammar |
| sg1 = (SchemaGrammar)grammars.elementAt(i); |
| // check whether the bucket has one with the same tns |
| sg2 = getGrammar(sg1.fTargetNamespace); |
| if (sg2 == null) { |
| // we need to add grammars imported by sg1 too |
| gs = sg1.getImportedGrammars(); |
| // for all grammars imported by sg2, but not in the vector |
| // we add them to the vector |
| if(gs == null) continue; |
| for (int j = gs.size() - 1; j >= 0; j--) { |
| sg2 = (SchemaGrammar)gs.elementAt(j); |
| if (!grammars.contains(sg2)) |
| grammars.addElement(sg2); |
| } |
| } |
| // we found one with the same target namespace, ignore it |
| else { |
| grammars.remove(sg1); |
| } |
| } |
| |
| // now we have all imported grammars stored in the vector. add them |
| for (int i = grammars.size() - 1; i >= 0; i--) { |
| putGrammar((SchemaGrammar)grammars.elementAt(i)); |
| } |
| |
| return true; |
| } |
| |
| /** |
| * get all grammars in the registry |
| * |
| * @return an array of SchemaGrammars. |
| */ |
| public SchemaGrammar[] getGrammars() { |
| // get the number of grammars |
| int count = fGrammarRegistry.size() + (fNoNSGrammar==null ? 0 : 1); |
| SchemaGrammar[] grammars = new SchemaGrammar[count]; |
| // get grammars with target namespace |
| int i = 0; |
| for(Map.Entry<String, SchemaGrammar> entry : fGrammarRegistry.entrySet()){ |
| grammars[i++] = entry.getValue(); |
| } |
| |
| // add the grammar without target namespace, if any |
| if (fNoNSGrammar != null) |
| grammars[count-1] = fNoNSGrammar; |
| return grammars; |
| } |
| |
| /** |
| * Clear the registry. |
| * REVISIT: update to use another XSGrammarBucket |
| */ |
| public void reset() { |
| fNoNSGrammar = null; |
| fGrammarRegistry.clear(); |
| } |
| |
| } // class XSGrammarBucket |