Results 1 to 3 of 3
  1. #1
    godshawk's Avatar
    Join Date
    Mar 2013
    Gender
    female
    Location
    root@google ~#
    Posts
    90
    Reputation
    14
    Thanks
    134
    My Mood
    Crappy

    [This should say Source Code] Better options management

    Right, so today am gonna teach you a nicer way to handle options/config/whatever you wanna call it. This requires that you have/know how to make:
    • A module system
    • Java Reflection
    • Brains
    • Basic Java knowledge


    This method of managing options is annotation-based because I love annotations.

    So first we need the option annotation. It looks like this:
    Code:
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
      @retention( RetentionPolicy.RUNTIME )
      @target( ElementType.FIELD )
    public  @interface Option {
    	String name();
    	
    	EnumOptionType type() default EnumOptionType.INT;
    }
    The Retention annotation tells the compiler to keep this annotation at runtime. The Target annotation tells the compiler that this annotation can only be placed on Fields.

    The name() method is what the option will be called when you save the config file. The type method will tell what kind of option it is; this defaults to Integer.

    Of course, this requires the EnumOptionType class, so here that is:
    Code:
    public enum EnumOptionType {
    	INT, FLOAT, DOUBLE, STRING, BOOLEAN;
    }
    Not much to say about this one.

    Now we just need to be able to register classes that have options, and get the relevant data, and we'll be good. The class for that looks like this:
    Code:
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map.Entry;
    
    /**
     * Scrapes/cleans options
     */
    public class OptionsScraper {
    	private static OptionsScraper instance;
    	
    	private final LinkedHashMap< Tuple< Object, String >, List< Field >> options;
    	
    	private OptionsScraper() {
    		options = new LinkedHashMap<>();
    	}
    	
    	public void registerOption( final Object opiner, final String name ) {
    		final List< Field > options = new ArrayList<>();
    		for( final Field f : opiner.getClass().getDeclaredFields() ) {
    			f.setAccessible( true );
    			if( f.isAnnotationPresent( Option.class ) ) {
    				options.add( f );
    			}
    			f.setAccessible( false );
    		}
    		
    		if( options.size() == 0 ) {
    			return;
    		}
    		this.options.put( new Tuple< Object, String >( opiner, name ), options );
    	}
    	
    	public List< String > scrapeOptions() {
    		final List< String > scrapes = new ArrayList<>();
    		for( final Entry< Tuple< Object, String >, List< Field >> en : options.entrySet() ) {
    			String opt = en.getKey().getKey();
    			for( final Field e : en.getValue() ) {
    				e.setAccessible( true );
    				final Option o = e.getAnnotation( Option.class );
    				opt += " " + o.name() + " " + o.type().name();
    				
    				String val = "";
    				
    				try {
    					val = e.get( en.getKey().getEntry() ).toString();
    				} catch( IllegalArgumentException | IllegalAccessException e1 ) {
    					e1.printStackTrace();
    					return null;
    				}
    				opt += " " + val;
    				e.setAccessible( false );
    				scrapes.add( opt );
    			}
    		}
    		return scrapes;
    	}
    	
    	public static OptionsScraper getInstance() {
    		if( instance == null ) {
    			instance = new OptionsScraper();
    		}
    		return instance;
    	}
    }
    And the relevant Tuple class:
    Code:
    /**
     * Stores 2 things, like a Tuple in Python.
     * <p>
     * And for what I use this for, it'd be a waste to make some kind of Map.
     * 
     *  @Author godshawk
     * 
     *  @param <K>
     *  @param <V>
     */
    public final class Tuple< K, V > {
    	
    	private K thing1;
    	private V thing2;
    	
    	public Tuple( final K thing1, final V thing2 ) {
    		this.thing1 = thing1;
    		this.thing2 = thing2;
    	}
    	
    	public K getEntry() {
    		return thing1;
    	}
    	
    	public V getKey() {
    		return thing2;
    	}
    	
    	public void setEntry( final K k ) {
    		this.thing1 = k;
    	}
    	
    	public void setKey( final V v ) {
    		this.thing2 = v;
    	}
    }
    How it works:
    • The options manager thingie has a HashMap that stores a Tuple and a List of Fields. The Tuple, in turn, stores a String for the name of the class that stores the options, and an instance of said class.
    • When you register a new option class, it creates a new List of Fields. After this, it iterates through the list of fields declared in the class of the Object passed in
    • For each field, it checks if it has the Option annotation
    • If it does, it's added to the list.
    • Once it's finished iterating over fields, it stores the information in the HashMap.
    • When it goes to save the options, it iterates over the HashMap
    • For each entry, it tries to get the value of the Field and the name from the Option annotation. If this succeeds, it adds the resulting String to a List of Strings it created at the start of the method.
    • Once this is complete, it returns the List of Strings.


    And you would use it like this:
    Code:
    public class ModuleTracers extends Module {
    	// Irrelevant stuff was here
      @Option( name = "tracerWidth", type = EnumOptionType.FLOAT )
    	private float tracerWidth = 1.0F;
    	// Irrelevant stuff was here
    	
    }
    And register it like this:
    Code:
    OptionsScraper.getInstance().registerOption(module, "MyModule");
    Last edited by godshawk; 03-04-2014 at 03:31 PM.

    PM me if you need something.

    DOGE: DLunanNyoE7wmiiKQMVXpSxcQag3eN7kB5

  2. The Following User Says Thank You to godshawk For This Useful Post:

    Caezer99 (03-07-2014)

  3. #2
    LordPankake's Avatar
    Join Date
    Aug 2012
    Gender
    male
    Posts
    1,010
    Reputation
    260
    Thanks
    2,466
    My Mood
    Angry


    I liek potatoes

    Also, dat 1K

    ----Edited opinion as I said I would---------

    Do you honestly think anyone where looking in this section will be able to understand this level of java? It's certainly nice, but not useful to the majority of people here seeing that they don't usually get past statically loaded arraylists.
    Last edited by LordPankake; 03-04-2014 at 04:12 PM.

  4. The Following User Says Thank You to LordPankake For This Useful Post:

    Caezer99 (03-07-2014)

  5. #3
    Not2EXcEL's Avatar
    Join Date
    Feb 2014
    Gender
    male
    Posts
    22
    Reputation
    10
    Thanks
    5
    My Mood
    Stressed
    y u no mek Tuple impilmintaeshun of de Entry

Similar Threads

  1. [Release] DayZ Key Manager [Awesome Options]
    By zombie1004 in forum DayZ Mod & Standalone Hacks & Cheats
    Replies: 21
    Last Post: 02-26-2013, 04:51 PM
  2. What Do You Hate? +More Options & Better Title!
    By Arctikranqe51 in forum Combat Arms Discussions
    Replies: 45
    Last Post: 07-11-2012, 10:13 PM
  3. Which sig looks better
    By Killclowns in forum Art & Graphic Design
    Replies: 5
    Last Post: 02-10-2006, 07:13 AM
  4. What do ya like better?
    By i eat trees in forum Entertainment
    Replies: 5
    Last Post: 02-09-2006, 10:57 PM
  5. 2nd sig much better!
    By darkone1149 in forum Art & Graphic Design
    Replies: 5
    Last Post: 02-08-2006, 05:15 PM