| /************************************************************** |
| * |
| * 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 org.apache.openoffice.ooxml.parser.attribute; |
| |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.Vector; |
| |
| import org.apache.openoffice.ooxml.parser.Log; |
| import org.apache.openoffice.ooxml.parser.NameMap; |
| import org.apache.openoffice.ooxml.parser.NamespaceMap; |
| import org.apache.openoffice.ooxml.parser.type.SimpleTypeManager; |
| |
| |
| /** Match a set of attributes from the document with the attribute |
| * specifications of a state. |
| * |
| */ |
| public class AttributeManager |
| { |
| /** Create a new AttributeManager for the attribute specifications that |
| * are given in the parse table. |
| */ |
| public AttributeManager ( |
| final Vector<String[]> aData, |
| final NamespaceMap aNamespaceMap, |
| final NameMap aNameMap, |
| final NameMap aStateNameMap, |
| final SimpleTypeManager aSimpleTypeManager, |
| final Vector<String> aErrorsAndWarnings) |
| { |
| maStateIdToAttributesMap = new HashMap<>(); |
| maNamespaceMap = aNamespaceMap; |
| maNameMap = aNameMap; |
| maStateNameMap = aStateNameMap; |
| maSimpleTypeManager = aSimpleTypeManager; |
| maErrorsAndWarnings = aErrorsAndWarnings; |
| ParseData(aData); |
| } |
| |
| |
| |
| |
| private void ParseData (final Vector<String[]> aData) |
| { |
| for (final String[] aLine : aData) |
| { |
| final int nStateId = Integer.parseInt(aLine[1]); |
| final int nPrefixId = Integer.parseInt(aLine[2]); |
| final boolean bCanBeUnqualified = aLine[3].startsWith("u"); |
| final int nAttributeId = Integer.parseInt(aLine[4]); |
| final int nAttributeTypeId = aLine[5].equals("null") ? -1 : Integer.parseInt(aLine[5]); |
| final boolean bIsOptional = aLine[6].startsWith("o"); |
| final String sDefault = aLine[7]; |
| // State name. |
| final String sAttributeName = aLine[9]; |
| // Attribute type name. |
| |
| Map<Integer,AttributeDescriptor> aAttributesPerState = maStateIdToAttributesMap.get(nStateId); |
| if (aAttributesPerState == null) |
| { |
| aAttributesPerState = new HashMap<>(); |
| maStateIdToAttributesMap.put(nStateId, aAttributesPerState); |
| } |
| |
| final AttributeDescriptor aAttributeDescriptor = new AttributeDescriptor( |
| nPrefixId, |
| nAttributeId, |
| bCanBeUnqualified, |
| bIsOptional, |
| sDefault, |
| sAttributeName, |
| nAttributeTypeId); |
| |
| aAttributesPerState.put( |
| (nPrefixId<<16)|nAttributeId, |
| aAttributeDescriptor); |
| if (bCanBeUnqualified) |
| aAttributesPerState.put( |
| nAttributeId, |
| aAttributeDescriptor); |
| } |
| } |
| |
| |
| |
| |
| /** For the state with id nStateId, match the attributes from the document |
| * with the attribute specifications of that state. |
| */ |
| public AttributeValues ParseAttributes ( |
| final int nStateId, |
| final AttributeProvider aDocumentAttributes) |
| { |
| final AttributeValues aValues = new AttributeValues(); |
| |
| final Map<Integer,AttributeDescriptor> aAttributesPerState = maStateIdToAttributesMap.get(nStateId); |
| if (aAttributesPerState == null) |
| { |
| if (aDocumentAttributes.HasAttributes()) |
| { |
| Log.Std.printf("state has not attributes defined but document provides %d attributes\n", |
| aDocumentAttributes.GetAttributeCount()); |
| for (final String[] aEntry : aDocumentAttributes) |
| { |
| Log.Dbg.printf(" %s -> %s\n", aEntry[0], aEntry[1]); |
| } |
| throw new RuntimeException(); |
| } |
| } |
| else |
| { |
| final Set<AttributeDescriptor> aUsedAttributes = new HashSet<>(); |
| |
| // Process all attributes from the document. |
| for (final String[] aEntry : aDocumentAttributes) |
| { |
| final String sRawValue = aEntry[2]; |
| final AttributeDescriptor aAttributeDescriptor = ProcessAttribute( |
| aEntry[0], |
| aEntry[1], |
| sRawValue, |
| aAttributesPerState); |
| aUsedAttributes.add(aAttributeDescriptor); |
| final Object aProcessedValue = maSimpleTypeManager.PreprocessValue( |
| sRawValue, |
| aAttributeDescriptor); |
| if (aProcessedValue == null) |
| { |
| maSimpleTypeManager.PreprocessValue( |
| sRawValue, |
| aAttributeDescriptor); |
| throw new RuntimeException( |
| String.format("value '%s' of attribute '%s' is not recognized", |
| sRawValue, |
| aAttributeDescriptor.GetName())); |
| } |
| aValues.AddAttribute( |
| aAttributeDescriptor, |
| sRawValue, |
| aProcessedValue); |
| |
| if (Log.Dbg != null) |
| { |
| if (aAttributeDescriptor == null) |
| Log.Dbg.printf("attribute %s%s is not known\n", |
| aEntry[0]==null ? "" : ":"+aEntry[0], |
| aEntry[1]); |
| else |
| Log.Dbg.printf("attribute %s:%s(%d:%d) has type %s(%d) and value %s('%s')\n", |
| maNamespaceMap.GetDescriptorForId(aAttributeDescriptor.GetNamespaceId()).Prefix, |
| maNameMap.GetNameForId(aAttributeDescriptor.GetNameId()), |
| aAttributeDescriptor.GetNamespaceId(), |
| aAttributeDescriptor.GetNameId(), |
| maStateNameMap.GetNameForId(aAttributeDescriptor.GetTypeId()), |
| aAttributeDescriptor.GetTypeId(), |
| aProcessedValue, |
| sRawValue); |
| } |
| } |
| |
| // Check if all required attributes where given. |
| for (final AttributeDescriptor aAttribute : aAttributesPerState.values()) |
| { |
| if ( ! aUsedAttributes.contains(aAttribute)) |
| { |
| if ( ! aAttribute.IsOptional()) |
| { |
| final String sMessage = String.format("attribute '"+aAttribute.GetName()+"' is not present but also not optional"); |
| if (maErrorsAndWarnings != null) |
| maErrorsAndWarnings.add(sMessage); |
| else |
| throw new RuntimeException(sMessage); |
| } |
| else |
| { |
| // Add an entry that gives access to the default value. |
| aValues.AddAttribute(aAttribute, null, null); |
| } |
| } |
| } |
| } |
| |
| return aValues; |
| } |
| |
| |
| |
| |
| private AttributeDescriptor ProcessAttribute ( |
| final String sNamespace, |
| final String sAttributeName, |
| final String sAttributeValue, |
| final Map<Integer,AttributeDescriptor> aAttributesPerState) |
| { |
| final AttributeDescriptor aAttributeDescriptor; |
| if (sNamespace == null) |
| { |
| // Attribute name has no namespace. |
| final int nAttributeNameId = maNameMap.GetIdForName(sAttributeName); |
| aAttributeDescriptor = aAttributesPerState.get(nAttributeNameId); |
| } |
| else |
| { |
| // Attribute name has explicit namespace. |
| final NamespaceMap.NamespaceDescriptor aDescriptor = maNamespaceMap.GetDescriptorForURI(sNamespace); |
| final int nAttributeNameId = maNameMap.GetIdForName(sAttributeName); |
| aAttributeDescriptor = aAttributesPerState.get((aDescriptor.Id<<16) | nAttributeNameId); |
| } |
| return aAttributeDescriptor; |
| } |
| |
| |
| |
| |
| /** Remove the quotes around the given string. |
| * If it has the special value null (without quotes) then the null reference |
| * is returned. |
| */ |
| private String UnquoteString (final String sValue) |
| { |
| if (sValue.equals("null")) |
| return null; |
| else |
| { |
| assert(sValue.startsWith("\"")); |
| assert(sValue.endsWith("\"")); |
| return sValue.substring(1, sValue.length()-1); |
| } |
| } |
| |
| |
| |
| |
| public int GetAttributeCount () |
| { |
| int nCount = 0; |
| for (final Map<Integer,AttributeDescriptor> aMap : maStateIdToAttributesMap.values()) |
| nCount += aMap.size(); |
| return nCount; |
| } |
| |
| |
| |
| |
| private final Map<Integer,Map<Integer,AttributeDescriptor>> maStateIdToAttributesMap; |
| private final NamespaceMap maNamespaceMap; |
| private final NameMap maNameMap; |
| private final NameMap maStateNameMap; |
| private final SimpleTypeManager maSimpleTypeManager; |
| private final Vector<String> maErrorsAndWarnings; |
| } |