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.database.frontend.DatabaseWrapper;
36 import org.mxchange.addressbook.manager.contact.ManageableContact;
41 * @author Roland Haeder
43 public class BaseFrameworkSystem implements FrameworkInterface {
45 * Instance for own properties
47 private static final Properties properties = new Properties(System.getProperties());
52 private final Logger LOG;
55 * Application instance
57 private Application application;
62 private final ResourceBundle bundle;
67 private Client client;
70 * Contact manager instance
72 private ManageableContact contactManager;
76 * Name of used database table, handled over to backend
78 private String tableName;
81 * DatabaseWrapper instance
83 private DatabaseWrapper wrapper;
89 LOG = LogManager.getLogger(this);
90 bundle = ResourceBundle.getBundle("org/mxchange/addressbook/localization/bundle"); // NOI18N
94 * No instances can be created of this class
96 protected BaseFrameworkSystem () {
97 // Init properties file
98 this.initProperties();
102 * Application instance
104 * @return the application
107 public final Application getApplication () {
108 return this.application;
112 * Getter for human-readable string from given key
114 * @param key Key to return
115 * @return Human-readable message
118 public final String getMessageStringFromKey (final String key) {
120 return this.getBundle().getString(key);
124 * Some "getter for a value from given column name. This name will be
125 * translated into a method name and then this method is called.
127 * @param columnName Column name
128 * @return Value from field
131 public Object getValueFromColumn (final String columnName) {
132 throw new UnsupportedOperationException(MessageFormat.format("Not implemented. columnName={0}", columnName));
136 * Some "getter" for a Method instance from given method name
138 * @param instance Actual instance to call
139 * @param targetClass Target class name
140 * @param methodName Method name
141 * @return A Method instance
143 @SuppressWarnings ("unchecked")
144 private Method getMethodFromName (final FrameworkInterface instance, final String targetClass, final String methodName) {
146 this.getLogger().trace(MessageFormat.format("targetClass={0},methodName={1}", targetClass, methodName));
148 // Instance reflaction of this class
149 Class<? extends FrameworkInterface> c = instance.getClass();
152 while (!targetClass.equals(c.getSimpleName())) {
154 this.getLogger().debug("c=" + c.getSimpleName());
156 // Get super class (causes unchecked warning)
157 c = (Class<? extends FrameworkInterface>) c.getSuperclass();
160 // Init field instance
161 Method method = null;
163 // Use reflection to get all attributes
165 method = c.getDeclaredMethod(methodName, new Class<?>[0]);
166 } catch (final SecurityException ex) {
168 this.abortProgramWithException(ex);
169 } catch (final NoSuchMethodException ex) {
171 this.abortProgramWithException(ex);
175 assert(method instanceof Method) : "method is not a Method instance";
178 this.getLogger().trace(MessageFormat.format("method={0} - EXIT!", method));
185 * Aborts program with given exception
187 * @param throwable Any type of Throwable
189 protected final void abortProgramWithException (final Throwable throwable) {
191 this.getLogger().catching(throwable);
199 * Application instance
201 * @param application the application to set
203 protected final void setApplication (final Application application) {
204 this.application = application;
213 public final Client getClient () {
218 * Getter for bundle instance
220 * @return Resource bundle
222 protected final ResourceBundle getBundle () {
229 * @param client the client to set
231 protected final void setClient (final Client client) {
232 this.client = client;
236 * Contact manager instance
238 * @return the contactManager
241 public final ManageableContact getContactManager () {
242 return this.contactManager;
246 * Contact manager instance
248 * @param contactManager the contactManager to set
250 protected final void setContactManager (final ManageableContact contactManager) {
251 this.contactManager = contactManager;
255 * Checks if given boolean field is available and set to same value
257 * @param columnName Column name to check
258 * @param bool Boolean value
259 * @return Whether all conditions are met
262 public boolean isValueEqual (final String columnName, final boolean bool) {
264 throw new UnsupportedOperationException(MessageFormat.format("Not implemented. columnName={0},bool={1}", columnName, bool));
270 * @param exception Exception to log
273 public final void logException (final Throwable exception) {
274 // Log this exception
275 this.getLogger().catching(exception);
279 * Prepares all properties, the file is written if it is not found
281 private void initProperties () {
283 this.getLogger().trace("CALLED!"); //NOI18N
286 this.getLogger().debug(MessageFormat.format("{0} properties are loaded already.", BaseFrameworkSystem.properties.size())); //NOI18N
288 // Are some properties loaded?
289 if (!BaseFrameworkSystem.properties.isEmpty()) {
290 // Some are already loaded, abort here
296 BaseFrameworkSystem.properties.load(new BufferedReader(new InputStreamReader(new FileInputStream(FrameworkInterface.PROPERTIES_CONFIG_FILE))));
299 this.getLogger().debug(MessageFormat.format("{0} properties has been loaded.", BaseFrameworkSystem.properties.size())); //NOI18N
300 } catch (final FileNotFoundException ex) {
302 this.getLogger().debug(MessageFormat.format("Properties file {0} not found: {1}", FrameworkInterface.PROPERTIES_CONFIG_FILE, ex)); //NOI18N
305 * The file is not found which is normal for first run, so
306 * initialize default values.
308 this.initPropertiesWithDefault();
311 this.writePropertiesFile();
312 } catch (final IOException ex) {
313 // Something else didn't work
314 this.abortProgramWithException(ex);
318 this.getLogger().trace("EXIT!"); //NOI18N
322 * Initializes properties with default values
324 private void initPropertiesWithDefault () {
326 this.getLogger().trace("CALLED!"); //NOI18N
328 // Init default values:
329 // Default database backend
330 BaseFrameworkSystem.properties.put("org.mxchange.addressbook.database.backendType", "base64csv"); //NOI18N
333 BaseFrameworkSystem.properties.put("org.mxchange.addressbook.database.mysql.host", "localhost"); //NOI18N
334 BaseFrameworkSystem.properties.put("org.mxchange.addressbook.database.mysql.dbname", "test"); //NOI18N
335 BaseFrameworkSystem.properties.put("org.mxchange.addressbook.database.mysql.login", ""); //NOI18N
336 BaseFrameworkSystem.properties.put("org.mxchange.addressbook.database.mysql.password", ""); //NOI18N
339 this.getLogger().trace("EXIT!"); //NOI18N
343 * Writes the properties file to disk
345 private void writePropertiesFile () {
347 this.getLogger().trace("CALLED!"); //NOI18N
351 BaseFrameworkSystem.properties.store(new PrintWriter(FrameworkInterface.PROPERTIES_CONFIG_FILE), "This file is automatically generated. You may wish to alter it."); //NOI18N
352 } catch (final IOException ex) {
353 this.abortProgramWithException(ex);
357 this.getLogger().trace("EXIT!"); //NOI18N
361 * Converts a column name like "foo_bar" to an attribute name like "fooBar"
363 * @param columnName Column name to convert
364 * @return Attribute name
366 protected String convertColumnNameToAttribute (final String columnName) {
368 this.getLogger().trace(MessageFormat.format("columnName={0} - CALLED!", columnName));
370 // First all lower case
371 String lower = columnName.toLowerCase();
374 StringTokenizer tokenizer = new StringTokenizer(lower, "_");
377 StringBuilder builder = new StringBuilder(tokenizer.countTokens());
383 while (tokenizer.hasMoreTokens()) {
385 String token = tokenizer.nextToken();
387 // Is later than first element?
389 // Make first character upper-case
390 char c = token.charAt(0);
391 token = String.valueOf(c).toUpperCase() + token.substring(1);
395 builder.append(token);
402 this.getLogger().trace(MessageFormat.format("builder={0} - EXIT!", builder));
405 return builder.toString();
409 * Converts a column name like "foo_bar" to a method name like "getFooBar"
410 * for non-booleans and to "isFooBar" for boolean fields.
412 * @param columnName Column name to convert
413 * @param isBool Whether the parameter is boolean
414 * @return Attribute name
416 protected String convertColumnNameToGetterMethod (final String columnName, boolean isBool) {
418 this.getLogger().trace(MessageFormat.format("columnName={0} - CALLED!", columnName));
420 // First all lower case
421 String lower = columnName.toLowerCase();
424 StringTokenizer tokenizer = new StringTokenizer(lower, "_");
427 StringBuilder builder = new StringBuilder(tokenizer.countTokens());
432 builder.append("is");
435 builder.append("get");
439 while (tokenizer.hasMoreTokens()) {
441 String token = tokenizer.nextToken();
444 this.getLogger().debug(MessageFormat.format("token={0}", token));
446 // Make it upper-case
447 char c = token.charAt(0);
448 token = String.valueOf(c).toUpperCase() + token.substring(1);
451 builder.append(token);
455 this.getLogger().trace(MessageFormat.format("builder={0} - EXIT!", builder));
458 return builder.toString();
462 * Returns boolean field value from given method call
464 * @param instance The instance to call
465 * @param targetClass Target class to look in
466 * @param methodName Method name to look for
467 * @return Boolean value from field
469 protected boolean getBooleanField (final FrameworkInterface instance, final String targetClass, final String methodName) {
471 this.getLogger().trace(MessageFormat.format("targetClass={0},methodName={1}", targetClass, methodName));
473 // Get method instance
474 Method method = this.getMethodFromName(instance, targetClass, methodName);
476 // Get value from field
477 Boolean value = false;
480 value = (Boolean) method.invoke(instance);
481 } catch (final IllegalArgumentException ex) {
483 this.abortProgramWithException(ex);
484 } catch (final IllegalAccessException ex) {
486 this.abortProgramWithException(ex);
487 } catch (final InvocationTargetException ex) {
489 this.abortProgramWithException(ex);
497 * Returns any field value from given method call
499 * @param instance The instance to call
500 * @param targetClass Target class to look in
501 * @param methodName Method name to look for
502 * @return Any value from field
504 protected Object getField (final FrameworkInterface instance, final String targetClass, final String methodName) {
506 this.getLogger().trace(MessageFormat.format("targetClass={0},methodName={1}", targetClass, methodName));
508 // Get method to call
509 Method method = this.getMethodFromName(instance, targetClass, methodName);
511 // Get value from field
512 Object object = null;
515 object = method.invoke(instance);
516 } catch (final IllegalArgumentException ex) {
518 this.abortProgramWithException(ex);
519 } catch (final IllegalAccessException ex) {
521 this.abortProgramWithException(ex);
522 } catch (final InvocationTargetException ex) {
524 this.abortProgramWithException(ex);
536 protected final Logger getLogger () {
541 * Getter for property which must exist
543 * @param key Key to get
544 * @return Propety value
546 protected final String getProperty (final String key) {
547 return BaseFrameworkSystem.properties.getProperty(String.format("org.mxchange.addressbook.%s", key)); //NOI18N
551 * Name of used database table, handled over to backend
553 * @return the tableName
555 protected final String getTableName () {
556 return this.tableName;
560 * Name of used database table, handled over to backend
562 * @param tableName the tableName to set
564 protected final void setTableName (final String tableName) {
565 this.tableName = tableName;
569 * Getter for DatabaseWrapper instance
571 * @return DatabaseWrapper instance
573 protected DatabaseWrapper getWrapper () {
578 * Setter for wrapper instance
580 * @param wrapper A DatabaseWrapper instance
582 protected void setWrapper (final DatabaseWrapper wrapper) {
583 this.wrapper = wrapper;