1cf936e33SAndre Fischer /************************************************************** 2cf936e33SAndre Fischer * 3cf936e33SAndre Fischer * Licensed to the Apache Software Foundation (ASF) under one 4cf936e33SAndre Fischer * or more contributor license agreements. See the NOTICE file 5cf936e33SAndre Fischer * distributed with this work for additional information 6cf936e33SAndre Fischer * regarding copyright ownership. The ASF licenses this file 7cf936e33SAndre Fischer * to you under the Apache License, Version 2.0 (the 8cf936e33SAndre Fischer * "License"); you may not use this file except in compliance 9cf936e33SAndre Fischer * with the License. You may obtain a copy of the License at 10cf936e33SAndre Fischer * 11cf936e33SAndre Fischer * http://www.apache.org/licenses/LICENSE-2.0 12cf936e33SAndre Fischer * 13cf936e33SAndre Fischer * Unless required by applicable law or agreed to in writing, 14cf936e33SAndre Fischer * software distributed under the License is distributed on an 15cf936e33SAndre Fischer * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16cf936e33SAndre Fischer * KIND, either express or implied. See the License for the 17cf936e33SAndre Fischer * specific language governing permissions and limitations 18cf936e33SAndre Fischer * under the License. 19cf936e33SAndre Fischer * 20cf936e33SAndre Fischer *************************************************************/ 21cf936e33SAndre Fischer 227d97ce35SAndre Fischer package org.apache.openoffice.ooxml.parser.attribute; 23cf936e33SAndre Fischer 24cf936e33SAndre Fischer import java.util.HashMap; 2562886075SAndre Fischer import java.util.HashSet; 26cf936e33SAndre Fischer import java.util.Map; 2762886075SAndre Fischer import java.util.Set; 286cde7e4aSAndre Fischer import java.util.Vector; 29cf936e33SAndre Fischer 307d97ce35SAndre Fischer import org.apache.openoffice.ooxml.parser.Log; 317d97ce35SAndre Fischer import org.apache.openoffice.ooxml.parser.NameMap; 327d97ce35SAndre Fischer import org.apache.openoffice.ooxml.parser.NamespaceMap; 337d97ce35SAndre Fischer import org.apache.openoffice.ooxml.parser.type.SimpleTypeManager; 347d97ce35SAndre Fischer 3562886075SAndre Fischer 3662886075SAndre Fischer /** Match a set of attributes from the document with the attribute 3762886075SAndre Fischer * specifications of a state. 3862886075SAndre Fischer * 3962886075SAndre Fischer */ 40cf936e33SAndre Fischer public class AttributeManager 41cf936e33SAndre Fischer { 4262886075SAndre Fischer /** Create a new AttributeManager for the attribute specifications that 4362886075SAndre Fischer * are given in the parse table. 4462886075SAndre Fischer */ AttributeManager( final Vector<String[]> aData, final NamespaceMap aNamespaceMap, final NameMap aNameMap, final NameMap aStateNameMap, final SimpleTypeManager aSimpleTypeManager, final Vector<String> aErrorsAndWarnings)4562886075SAndre Fischer public AttributeManager ( 4662886075SAndre Fischer final Vector<String[]> aData, 4762886075SAndre Fischer final NamespaceMap aNamespaceMap, 487d97ce35SAndre Fischer final NameMap aNameMap, 497d97ce35SAndre Fischer final NameMap aStateNameMap, 50*360147c7SAndre Fischer final SimpleTypeManager aSimpleTypeManager, 51*360147c7SAndre Fischer final Vector<String> aErrorsAndWarnings) 52cf936e33SAndre Fischer { 5362886075SAndre Fischer maStateIdToAttributesMap = new HashMap<>(); 5462886075SAndre Fischer maNamespaceMap = aNamespaceMap; 5562886075SAndre Fischer maNameMap = aNameMap; 567d97ce35SAndre Fischer maStateNameMap = aStateNameMap; 577d97ce35SAndre Fischer maSimpleTypeManager = aSimpleTypeManager; 58*360147c7SAndre Fischer maErrorsAndWarnings = aErrorsAndWarnings; 597d97ce35SAndre Fischer ParseData(aData); 607d97ce35SAndre Fischer } 617d97ce35SAndre Fischer 627d97ce35SAndre Fischer 637d97ce35SAndre Fischer 647d97ce35SAndre Fischer ParseData(final Vector<String[]> aData)657d97ce35SAndre Fischer private void ParseData (final Vector<String[]> aData) 667d97ce35SAndre Fischer { 6762886075SAndre Fischer for (final String[] aLine : aData) 6862886075SAndre Fischer { 6962886075SAndre Fischer final int nStateId = Integer.parseInt(aLine[1]); 7062886075SAndre Fischer final int nPrefixId = Integer.parseInt(aLine[2]); 7162886075SAndre Fischer final boolean bCanBeUnqualified = aLine[3].startsWith("u"); 7262886075SAndre Fischer final int nAttributeId = Integer.parseInt(aLine[4]); 737d97ce35SAndre Fischer final int nAttributeTypeId = aLine[5].equals("null") ? -1 : Integer.parseInt(aLine[5]); 7462886075SAndre Fischer final boolean bIsOptional = aLine[6].startsWith("o"); 757d97ce35SAndre Fischer final String sDefault = aLine[7]; 767d97ce35SAndre Fischer // State name. 777d97ce35SAndre Fischer final String sAttributeName = aLine[9]; 787d97ce35SAndre Fischer // Attribute type name. 7962886075SAndre Fischer 8062886075SAndre Fischer Map<Integer,AttributeDescriptor> aAttributesPerState = maStateIdToAttributesMap.get(nStateId); 8162886075SAndre Fischer if (aAttributesPerState == null) 8262886075SAndre Fischer { 8362886075SAndre Fischer aAttributesPerState = new HashMap<>(); 8462886075SAndre Fischer maStateIdToAttributesMap.put(nStateId, aAttributesPerState); 8562886075SAndre Fischer } 8662886075SAndre Fischer 8762886075SAndre Fischer final AttributeDescriptor aAttributeDescriptor = new AttributeDescriptor( 8862886075SAndre Fischer nPrefixId, 8962886075SAndre Fischer nAttributeId, 9062886075SAndre Fischer bCanBeUnqualified, 9162886075SAndre Fischer bIsOptional, 9262886075SAndre Fischer sDefault, 9362886075SAndre Fischer sAttributeName, 947d97ce35SAndre Fischer nAttributeTypeId); 9562886075SAndre Fischer 9662886075SAndre Fischer aAttributesPerState.put( 9762886075SAndre Fischer (nPrefixId<<16)|nAttributeId, 9862886075SAndre Fischer aAttributeDescriptor); 9962886075SAndre Fischer if (bCanBeUnqualified) 10062886075SAndre Fischer aAttributesPerState.put( 10162886075SAndre Fischer nAttributeId, 10262886075SAndre Fischer aAttributeDescriptor); 10362886075SAndre Fischer } 104cf936e33SAndre Fischer } 105cf936e33SAndre Fischer 106cf936e33SAndre Fischer 107cf936e33SAndre Fischer 108cf936e33SAndre Fischer 10962886075SAndre Fischer /** For the state with id nStateId, match the attributes from the document 11062886075SAndre Fischer * with the attribute specifications of that state. 11162886075SAndre Fischer */ ParseAttributes( final int nStateId, final AttributeProvider aDocumentAttributes)112c0b458d0SAndre Fischer public AttributeValues ParseAttributes ( 113cf936e33SAndre Fischer final int nStateId, 11462886075SAndre Fischer final AttributeProvider aDocumentAttributes) 115cf936e33SAndre Fischer { 116c0b458d0SAndre Fischer final AttributeValues aValues = new AttributeValues(); 117c0b458d0SAndre Fischer 11862886075SAndre Fischer final Map<Integer,AttributeDescriptor> aAttributesPerState = maStateIdToAttributesMap.get(nStateId); 11962886075SAndre Fischer if (aAttributesPerState == null) 120cf936e33SAndre Fischer { 12162886075SAndre Fischer if (aDocumentAttributes.HasAttributes()) 12262886075SAndre Fischer { 12362886075SAndre Fischer Log.Std.printf("state has not attributes defined but document provides %d attributes\n", 12462886075SAndre Fischer aDocumentAttributes.GetAttributeCount()); 12562886075SAndre Fischer for (final String[] aEntry : aDocumentAttributes) 12662886075SAndre Fischer { 12762886075SAndre Fischer Log.Dbg.printf(" %s -> %s\n", aEntry[0], aEntry[1]); 12862886075SAndre Fischer } 12962886075SAndre Fischer throw new RuntimeException(); 13062886075SAndre Fischer } 131cf936e33SAndre Fischer } 132cf936e33SAndre Fischer else 133cf936e33SAndre Fischer { 13462886075SAndre Fischer final Set<AttributeDescriptor> aUsedAttributes = new HashSet<>(); 13562886075SAndre Fischer 13662886075SAndre Fischer // Process all attributes from the document. 13762886075SAndre Fischer for (final String[] aEntry : aDocumentAttributes) 138cf936e33SAndre Fischer { 1397d97ce35SAndre Fischer final String sRawValue = aEntry[2]; 14062886075SAndre Fischer final AttributeDescriptor aAttributeDescriptor = ProcessAttribute( 14162886075SAndre Fischer aEntry[0], 14262886075SAndre Fischer aEntry[1], 1437d97ce35SAndre Fischer sRawValue, 14462886075SAndre Fischer aAttributesPerState); 14562886075SAndre Fischer aUsedAttributes.add(aAttributeDescriptor); 1467d97ce35SAndre Fischer final Object aProcessedValue = maSimpleTypeManager.PreprocessValue( 1477d97ce35SAndre Fischer sRawValue, 1487d97ce35SAndre Fischer aAttributeDescriptor); 1497d97ce35SAndre Fischer if (aProcessedValue == null) 1507d97ce35SAndre Fischer { 1517d97ce35SAndre Fischer maSimpleTypeManager.PreprocessValue( 1527d97ce35SAndre Fischer sRawValue, 1537d97ce35SAndre Fischer aAttributeDescriptor); 1547d97ce35SAndre Fischer throw new RuntimeException( 1557d97ce35SAndre Fischer String.format("value '%s' of attribute '%s' is not recognized", 1567d97ce35SAndre Fischer sRawValue, 1577d97ce35SAndre Fischer aAttributeDescriptor.GetName())); 1587d97ce35SAndre Fischer } 1597d97ce35SAndre Fischer aValues.AddAttribute( 1607d97ce35SAndre Fischer aAttributeDescriptor, 1617d97ce35SAndre Fischer sRawValue, 1627d97ce35SAndre Fischer aProcessedValue); 163c0b458d0SAndre Fischer 16462886075SAndre Fischer if (Log.Dbg != null) 16562886075SAndre Fischer { 16662886075SAndre Fischer if (aAttributeDescriptor == null) 16762886075SAndre Fischer Log.Dbg.printf("attribute %s%s is not known\n", 16862886075SAndre Fischer aEntry[0]==null ? "" : ":"+aEntry[0], 16962886075SAndre Fischer aEntry[1]); 17062886075SAndre Fischer else 1717d97ce35SAndre Fischer Log.Dbg.printf("attribute %s:%s(%d:%d) has type %s(%d) and value %s('%s')\n", 17262886075SAndre Fischer maNamespaceMap.GetDescriptorForId(aAttributeDescriptor.GetNamespaceId()).Prefix, 17362886075SAndre Fischer maNameMap.GetNameForId(aAttributeDescriptor.GetNameId()), 17462886075SAndre Fischer aAttributeDescriptor.GetNamespaceId(), 17562886075SAndre Fischer aAttributeDescriptor.GetNameId(), 1767d97ce35SAndre Fischer maStateNameMap.GetNameForId(aAttributeDescriptor.GetTypeId()), 1777d97ce35SAndre Fischer aAttributeDescriptor.GetTypeId(), 1787d97ce35SAndre Fischer aProcessedValue, 1797d97ce35SAndre Fischer sRawValue); 18062886075SAndre Fischer } 18162886075SAndre Fischer } 18262886075SAndre Fischer 18362886075SAndre Fischer // Check if all required attributes where given. 18462886075SAndre Fischer for (final AttributeDescriptor aAttribute : aAttributesPerState.values()) 18562886075SAndre Fischer { 1867d97ce35SAndre Fischer if ( ! aUsedAttributes.contains(aAttribute)) 18762886075SAndre Fischer { 1887d97ce35SAndre Fischer if ( ! aAttribute.IsOptional()) 189*360147c7SAndre Fischer { 190*360147c7SAndre Fischer final String sMessage = String.format("attribute '"+aAttribute.GetName()+"' is not present but also not optional"); 191*360147c7SAndre Fischer if (maErrorsAndWarnings != null) 192*360147c7SAndre Fischer maErrorsAndWarnings.add(sMessage); 193*360147c7SAndre Fischer else 194*360147c7SAndre Fischer throw new RuntimeException(sMessage); 195*360147c7SAndre Fischer } 1967d97ce35SAndre Fischer else 1977d97ce35SAndre Fischer { 1987d97ce35SAndre Fischer // Add an entry that gives access to the default value. 1997d97ce35SAndre Fischer aValues.AddAttribute(aAttribute, null, null); 2007d97ce35SAndre Fischer } 20162886075SAndre Fischer } 202cf936e33SAndre Fischer } 203cf936e33SAndre Fischer } 204c0b458d0SAndre Fischer 205c0b458d0SAndre Fischer return aValues; 206cf936e33SAndre Fischer } 20762886075SAndre Fischer 20862886075SAndre Fischer 20962886075SAndre Fischer 21062886075SAndre Fischer ProcessAttribute( final String sNamespace, final String sAttributeName, final String sAttributeValue, final Map<Integer,AttributeDescriptor> aAttributesPerState)21162886075SAndre Fischer private AttributeDescriptor ProcessAttribute ( 21262886075SAndre Fischer final String sNamespace, 21362886075SAndre Fischer final String sAttributeName, 21462886075SAndre Fischer final String sAttributeValue, 21562886075SAndre Fischer final Map<Integer,AttributeDescriptor> aAttributesPerState) 21662886075SAndre Fischer { 21762886075SAndre Fischer final AttributeDescriptor aAttributeDescriptor; 21862886075SAndre Fischer if (sNamespace == null) 21962886075SAndre Fischer { 22062886075SAndre Fischer // Attribute name has no namespace. 22162886075SAndre Fischer final int nAttributeNameId = maNameMap.GetIdForName(sAttributeName); 22262886075SAndre Fischer aAttributeDescriptor = aAttributesPerState.get(nAttributeNameId); 22362886075SAndre Fischer } 22462886075SAndre Fischer else 22562886075SAndre Fischer { 22662886075SAndre Fischer // Attribute name has explicit namespace. 22762886075SAndre Fischer final NamespaceMap.NamespaceDescriptor aDescriptor = maNamespaceMap.GetDescriptorForURI(sNamespace); 22862886075SAndre Fischer final int nAttributeNameId = maNameMap.GetIdForName(sAttributeName); 22962886075SAndre Fischer aAttributeDescriptor = aAttributesPerState.get((aDescriptor.Id<<16) | nAttributeNameId); 23062886075SAndre Fischer } 23162886075SAndre Fischer return aAttributeDescriptor; 23262886075SAndre Fischer } 23362886075SAndre Fischer 23462886075SAndre Fischer 23562886075SAndre Fischer 23662886075SAndre Fischer 23762886075SAndre Fischer /** Remove the quotes around the given string. 23862886075SAndre Fischer * If it has the special value null (without quotes) then the null reference 23962886075SAndre Fischer * is returned. 24062886075SAndre Fischer */ UnquoteString(final String sValue)24162886075SAndre Fischer private String UnquoteString (final String sValue) 24262886075SAndre Fischer { 24362886075SAndre Fischer if (sValue.equals("null")) 24462886075SAndre Fischer return null; 24562886075SAndre Fischer else 24662886075SAndre Fischer { 24762886075SAndre Fischer assert(sValue.startsWith("\"")); 24862886075SAndre Fischer assert(sValue.endsWith("\"")); 24962886075SAndre Fischer return sValue.substring(1, sValue.length()-1); 25062886075SAndre Fischer } 25162886075SAndre Fischer } 25262886075SAndre Fischer 253cf936e33SAndre Fischer 254cf936e33SAndre Fischer 255cf936e33SAndre Fischer GetAttributeCount()25662886075SAndre Fischer public int GetAttributeCount () 257cf936e33SAndre Fischer { 25862886075SAndre Fischer int nCount = 0; 25962886075SAndre Fischer for (final Map<Integer,AttributeDescriptor> aMap : maStateIdToAttributesMap.values()) 26062886075SAndre Fischer nCount += aMap.size(); 26162886075SAndre Fischer return nCount; 262cf936e33SAndre Fischer } 263cf936e33SAndre Fischer 264cf936e33SAndre Fischer 265cf936e33SAndre Fischer 266cf936e33SAndre Fischer 26762886075SAndre Fischer private final Map<Integer,Map<Integer,AttributeDescriptor>> maStateIdToAttributesMap; 26862886075SAndre Fischer private final NamespaceMap maNamespaceMap; 26962886075SAndre Fischer private final NameMap maNameMap; 2707d97ce35SAndre Fischer private final NameMap maStateNameMap; 2717d97ce35SAndre Fischer private final SimpleTypeManager maSimpleTypeManager; 272*360147c7SAndre Fischer private final Vector<String> maErrorsAndWarnings; 273cf936e33SAndre Fischer } 274