ConfigEntryTable.java |
1 /** 2 * Distribution License: 3 * JSword is free software; you can redistribute it and/or modify it under 4 * the terms of the GNU Lesser General Public License, version 2.1 or later 5 * as published by the Free Software Foundation. This program is distributed 6 * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even 7 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 * See the GNU Lesser General Public License for more details. 9 * 10 * The License is available on the internet at: 11 * http://www.gnu.org/copyleft/lgpl.html 12 * or by writing to: 13 * Free Software Foundation, Inc. 14 * 59 Temple Place - Suite 330 15 * Boston, MA 02111-1307, USA 16 * 17 * © CrossWire Bible Society, 2005 - 2016 18 * 19 */ 20 package org.crosswire.jsword.book.sword; 21 22 /** 23 * A utility class for loading the entries in a Sword book's conf file. Since 24 * the conf files are manually maintained, there can be all sorts of errors in 25 * them. This class does robust checking and reporting. 26 * <p/> 27 * <p/> 28 * Config file format. See also: <a href= 29 * "http://sword.sourceforge.net/cgi-bin/twiki/view/Swordapi/ConfFileLayout"> 30 * http://sword.sourceforge.net/cgi-bin/twiki/view/Swordapi/ConfFileLayout</a> 31 * <p/> 32 * <p/> 33 * The contents of the About field are in rtf. 34 * <p/> 35 * \ is used as a continuation line. 36 * 37 * @author Mark Goodwin 38 * @author Joe Walker 39 * @author Jacky Cheung 40 * @author DM Smith 41 * @see gnu.lgpl.License The GNU Lesser General Public License for details.<br> 42 * The copyright to this program is held by its authors. 43 */ 44 public final class ConfigEntryTable { 45 46 /** 47 * Create an empty Sword config for the named book. 48 * 49 * @param bookName the name of the book 50 * @param isRootConfig true to indicate a root configuration 51 */ 52 public ConfigEntryTable(String bookName, boolean isRootConfig) { 53 this(bookName, isRootConfig, null); 54 } 55 56 /** 57 * Sometimes, we're creating the config off another config, and so need to ensure the initials match exactly. 58 * 59 * @param bookName the name of the book 60 * @param isRootConfig true to indicate a root configuration 61 * @param initials the set of initials used to identify this module. This could be different to the bookName (which may be lowercase) 62 */ 63 public ConfigEntryTable(String bookName, boolean isRootConfig, String initials) { 64 this.initials = initials == null ? bookName : initials; 65 } 66 67 /** 68 * Build's a SWORD conf file as a string. The result is not identical to the 69 * original, cleaning up problems in the original and re-arranging the 70 * entries into a predictable order. 71 * 72 * @return the well-formed conf. 73 */ 74 public String toConf() { 75 StringBuilder buf = new StringBuilder(); 76 buf.append('['); 77 buf.append(initials); 78 buf.append("]\n"); 79 /* 80 toConf(buf, BASIC_INFO); 81 toConf(buf, SYSTEM_INFO); 82 toConf(buf, HIDDEN); 83 toConf(buf, FEATURE_INFO); 84 toConf(buf, LANG_INFO); 85 toConf(buf, COPYRIGHT_INFO); 86 toConf(buf, extra); 87 */ 88 return buf.toString(); 89 } 90 91 /* 92 protected void report() { 93 Iterator<String> kIter = config.keySet().iterator(); 94 while (kIter.hasNext()) { 95 String key = kIter.next(); 96 Iterator<String> vIter = config.getValues(key).iterator(); 97 while (vIter.hasNext()) { 98 String value = vIter.next(); 99 100 // Only CIPHER_KEYS that are empty are not ignored 101 if (value.length() == 0 && !SwordBookMetaData.KEY_CIPHER_KEY.equalsIgnoreCase(key)) { 102 log.warn("Ignoring empty entry in [{}]{}=", initials, key); 103 continue; 104 } 105 106 // Create a configEntry so that the name is normalized. 107 ConfigEntry configEntry = new ConfigEntry(initials, key); 108 ConfigEntryType type = configEntry.getType(); 109 ConfigEntry e = null; // table.get(type); 110 111 if (e == null) { 112 if (type == null) { 113 log.warn("Extra entry in [{}]{}", initials, configEntry.getName()); 114 // extra.put(key, configEntry); 115 } else if (type.isSynthetic()) { 116 log.warn("Ignoring unexpected entry in [{}]{}", initials, configEntry.getName()); 117 } else { 118 // table.put(type, configEntry); 119 } 120 } else { 121 configEntry = e; 122 } 123 // History is a special case it is of the form History_x.x 124 // The config entry is History without the x.x. 125 // We want to put x.x at the beginning of the string 126 if (ConfigEntryType.HISTORY.equals(type)) { 127 int pos = key.indexOf('_'); 128 value = key.substring(pos + 1) + ' ' + value; 129 } 130 131 configEntry.addValue(value); 132 133 // Filter known types of entries 134 if (type != null) { 135 value = type.filter(value); 136 137 // Report on fields that shouldn't have RTF but do 138 if (!type.allowsRTF() && RTF_PATTERN.matcher(value).find()) { 139 log.info("Unexpected RTF for [{}]{} = {}", initials, key, value); 140 } 141 142 if (type.mayRepeat()) { 143 if (!type.isAllowed(value)) { 144 log.info("Unknown config value for [{}]{} = {}", initials, key, value); 145 } 146 } else { 147 if (value != null) { 148 log.info("Ignoring unexpected additional entry for [{}]{} = {}", initials, key, value); 149 } else { 150 if (!type.isAllowed(value)) { 151 log.info("Unknown config value for [{}]{} = {}", initials, key, value); 152 } 153 } 154 } 155 } 156 } 157 } 158 } 159 */ 160 161 /** 162 * Build an ordered map so that it displays in a consistent order. 163 */ 164 /* 165 private void toConf(StringBuilder buf, ConfigEntryType[] category) { 166 for (int i = 0; i < category.length; i++) { 167 168 String entry = table.get(category[i]); 169 170 if (entry != null && !category[i].isSynthetic()) { 171 String text = entry.toConf(); 172 if (text != null && text.length() > 0) { 173 buf.append(entry.toConf()); 174 } 175 } 176 } 177 } 178 */ 179 /** 180 * Build an ordered map so that it displays in a consistent order. 181 */ 182 /* 183 private void toConf(StringBuilder buf, Map<String, ConfigEntry> map) { 184 for (Map.Entry<String, ConfigEntry> mapEntry : map.entrySet()) { 185 ConfigEntry entry = mapEntry.getValue(); 186 String text = entry.toConf(); 187 if (text != null && text.length() > 0) { 188 buf.append(text); 189 } 190 } 191 } 192 */ 193 194 /** 195 * The set of initials identifying this book 196 */ 197 private String initials; 198 199 /** 200 * A pattern of allowable RTF in a SWORD conf. These are: \pard, \pae, \par, \qc \b, \i and embedded Unicode 201 */ 202 // private static final Pattern RTF_PATTERN = Pattern.compile("\\\\pard|\\\\pa[er]|\\\\qc|\\\\[bi]|\\\\u-?[0-9]{4,6}+"); 203 204 } 205