]> git.mxchange.org Git - jcore.git/blob - src/org/mxchange/jcore/BaseFrameworkSystem.java
Sorted members + removed setSelfInstance()
[jcore.git] / src / org / mxchange / jcore / BaseFrameworkSystem.java
1 /*
2  * Copyright (C) 2015 Roland Haeder
3  *
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.
8  *
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.
13  *
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/>.
16  */
17 package org.mxchange.jcore;
18
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.Field;
26 import java.lang.reflect.InvocationTargetException;
27 import java.lang.reflect.Method;
28 import java.text.MessageFormat;
29 import java.util.Arrays;
30 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.Map;
33 import java.util.Properties;
34 import java.util.ResourceBundle;
35 import java.util.StringTokenizer;
36 import org.apache.commons.lang3.ArrayUtils;
37 import org.apache.logging.log4j.LogManager;
38 import org.apache.logging.log4j.Logger;
39 import org.mxchange.jcore.application.Application;
40 import org.mxchange.jcore.client.Client;
41 import org.mxchange.jcore.contact.Contact;
42 import org.mxchange.jcore.database.backend.DatabaseBackend;
43 import org.mxchange.jcore.database.frontend.DatabaseFrontend;
44 import org.mxchange.jcore.database.storage.Storable;
45 import org.mxchange.jcore.manager.Manageable;
46
47 /**
48  * General class
49  *
50  * @author Roland Haeder
51  */
52 public class BaseFrameworkSystem implements FrameworkInterface {
53
54         /**
55          * Bundle instance
56          */
57         private static ResourceBundle bundle;
58
59         /**
60          * Instance for own properties
61          */
62         private static final Properties properties = new Properties(System.getProperties());
63
64         /**
65          * Self instance
66          */
67         private static FrameworkInterface selfInstance;
68
69         /**
70          * Class' logger
71          */
72         private final Logger LOG;
73
74         /**
75          * Application instance
76          */
77         private Application application;
78
79         /**
80          * Instance for database backend
81          */
82         private DatabaseBackend backend;
83
84         /**
85          * Client instance
86          */
87         private Client client;
88
89         /**
90          * Contact instance
91          */
92         private Contact contact;
93
94         /**
95          * DatabaseFrontend instance
96          */
97         private DatabaseFrontend frontend;
98
99         /**
100          * Manager instance
101          */
102         private Manageable manager;
103
104         /**
105          * Session id assigned with this basket, or any other unique identifier
106          */
107         private String sessionId;
108
109         /**
110          * Name of used database table, handled over to backend
111          */
112         private String tableName;
113
114         /**
115          * Initialize object
116          */
117         {
118                 // Init logger
119                 this.LOG = LogManager.getLogger(this);
120
121                 // Need to set it here
122                 selfInstance = this;
123         }
124
125         /**
126          * No instances can be created of this class
127          */
128         protected BaseFrameworkSystem () {
129         }
130
131         /**
132          * Getter for this application
133          *
134          * @return Instance from this application
135          */
136         public static final FrameworkInterface getInstance () {
137                 // Return it
138                 return selfInstance;
139         }
140
141         @Override
142         public final Application getApplication () {
143                 return this.application;
144         }
145
146         @Override
147         public final Logger getLogger () {
148                 return this.LOG;
149         }
150
151         @Override
152         public final Manageable getManager () {
153                 return this.manager;
154         }
155
156         @Override
157         public final String getMessageStringFromKey (final String key) {
158                 // Return message
159                 return this.getBundle().getString(key);
160         }
161
162         /**
163          * Some "getter" for target class instance from given name.
164          *
165          * @param instance Instance to iterate on
166          * @param targetClass Class name to look for
167          * @return Class instance
168          */
169         @SuppressWarnings ("unchecked")
170         private Class<? extends FrameworkInterface> getClassFromTarget (final FrameworkInterface instance, final String targetClass) {
171                 // Trace message
172                 this.getLogger().debug(MessageFormat.format("instance={0},targetClass={1}", instance, targetClass)); //NOI18N
173
174                 // Instance reflaction of this class
175                 Class<? extends FrameworkInterface> c = instance.getClass();
176
177                 // Analyze class
178                 while (!targetClass.equals(c.getSimpleName())) {
179                         // Debug message
180                         this.getLogger().debug(MessageFormat.format("c={0}", c.getSimpleName())); //NOI18N
181
182                         // Get super class (causes unchecked warning)
183                         c = (Class<? extends FrameworkInterface>) c.getSuperclass();
184                 }
185
186                 // Trace message
187                 this.getLogger().trace(MessageFormat.format("c={0} - EXIT!", c)); //NOI18N
188
189                 // Return it
190                 return c;
191         }
192
193         /**
194          * Some "getter" for a Method instance from given method name
195          *
196          * @param instance Actual instance to call
197          * @param targetClass Target class name
198          * @param methodName Method name
199          * @return A Method instance
200          */
201         private Method getMethodFromName (final FrameworkInterface instance, final String targetClass, final String methodName) throws NoSuchMethodException {
202                 // Trace messahe
203                 this.getLogger().trace(MessageFormat.format("targetClass={0},methodName={1}", targetClass, methodName)); //NOI18N
204
205                 // Init method instance
206                 Method method = null;
207
208                 // Try it from target class
209                 try {
210                         // Get target class instance
211                         Class<? extends FrameworkInterface> c = this.getClassFromTarget(instance, targetClass);
212
213                         // Init field instance
214                         method = c.getDeclaredMethod(methodName, new Class<?>[0]);
215                 } catch (final NoSuchMethodException e) {
216                         // Didn't found it
217                         this.getLogger().debug(e);
218
219                         // So try it from super class
220                         Class<? extends FrameworkInterface> c = this.getClassFromTarget(instance, "BaseFrameworkSystem"); //NOI18N
221
222                         // Init field instance
223                         method = c.getDeclaredMethod(methodName, new Class<?>[0]);
224                 }
225
226                 // Assert on field
227                 assert (method instanceof Method) : "method is not a Method instance"; //NOI18N
228
229                 // Trace message
230                 this.getLogger().trace(MessageFormat.format("method={0} - EXIT!", method)); //NOI18N
231
232                 // Return it
233                 return method;
234         }
235
236         /**
237          * Some "getter" for a Method instance from given method name
238          *
239          * @param instance Actual instance to call
240          * @param targetClass Target class name
241          * @param methodName Method name
242          * @param type Type reflection to check type from
243          * @return A Method instance
244          */
245         private Method getMethodFromName (final FrameworkInterface instance, final String targetClass, final String methodName, final Class<?> type) throws NoSuchMethodException {
246                 // Trace messahe
247                 this.getLogger().trace(MessageFormat.format("targetClass={0},methodName={1},type={2}", targetClass, methodName, type)); //NOI18N
248
249                 // Init method instance
250                 Method method = null;
251
252                 // Try it from target class
253                 try {
254                         // Get target class instance
255                         Class<? extends FrameworkInterface> c = this.getClassFromTarget(instance, targetClass);
256
257                         // Init field instance
258                         method = c.getDeclaredMethod(methodName, type);
259                 } catch (final NoSuchMethodException e) {
260                         // Didn't found it
261                         this.getLogger().debug(e);
262
263                         // So try it from super class
264                         Class<? extends FrameworkInterface> c = this.getClassFromTarget(instance, "BaseFrameworkSystem"); //NOI18N
265
266                         // Init field instance
267                         method = c.getDeclaredMethod(methodName, type);
268                 }
269
270                 // Assert on field
271                 assert (method instanceof Method) : "method is not a Method instance"; //NOI18N
272
273                 // Trace message
274                 this.getLogger().trace(MessageFormat.format("method={0} - EXIT!", method)); //NOI18N
275
276                 // Return it
277                 return method;
278         }
279
280         /**
281          * Aborts program with given exception
282          *
283          * @param throwable Any type of Throwable
284          */
285         protected final void abortProgramWithException (final Throwable throwable) {
286                 // Log exception ...
287                 this.logException(throwable);
288
289                 // .. and exit
290                 System.exit(1);
291         }
292
293         /**
294          * Application instance
295          *
296          * @param application the application to set
297          */
298         protected final void setApplication (final Application application) {
299                 this.application = application;
300         }
301
302         @Override
303         public final Client getClient () {
304                 return this.client;
305         }
306
307         /**
308          * Getter for bundle instance
309          *
310          * @return Resource bundle
311          */
312         protected final ResourceBundle getBundle () {
313                 return BaseFrameworkSystem.bundle;
314         }
315
316         /**
317          * Setter for bundle instance
318          *
319          * @param bundle the bundle to set
320          */
321         protected static void setBundle (final ResourceBundle bundle) {
322                 BaseFrameworkSystem.bundle = bundle;
323         }
324
325         /**
326          * Client instance
327          *
328          * @param client the client to set
329          */
330         protected final void setClient (final Client client) {
331                 this.client = client;
332         }
333
334         /**
335          * Getter for session id
336          *
337          * @return Session id
338          */
339         @Override
340         public final String getSessionId () {
341                 return this.sessionId;
342         }
343
344         /**
345          * Setter for session id
346          *
347          * @param sessionId Session id
348          */
349         @Override
350         public final void setSessionId (final String sessionId) {
351                 this.sessionId = sessionId;
352         }
353
354         /**
355          * Name of used database table, handled over to backend
356          *
357          * @return the tableName
358          */
359         public final String getTableName () {
360                 return this.tableName;
361         }
362
363         @Override
364         public boolean isFieldValueEqual (final String columnName, final boolean bool) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
365                 // Not implemented
366                 throw new UnsupportedOperationException(MessageFormat.format("Not implemented. columnName={0},bool={1}", columnName, bool)); //NOI18N
367         }
368
369         @Override
370         public final void logException (final Throwable exception) {
371                 // Log this exception
372                 this.getLogger().catching(exception);
373         }
374
375         /**
376          * Initializes properties with default values
377          */
378         private void initPropertiesWithDefault () {
379                 // Trace message
380                 this.getLogger().trace("CALLED!"); //NOI18N
381
382                 // Init default values:
383                 // Default database backend
384                 BaseFrameworkSystem.properties.put("org.mxchange.database.backend.class", "org.mxchange.jcore.database.backend.base64.Base64CsvDatabaseBackend"); //NOI18N
385                 BaseFrameworkSystem.properties.put("org.mxchange.database.backend.storagepath", "data/"); //NOI18N
386                 BaseFrameworkSystem.properties.put("org.mxchange.database.datasource.name", ""); //NOI18N
387
388                 // For MySQL backend
389                 BaseFrameworkSystem.properties.put("org.mxchange.database.mysql.host", "localhost"); //NOI18N
390                 BaseFrameworkSystem.properties.put("org.mxchange.database.mysql.dbname", "test"); //NOI18N
391                 BaseFrameworkSystem.properties.put("org.mxchange.database.mysql.login", ""); //NOI18N
392                 BaseFrameworkSystem.properties.put("org.mxchange.database.mysql.password", ""); //NOI18N
393
394                 // Trace message
395                 this.getLogger().trace("EXIT!"); //NOI18N
396         }
397
398         /**
399          * Writes the properties file to disk
400          */
401         private void writePropertiesFile () throws IOException {
402                 // Trace message
403                 this.getLogger().trace("CALLED!"); //NOI18N
404
405                 // Write it
406                 BaseFrameworkSystem.properties.store(new PrintWriter(FrameworkInterface.PROPERTIES_CONFIG_FILE), "This file is automatically generated. You may wish to alter it."); //NOI18N
407
408                 // Trace message
409                 this.getLogger().trace("EXIT!"); //NOI18N
410         }
411
412         /**
413          * Converts a column name like "foo_bar" to an attribute name like "fooBar"
414          *
415          * @param columnName Column name to convert
416          * @return Attribute name
417          */
418         protected String convertColumnNameToFieldName (final String columnName) {
419                 // Trace message
420                 this.getLogger().trace(MessageFormat.format("columnName={0} - CALLED!", columnName)); //NOI18N
421
422                 // Split on "_"
423                 StringTokenizer tokenizer = new StringTokenizer(columnName, "_"); //NOI18N
424
425                 // Resulting string
426                 StringBuilder builder = new StringBuilder(tokenizer.countTokens());
427
428                 // Init counter
429                 int count = 0;
430
431                 // Walk through all
432                 while (tokenizer.hasMoreTokens()) {
433                         // Get token
434                         String token = tokenizer.nextToken();
435
436                         // Is later than first element?
437                         if (count > 0) {
438                                 // Make first character upper-case
439                                 char c = token.charAt(0);
440                                 token = String.valueOf(c).toUpperCase() + token.substring(1);
441                         }
442
443                         // Add token
444                         builder.append(token);
445
446                         // Increment counter
447                         count++;
448                 }
449
450                 // Trace message
451                 this.getLogger().trace(MessageFormat.format("builder={0} - EXIT!", builder)); //NOI18N
452
453                 // Return result
454                 return builder.toString();
455         }
456
457         /**
458          * Converts a column name like "foo_bar" to a method name like "getFooBar"
459          * for non-booleans and to "isFooBar" for boolean fields.
460          *
461          * @param columnName Column name to convert
462          * @param isBool Whether the parameter is boolean
463          * @return Attribute name
464          */
465         protected String convertColumnNameToGetterMethod (final String columnName, boolean isBool) {
466                 // Trace message
467                 this.getLogger().trace(MessageFormat.format("columnName={0},isBool={1} - CALLED!", columnName, isBool)); //NOI18N
468
469                 // Then split on "_"
470                 StringTokenizer tokenizer = new StringTokenizer(columnName, "_"); //NOI18N
471
472                 // Resulting string
473                 StringBuilder builder = new StringBuilder(tokenizer.countTokens());
474
475                 // Is it boolean?
476                 if (isBool) {
477                         // Append "is"
478                         builder.append("is"); //NOI18N
479                 } else {
480                         // Append "get"
481                         builder.append("get"); //NOI18N
482                 }
483
484                 // Walk through all
485                 while (tokenizer.hasMoreTokens()) {
486                         // Get token
487                         String token = tokenizer.nextToken();
488
489                         // Debug message
490                         this.getLogger().debug(MessageFormat.format("token={0}", token)); //NOI18N
491
492                         // Make it upper-case
493                         char c = token.charAt(0);
494                         token = String.valueOf(c).toUpperCase() + token.substring(1);
495
496                         // Add token
497                         builder.append(token);
498                 }
499
500                 // Trace message
501                 this.getLogger().trace(MessageFormat.format("builder={0} - EXIT!", builder)); //NOI18N
502
503                 // Return result
504                 return builder.toString();
505         }
506
507         /**
508          * Converts a column name like "foo_bar" to a method name like "getFooBar"
509          * for non-booleans and to "isFooBar" for boolean fields.
510          *
511          * @param columnName Column name to convert
512          * @return Attribute name
513          */
514         protected String convertColumnNameToSetterMethod (final String columnName) {
515                 // Trace message
516                 this.getLogger().trace(MessageFormat.format("columnName={0} - CALLED!", columnName)); //NOI18N
517
518                 // Then split on "_"
519                 StringTokenizer tokenizer = new StringTokenizer(columnName, "_"); //NOI18N
520
521                 // Resulting string
522                 StringBuilder builder = new StringBuilder(tokenizer.countTokens());
523
524                 // Append "set"
525                 builder.append("set"); //NOI18N
526
527                 // Walk through all
528                 while (tokenizer.hasMoreTokens()) {
529                         // Get token
530                         String token = tokenizer.nextToken();
531
532                         // Debug message
533                         this.getLogger().debug(MessageFormat.format("token={0} - BEFORE", token)); //NOI18N
534
535                         // Make it upper-case
536                         char c = token.charAt(0);
537                         token = String.valueOf(c).toUpperCase() + token.substring(1);
538
539                         // Debug message
540                         this.getLogger().debug(MessageFormat.format("token={0} - AFTER", token)); //NOI18N
541
542                         // Add token
543                         builder.append(token);
544                 }
545
546                 // Trace message
547                 this.getLogger().trace(MessageFormat.format("builder={0} - EXIT!", builder)); //NOI18N
548
549                 // Return result
550                 return builder.toString();
551         }
552
553         /**
554          * Some "getter" for an array from given string and tokenizer
555          *
556          * @param str String to tokenize and get array from
557          * @param delimiter Delimiter
558          * @return Array from tokenized string TODO Get rid of size parameter
559          */
560         protected String[] getArrayFromString (final String str, final String delimiter) {
561                 // Trace message
562                 this.getLogger().trace(MessageFormat.format("str={0},delimiter={1} - CALLED!", str, delimiter)); //NOI18N
563
564                 // Get tokenizer
565                 StringTokenizer tokenizer = new StringTokenizer(str, delimiter);
566
567                 // Init array and index
568                 String[] tokens = new String[tokenizer.countTokens()];
569                 int index = 0;
570
571                 // Run through all tokens
572                 while (tokenizer.hasMoreTokens()) {
573                         // Get current token and add it
574                         tokens[index] = tokenizer.nextToken();
575
576                         // Debug message
577                         this.getLogger().debug(MessageFormat.format("Token at index{0}: {1}", index, tokens[1])); //NOI18N
578
579                         // Increment index
580                         index++;
581                 }
582
583                 // Trace message
584                 this.getLogger().trace(MessageFormat.format("tokens({0})={1} - EXIT!", tokens.length, Arrays.toString(tokens))); //NOI18N
585
586                 // Return it
587                 return tokens;
588         }
589
590         /**
591          * Returns boolean field value from given method name by invoking it
592          *
593          * @param instance The instance to call
594          * @param targetClass Target class to look in
595          * @param methodName Method name to look for
596          * @return Boolean value from field
597          * @throws java.lang.NoSuchMethodException If the method was not found
598          * @throws java.lang.IllegalAccessException If the method cannot be accessed
599          * @throws java.lang.reflect.InvocationTargetException Some other problems?
600          */
601         protected boolean getBooleanField (final FrameworkInterface instance, final String targetClass, final String methodName) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
602                 // Trace messahe
603                 this.getLogger().trace(MessageFormat.format("targetClass={0},methodName={1}", targetClass, methodName)); //NOI18N
604
605                 // Get method instance
606                 Method method = this.getMethodFromName(instance, targetClass, methodName);
607
608                 // Get value from field
609                 Boolean value = (Boolean) method.invoke(instance);
610
611                 // Trace message
612                 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
613
614                 // Return value
615                 return value;
616         }
617
618         /**
619          * Manager instance
620          *
621          * @param manager the manager instance to set
622          */
623         protected final void setContactManager (final Manageable manager) {
624                 this.manager = manager;
625         }
626
627         /**
628          * Returns any field value from given method name by invoking it
629          *
630          * @param instance The instance to call
631          * @param targetClass Target class to look in
632          * @param methodName Method name to look for
633          * @return Any value from field
634          * @throws java.lang.NoSuchMethodException If the method was not found
635          * @throws java.lang.IllegalAccessException If the method cannot be accessed
636          * @throws java.lang.reflect.InvocationTargetException Some other problems?
637          */
638         protected Object getField (final FrameworkInterface instance, final String targetClass, final String methodName) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
639                 // Trace messahe
640                 this.getLogger().trace(MessageFormat.format("instance={0},targetClass={1},methodName={2}", instance, targetClass, methodName)); //NOI18N
641
642                 // Get method to call
643                 Method method = this.getMethodFromName(instance, targetClass, methodName);
644
645                 // Debug message
646                 this.getLogger().debug(MessageFormat.format("method={0},instance={1}", method, instance)); //NOI18N
647
648                 // Get value from field
649                 Object value = method.invoke(instance);
650
651                 // Trace messahe
652                 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
653
654                 // Return value
655                 return value;
656         }
657
658         /**
659          * Getter for property which must exist
660          *
661          * @param key Key to get
662          * @return Propety value
663          */
664         protected final String getProperty (final String key) {
665                 return BaseFrameworkSystem.properties.getProperty(String.format("org.mxchange.%s", key)); //NOI18N
666         }
667
668         /**
669          * Name of used database table, handled over to backend
670          *
671          * @param tableName the tableName to set
672          */
673         protected final void setTableName (final String tableName) {
674                 this.tableName = tableName;
675         }
676
677         /**
678          * Some getter for type reflection of given column name
679          *
680          * @param instance The instance to check
681          * @param targetClass Target class to check
682          * @param columnName Column name
683          * @return Type reflection of value
684          */
685         private Class<?> getType (final FrameworkInterface instance, final String targetClass, final String columnName) {
686                 // Trace message
687                 this.getLogger().trace(MessageFormat.format("instance={0},targetClass={1},columnName={2} - CALLED!", instance, targetClass, columnName)); //NOI18N
688
689                 // Init field tye
690                 Class<?> type = null;
691
692                 // Get super class fields
693                 Field[] superFields = this.getClassFromTarget(instance, "BaseFrameworkSystem").getDeclaredFields(); //NOI18N
694
695                 // Get all attributes from given instance
696                 Field[] fields = ArrayUtils.addAll(superFields, this.getClassFromTarget(instance, targetClass).getDeclaredFields());
697
698                 // Debug message
699                 this.getLogger().debug(MessageFormat.format("fields()={0}", fields.length)); //NOI18N
700
701                 // Convert column_name to fieldName ;-)
702                 String fieldName = this.convertColumnNameToFieldName(columnName);
703
704                 // Debug message
705                 this.getLogger().debug(MessageFormat.format("fieldName={0}", fieldName)); //NOI18N
706
707                 // Search for proper field instance
708                 for (final Field field : fields) {
709                         // Is a dollar character there?
710                         if (field.getName().startsWith("$")) { //NOI18N
711                                 // Debug message
712                                 this.getLogger().debug(MessageFormat.format("Field name {0} starts with a dollar, skipped.", field.getName())); //NOI18N
713                                 // Skip this
714                                 continue;
715                         }
716
717                         // Debug message
718                         this.getLogger().debug(MessageFormat.format("field.getName()={0},fieldName={1}", field.getName(), fieldName)); //NOI18N
719
720                         // Does it match?
721                         if (field.getName().equals(fieldName)) {
722                                 // Found it
723                                 type = field.getType();
724
725                                 // Debug message
726                                 this.getLogger().debug(MessageFormat.format("Found fieldName={0}: setting type={1}", fieldName, type.getSimpleName())); //NOI18N
727
728                                 // Don't continue with searching
729                                 break;
730                         }
731                 }
732
733                 // Debug message
734                 this.getLogger().debug(MessageFormat.format("type={0}", type)); //NOI18N
735
736                 // type should not be null
737                 if (null == type) {
738                         // No null allowed
739                         throw new NullPointerException("type is null"); //NOI18N
740                 }
741
742                 // Trace message
743                 this.getLogger().debug(MessageFormat.format("type={0} - EXIT!", type)); //NOI18N
744
745                 // Return it
746                 return type;
747         }
748
749         /**
750          * Converts null to empty string or leaves original string.
751          *
752          * @param str Any string
753          * @return Empty string if null or original string
754          */
755         protected Object convertNullToEmpty (final Object str) {
756                 // Trace message
757                 this.getLogger().trace(MessageFormat.format("str={0}", str)); //NOI18N
758
759                 // Is it null?
760                 if (null == str) {
761                         // Return empty string
762                         return ""; //NOI18N
763                 }
764
765                 // Trace message
766                 this.getLogger().trace(MessageFormat.format("str={0} - EXIT!", str)); //NOI18N
767
768                 // Return it
769                 return str;
770         }
771
772         /**
773          * Creates an iterator from given instance and class name.
774          *
775          * @param instance Instance to run getter calls on
776          * @param className Class name to iterate over
777          * @return An iterator over all object's fields
778          * @throws java.lang.NoSuchMethodException If the called method does not
779          * exist
780          * @throws java.lang.IllegalAccessException If the method cannot be accessed
781          * @throws java.lang.reflect.InvocationTargetException Any other problems?
782          */
783         protected Iterator<Map.Entry<Field, Object>> fieldIterator (final Storable instance, final String className) throws IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
784                 // Trace message
785                 this.getLogger().trace(MessageFormat.format("instance={0},className={1} - CALLED!", instance, className)); //NOI18N
786
787                 // Get all attributes from given instance
788                 Field[] fields = this.getClassFromTarget(instance, className).getDeclaredFields();
789
790                 // Debug message
791                 this.getLogger().debug(MessageFormat.format("Found {0} fields.", fields.length)); //NOI18N
792
793                 // A simple map with K=fieldName and V=Value is fine
794                 Map<Field, Object> map = new HashMap<>(fields.length);
795
796                 // Walk through all
797                 for (final Field field : fields) {
798                         // Debug log
799                         this.getLogger().debug(MessageFormat.format("field={0}", field.getName())); //NOI18N
800
801                         // Does the field start with "$"?
802                         if (field.getName().startsWith("$")) { //NOI18N
803                                 // Debug message
804                                 this.getLogger().debug(MessageFormat.format("Skipping field={0} as it starts with a dollar character.", field.getName())); //NOI18N
805
806                                 // Skip it silently
807                                 continue;
808                         }
809
810                         // Debug message
811                         this.getLogger().debug(MessageFormat.format("Calling getValueFromColumn({0}) on instance {1} ...", field.getName(), instance)); //NOI18N
812
813                         // Get value from it
814                         Object value = instance.getValueFromColumn(field.getName());
815
816                         // Debug message
817                         this.getLogger().debug(MessageFormat.format("Adding field={0},value={1}", field.getName(), value)); //NOI18N
818
819                         // Add it to list
820                         map.put(field, value);
821                 }
822
823                 // Debug message
824                 this.getLogger().debug(MessageFormat.format("Returning iterator for {0} entries ...", map.size())); //NOI18N
825
826                 // Return list iterator
827                 return map.entrySet().iterator();
828         }
829
830         /**
831          * Instance for database backend
832          *
833          * @return the backend
834          */
835         protected final DatabaseBackend getBackend () {
836                 return this.backend;
837         }
838
839         /**
840          * Instance for database backend
841          *
842          * @param backend the backend to set
843          */
844         protected final void setBackend (final DatabaseBackend backend) {
845                 this.backend = backend;
846         }
847
848         /**
849          * Getter for Contact instance
850          *
851          * @return Contact instance
852          */
853         protected final Contact getContact () {
854                 return this.contact;
855         }
856
857         /**
858          * Setter for Contact instance
859          *
860          * @param contact A Contact instance
861          */
862         protected final void setContact (final Contact contact) {
863                 this.contact = contact;
864         }
865
866         /**
867          * Getter for DatabaseFrontend instance
868          *
869          * @return DatabaseFrontend instance
870          */
871         protected final DatabaseFrontend getFrontend () {
872                 return this.frontend;
873         }
874
875         /**
876          * Setter for wrapper instance
877          *
878          * @param frontend A DatabaseFrontend instance
879          */
880         protected final void setFrontend (final DatabaseFrontend frontend) {
881                 this.frontend = frontend;
882         }
883
884         /**
885          * Some getter for properties names (without org.mxchange)
886          *
887          * @return An array with property names
888          */
889         protected String[] getPropertyNames () {
890                 // Init array
891                 String[] names = {
892                         "database.backend.class", //NOI18N
893                         "database.backend.storagepath", //NOI18N
894                         "database.mysql.login", //NOI18N
895                         "database.mysql.host", //NOI18N
896                         "database.mysql.password", //NOI18N
897                         "database.mysql.dbname", //NOI18N
898                 };
899
900                 // Return it
901                 return names;
902         }
903
904         /**
905          * Some "getter" for a value from given Storable instance and target class
906          *
907          * @param instance An instance of a Storable class
908          * @param targetClass The target class (where the field resides)
909          * @param columnName Column name (= field name)
910          * @return value Value to get
911          * @throws java.lang.NoSuchMethodException If the getter was not found
912          * @throws java.lang.IllegalAccessException If the getter cannot be accessed
913          * @throws java.lang.reflect.InvocationTargetException Some other problems?
914          */
915         protected Object getValueInStorableFromColumn (final Storable instance, final String targetClass, final String columnName) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
916                 // Trace message
917                 this.getLogger().trace(MessageFormat.format("instance={0},targetClass={1},columnName={2} - CALLED!", instance, targetClass, columnName)); //NOI18N
918
919                 // A '$' means not our field
920                 if (columnName.startsWith("$")) { //NOI18N
921                         // Don't handle these
922                         throw new IllegalArgumentException("columnsName contains $"); //NOI18N
923                 }
924
925                 // Determine if the given column is boolean
926                 if (this.isBooleanField(instance, targetClass, columnName)) {
927                         // Debug message
928                         this.getLogger().debug(MessageFormat.format("Column {0} represents a boolean field.", columnName)); //NOI18N
929
930                         // Yes, then call other method
931                         return this.getBooleanField(instance, targetClass, this.convertColumnNameToGetterMethod(columnName, true));
932                 }
933
934                 // Convert column name to field name
935                 String methodName = this.convertColumnNameToGetterMethod(columnName, false);
936
937                 // Debug message
938                 this.getLogger().debug(MessageFormat.format("methodName={0}", methodName)); //NOI18N
939
940                 // Get field
941                 Object value = this.getField(instance, targetClass, methodName);
942
943                 // Trace message
944                 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
945
946                 // Return value
947                 return value;
948         }
949
950         /**
951          * Initializes i18n bundles
952          */
953         protected void initBundle () {
954                 // Trace message
955                 this.getLogger().trace("CALLED!"); //NOI18N
956
957                 // Is the bundle set?
958                 if (this.isBundledInitialized()) {
959                         // Is already set
960                         throw new IllegalStateException("called twice"); //NOI18N
961                 }
962
963                 // Set instance
964                 setBundle(ResourceBundle.getBundle(FrameworkInterface.I18N_BUNDLE_FILE)); // NOI18N
965
966                 // Trace message
967                 this.getLogger().trace("EXIT!"); //NOI18N
968         }
969
970         /**
971          * Prepares all properties, the file is written if it is not found
972          *
973          * @throws java.io.IOException If any IO problem occurs
974          */
975         protected void initProperties () throws IOException {
976                 // Trace message
977                 this.getLogger().trace("CALLED!"); //NOI18N
978
979                 // Debug message
980                 this.getLogger().debug(MessageFormat.format("{0} properties are loaded already.", BaseFrameworkSystem.properties.size())); //NOI18N
981
982                 // Are some properties loaded?
983                 if (!BaseFrameworkSystem.properties.isEmpty()) {
984                         // Some are already loaded, abort here
985                         return;
986                 }
987
988                 try {
989                         // Try to read it
990                         BaseFrameworkSystem.properties.load(new BufferedReader(new InputStreamReader(new FileInputStream(FrameworkInterface.PROPERTIES_CONFIG_FILE))));
991
992                         // Debug message
993                         this.getLogger().debug(MessageFormat.format("{0} properties has been loaded.", BaseFrameworkSystem.properties.size())); //NOI18N
994                 } catch (final FileNotFoundException ex) {
995                         // Debug message
996                         this.getLogger().debug(MessageFormat.format("Properties file {0} not found: {1}", FrameworkInterface.PROPERTIES_CONFIG_FILE, ex)); //NOI18N
997
998                         /*
999                          * The file is not found which is normal for first run, so
1000                          * initialize default values.
1001                          */
1002                         this.initPropertiesWithDefault();
1003
1004                         // Write file
1005                         this.writePropertiesFile();
1006                 }
1007
1008                 // Trace message
1009                 this.getLogger().trace("EXIT!"); //NOI18N
1010         }
1011
1012         /**
1013          * Checks whether the given field is a boolean field by probing it.
1014          *
1015          * @param instance Instance to call
1016          * @param targetClass Target class
1017          * @param columnName Column name to check
1018          * @return Whether the given column name represents a boolean field
1019          */
1020         protected boolean isBooleanField (final FrameworkInterface instance, final String targetClass, final String columnName) {
1021                 // Trace message
1022                 this.getLogger().trace(MessageFormat.format("instance={0},targetCLass={1},columnName={2} - CALLED!", instance, targetClass, columnName)); //NOI18N
1023
1024                 // Convert column name to getter name (boolean)
1025                 String methodName = this.convertColumnNameToGetterMethod(columnName, true);
1026
1027                 // Get class instance
1028                 Class<? extends FrameworkInterface> c = this.getClassFromTarget(instance, targetClass);
1029
1030                 // Defauzlt is boolean
1031                 boolean isBool = true;
1032
1033                 try {
1034                         // Now try to instance the method
1035                         Method method = c.getDeclaredMethod(methodName, new Class<?>[0]);
1036                 } catch (final NoSuchMethodException ex) {
1037                         // Debug message
1038                         this.getLogger().debug(MessageFormat.format("Method {0} does not exist, field {1} cannot be boolean: {2}", methodName, columnName, ex)); //NOI18N
1039
1040                         // Not found
1041                         isBool = false;
1042                 }
1043
1044                 // Trace message
1045                 this.getLogger().trace(MessageFormat.format("isBool={0} - EXIT!", isBool)); //NOI18N
1046
1047                 // Return result
1048                 return isBool;
1049         }
1050
1051         /**
1052          * Checks if the bundle is initialized
1053          *
1054          * @return Whether the bundle has been initialized
1055          */
1056         protected boolean isBundledInitialized () {
1057                 // Check it
1058                 return (bundle instanceof ResourceBundle);
1059         }
1060
1061         /**
1062          * Sets boolean field value with given method name by invoking it
1063          *
1064          * @param instance The instance to call
1065          * @param targetClass Target class to look in
1066          * @param methodName Method name to look for
1067          * @param columnName Column name
1068          * @param value Boolean value from field
1069          * @throws java.lang.NoSuchMethodException If the method was not found
1070          * @throws java.lang.IllegalAccessException If the method cannot be accessed
1071          * @throws java.lang.reflect.InvocationTargetException Some other problems?
1072          */
1073         protected void setBooleanField (final FrameworkInterface instance, final String targetClass, final String methodName, final String columnName, final Boolean value) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
1074                 // Trace messahe
1075                 this.getLogger().trace(MessageFormat.format("targetClass={0},methodName={1}", targetClass, methodName)); //NOI18N
1076
1077                 // Get field type
1078                 Class<?> type = this.getType(instance, targetClass, columnName);
1079
1080                 // Get method instance
1081                 Method method = this.getMethodFromName(instance, targetClass, methodName, type);
1082
1083                 // Try to get the value by invoking the method
1084                 method.invoke(instance, value);
1085
1086                 // Trace message
1087                 this.getLogger().trace("EXIT!"); //NOI18N
1088         }
1089
1090         /**
1091          * Sets any field value with given method name by invoking it
1092          *
1093          * @param instance The instance to call
1094          * @param targetClass Target class to look in
1095          * @param methodName Method name to look for
1096          * @param columnName Column name
1097          * @param value Any value from field
1098          * @throws java.lang.NoSuchMethodException If the method was not found
1099          * @throws java.lang.IllegalAccessException If the method cannot be accessed
1100          * @throws java.lang.reflect.InvocationTargetException Some other problems?
1101          */
1102         protected void setField (final FrameworkInterface instance, final String targetClass, final String methodName, final String columnName, final Object value) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
1103                 // Trace messahe
1104                 this.getLogger().trace(MessageFormat.format("instance={0},targetClass={1},methodName={2},value={3}", instance, targetClass, methodName, value)); //NOI18N
1105
1106                 // Get field type
1107                 Class<?> type = this.getType(instance, targetClass, columnName);
1108
1109                 // Debug message
1110                 this.getLogger().debug(MessageFormat.format("type={0}", type)); //NOI18N
1111
1112                 // Init object
1113                 Object object = value;
1114
1115                 // Is the value null?
1116                 if ("null".equals(value)) { //NOI18N
1117                         // Warning message
1118                         this.getLogger().warn(MessageFormat.format("columnName={0} has null value.", columnName)); //NOI18N
1119
1120                         // Set null
1121                         object = null;
1122                 } else {
1123                         // Hard-coded "cast" again ... :-(
1124                         // TODO Can't we get rid of this???
1125                         switch (type.getSimpleName()) {
1126                                 case "Long": // Long object //NOI18N
1127                                         object = Long.parseLong((String) value);
1128                                         break;
1129
1130                                 case "Float": // Float object //NOI18N
1131                                         object = Float.parseFloat((String) value);
1132                                         break;
1133
1134                                 case "Boolean": // Boolean object //NOI18N
1135                                         object = Boolean.parseBoolean((String) value);
1136                                         break;
1137
1138                                 case "String": // String object //NOI18N
1139                                         break;
1140
1141                                 default: // Unsupported type
1142                                         throw new IllegalArgumentException(MessageFormat.format("value {0} has unsupported type {1}", value, type.getSimpleName())); //NOI18N
1143                         }
1144                 }
1145
1146                 // Debug message
1147                 this.getLogger().debug(MessageFormat.format("object={0}", object)); //NOI18N
1148
1149                 // Get method to call
1150                 Method method = this.getMethodFromName(instance, targetClass, methodName, type);
1151
1152                 // Debug message
1153                 this.getLogger().debug(MessageFormat.format("method={0},instance={1},value[{2}]={3}", method, instance, value.getClass().getSimpleName(), value)); //NOI18N
1154
1155                 // Get value from field
1156                 method.invoke(instance, object);
1157
1158                 // Trace messahe
1159                 this.getLogger().trace("EXIT!"); //NOI18N
1160         }
1161
1162         /**
1163          * Sets value in properties instance.
1164          *
1165          * @param key Property key (part) to set
1166          * @param value Property value to set
1167          */
1168         protected void setProperty (final String key, final String value) {
1169                 // Trace message
1170                 this.getLogger().trace(MessageFormat.format("key={0},value={1} - CALLED!", key, value)); //NOI18N
1171
1172                 // Both should not be null
1173                 if (null == key) {
1174                         // key is null
1175                         throw new NullPointerException("key is null"); //NOI18N
1176                 } else if (null == value) {
1177                         // value is null
1178                         throw new NullPointerException("value is null"); //NOI18N
1179                 }
1180
1181                 // Set it
1182                 properties.setProperty(String.format("org.mxchange.%s", key), value); //NOI18N
1183
1184                 // Trace message
1185                 this.getLogger().trace("EXIT!"); //NOI18N
1186         }
1187
1188         /**
1189          * Some "setter" for a value in given Storable instance and target class
1190          *
1191          * @param instance An instance of a Storable class
1192          * @param targetClass The target class (where the field resides)
1193          * @param columnName Column name (= field name)
1194          * @param value Value to set
1195          * @throws java.lang.NoSuchMethodException If the setter is not found
1196          * @throws java.lang.IllegalAccessException If the setter cannot be accessed
1197          * @throws java.lang.reflect.InvocationTargetException Any other problem?
1198          */
1199         protected void setValueInStorableFromColumn (final Storable instance, final String targetClass, final String columnName, final Object value) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
1200                 // Trace message
1201                 this.getLogger().trace(MessageFormat.format("instance={0},targetClass={1},columnName={2},value={3} - CALLED!", instance, targetClass, columnName, value)); //NOI18N
1202
1203                 // A '$' means not our field
1204                 if (columnName.startsWith("$")) { //NOI18N
1205                         // Don't handle these
1206                         throw new IllegalArgumentException("columnsName contains $"); //NOI18N
1207                 }
1208
1209                 // Determine if the given column is boolean
1210                 if (this.isBooleanField(instance, targetClass, columnName)) {
1211                         // Debug message
1212                         this.getLogger().debug(MessageFormat.format("Column {0} represents a boolean field.", columnName)); //NOI18N
1213
1214                         // Yes, then call other method
1215                         this.setBooleanField(instance, targetClass, this.convertColumnNameToSetterMethod(columnName), columnName, (Boolean) value);
1216                 }
1217
1218                 // Convert column name to field name
1219                 String methodName = this.convertColumnNameToSetterMethod(columnName);
1220
1221                 // Debug message
1222                 this.getLogger().debug(MessageFormat.format("methodName={0}", methodName)); //NOI18N
1223
1224                 // Get field
1225                 this.setField(instance, targetClass, methodName, columnName, value);
1226
1227                 // Trace message
1228                 this.getLogger().trace("EXIT!"); //NOI18N
1229         }
1230 }