source: trunk/src/org/expeditee/settings/Settings.java@ 1393

Last change on this file since 1393 was 1393, checked in by bln4, 5 years ago

Maintain caseing for settings.

File size: 10.4 KB
Line 
1/**
2 * Settings.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.settings;
20
21import java.lang.reflect.Field;
22import java.lang.reflect.Method;
23import java.util.HashMap;
24import java.util.Iterator;
25import java.util.LinkedList;
26import java.util.List;
27
28import org.expeditee.gui.AttributeValuePair;
29import org.expeditee.gui.Frame;
30import org.expeditee.gui.FrameCreator;
31import org.expeditee.gui.MessageBay;
32import org.expeditee.items.Text;
33import org.expeditee.items.widgets.Password;
34import org.expeditee.reflection.PackageLoader;
35import org.expeditee.setting.Setting;
36import org.expeditee.setting.VariableSetting;
37
38public abstract class Settings {
39
40 public static final String SETTINGS_PACKAGE_PARENT = "org.expeditee.";
41 public static final String SETTINGS_PACKAGE = SETTINGS_PACKAGE_PARENT + "settings.";
42
43 private static final class PageDescriptor {
44
45 private final HashMap<String, Setting> settings = new HashMap<String, Setting>();
46 private final List<String> orderedEntries = new LinkedList<String>();
47 private final List<VariableSetting> settingsList = new LinkedList<VariableSetting>();
48 private final Method onParsed;
49
50 private PageDescriptor(Class<?> clazz) {
51
52 // populate map of settings
53 for(Field f : clazz.getFields()) {
54 // Only allow classes that inherit from Setting
55 if(!Setting.class.isAssignableFrom(f.getType())) continue;
56
57 try {
58 Setting s = (Setting) f.get(null);
59 settings.put(f.getName().toLowerCase(), s);
60 if (s instanceof VariableSetting) settingsList.add((VariableSetting) s);
61 orderedEntries.add(f.getName());
62 } catch (Exception e) {
63 e.printStackTrace();
64 }
65 }
66
67 Method m = null;
68
69 try {
70 m = clazz.getMethod("onParsed", Text.class);
71 } catch(Exception e) {
72 // System.err.println(clazz.getName() + " has no onParsed(Text t) callback");
73 }
74
75 this.onParsed = m;
76 }
77 }
78
79 private static HashMap<String, PageDescriptor> _pages = new HashMap<String, PageDescriptor>();
80
81 private static boolean _init = false;
82
83 public static void Init()
84 {
85 if(_init) return;
86
87 _init = true;
88
89 try {
90 for(Class<?> clazz : PackageLoader.getClassesNew(SETTINGS_PACKAGE)) {
91 // Ignore this class since it's the controller
92 if(clazz.equals(Settings.class)) continue;
93
94 String settingsPageName = clazz.getPackage().getName().toLowerCase().substring(SETTINGS_PACKAGE_PARENT.length());
95
96 // System.out.println(settingsPage + " : " + clazz.getName());
97 _pages.put(settingsPageName, new PageDescriptor(clazz));
98 }
99
100 } catch (Exception e) {
101 e.printStackTrace();
102 }
103 }
104
105 /** Parses the settings tree, then resets any settings that were not set. */
106 public static void parseSettings(Text text)
107 {
108 List<VariableSetting> set = parseSettings(text, "");
109 List<VariableSetting> toDefault = new LinkedList<VariableSetting>();
110
111 for(PageDescriptor pd : _pages.values()) toDefault.addAll(pd.settingsList);
112
113 toDefault.removeAll(set);
114
115 for(VariableSetting s : toDefault) {
116 try {
117 s.reset();
118 } catch (Exception e) {
119 e.printStackTrace();
120 }
121 }
122 }
123
124 public static void resetAllSettings() {
125 for (PageDescriptor pd : _pages.values()) {
126 for (VariableSetting s : pd.settingsList) {
127 s.reset();
128 }
129 }
130 }
131
132 /**
133 * Sets all the simple settings.
134 *
135 * @param text
136 * @param prefix
137 *
138 * @return List of VariableSettings that were changed
139 */
140 private static List<VariableSetting> parseSettings(Text text, String prefix) {
141
142 List<VariableSetting> set = new LinkedList<VariableSetting>();
143
144 Frame child = text.getChild();
145
146 if(child == null) return set;
147
148 String settingsPage = prefix + text.getText().trim().toLowerCase().replaceAll("^@", "");
149 PageDescriptor pd = _pages.get(settingsPage);
150 if(pd == null) return set;
151
152 try {
153 // set the fields
154 List<Text> items = child.getBodyTextItems(false);
155 List<Text> annotations = new LinkedList<Text>(child.getAnnotationItems());
156 List<Frame> seen = new LinkedList<Frame>(); // to avoid getting stuck in a loop
157 seen.add(child);
158 // find all the frames for this settings page
159 while(!annotations.isEmpty()) {
160 Text annotation = annotations.remove(0);
161 Frame next = annotation.getChild();
162 if(next != null && !seen.contains(next)) {
163 items.addAll(next.getBodyTextItems(false));
164 annotations.addAll(next.getAnnotationItems());
165 seen.add(next);
166 }
167 }
168
169 // parse all the settings items on this page
170 for(Text t : items) {
171 AttributeValuePair avp = new AttributeValuePair(t.getText(), false);
172 try {
173 String settingName = avp.getAttributeOrValue().trim().toLowerCase();
174 // System.out.println(avp.getAttributeOrValue().trim().toLowerCase().replaceAll("^@", ""));
175 Setting s = pd.settings.get(settingName);//.replaceAll("^@", ""));
176 if(s == null) {
177 if(settingName.startsWith("//") || settingName.startsWith("@")) {
178 continue;
179 }
180 // System.out.println("Couldn't find setting \"" + settingName + "\"");
181 List<String> validPages = new LinkedList<String>();
182 // if the setting isn't found on the current page, check all child pages
183 for(String k : _pages.keySet()) {
184 if(k.startsWith(settingsPage) && k.length() > settingsPage.length()) {
185 // System.out.println(k + " is a child of " + settingsPage);
186 PageDescriptor cpd = _pages.get(k);
187 Setting tmp = cpd.settings.get(settingName);
188 if(tmp != null) {
189 // System.out.println("Found setting in subpage: " + k);
190 s = tmp;
191 validPages.add(k);
192 }
193 }
194 }
195
196 if(s == null) continue;
197
198 if(validPages.size() > 1) {
199 StringBuffer warnMessage = new StringBuffer("Found multiple matching settings in the following settings subpages: ");
200 String lastPage = "";
201 for(String page : validPages) {
202 warnMessage.append("\"" + page + "\",");
203 lastPage = page;
204 }
205 warnMessage.deleteCharAt(warnMessage.length() - 1);
206 warnMessage.append(" - choosing " + lastPage);
207 MessageBay.warningMessage(warnMessage.toString());
208 }
209 }
210
211 if(s.setSetting(t) && s instanceof VariableSetting) set.add((VariableSetting) s);
212
213 } catch (Exception e) {
214 e.printStackTrace();
215 }
216 }
217
218 // call the onParsed method if one exists
219 if(pd.onParsed != null) {
220 pd.onParsed.invoke(null, text);
221 }
222
223 } catch (Exception e) {
224 e.printStackTrace();
225 return set;
226 }
227
228 // if the page was a settings page, check if it has any subpages
229 for(Text t : child.getTextItems()) {
230 set.addAll(parseSettings(t, settingsPage + "."));
231 }
232 return set;
233 }
234
235 public static void generateSettingsTree(Text link) {
236 generateSettingsTree("settings", link);
237 }
238
239 private static void generateSettingsTree(String page, Text text) {
240 Frame parent = text.getParentOrCurrentFrame();
241 FrameCreator frames = new FrameCreator(parent.getFramesetName(), parent.getPath(), page, FrameCreator.ExistingFramesetOptions.AppendSegregatedFrames, false, null);
242 text.setLink(frames.getName());
243
244 // Add subpages of the current page by recursing
245 for (String k: _pages.keySet()) {
246 if (k.startsWith(page.toLowerCase()) && !k.equals(page)) {
247 String name = k.substring(page.length() + 1);
248 if (name.indexOf('.') != -1) {
249 continue;
250 }
251 System.out.println("@Settings: Generating " + name);
252 generateSettingsTree(k, frames.addText(name.substring(0, 1).toUpperCase() + name.substring(1), null, null, null, false));
253 }
254 }
255
256 // Start building current page
257 frames.setLastY(frames.getLastY() + 20);
258 // Add Settings of the current page
259 PageDescriptor pd = _pages.get(page);
260 if (pd == null) {
261 frames.save();
262 return;
263 }
264
265 //Iterator<String> keys = pd.orderedEntries.stream().map(t -> t.toLowerCase()).iterator();
266 Iterator<String> keys = pd.orderedEntries.iterator();
267 while(keys.hasNext()) {
268 String key = keys.next();
269 Setting setting = pd.settings.get(key.toLowerCase());
270 if (setting == null) {
271 continue;
272 }
273
274 // Keep track of were we are placing items on Frames.
275 int x = 0, y = 0;
276
277 if (key.toLowerCase().equals("pass")) {
278 // Special case for Password widgets
279 Text passwordWidgetText = frames.addText("iw: org.expeditee.items.widgets.Passwsord", null, null, null, false);
280 Password pw = new Password(passwordWidgetText, null);
281 pw.setPassword("");
282 frames.getCurrentFrame().removeItem(passwordWidgetText);
283 frames.getCurrentFrame().addAllItems(pw.getItems());
284 x = passwordWidgetText.getX() + passwordWidgetText.getBoundsWidth();
285 y = passwordWidgetText.getY();
286 } else {
287 // Determine the content for a setting label.
288 //String name = key.substring(0, 1).toUpperCase() + key.substring(1);
289 //String name = key;
290
291 // Construct and add text representation for setting.
292 // If a setting has no initialised value then it is not included.
293 Text settingRepresentation = setting.generateRepresentation(key, frames.getCurrentFrame().getFramesetName()).copy();
294 if (settingRepresentation.getBounds() == null) {
295 continue;
296 }
297 settingRepresentation.setID(frames.getCurrentFrame().getNextItemID());
298 frames.addItem(settingRepresentation, false);
299 x = settingRepresentation.getX() + settingRepresentation.getBoundsWidth();
300 y = settingRepresentation.getY();
301 }
302
303 x = Math.max(250, x + 20);
304 // Add tooltip for setting
305 Text tooltip = frames.getCurrentFrame().addText(x, y, "// " + setting.getTooltip(), null);
306 tooltip.rebuild(true);
307 if (tooltip.getY() + tooltip.getBoundsHeight() > frames.getLastY()) {
308 frames.setLastY(tooltip.getY() + tooltip.getBoundsHeight());
309 }
310 }
311
312 frames.save();
313 }
314}
Note: See TracBrowser for help on using the repository browser.