2 * Copyright (C) 2015 Roland Haeder
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 package org.mxchange.addressbook;
19 import java.io.BufferedReader;
20 import java.io.FileInputStream;
21 import java.io.FileNotFoundException;
22 import java.io.IOException;
23 import java.io.InputStreamReader;
24 import java.io.PrintWriter;
25 import java.lang.reflect.InvocationTargetException;
26 import java.lang.reflect.Method;
27 import java.text.MessageFormat;
28 import java.util.Properties;
29 import java.util.ResourceBundle;
30 import java.util.StringTokenizer;
31 import org.apache.logging.log4j.LogManager;
32 import org.apache.logging.log4j.Logger;
33 import org.mxchange.addressbook.application.Application;
34 import org.mxchange.addressbook.client.Client;
35 import org.mxchange.addressbook.manager.contact.ManageableContact;
40 * @author Roland Haeder
42 public class BaseFrameworkSystem implements FrameworkInterface {
44 * Instance for own properties
46 private static final Properties properties = new Properties(System.getProperties());
51 private final Logger LOG;
54 * Application instance
56 private Application application;
61 private final ResourceBundle bundle;
66 private Client client;
69 * Contact manager instance
71 private ManageableContact contactManager;
75 * Name of used database table, handled over to backend
77 private String tableName;
83 LOG = LogManager.getLogger(this);
84 bundle = ResourceBundle.getBundle("org/mxchange/addressbook/localization/bundle"); // NOI18N
88 * No instances can be created of this class
90 protected BaseFrameworkSystem () {
91 // Init properties file
92 this.initProperties();
96 * Application instance
98 * @return the application
101 public final Application getApplication () {
102 return this.application;
106 * Getter for human-readable string from given key
108 * @param key Key to return
109 * @return Human-readable message
112 public final String getMessageStringFromKey (final String key) {
114 return this.getBundle().getString(key);
118 * Aborts program with given exception
120 * @param throwable Any type of Throwable
122 protected final void abortProgramWithException (final Throwable throwable) {
124 this.getLogger().catching(throwable);
132 * Application instance
134 * @param application the application to set
136 protected final void setApplication (final Application application) {
137 this.application = application;
146 public final Client getClient () {
151 * Getter for bundle instance
153 * @return Resource bundle
155 protected final ResourceBundle getBundle () {
162 * @param client the client to set
164 protected final void setClient (final Client client) {
165 this.client = client;
169 * Contact manager instance
171 * @return the contactManager
174 public final ManageableContact getContactManager () {
175 return this.contactManager;
179 * Contact manager instance
181 * @param contactManager the contactManager to set
183 protected final void setContactManager (final ManageableContact contactManager) {
184 this.contactManager = contactManager;
190 * @param exception Exception to log
193 public final void logException (final Throwable exception) {
194 // Log this exception
195 this.getLogger().catching(exception);
199 * Prepares all properties, the file is written if it is not found
201 private void initProperties () {
203 this.getLogger().trace("CALLED!"); //NOI18N
206 this.getLogger().debug(MessageFormat.format("{0} properties are loaded already.", BaseFrameworkSystem.properties.size())); //NOI18N
208 // Are some properties loaded?
209 if (!BaseFrameworkSystem.properties.isEmpty()) {
210 // Some are already loaded, abort here
216 BaseFrameworkSystem.properties.load(new BufferedReader(new InputStreamReader(new FileInputStream(FrameworkInterface.PROPERTIES_CONFIG_FILE))));
219 this.getLogger().debug(MessageFormat.format("{0} properties has been loaded.", BaseFrameworkSystem.properties.size())); //NOI18N
220 } catch (final FileNotFoundException ex) {
222 this.getLogger().debug(MessageFormat.format("Properties file {0} not found: {1}", FrameworkInterface.PROPERTIES_CONFIG_FILE, ex)); //NOI18N
225 * The file is not found which is normal for first run, so
226 * initialize default values.
228 this.initPropertiesWithDefault();
231 this.writePropertiesFile();
232 } catch (final IOException ex) {
233 // Something else didn't work
234 this.abortProgramWithException(ex);
238 this.getLogger().trace("EXIT!"); //NOI18N
242 * Initializes properties with default values
244 private void initPropertiesWithDefault () {
246 this.getLogger().trace("CALLED!"); //NOI18N
248 // Init default values:
249 // Default database backend
250 BaseFrameworkSystem.properties.put("org.mxchange.addressbook.database.backendType", "base64csv"); //NOI18N
253 BaseFrameworkSystem.properties.put("org.mxchange.addressbook.database.mysql.host", "localhost"); //NOI18N
254 BaseFrameworkSystem.properties.put("org.mxchange.addressbook.database.mysql.dbname", "test"); //NOI18N
255 BaseFrameworkSystem.properties.put("org.mxchange.addressbook.database.mysql.login", ""); //NOI18N
256 BaseFrameworkSystem.properties.put("org.mxchange.addressbook.database.mysql.password", ""); //NOI18N
259 this.getLogger().trace("EXIT!"); //NOI18N
263 * Writes the properties file to disk
265 private void writePropertiesFile () {
267 this.getLogger().trace("CALLED!"); //NOI18N
271 BaseFrameworkSystem.properties.store(new PrintWriter(FrameworkInterface.PROPERTIES_CONFIG_FILE), "This file is automatically generated. You may wish to alter it."); //NOI18N
272 } catch (final IOException ex) {
273 this.abortProgramWithException(ex);
277 this.getLogger().trace("EXIT!"); //NOI18N
281 * Converts a column name like "foo_bar" to an attribute name like "fooBar"
283 * @param columnName Column name to convert
284 * @return Attribute name
286 protected String convertColumnNameToAttribute (final String columnName) {
288 this.getLogger().trace(MessageFormat.format("columnName={0} - CALLED!", columnName));
290 // First all lower case
291 String lower = columnName.toLowerCase();
294 StringTokenizer tokenizer = new StringTokenizer(lower, "_");
297 StringBuilder builder = new StringBuilder(tokenizer.countTokens());
303 while (tokenizer.hasMoreTokens()) {
305 String token = tokenizer.nextToken();
307 // Is later than first element?
309 // Make first character upper-case
310 char c = token.charAt(0);
311 token = String.valueOf(c).toUpperCase() + token.substring(1);
315 builder.append(token);
322 this.getLogger().trace(MessageFormat.format("builder={0} - EXIT!", builder));
325 return builder.toString();
329 * Converts a column name like "foo_bar" to a method name like "getFooBar"
330 * for non-booleans and to "isFooBar" for boolean fields.
332 * @param columnName Column name to convert
333 * @param isBool Whether the parameter is boolean
334 * @return Attribute name
336 protected String convertColumnNameToGetterMethod (final String columnName, boolean isBool) {
338 this.getLogger().trace(MessageFormat.format("columnName={0} - CALLED!", columnName));
340 // First all lower case
341 String lower = columnName.toLowerCase();
344 StringTokenizer tokenizer = new StringTokenizer(lower, "_");
347 StringBuilder builder = new StringBuilder(tokenizer.countTokens());
352 builder.append("is");
355 builder.append("get");
359 while (tokenizer.hasMoreTokens()) {
361 String token = tokenizer.nextToken();
364 this.getLogger().debug(MessageFormat.format("token={0}", token));
366 // Make it upper-case
367 char c = token.charAt(0);
368 token = String.valueOf(c).toUpperCase() + token.substring(1);
371 builder.append(token);
375 this.getLogger().trace(MessageFormat.format("builder={0} - EXIT!", builder));
378 return builder.toString();
386 protected final Logger getLogger () {
391 * Getter for property which must exist
393 * @param key Key to get
394 * @return Propety value
396 protected final String getProperty (final String key) {
397 return BaseFrameworkSystem.properties.getProperty(String.format("org.mxchange.addressbook.%s", key)); //NOI18N
401 * Name of used database table, handled over to backend
403 * @return the tableName
405 protected final String getTableName () {
406 return this.tableName;
410 * Name of used database table, handled over to backend
412 * @param tableName the tableName to set
414 protected final void setTableName (final String tableName) {
415 this.tableName = tableName;
419 * Returns boolean field value from given method call
421 * @param instance The instance to call
422 * @param targetClass Target class to look in
423 * @param methodName Method name to look for
424 * @return Boolean value from field
426 @SuppressWarnings ("unchecked")
427 protected boolean getBooleanField (final FrameworkInterface instance, final String targetClass, final String methodName) {
429 this.getLogger().trace(MessageFormat.format("targetClass={0},methodName={1}", targetClass, methodName));
431 // Instance reflaction of this class
432 Class<? extends FrameworkInterface> c = instance.getClass();
435 while (!targetClass.equals(c.getSimpleName())) {
437 this.getLogger().debug("c=" + c.getSimpleName());
439 // Get super class (causes unchecked warning)
440 c = (Class<? extends FrameworkInterface>) c.getSuperclass();
443 // Init field instance
444 Method method = null;
446 // Use reflection to get all attributes
448 method = c.getDeclaredMethod(methodName, new Class<?>[0]);
449 } catch (final SecurityException ex) {
451 this.abortProgramWithException(ex);
452 } catch (final NoSuchMethodException ex) {
454 this.abortProgramWithException(ex);
458 assert(method instanceof Method) : "method is not a Method instance";
460 // Get value from field
461 boolean value = false;
464 value = (boolean) method.invoke(instance);
465 } catch (final IllegalArgumentException ex) {
467 this.abortProgramWithException(ex);
468 } catch (final IllegalAccessException ex) {
470 this.abortProgramWithException(ex);
471 } catch (final InvocationTargetException ex) {
473 this.abortProgramWithException(ex);