| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| ConfigEntryTable |
|
| 1.3333333333333333;1.333 |
| 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 | 0 | this(bookName, isRootConfig, null); |
| 54 | 0 | } |
| 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 | 0 | public ConfigEntryTable(String bookName, boolean isRootConfig, String initials) { |
| 64 | 0 | this.initials = initials == null ? bookName : initials; |
| 65 | 0 | } |
| 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 | 0 | StringBuilder buf = new StringBuilder(); |
| 76 | 0 | buf.append('['); |
| 77 | 0 | buf.append(initials); |
| 78 | 0 | 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 | 0 | 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 | } |