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

Last change on this file since 1498 was 1498, checked in by bnemhaus, 4 years ago

Refactored variable name for clarity.

Comments explaining why an exception is being suppressed.

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