001/* 002 * $Id: ChainedProperties.java 4666 2011-01-29 12:53:09Z blowagie $ 003 * 004 * This file is part of the iText (R) project. 005 * Copyright (c) 1998-2011 1T3XT BVBA 006 * Authors: Bruno Lowagie, Paulo Soares, et al. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Affero General Public License version 3 010 * as published by the Free Software Foundation with the addition of the 011 * following permission added to Section 15 as permitted in Section 7(a): 012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT, 013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. 014 * 015 * This program is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 017 * or FITNESS FOR A PARTICULAR PURPOSE. 018 * See the GNU Affero General Public License for more details. 019 * You should have received a copy of the GNU Affero General Public License 020 * along with this program; if not, see http://www.gnu.org/licenses or write to 021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 022 * Boston, MA, 02110-1301 USA, or download the license from the following URL: 023 * http://itextpdf.com/terms-of-use/ 024 * 025 * The interactive user interfaces in modified source and object code versions 026 * of this program must display Appropriate Legal Notices, as required under 027 * Section 5 of the GNU Affero General Public License. 028 * 029 * In accordance with Section 7(b) of the GNU Affero General Public License, 030 * a covered work must retain the producer line in every PDF that is created 031 * or manipulated using iText. 032 * 033 * You can be released from the requirements of the license by purchasing 034 * a commercial license. Buying such a license is mandatory as soon as you 035 * develop commercial activities involving the iText software without 036 * disclosing the source code of your own applications. 037 * These activities include: offering paid services to customers as an ASP, 038 * serving PDFs on the fly in a web application, shipping iText with a closed 039 * source product. 040 * 041 * For more information, please contact iText Software Corp. at this 042 * address: sales@itextpdf.com 043 */ 044package com.itextpdf.text.html.simpleparser; 045 046import java.util.ArrayList; 047import java.util.List; 048import java.util.Map; 049 050import com.itextpdf.text.html.HtmlTags; 051import com.itextpdf.text.html.HtmlUtilities; 052 053/** 054 * Stores the hierarchy of tags along with the attributes of each tag. 055 * @since 5.0.6 renamed from ChainedProperties 056 */ 057public class ChainedProperties { 058 059 /** 060 * Class that stores the info about one tag in the chain. 061 */ 062 private static final class TagAttributes { 063 /** A possible tag */ 064 final String tag; 065 /** The styles corresponding with the tag */ 066 final Map<String, String> attrs; 067 /** 068 * Constructs a chained property. 069 * @param tag an XML/HTML tag 070 * @param attrs the tag's attributes 071 */ 072 TagAttributes(String tag, Map<String, String> attrs) { 073 this.tag = tag; 074 this.attrs = attrs; 075 } 076 } 077 078 /** A list of chained properties representing the tag hierarchy. */ 079 public List<TagAttributes> chain = new ArrayList<TagAttributes>(); 080 081 /** Creates a new instance of ChainedProperties */ 082 public ChainedProperties() { 083 } 084 085 /** 086 * Walks through the hierarchy (bottom-up) looking for 087 * a property key. Returns a value as soon as a match 088 * is found or null if the key can't be found. 089 * @param key the key of the property 090 * @return the value of the property 091 */ 092 public String getProperty(String key) { 093 for (int k = chain.size() - 1; k >= 0; --k) { 094 TagAttributes p = chain.get(k); 095 Map<String, String> attrs = p.attrs; 096 String ret = attrs.get(key); 097 if (ret != null) 098 return ret; 099 } 100 return null; 101 } 102 103 /** 104 * Walks through the hierarchy (bottom-up) looking for 105 * a property key. Returns true as soon as a match is 106 * found or false if the key can't be found. 107 * @param key the key of the property 108 * @return true if the key is found 109 */ 110 public boolean hasProperty(String key) { 111 for (int k = chain.size() - 1; k >= 0; --k) { 112 TagAttributes p = chain.get(k); 113 Map<String, String> attrs = p.attrs; 114 if (attrs.containsKey(key)) 115 return true; 116 } 117 return false; 118 } 119 120 /** 121 * Adds a tag and its corresponding properties to the chain. 122 * @param tag the tags that needs to be added to the chain 123 * @param props the tag's attributes 124 */ 125 public void addToChain(String tag, Map<String, String> props) { 126 this.adjustFontSize(props); 127 chain.add(new TagAttributes(tag, props)); 128 } 129 130 /** 131 * Walks through the hierarchy (bottom-up) and removes the 132 * first occurrence of a tag that is encountered. 133 * @param tag the tag that needs to be removed 134 */ 135 public void removeChain(String tag) { 136 for (int k = chain.size() - 1; k >= 0; --k) { 137 if (tag.equals(chain.get(k).tag)) { 138 chain.remove(k); 139 return; 140 } 141 } 142 } 143 144 /** 145 * If the properties contain a font size, the size may need to 146 * be adjusted based on font sizes higher in the hierarchy. 147 * @param attrs the attributes that may have to be updated 148 * @since 5.0.6 (renamed) 149 */ 150 protected void adjustFontSize(Map<String, String> attrs) { 151 // fetch the font size 152 String value = attrs.get(HtmlTags.SIZE); 153 // do nothing if the font size isn't defined 154 if (value == null) 155 return; 156 // the font is defined as a real size: remove "pt" 157 if (value.endsWith("pt")) { 158 attrs.put(HtmlTags.SIZE, 159 value.substring(0, value.length() - 2)); 160 return; 161 } 162 String old = getProperty(HtmlTags.SIZE); 163 attrs.put(HtmlTags.SIZE, Integer.toString(HtmlUtilities.getIndexedFontSize(value, old))); 164 } 165}