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

org.refcodes.mixin.AbstractSchema 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")
// -----------------------------------------------------------------------------
// 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.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

/**
 * The purpose of a {@link Schema} is automatically generate documentation of
 * nested data structures.
 */
public abstract class AbstractSchema extends HashMap implements Schema {

	private static final long serialVersionUID = 1L;

	// /////////////////////////////////////////////////////////////////////////
	// CONSTANTS:
	// /////////////////////////////////////////////////////////////////////////

	private static final String INDENT = "  ";

	// /////////////////////////////////////////////////////////////////////////
	// VARIABLES:
	// /////////////////////////////////////////////////////////////////////////

	private Schema[] _children = null;

	// /////////////////////////////////////////////////////////////////////////
	// CONSTRUCTORS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Constructs a {@link Schema} with the provided arguments.
	 *
	 * @param aType The type providing the this {@link Schema} instance.
	 * @param aDescription The description of the schema described by the
	 *        {@link Schema} providing type.
	 */
	public AbstractSchema( Class aType, String aDescription ) {
		put( TYPE, aType );
		put( DESCRIPTION, aDescription );
	}

	/**
	 * Constructs a {@link Schema} with the provided arguments.
	 *
	 * @param aAlias The alias (name) of the schema described by the
	 *        {@link Schema} providing type.
	 * @param aType The type providing the this {@link Schema} instance.
	 */
	public AbstractSchema( String aAlias, Class aType ) {
		put( TYPE, aType );
		put( ALIAS, aAlias );
	}

	/**
	 * Constructs a {@link Schema} with the provided arguments.
	 * 
	 * @param aAlias The alias (name) of the schema described by the
	 *        {@link Schema} providing type.
	 * @param aType The type providing the this {@link Schema} instance.
	 * @param aDescription The description of the schema described by the
	 *        {@link Schema} providing type.
	 */
	public AbstractSchema( String aAlias, Class aType, String aDescription ) {
		put( TYPE, aType );
		put( ALIAS, aAlias );
		put( DESCRIPTION, aDescription );
	}

	/**
	 * Constructs a {@link Schema} with the provided arguments.
	 *
	 * @param aType The type providing the this {@link Schema} instance.
	 * @param aDescription The description of the schema described by the
	 *        {@link Schema} providing type.
	 * @param aChildren The children's {@link Schema} descriptions representing
	 *        part of the {@link Schema} providing type.
	 */
	public AbstractSchema( Class aType, String aDescription, Schema... aChildren ) {
		_children = aChildren;
		put( TYPE, aType );
		put( DESCRIPTION, aDescription );
	}

	/**
	 * Constructs a {@link Schema} with the provided arguments.
	 * 
	 * @param aAlias The alias (name) of the schema described by the
	 *        {@link Schema} providing type.
	 * @param aType The type providing the this {@link Schema} instance.
	 * @param aDescription The description of the schema described by the
	 *        {@link Schema} providing type.
	 * @param aChildren The children's {@link Schema} descriptions representing
	 *        part of the {@link Schema} providing type.
	 */
	public AbstractSchema( String aAlias, Class aType, String aDescription, Schema... aChildren ) {
		_children = aChildren;
		put( TYPE, aType );
		put( ALIAS, aAlias );
		put( DESCRIPTION, aDescription );
	}

	/**
	 * Constructs a {@link Schema} with the properties of the provided
	 * {@link Schema} ("copy constructor"),.
	 *
	 * @param aSchema The {@link Schema} from which to copy the attributes.
	 */
	public AbstractSchema( Schema aSchema ) {
		super( aSchema );
		_children = aSchema.getChildren();
		put( TYPE, aSchema.getType() );
		put( ALIAS, aSchema.getAlias() );
		put( DESCRIPTION, aSchema.getDescription() );
	}

	/**
	 * Constructs a {@link Schema} with the provided arguments.
	 * 
	 * @param aType The type providing the this {@link Schema} instance.
	 * @param aSchema The {@link Schema} from which to copy the attributes.
	 */
	public AbstractSchema( Class aType, Schema aSchema ) {
		_children = aSchema.getChildren();
		putAll( aSchema );
		put( TYPE, aType );
		put( ALIAS, aSchema.getAlias() );
		put( DESCRIPTION, aSchema.getDescription() );
	}

	/**
	 * Constructs a {@link Schema} with the properties of the provided
	 * {@link Schema} ("copy constructor"),.
	 *
	 * @param aSchema The {@link Schema} from which to copy the attributes.
	 * @param aChildren The children's {@link Schema} descriptions representing
	 *        part of the {@link Schema} providing type.
	 */
	public AbstractSchema( Schema aSchema, Schema... aChildren ) {
		super( aSchema );
		_children = aChildren;
		put( TYPE, aSchema.getType() );
		put( ALIAS, aSchema.getAlias() );
		put( DESCRIPTION, aSchema.getDescription() );
	}

	// /////////////////////////////////////////////////////////////////////////
	// METHODS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Schema[] getChildren() {
		return _children;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String toString() {
		return toString( this, 0 );
	}

	// /////////////////////////////////////////////////////////////////////////
	// HOOKS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Hook method for converting a type to an according {@link String}.
	 * 
	 * @param aValue The value of a given type to be converted accordingly.
	 * 
	 * @return The accordingly converted value.
	 */
	protected String toString( Object aValue ) {
		if ( aValue != null && aValue.getClass().isArray() ) {
			String theValue = "{ ";
			final int theLength = Array.getLength( aValue );
			for ( int i = 0; i < theLength; i++ ) {
				theValue = theValue + toString( Array.get( aValue, i ) );
				if ( i < theLength - 1 ) {
					theValue += ", ";
				}
			}
			return theValue + " }";
		}
		else {
			if ( aValue instanceof String || ( aValue != null && aValue.getClass().isEnum() ) ) {
				return "\"" + aValue + "\"";
			}
			if ( aValue instanceof Character ) {
				return "'" + aValue + "'";
			}
			if ( aValue instanceof Byte ) {
				return toHexString( (byte) aValue );
			}
			if ( aValue instanceof Class ) {
				return "\"" + ( (Class) aValue ).getName() + "\"";
			}
			if ( aValue instanceof Exception ) {
				return "\"" + aValue + "\"";
			}
		}
		return aValue != null ? aValue.toString() : null;
	}

	// /////////////////////////////////////////////////////////////////////////
	// HELPER:
	// /////////////////////////////////////////////////////////////////////////

	private String toString( Schema aSchema, int aIndent ) {
		String theIndent = "";
		for ( int i = 0; i < aIndent; i++ ) {
			theIndent += INDENT;
		}
		if ( aSchema != null ) {
			final StringBuilder theBuffer = new StringBuilder();
			theBuffer.append( theIndent );
			theBuffer.append( aSchema.getType().getSimpleName() );
			theBuffer.append( ": {" );
			final ArrayList theKeys = new ArrayList<>( aSchema.keySet() );
			Collections.sort( theKeys );
			Object eValue;
			String eStrValue;
			for ( String eKey : theKeys ) {
				eStrValue = "";
				eValue = aSchema.get( eKey );
				eStrValue = toString( eValue );
				appendAttribute( INDENT + eKey + ": " + eStrValue, theBuffer, theIndent );
			}
			if ( aSchema.getChildren() != null ) {
				for ( int i = 0; i < aSchema.getChildren().length; i++ ) {
					if ( theBuffer.charAt( theBuffer.length() - 1 ) == '"' || theBuffer.charAt( theBuffer.length() - 1 ) == '}' ) {
						theBuffer.append( ',' );
					}
					theBuffer.append( System.lineSeparator() );
					theBuffer.append( toString( aSchema.getChildren()[i], aIndent + 1 ) );
				}
			}
			if ( theBuffer.charAt( theBuffer.length() - 1 ) != '{' ) {
				theBuffer.append( System.lineSeparator() );
				theBuffer.append( theIndent );
			}
			theBuffer.append( "}" );
			return theBuffer.toString();
		}
		return theIndent + "null";
	}

	private static String toHexString( byte aByte ) {
		final StringBuilder theBuffer = new StringBuilder();
		theBuffer.append( "0x" );
		theBuffer.append( Character.forDigit( ( aByte >> 4 ) & 0xF, 16 ) );
		theBuffer.append( Character.forDigit( ( aByte & 0xF ), 16 ) );
		return theBuffer.toString();
	}

	private static void appendAttribute( String aText, StringBuilder aBuffer, String aIndent ) {
		if ( aBuffer.charAt( aBuffer.length() - 1 ) != '{' ) {
			aBuffer.append( ',' );
		}
		aBuffer.append( System.lineSeparator() );
		aBuffer.append( aIndent );
		aBuffer.append( aText );
	}

	//	private static String toAlias( String aAlias, Class aType ) {
	//		if ( aType != null && (aAlias == null || aAlias.length() == 0) ) {
	//			aAlias = Character.toLowerCase( aType.getSimpleName().charAt( 0 ) ) + aType.getSimpleName().substring( 1 );
	//		}
	//		return aAlias != null && aAlias.length() != 0 ? aAlias : null;
	//	}

	//	private static String toAlias( Class aType ) {
	//		if ( aType != null ) {
	//			return Character.toLowerCase( aType.getSimpleName().charAt( 0 ) ) + aType.getSimpleName().substring( 1 );
	//		}
	//		return null;
	//	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy