1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 package org.apache.openoffice.ooxml.schema.model.schema; 23 24 import java.util.HashMap; 25 import java.util.Iterator; 26 import java.util.Map; 27 import java.util.Map.Entry; 28 import java.util.TreeMap; 29 30 /** Map between namespace prefixes and URIs. 31 * While namespace URIs can have different prefixes in different schemas, 32 * we will use only one prefix in the OOXML parser. This class 33 * provides these global prefixes. 34 */ 35 public class NamespaceMap 36 implements Iterable<Entry<String, String>> 37 { NamespaceMap()38 public NamespaceMap () 39 { 40 maURIToPrefixMap = new HashMap<>(maPredefinedURIToPrefixMap); 41 42 // Predefine namespace prefixes. 43 // If possible then use the ones already in use in the schema files or documents written by MS Office, 44 // appended with a 06 or 12 for the ECMA-376 standards of 2006 (1st edition) or 2012 (4th edition). 45 maURIToPrefixMap.put("http://schemas.openxmlformats.org/drawingml/2006/main", "a06"); 46 maURIToPrefixMap.put("http://purl.oclc.org/ooxml/drawingml/main", "a12"); 47 48 maURIToPrefixMap.put("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", "wp06"); 49 maURIToPrefixMap.put("http://purl.oclc.org/ooxml/drawingml/wordprocessingDrawing", "wp12"); 50 51 maURIToPrefixMap.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w06"); 52 maURIToPrefixMap.put("http://purl.oclc.org/ooxml/wordprocessingml/main", "w12"); 53 54 maURIToPrefixMap.put("http://schemas.openxmlformats.org/drawingml/2006/picture", "dpct06"); 55 maURIToPrefixMap.put("http://purl.oclc.org/ooxml/drawingml/picture", "dpct12"); 56 57 maURIToPrefixMap.put("http://schemas.openxmlformats.org/officeDocument/2006/math", "m06"); 58 maURIToPrefixMap.put("http://purl.oclc.org/ooxml/officeDocument/math", "m12"); 59 60 maURIToPrefixMap.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r06"); 61 maURIToPrefixMap.put("http://purl.oclc.org/ooxml/officeDocument/relationships", "r12"); 62 63 // Invent prefixes that are not in use. 64 maURIToPrefixMap.put("http://schemas.openxmlformats.org/spreadsheetml/2006/main", "s06"); 65 maURIToPrefixMap.put("http://purl.oclc.org/ooxml/spreadsheetml/main", "s12"); 66 67 maURIToPrefixMap.put("http://schemas.openxmlformats.org/presentationml/2006/main", "p06"); 68 maURIToPrefixMap.put("http://purl.oclc.org/ooxml/presentationml/main", "p12"); 69 70 maURIToPrefixMap.put("http://schemas.openxmlformats.org/schemaLibrary/2006/main", "sl06"); 71 maURIToPrefixMap.put("http://purl.oclc.org/ooxml/schemaLibrary/main", "sl12"); 72 73 maURIToPrefixMap.put("http://purl.oclc.org/ooxml/drawingml/diagram", "dd12"); 74 maURIToPrefixMap.put("http://purl.oclc.org/ooxml/drawingml/chart", "dc12"); 75 maURIToPrefixMap.put("http://purl.oclc.org/ooxml/drawingml/lockedCanvas", "dlc12"); 76 } 77 78 79 80 ProvideNamespace( final String sNamespaceURI, final String sDefaultPrefix)81 public void ProvideNamespace ( 82 final String sNamespaceURI, 83 final String sDefaultPrefix) 84 { 85 if ( ! maURIToPrefixMap.containsKey(sNamespaceURI)) 86 { 87 final String sPrefix; 88 // Check if we can use the given prefix. 89 if (sDefaultPrefix==null || IsPrefixUsed(sDefaultPrefix)) 90 { 91 // Prefix is already used. We have to create a new and unique one. 92 String sCandidate = null; 93 for (int nIndex=0; nIndex<=26; ++nIndex) 94 { 95 if (nIndex == 26) 96 throw new RuntimeException("can not invent more than 26 namespace names"); 97 sCandidate= new String(new byte[]{(byte)('A'+nIndex)}); 98 if ( ! maURIToPrefixMap.containsKey(sCandidate)) 99 break; 100 } 101 sPrefix = sCandidate; 102 } 103 else 104 { 105 // Use the given prefix. 106 sPrefix = sDefaultPrefix; 107 } 108 109 maURIToPrefixMap.put(sNamespaceURI, sPrefix); 110 } 111 } 112 113 114 115 GetNamespacePrefix(final String sURI)116 public String GetNamespacePrefix (final String sURI) 117 { 118 return maURIToPrefixMap.get(sURI); 119 } 120 121 122 123 iterator()124 public Iterator<Entry<String,String>> iterator () 125 { 126 return maURIToPrefixMap.entrySet().iterator(); 127 } 128 129 130 131 GetCount()132 public Object GetCount() 133 { 134 return maURIToPrefixMap.size(); 135 } 136 137 138 139 140 /** Return all namespace entries sorted on the prefix. 141 */ GetSorted()142 public Iterable<Entry<String,String>> GetSorted () 143 { 144 final Map<String,Entry<String,String>> aSortedEntries = new TreeMap<>(); 145 for (final Entry<String,String> aEntry : maURIToPrefixMap.entrySet()) 146 if (aEntry.getValue() == null) 147 aSortedEntries.put("", aEntry); 148 else 149 aSortedEntries.put(aEntry.getValue(), aEntry); 150 return aSortedEntries.values(); 151 } 152 153 154 155 IsPrefixUsed(final String sPrefix)156 private boolean IsPrefixUsed (final String sPrefix) 157 { 158 for (final String sUsedPrefix : maURIToPrefixMap.values()) 159 { 160 if (sUsedPrefix == null) 161 continue; 162 if (sUsedPrefix.equals(sPrefix)) 163 return true; 164 } 165 return false; 166 } 167 168 169 170 171 private final Map<String,String> maURIToPrefixMap; 172 private final static Map<String,String> maPredefinedURIToPrefixMap; 173 static 174 { 175 maPredefinedURIToPrefixMap = new HashMap<>(); 176 maPredefinedURIToPrefixMap.put("http://www.w3.org/2001/XMLSchema", "xsd"); 177 } 178 } 179