All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.refcodes.mixin.Dumpable Maven / Gradle / Ivy

There is a newer version: 3.3.8
Show newest version
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// =============================================================================
// This code is copyright (c) by Siegfried Steiner, Munich, Germany, distributed
// on an "AS IS" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, and licen-
// sed under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// =============================================================================
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// together with the GPL linking exception applied; as being applied by the GNU
// Classpath ("http://www.gnu.org/software/classpath/license.html")
// =============================================================================
// Apache License, v2.0 ("http://www.apache.org/licenses/TEXT-2.0")
// =============================================================================
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////

package org.refcodes.mixin;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * Dumps the state of the instance into a {@link Map}. Each property
 * representing the implementing class's state should be dumped into a separate
 * key/value pair of the {@link Map}. The default implementation of this
 * interface applies basic reflection mechanisms to create a dump of the
 * implementing instance's state.
 */
public interface Dumpable {

	/**
	 * Dumps the state of the implementing instance into a {@link Map} which is
	 * returned as result. The {@link #toDump()} method may call the
	 * {@link #toDump(Map)} methods of internal instances also being part of the
	 * state. The default implementation creates a new {@link Map} and calls
	 * {@link #toDump(Map)}. So you most probably implement the
	 * {@link #toDump(Map)} method.
	 * 
	 * @return The {@link Map} with the dumped properties of the implementing
	 *         instance.
	 */
	default Map toDump() {
		return toDump( new HashMap<>() );
	}

	/**
	 * Dumps the state of the implementing instance into the provided
	 * {@link Map} which is returned as result. The {@link #toDump(Map)} method
	 * may call the {@link #toDump(Map)} methods of internal instances also
	 * being part of the state. You most probably implement the
	 * {@link #toDump(Map)} method as the {@link #toDump()} method has a default
	 * implementation invoking {@link #toDump(Map)} with an empty {@link Map}.
	 * This default implementation uses reflection to create a basic dump.
	 * {@link Map} properties are processed but not recursively digged into.
	 * Existing properties are overwritten in case shadowing super-class's
	 * properties.
	 *
	 * @param aDump the {@link Map} where to dump to.
	 * 
	 * @return The {@link Map} with the dumped properties of the implementing
	 *         instance.
	 */
	default Map toDump( Map aDump ) {
		Field[] eFields;
		String eFieldName;
		Object eValue;
		Map eMap;
		Map eDump;
		String eStringValue;
		Class eClass = getClass();
		String eKeyString;
		if ( this instanceof Map ) {
			eMap = (Map) this;
			for ( Object eKey : eMap.keySet() ) {
				eValue = eMap.get( eKey );
				try {
					aDump.put( eKey != null ? eKey.toString() : null, eValue != null ? eValue.toString() : null );
				}
				// ---------------------------------------------
				// In case the Map does not support null values:
				// ---------------------------------------------
				catch ( NullPointerException e ) {
					eKeyString = eKey != null ? eKey.toString() : "null";
					eStringValue = eValue != null ? eValue.toString() : "null";
					aDump.put( eKeyString, eStringValue );
				}
				// ---------------------------------------------
			}
		}

		do {
			eFields = eClass.getDeclaredFields();
			for ( Field eField : eFields ) {
				eFieldName = eField.getName();
				try {
					// Don't in Java 9 |-->
					try {
						eField.setAccessible( true );
					}
					catch ( Exception ignore ) {}
					// Don't in Java 9 <--|
					eValue = eField.get( this );
					if ( eValue instanceof Dumpable ) {
						eDump = ( (Dumpable) eValue ).toDump();
						for ( String eKey : eDump.keySet() ) {
							aDump.put( eFieldName + "." + eKey, eDump.get( eKey ) );
						}
					}
					else {
						if ( eValue instanceof Map ) {
							eMap = (Map) eValue;
							for ( Object eKey : eMap.keySet() ) {
								eValue = eMap.get( eKey );
								try {
									eKeyString = eKey != null ? eKey.toString() : null;
									eStringValue = eValue != null ? eValue.toString() : null;
									aDump.put( eFieldName + "." + eKeyString, eStringValue );
								}
								// ---------------------------------------------
								// In case the Map does not support null values:
								// ---------------------------------------------
								catch ( NullPointerException e ) {
									eKeyString = eKey != null ? eKey.toString() : "null";
									eStringValue = eValue != null ? eValue.toString() : "null";
									aDump.put( eFieldName + "." + eKeyString, eStringValue );
								}
								// ---------------------------------------------
							}
						}
						else {
							eStringValue = eValue != null ? eValue.toString() : null;
							aDump.put( eFieldName, eStringValue );
						}
					}
				}
				catch ( IllegalArgumentException | IllegalAccessException e ) {
					aDump.put( eFieldName, "(unaccessible field)" );
				}
			}
			eClass = eClass.getSuperclass();
		} while ( eClass != null );
		return aDump;
	}

	/**
	 * Creates a printable representation of the content of this map.
	 * 
	 * @return A {@link String} with the content of this map which directly can
	 *         be printed.
	 */
	//	default String toPrintable() {
	//		StringBuilder theBuilder = new StringBuilder();
	//		String eValue;
	//		Map theDump = toDump();
	//		List theKeys = new ArrayList<>( theDump.keySet() );
	//		Collections.sort( theKeys );
	//		for ( String eKey : theKeys ) {
	//			eValue = theDump.get( eKey );
	//			if ( eValue != null ) {
	//				eValue = "\"" + eValue + "\"";
	//			}
	//			else {
	//				eValue = "null";
	//			}
	//			theBuilder.append( "\"" + eKey + "\" = " + eValue );
	//			theBuilder.append( System.lineSeparator() );
	//		}
	//		return theBuilder.toString();
	//	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy