View Javadoc
1   /**
2    * The contents of this file are subject to the Mozilla Public License Version 1.1
3    * (the "License"); you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
5    * Software distributed under the License is distributed on an "AS IS" basis,
6    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
7    * specific language governing rights and limitations under the License.
8    *
9    * The Original Code is ""  Description:
10   * ""
11   *
12   * The Initial Developer of the Original Code is University Health Network. Copyright (C)
13   * 2001.  All Rights Reserved.
14   *
15   * Contributor(s): ______________________________________.
16   *
17   * Alternatively, the contents of this file may be used under the terms of the
18   * GNU General Public License (the  "GPL"), in which case the provisions of the GPL are
19   * applicable instead of those above.  If you wish to allow use of your version of this
20   * file only under the terms of the GPL and not to allow others to use your version
21   * of this file under the MPL, indicate your decision by deleting  the provisions above
22   * and replace  them with the notice and other provisions required by the GPL License.
23   * If you do not delete the provisions above, a recipient may use your version of
24   * this file under either the MPL or the GPL.
25   */
26  package ca.uhn.hl7v2.testpanel.controller;
27  
28  import static org.apache.commons.lang.StringUtils.*;
29  
30  import java.awt.Dimension;
31  import java.awt.Font;
32  import java.awt.Point;
33  import java.io.File;
34  import java.io.FileOutputStream;
35  import java.io.FileWriter;
36  import java.io.IOException;
37  import java.io.OutputStreamWriter;
38  import java.io.StringReader;
39  import java.io.StringWriter;
40  import java.io.Writer;
41  import java.nio.charset.Charset;
42  import java.util.ArrayList;
43  import java.util.Arrays;
44  import java.util.Collections;
45  import java.util.List;
46  import java.util.prefs.BackingStoreException;
47  import java.util.prefs.Preferences;
48  
49  import jakarta.xml.bind.JAXB;
50  import jakarta.xml.bind.JAXBContext;
51  import jakarta.xml.bind.JAXBException;
52  import jakarta.xml.bind.annotation.XmlAccessType;
53  import jakarta.xml.bind.annotation.XmlAccessorType;
54  import jakarta.xml.bind.annotation.XmlElement;
55  import jakarta.xml.bind.annotation.XmlRootElement;
56  
57  import org.apache.commons.lang.StringUtils;
58  import org.apache.commons.lang.Validate;
59  import org.slf4j.Logger;
60  import org.slf4j.LoggerFactory;
61  
62  import ca.uhn.hl7v2.hoh.util.IOUtils;
63  import ca.uhn.hl7v2.testpanel.model.conf.ExportedProfileGroupFile;
64  import ca.uhn.hl7v2.testpanel.model.conf.ProfileFileList;
65  import ca.uhn.hl7v2.testpanel.model.conf.ProfileGroup;
66  import ca.uhn.hl7v2.testpanel.model.conf.TableFileList;
67  import ca.uhn.hl7v2.testpanel.model.msg.Hl7V2MessageCollection;
68  import ca.uhn.hl7v2.testpanel.model.msg.Hl7V2MessageCollection.XmlFormat;
69  import ca.uhn.hl7v2.testpanel.util.CharsetUtils;
70  import ca.uhn.hl7v2.testpanel.util.FileNameComparator;
71  import ca.uhn.hl7v2.testpanel.util.FontUtil;
72  import ca.uhn.hl7v2.testpanel.util.LineEndingsEnum;
73  import ca.uhn.hl7v2.util.StringUtil;
74  
75  @XmlRootElement(name = "TestPanelPrefs", namespace = "urn:ca.uhn.hapi:testpanel:prefs")
76  @XmlAccessorType(XmlAccessType.FIELD)
77  public class Prefs {
78  
79  	private static final String GET_EXPORT_PROFILE_GROUP_DIRECTORY = "getExportProfileGroupDirectory";
80  	private static final String GET_HL7_EDITOR_SPLIT = "getHl7EditorSplit";
81  	private static final String GET_HL7V2_DIFF_FILE1 = "getHl7V2DiffFile1";
82  	private static final String GET_HL7V2_DIFF_FILE2 = "getHl7V2DiffFile2";
83  	private static final String GET_HL7V2_DIFF_SHOW_WHOLE_MESSAGE_ON_ERROR = "getHl7V2DiffShowWholeMessageOnError";
84  	private static final String GET_HL7V2_DIFF_STOP_ON_FIRST_ERROR = "getHl7V2DiffStopOnFirstError";
85  	private static final String GET_HL7V2_SORT_BY = "getHl7V2SortBy";
86  	private static final String GET_HL7V2_SORT_INPUT = "getHl7V2SortInputFile";
87  	private static final String GET_HL7V2_SORT_OUTPUT = "getHl7V2SortOutputFile";
88  	private static final String GET_HL7V2_SORT_OVERWRITE_MODE = "getHl7V2SortOverwriteMode";
89  	private static final String GET_INBOUND_CONNECTION_LIST = "getInboundConnectionList";
90  	private static final String GET_INTERFACE_HOH_SECURITY_KEYSTORE_DIRECTORY = "getInterfaceHohSecurityKeystoreDirectory";
91  	private static final String GET_MOST_RECENT_CONNECTION_CHARSET = "getMostRecentConnectionCharset";
92  	private static final String GET_MOST_RECENTLY_SELECTED_ITEM_ID = "getMostRecentlySelectedItemId";
93  	private static final String GET_OPEN_PATH_CONFORMANCE_PROFILE = "getOpenPathConformanceProfile";
94  	private static final String GET_OPEN_PATH_MESSAGES = "getOpenPathMessages";
95  	private static final String GET_OPEN_TABLE_FILES = "getOpenTableFiles";
96  	private static final String GET_OPENSAVE_CHARSET = "getOpenOrSaveCharset";
97  	private static final String GET_OUTBOUND_CONNECTION_LIST = "getOutboundConnectionList";
98  	private static final String GET_RECENT_MESSAGE_FILES = "getRecentMessageFiles";
99  	private static final String GET_SAVE_LINE_ENDINGS = "getSaveLineEndings";
100 	private static final String GET_SAVE_PATH_MESSAGES = "getSavePathMessages";
101 	private static final String GET_SAVE_STRIP_COMMENTS = "getSaveStripComments";
102 	private static final String GET_SHOW_LOG_CONSOLE = "getShowLogConsole";
103 	private static final String GET_WINDOW_MAXIMIZED = "getWindowMaximized";
104 	private static final String GET_WINDOW_POSITIONH = "getWindowPositionH";
105 	private static final String GET_WINDOW_POSITIONW = "getWindowPositionW";
106 	private static final String GET_WINDOW_POSITIONX = "getWindowPositionX";
107 	private static final String GET_WINDOW_POSITIONY = "getWindowPositionY";
108 
109 	private static Prefs ourInstance;
110 	private static JAXBContext ourJaxbContext;
111 	private static final Logger ourLog = LoggerFactory.getLogger(Prefs.class);
112 	private static final Preferences ourPrefs = Preferences.userNodeForPackage(ca.uhn.hl7v2.testpanel.controller.Prefs.class);
113 	private transient Controller myController;
114 
115 	@XmlElement(name = "export_profile_group_directory")
116 	private String myExportProfileGroupDirectory;
117 
118 	@XmlElement(name = "hl7v2_editor_split")
119 	private Integer myHl7EditorSplit;
120 
121 	@XmlElement(name = "hl7v2_diff_file1")
122 	private String myHl7V2DiffFile1;
123 
124 	@XmlElement(name = "hl7v2_diff_file2")
125 	private String myHl7V2DiffFile2;
126 
127 	@XmlElement(name = "hl7v2_show_whole_message_on_error")
128 	private boolean myHl7V2DiffShowWholeMessageOnError;
129 
130 	@XmlElement(name = "hl7v2_diff_stop_on_first_error")
131 	private boolean myHl7V2DiffStopOnFirstError;
132 
133 	@XmlElement(name = "hl7v2_sort_by")
134 	private String myHl7V2SortBy;
135 
136 	@XmlElement(name = "hl7v2_sort_input_file")
137 	private String myHl7V2SortInputFile;
138 
139 	@XmlElement(name = "hl7v2_output_file")
140 	private String myHl7V2SortOutputFile;
141 
142 	@XmlElement(name = "hl7v2_sort_override_mode")
143 	private String myHl7V2SortOverwriteMode;
144 
145 	@XmlElement(name = "import_profile_group_directory")
146 	private String myImportProfileGroupDirectory;
147 
148 	@XmlElement(name = "inbound_connection_list")
149 	private String myInboundConnectionList;
150 
151 	@XmlElement(name = "interface_hoh_security_keystore_directory")
152 	private String myInterfaceHohSecurityKeystoreDirectory;
153 
154 	private transient String myLastPrefsFileSaveValue;
155 
156 	@XmlElement(name = "most_recent_communication_charset")
157 	private String myMostRecentConnectionCharset;
158 
159 	@XmlElement(name = "most_recently_selected_item_id")
160 	private String myMostRecentlySelectedItemId;
161 
162 	// private List<OpenImportedProfileGroupFile>
163 	// myOpenImportedProfileGroupFile;
164 
165 	@XmlElement(name = "open_or_save_charset")
166 	private String myOpenOrSaveCharset;
167 
168 	@XmlElement(name = "open_path_conformance_profile")
169 	private String myOpenPathConformanceProfile;
170 
171 	@XmlElement(name = "open_path_messages")
172 	private String myOpenPathMessages;
173 
174 	@XmlElement(name = "open_table_files")
175 	private ArrayList<String> myOpenTableFiles;
176 
177 	@XmlElement(name = "outbound_connection_list")
178 	private String myOutboundConnectionList;
179 
180 	@XmlElement(name = "recent_message_xml_files")
181 	private List<XmlFormat> myRecentMessageXmlFiles;
182 
183 	@XmlElement(name = "save_line_endings")
184 	private String mySaveLineEndings;
185 
186 	@XmlElement(name = "save_path_messages")
187 	private String mySavePathMessages;
188 
189 	@XmlElement(name = "save_strip_comments")
190 	private boolean mySaveStripComments;
191 
192 	@XmlElement(name = "show_log_console")
193 	private boolean myShowLogConsole;
194 
195 	@XmlElement(name = "window_maximized")
196 	private boolean myWindowMaximized;
197 
198 	@XmlElement(name = "window_position_h")
199 	private int myWindowPositionH;
200 
201 	@XmlElement(name = "window_position_w")
202 	private int myWindowPositionW;
203 
204 	@XmlElement(name = "window_position_x")
205 	private Integer myWindowPositionX;
206 
207 	@XmlElement(name = "window_position_y")
208 	private Integer myWindowPositionY;
209 
210 	/**
211 	 * Non instantiable
212 	 */
213 	private Prefs() {
214 	}
215 
216 	public void addMessagesFileXmlToRecents(ProfileFileList theProfileFileList, List<Hl7V2MessageCollection> theMessageFiles) {
217 		List<Hl7V2MessageCollection> current = getRecentMessageXmlFiles(theProfileFileList);
218 		for (Hl7V2MessageCollection next : theMessageFiles) {
219 			if (StringUtils.isBlank(next.getSaveFileName())) {
220 				continue;
221 			}
222 			if (current.contains(next) == false) {
223 				current.add(0, next);
224 			}
225 		}
226 
227 		if (current.size() > 10) {
228 			current = current.subList(0, 10);
229 		}
230 
231 		myRecentMessageXmlFiles = new ArrayList<Hl7V2MessageCollection.XmlFormat>();
232 		for (Hl7V2MessageCollection string : current) {
233 			myRecentMessageXmlFiles.add(string.exportConfigToXmlWithoutContents());
234 		}
235 		sync();
236 	}
237 
238 	// public void addOpenImportedProfileGroupFile(OpenImportedProfileGroupFile
239 	// theFile) {
240 	// getOpenImportedProfileGroupFile().add(theFile);
241 	// sync();
242 	// }
243 
244 	public void clearRecentMessageXmlFiles() {
245 		myRecentMessageXmlFiles = new ArrayList<Hl7V2MessageCollection.XmlFormat>();
246 		sync();
247 	}
248 
249 	public String getExportProfileGroupDirectory() {
250 		return defaultString(myExportProfileGroupDirectory);
251 	}
252 
253 	public Font getHl7EditorFont() {
254 		Font retVal;
255 
256 		List<String> fonts = FontUtil.getMonospacedFontNames();
257 		if (fonts.contains("Monaco")) {
258 			retVal = new Font("Monaco", Font.PLAIN, 12);
259 		} else if (fonts.contains("Andale Mono")) {
260 			retVal = new Font("Andale Mono", Font.PLAIN, 12);
261 		} else if (fonts.contains("Lucida Console")) {
262 			retVal = new Font("Lucida Console", Font.PLAIN, 12);
263 		} else if (fonts.contains("Consolas")) {
264 			retVal = new Font("Consolas", Font.PLAIN, 12);
265 		} else if (fonts.contains("Lucida Sans Typewriter")) {
266 			retVal = new Font("Lucida Sans Typewriter", Font.PLAIN, 12);
267 		} else {
268 			retVal = new Font("Monospace", Font.PLAIN, 12);
269 		}
270 
271 		ourLog.info("Got font for HL7 editor: {}", retVal);
272 		return retVal;
273 	}
274 
275 	public double getHl7EditorSplit() {
276 		Double hl7EditorSplit = myHl7EditorSplit != null ? myHl7EditorSplit / 100.0 : 0.4;
277 		return enforceHl7EditorSplitLimits(hl7EditorSplit);
278 	}
279 
280 	public String getHl7V2DiffFile1() {
281 		return myHl7V2DiffFile1 == null ? "" : myHl7V2DiffFile1;
282 	}
283 
284 	public String getHl7V2DiffFile2() {
285 		return myHl7V2DiffFile2 == null ? "" : myHl7V2DiffFile2;
286 	}
287 
288 	public boolean getHl7V2DiffShowWholeMessageOnError() {
289 		return myHl7V2DiffShowWholeMessageOnError;
290 	}
291 
292 	public boolean getHl7V2DiffStopOnFirstError() {
293 		return myHl7V2DiffStopOnFirstError;
294 	}
295 
296 	public String getHl7V2SortBy() {
297 		return myHl7V2SortBy;
298 	}
299 
300 	public String getHl7V2SortInputFile() {
301 		return myHl7V2SortInputFile;
302 	}
303 
304 	public String getHl7V2SortOutputFile() {
305 		return myHl7V2SortOutputFile;
306 	}
307 
308 	public String getHl7V2SortOverwriteMode() {
309 		return myHl7V2SortOverwriteMode;
310 	}
311 
312 	public File getImportProfileGroupDirectory() {
313 		return new File(defaultString(myImportProfileGroupDirectory, "."));
314 	}
315 
316 	public String getInboundConnectionList() {
317 		return myInboundConnectionList;
318 	}
319 
320 	public String getInterfaceHohSecurityKeystoreDirectory() {
321 		return myInterfaceHohSecurityKeystoreDirectory;
322 	}
323 
324 	public Charset getMostRecentConnectionCharset() {
325 		String charset = isNotBlank(myMostRecentConnectionCharset) ? myMostRecentConnectionCharset : CharsetUtils.DEFAULT_CONNECTION_CHARSET.displayName();
326 		try {
327 			return Charset.forName(charset);
328 		} catch (Exception e) {
329 			return CharsetUtils.DEFAULT_CONNECTION_CHARSET;
330 		}
331 	}
332 
333 	public String getMostRecentlySelectedItemId() {
334 		return myMostRecentlySelectedItemId;
335 	}
336 
337 	// /**
338 	// * @return the openImportedProfileGroupFile
339 	// */
340 	// public List<OpenImportedProfileGroupFile>
341 	// getOpenImportedProfileGroupFile() {
342 	// if (myOpenImportedProfileGroupFile == null) {
343 	// myOpenImportedProfileGroupFile = new
344 	// ArrayList<Prefs.OpenImportedProfileGroupFile>();
345 	// }
346 	// return myOpenImportedProfileGroupFile;
347 	// }
348 
349 	public Charset getOpenOrSaveCharset() {
350 		String savedVal = defaultString(myOpenOrSaveCharset, Charset.defaultCharset().name());
351 
352 		Charset retVal;
353 		try {
354 			retVal = Charset.forName(savedVal);
355 		} catch (Exception e) {
356 			retVal = Charset.defaultCharset();
357 		}
358 		return retVal;
359 	}
360 
361 	public String getOpenPathConformanceProfile() {
362 		return defaultString(myOpenPathConformanceProfile, ".");
363 	}
364 
365 	public String getOpenPathMessages() {
366 		return defaultString(myOpenPathMessages, ".");
367 	}
368 
369 	public List<File> getOpenTableFiles() {
370 		ArrayList<File> retVal = new ArrayList<File>();
371 		if (myOpenTableFiles == null) {
372 			myOpenTableFiles = new ArrayList<String>();
373 		}
374 		for (String next : myOpenTableFiles) {
375 			retVal.add(new File(next));
376 		}
377 		return retVal;
378 
379 	}
380 
381 	public String getOutboundConnectionList() {
382 		return myOutboundConnectionList;
383 	}
384 
385 	public List<Hl7V2MessageCollection> getRecentMessageXmlFiles(ProfileFileList theProfileFileList) {
386 		List<Hl7V2MessageCollection> retVal = new ArrayList<Hl7V2MessageCollection>();
387 		List<XmlFormat> savedVals = myRecentMessageXmlFiles;
388 		for (XmlFormat string : savedVals) {
389 			try {
390 				Hl7V2MessageCollection nextMsg = Hl7V2MessageCollection.fromXml(theProfileFileList, string);
391 				if (StringUtils.isNotBlank(nextMsg.getSaveFileName())) {
392 					retVal.add(nextMsg);
393 				}
394 			} catch (Exception e) {
395 				ourLog.error("Failed to restore profile", e);
396 			}
397 		}
398 		return retVal;
399 
400 	}
401 
402 	public LineEndingsEnum getSaveLineEndings() {
403 		String savedVal = defaultString(mySaveLineEndings, LineEndingsEnum.HL7.name());
404 		LineEndingsEnum retVal;
405 		try {
406 			retVal = LineEndingsEnum.valueOf(savedVal);
407 		} catch (Exception e) {
408 			retVal = LineEndingsEnum.HL7;
409 		}
410 		return retVal;
411 
412 	}
413 
414 	public String getSavePathMessages() {
415 		return defaultString(mySavePathMessages, ".");
416 	}
417 
418 	public boolean getSaveStripComments() {
419 		return mySaveStripComments;
420 	}
421 
422 	public boolean getShowLogConsole() {
423 		return myShowLogConsole;
424 	}
425 
426 	/**
427 	 * Returns (0,0) if nothing was stored
428 	 */
429 	public Dimension getWindowDimension() {
430 		int width = myWindowPositionW;
431 		int height = myWindowPositionH;
432 		return new Dimension(width, height);
433 	}
434 
435 	public boolean getWindowMaximized() {
436 		return myWindowMaximized;
437 	}
438 
439 	/**
440 	 * Returns (-1,-1) if nothing was stored
441 	 */
442 	public Point getWindowPosition() {
443 		int x = myWindowPositionX != null ? myWindowPositionX : -1;
444 		int y = myWindowPositionY != null ? myWindowPositionY : -1;
445 		return new Point(x, y);
446 	}
447 
448 	private void initFromJavaPrefs() {
449 		myOpenTableFiles = new ArrayList<String>();
450 		String savedValsSplit = ourPrefs.get(GET_OPEN_TABLE_FILES, "");
451 		String[] savedVals = defaultString(savedValsSplit).split("\\n");
452 		for (String string : savedVals) {
453 			if (StringUtils.isNotBlank(string)) {
454 				myOpenTableFiles.add(string);
455 			}
456 		}
457 
458 		myOutboundConnectionList = ourPrefs.get(GET_OUTBOUND_CONNECTION_LIST, null);
459 		myOpenPathConformanceProfile = ourPrefs.get(GET_OPEN_PATH_CONFORMANCE_PROFILE, ".");
460 		myOpenPathMessages = ourPrefs.get(GET_OPEN_PATH_MESSAGES, ".");
461 		myInterfaceHohSecurityKeystoreDirectory = ourPrefs.get(GET_INTERFACE_HOH_SECURITY_KEYSTORE_DIRECTORY, null);
462 		myMostRecentlySelectedItemId = ourPrefs.get(GET_MOST_RECENTLY_SELECTED_ITEM_ID, "");
463 		myOpenOrSaveCharset = ourPrefs.get(GET_OPENSAVE_CHARSET, Charset.defaultCharset().name());
464 		myHl7V2SortInputFile = ourPrefs.get(GET_HL7V2_SORT_INPUT, "");
465 		myHl7V2SortOverwriteMode = ourPrefs.get(GET_HL7V2_SORT_OVERWRITE_MODE, "");
466 		myInboundConnectionList = ourPrefs.get(GET_INBOUND_CONNECTION_LIST, null);
467 		myHl7V2SortOutputFile = ourPrefs.get(GET_HL7V2_SORT_OUTPUT, "");
468 		myHl7V2DiffStopOnFirstError = ourPrefs.getBoolean(GET_HL7V2_DIFF_STOP_ON_FIRST_ERROR, false);
469 		myExportProfileGroupDirectory = ourPrefs.get(GET_EXPORT_PROFILE_GROUP_DIRECTORY, "");
470 		myHl7V2DiffShowWholeMessageOnError = ourPrefs.getBoolean(GET_HL7V2_DIFF_SHOW_WHOLE_MESSAGE_ON_ERROR, false);
471 		myHl7V2SortBy = ourPrefs.get(GET_HL7V2_SORT_BY, "");
472 		myMostRecentConnectionCharset = ourPrefs.get(GET_MOST_RECENT_CONNECTION_CHARSET, CharsetUtils.DEFAULT_CONNECTION_CHARSET.displayName());
473 		myHl7EditorSplit = (int) (ourPrefs.getDouble(GET_HL7_EDITOR_SPLIT, 0.4) * 100.0);
474 		myHl7V2DiffFile1 = ourPrefs.get(GET_HL7V2_DIFF_FILE1, "");
475 		myHl7V2DiffFile2 = ourPrefs.get(GET_HL7V2_DIFF_FILE2, "");
476 		mySavePathMessages = ourPrefs.get(GET_SAVE_PATH_MESSAGES, ".");
477 
478 		String recentMessageXmlFiles = ourPrefs.get(GET_RECENT_MESSAGE_FILES, "");
479 		ArrayList<String> recentMessageXmlFilesSplit = new ArrayList<String>(Arrays.asList(defaultString(recentMessageXmlFiles).split("\\n")));
480 		myRecentMessageXmlFiles = new ArrayList<Hl7V2MessageCollection.XmlFormat>();
481 		for (String string : recentMessageXmlFilesSplit) {
482 			try {
483 				myRecentMessageXmlFiles.add(JAXB.unmarshal(new StringReader(string), Hl7V2MessageCollection.XmlFormat.class));
484 			} catch (Exception e) {
485 				ourLog.error("Failed to restore file \"" + string + "\": " + e.getMessage(), e);
486 			}
487 		}
488 
489 		mySaveLineEndings = ourPrefs.get(GET_SAVE_LINE_ENDINGS, LineEndingsEnum.HL7.name());
490 		mySaveStripComments = ourPrefs.getBoolean(GET_SAVE_STRIP_COMMENTS, false);
491 		myWindowMaximized = ourPrefs.getBoolean(GET_WINDOW_MAXIMIZED, false);
492 		myWindowPositionX = ourPrefs.getInt(GET_WINDOW_POSITIONX, -1);
493 		myWindowPositionY = ourPrefs.getInt(GET_WINDOW_POSITIONY, -1);
494 		myWindowPositionW = ourPrefs.getInt(GET_WINDOW_POSITIONW, 0);
495 		myWindowPositionH = ourPrefs.getInt(GET_WINDOW_POSITIONH, 0);
496 		myShowLogConsole = ourPrefs.getBoolean(GET_SHOW_LOG_CONSOLE, false);
497 
498 	}
499 
500 	// public void
501 	// removeOpenImportedProfileGroupFile(OpenImportedProfileGroupFile theFile)
502 	// {
503 	// getOpenImportedProfileGroupFile().remove(theFile);
504 	// sync();
505 	// }
506 
507 	/**
508 	 * @param theController
509 	 *            the controller to set
510 	 */
511 	public void setController(Controller theController) {
512 		myController = theController;
513 	}
514 
515 	public void setExportProfileGroupDirectory(String theDirectory) {
516 		myExportProfileGroupDirectory = theDirectory;
517 		sync();
518 	}
519 
520 	public void setHl7EditorSplit(double theRatio) {
521 		theRatio = enforceHl7EditorSplitLimits(theRatio);
522 		myHl7EditorSplit = (int) (theRatio * 100.0);
523 		sync();
524 	}
525 
526 	public void setHl7V2DiffFile1(String theFile) {
527 		myHl7V2DiffFile1 = theFile;
528 		sync();
529 
530 	}
531 
532 	public void setHl7V2DiffFile2(String theFile) {
533 		myHl7V2DiffFile2 = theFile;
534 		sync();
535 	}
536 
537 	public void setHl7V2DiffShowWholeMessageOnError(boolean theSelected) {
538 		myHl7V2DiffShowWholeMessageOnError = theSelected;
539 		sync();
540 	}
541 
542 	public void setHl7V2DiffStopOnFirstError(boolean theValue) {
543 		myHl7V2DiffStopOnFirstError = theValue;
544 		sync();
545 	}
546 
547 	public void setHl7V2SortBy(String theSelectedItem) {
548 		myHl7V2SortBy = theSelectedItem;
549 		sync();
550 	}
551 
552 	public void setHl7V2SortInputFile(String theText) {
553 		myHl7V2SortInputFile = theText;
554 		sync();
555 	}
556 
557 	public void setHl7V2SortOutputFile(String theText) {
558 		myHl7V2SortOutputFile = theText;
559 		sync();
560 	}
561 
562 	public void setHl7V2SortOverwriteMode(String theMode) {
563 		myHl7V2SortOverwriteMode = theMode;
564 		sync();
565 	}
566 
567 	/**
568 	 * @param theImportProfileGroupDirectory
569 	 *            the importProfileGroupDirectory to set
570 	 */
571 	public void setImportProfileGroupDirectory(File theImportProfileGroupDirectory) {
572 		if (theImportProfileGroupDirectory.isDirectory()) {
573 			myImportProfileGroupDirectory = theImportProfileGroupDirectory.getAbsolutePath();
574 			sync();
575 		}
576 
577 	}
578 
579 	public void setInboundConnectionList(String theValue) {
580 		Validate.notNull(theValue);
581 		myInboundConnectionList = theValue;
582 		sync();
583 	}
584 
585 	public void setInterfaceHohSecurityKeystoreDirectory(String theValue) {
586 		myInterfaceHohSecurityKeystoreDirectory = theValue;
587 		sync();
588 	}
589 
590 	public void setMostRecentConnectionCharset(String theCharSet) {
591 		assert theCharSet != null;
592 		myMostRecentConnectionCharset = theCharSet;
593 		sync();
594 	}
595 
596 	public void setMostRecentlySelectedItemId(String theId) {
597 		assert theId != null;
598 		myMostRecentlySelectedItemId = theId;
599 		sync();
600 	}
601 
602 	public void setOpenOrSaveCharset(Charset theValue) {
603 		Validate.notNull(theValue);
604 		myOpenOrSaveCharset = theValue.name();
605 		sync();
606 	}
607 
608 	public void setOpenPathConformanceProfile(String theValue) {
609 		StringUtil.validateNotEmpty(theValue);
610 
611 		if (theValue.lastIndexOf(File.separatorChar) > 0) {
612 			theValue = theValue.substring(0, theValue.lastIndexOf(File.separatorChar));
613 		}
614 
615 		myOpenPathConformanceProfile = theValue;
616 		sync();
617 	}
618 
619 	public void setOpenPathMessages(String theValue) {
620 		StringUtil.validateNotEmpty(theValue);
621 
622 		if (theValue.lastIndexOf(File.separatorChar) > 0) {
623 			theValue = theValue.substring(0, theValue.lastIndexOf(File.separatorChar));
624 		}
625 
626 		myOpenPathMessages = theValue;
627 		sync();
628 	}
629 
630 	public void setOpenProfiles(List<ProfileGroup> theProfiles, TableFileList theTableFileList) {
631 		int index = 0;
632 		List<File> files = new ArrayList<File>();
633 		try {
634 
635 			for (ProfileGroup profileGroup : theProfiles) {
636 				index++;
637 				String seq = StringUtils.leftPad(Integer.toString(index), 10, '0');
638 				File fileName = createProfileGroupFileName(seq, profileGroup);
639 				files.add(fileName);
640 
641 				FileOutputStream fos = new FileOutputStream(fileName);
642 				Writer nextWriter = new OutputStreamWriter(fos, Charset.forName("UTF-8"));
643 				if (isNotBlank(profileGroup.getSourceUrl())) {
644 					ExportedProfileGroupFile exported = new ExportedProfileGroupFile(profileGroup, theTableFileList);
645 					nextWriter.append(exported.exportConfigToXm());
646 				} else {
647 					nextWriter.append(profileGroup.exportConfigToXml());
648 				}
649 
650 				nextWriter.close();
651 			}
652 
653 			IOUtils.deleteAllFromDirectoryExcept(getProfileGroupFileDirectory(), files);
654 			
655 		} catch (IOException e) {
656 			ourLog.error("Failed to flush profile group file", e);
657 		}
658 	}
659 
660 	public void setOpenTableFiles(List<File> theFiles) {
661 		myOpenTableFiles = new ArrayList<String>();
662 		for (File file : theFiles) {
663 			myOpenTableFiles.add(file.getAbsolutePath());
664 		}
665 		sync();
666 	}
667 
668 	public void setOutboundConnectionList(String theValue) {
669 		Validate.notNull(theValue);
670 		myOutboundConnectionList = theValue;
671 		sync();
672 	}
673 
674 	public void setSaveLineEndings(LineEndingsEnum theValue) {
675 		Validate.notNull(theValue);
676 		mySaveLineEndings = theValue.name();
677 		sync();
678 	}
679 
680 	public void setSavePathMessages(String theValue) {
681 		StringUtil.validateNotEmpty(theValue);
682 
683 		if (theValue.lastIndexOf(File.separatorChar) > 0) {
684 			theValue = theValue.substring(0, theValue.lastIndexOf(File.separatorChar));
685 		}
686 
687 		mySavePathMessages = theValue;
688 		sync();
689 	}
690 
691 	public void setSaveStripComments(boolean theValue) {
692 		Validate.notNull(theValue);
693 		mySaveStripComments = theValue;
694 		sync();
695 	}
696 
697 	public void setShowLogConsole(boolean theValue) {
698 		Validate.notNull(theValue);
699 
700 		myShowLogConsole = theValue;
701 		sync();
702 	}
703 
704 	public void setWindowDimension(Dimension theDimension) {
705 		assert theDimension != null;
706 
707 		myWindowPositionH = theDimension.height;
708 		myWindowPositionY = theDimension.width;
709 		sync();
710 	}
711 
712 	public void setWindowMaximized(boolean theWindowMaximized) {
713 		myWindowMaximized = theWindowMaximized;
714 		sync();
715 	}
716 
717 	public void setWindowPosition(Point thePosition) {
718 		assert thePosition != null;
719 
720 		myWindowPositionX = thePosition.x;
721 		myWindowPositionY = thePosition.y;
722 		sync();
723 	}
724 
725 	private void sync() {
726 
727 		Runnable r = new Runnable() {
728 			public void run() {
729 				StringWriter writer = new StringWriter();
730 				try {
731 					ourJaxbContext.createMarshaller().marshal(Prefs.this, writer);
732 				} catch (JAXBException e) {
733 					ourLog.error("Failed to marshall prefs! This shouldn't happen", e);
734 				}
735 
736 				final String prefs = writer.toString();
737 				if (StringUtils.equals(myLastPrefsFileSaveValue, prefs)) {
738 					return;
739 				}
740 
741 				ourLog.info("Syncing user preferences to disk");
742 
743 				try {
744 					FileWriter w = new FileWriter(getPrefsFile(), false);
745 					w.append(prefs);
746 					w.close();
747 
748 					ourLog.info("Done synchronizing user prefs ({} chars)", prefs.length());
749 					myLastPrefsFileSaveValue = prefs;
750 
751 					try {
752 						ourPrefs.clear();
753 					} catch (BackingStoreException e) {
754 						// we can ignore this
755 					}
756 
757 				} catch (IOException e) {
758 					ourLog.error("Failed to write prefs file to disk", e);
759 				}
760 
761 			}
762 		};
763 
764 		if (myController != null) {
765 			myController.invokeInBackground(r);
766 		}
767 
768 	}
769 
770 	private static File createProfileGroupFileName(String theSeq, ProfileGroup profileGroup) {
771 		File dir = getProfileGroupFileDirectory();
772 		dir.mkdirs();
773 		return new File(dir, theSeq + "-" + profileGroup.getId() + ".xml");
774 	}
775 
776 	private static double enforceHl7EditorSplitLimits(double theRatio) {
777 		theRatio = Math.min(0.8, theRatio);
778 		theRatio = Math.max(0.2, theRatio);
779 		return theRatio;
780 	}
781 
782 	public static File getDefaultTableFileDirectory() {
783 		File testPanelHome = getTestpanelHomeDirectory();
784 		File retVal = new File(testPanelHome, "tables");
785 		retVal.mkdirs();
786 		return retVal;
787 	}
788 
789 	public static Prefs getInstance() {
790 		try {
791 			ourJaxbContext = JAXBContext.newInstance(Prefs.class, XmlFormat.class);
792 		} catch (JAXBException e) {
793 			throw new Error(e);
794 		}
795 
796 		if (ourInstance == null) {
797 			File prefsFile = getPrefsFile();
798 			if (prefsFile.exists() && prefsFile.isFile() && prefsFile.canRead()) {
799 				try {
800 					ourInstance = (Prefs) ourJaxbContext.createUnmarshaller().unmarshal(prefsFile);
801 				} catch (Exception e) {
802 					ourLog.error("Failed to load prefs- Using default!", e);
803 					ourInstance = new Prefs();
804 				}
805 			} else {
806 				ourInstance = new Prefs();
807 				try {
808 					if (ourPrefs.keys().length > 0) {
809 						ourInstance.initFromJavaPrefs(); // hopefully we will do
810 															// away
811 															// with this
812 															// eventually
813 					}
814 				} catch (BackingStoreException e) {
815 					// we can ignore this
816 				}
817 			}
818 		}
819 		return ourInstance;
820 	}
821 
822 	public static List<ProfileGroup> getOpenProfiles() {
823 		ArrayList<ProfileGroup> retVal = new ArrayList<ProfileGroup>();
824 
825 		File dir = getProfileGroupFileDirectory();
826 		dir.mkdirs();
827 
828 		ArrayList<File> files = new ArrayList<File>(Arrays.asList(dir.listFiles()));
829 		Collections.sort(files, new FileNameComparator());
830 		
831 		for (File next : files) {
832 			if (next.getName().toLowerCase().contains(".xml")) {
833 				try {
834 					retVal.add(ProfileGroup.readFromFile(next));
835 				} catch (Exception e) {
836 					ourLog.error("Failed to unmarshall profile file", e);
837 				}
838 			}
839 		}
840 
841 		return retVal;
842 	}
843 
844 	private static File getPrefsFile() {
845 		return new File(getTestpanelHomeDirectory(), "prefs.xml");
846 	}
847 
848 	public static File getProfileGroupFileDirectory() {
849 		File testPanelHome = getTestpanelHomeDirectory();
850 		File retVal = new File(testPanelHome, "profilegroups");
851 		retVal.mkdirs();
852 		return retVal;
853 	}
854 
855 	public static File getTempWorkfilesDirectory() throws IOException {
856 		File testPanelHome = getTestpanelHomeDirectory();
857 		File retVal = new File(testPanelHome, "workfiles");
858 		retVal.mkdirs();
859 		return retVal;
860 	}
861 
862 	public static File getTestpanelHomeDirectory() {
863 		File userHome = new File(System.getProperty("user.home"));
864 		File testPanelHome = new File(userHome, "HapiTestPanel");
865 		return testPanelHome;
866 	}
867 
868 	// @XmlType()
869 	// @XmlAccessorType(XmlAccessType.FIELD)
870 	// public static class OpenImportedProfileGroupFile {
871 	//
872 	// private String myId;
873 	// private String myUrl;
874 	//
875 	// public OpenImportedProfileGroupFile() {
876 	// super();
877 	// }
878 	//
879 	// public OpenImportedProfileGroupFile(String theUrl, String theId) {
880 	// super();
881 	// myUrl = theUrl;
882 	// myId = theId;
883 	// }
884 	//
885 	// /*
886 	// * (non-Javadoc)
887 	// *
888 	// * @see java.lang.Object#equals(java.lang.Object)
889 	// */
890 	// @Override
891 	// public boolean equals(Object obj) {
892 	// if (this == obj) {
893 	// return true;
894 	// }
895 	// if (obj == null) {
896 	// return false;
897 	// }
898 	// if (!(obj instanceof OpenImportedProfileGroupFile)) {
899 	// return false;
900 	// }
901 	// OpenImportedProfileGroupFile other = (OpenImportedProfileGroupFile) obj;
902 	// if (myId == null) {
903 	// if (other.myId != null) {
904 	// return false;
905 	// }
906 	// } else if (!myId.equals(other.myId)) {
907 	// return false;
908 	// }
909 	// return true;
910 	// }
911 	//
912 	// /**
913 	// * @return the id
914 	// */
915 	// public String getId() {
916 	// return myId;
917 	// }
918 	//
919 	// /**
920 	// * @return the url
921 	// */
922 	// public String getUrl() {
923 	// return myUrl;
924 	// }
925 	//
926 	// /*
927 	// * (non-Javadoc)
928 	// *
929 	// * @see java.lang.Object#hashCode()
930 	// */
931 	// @Override
932 	// public int hashCode() {
933 	// final int prime = 31;
934 	// int result = 1;
935 	// result = prime * result + ((myId == null) ? 0 : myId.hashCode());
936 	// return result;
937 	// }
938 	//
939 	// /**
940 	// * @param theId
941 	// * the id to set
942 	// */
943 	// public void setId(String theId) {
944 	// myId = theId;
945 	// }
946 	//
947 	// /**
948 	// * @param theUrl
949 	// * the url to set
950 	// */
951 	// public void setUrl(String theUrl) {
952 	// myUrl = theUrl;
953 	// }
954 	//
955 	// }
956 
957 }