Category Archives: development

React component with Media queries for Responsive

This is a very simple approach using matchMedia support. We store media queries and a listener function as an object in an array. When the media query returns true the listener function will set the relevant component state true.

In our actual project, this approach is used with Redux. The queries instead of setting component state, update the Store. Containers connected to this store send the breakPoint, orientation, and other props to each child component.

Just an experiment. If pursued further, would probably make it a HOC (Higher Order Component).

Gist available here.

Demo
If packed and loaded into a web page as we resize the browser we should see:

Change size of browser to test

state: { 
    "orientation": "landscape", 
    "breakPoint": "LG" 
}

Why?
While CSS media queries are very useful, sometimes being able to respond ‘behaviorally’ to media events is very powerful.

Tested on
Chrome, FireFox, IE, and Edge. I guess they all have JavaScript MediaQuery support.

How it works

In the life cycle method ‘componentDidMount’ we add a query to an array in the component:

this.mediaQueryFactory(obj, '(orientation: portrait)', this.onPortrait);

this.mediaQueryLists.push({
	mql: obj.mql,
	listener: this.onPortrait
});

the onPortrait is the listener function:

onPortrait : function(flag){
  if(flag){
	this.setState({orientation: 'portrait'});
  }
},

Full Code

Other MediaQuery React implementations

Addendum

{
  "name": "ReactMediaQuery",
  "version": "1.0.0",
  "description": "Attempt at using Media Queries in React",
  "main": "./index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack index.js dist/react-media-query-bundle.js"
  },
  "keywords": [
    "react"
  ],
  "author": "JosefBetancourt",
  "license": "SEE LICENSE IN COPYWRITE.TXT",
  "dependencies": {
    "babel-polyfill": "^6.9.1",
    "classnames": "^2.2.5",
    "react": "^15.3.0",
    "react-dom": "^15.3.0"
  },
  "devDependencies": {
    "babel-core": "^6.10.4",
    "babel-loader": "^6.2.4",
    "babel-plugin-add-module-exports": "^0.2.1",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-es2016": "^6.11.3",
    "babel-preset-react": "^6.3.13",
    "babel-preset-stage-2": "^6.11.0",
    "eslint": "^3.2.2",
    "webpack": "^1.13.1"
  }
}

package.json

var path = require('path');
const webpack = require('webpack');

module.exports = {
  /* entry point */
  entry: './index.js',
  /* output folder */
  output: {
    filename: 'dist/react-media-query-bundle.js'
  },
  devtool: 'source-map',
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        query: {
          presets: ['es2015', 'react', 'stage-2']
        }
      },
    ]
  },
  eslint: {
    configFile: path.join(__dirname, 'eslint.js'),
    useEslintrc: false
  },  
  plugins: [
  ],
  resolve: {
    extensions: ['', '.js', '.json'] 
  },
  resolveLoader: {
      modulesDirectories: [
          'node_modules'
      ]
  }
};

webpack.config.js

<!DOCTYPE html>
<html>
  <head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">  
  	<title>React Media Queries</title>
  </head>
  <body class="body">
    <div id="root" class="">Loading page, please wait ....</div>
	<script src="dist/react-media-query-bundle.js"></script>
  </body>
</html>

index.html

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Reactive client application state constraint contracts

As in Design By Contract (DbC), the contents and structure of a Store mutation can be constrained by Preconditions, Postconditions, and Invariants. These constraints are part of the Store implementation.

Background
Modern JavaScript frameworks are now emphasizing a form of “global” state storage. This is not really new, but gained new impetus when React came out, which synergistically combined this with other factors, like components, virtual-DOM, and one-way data flow.

React Stores

“… contain the application state and logic. Their role is somewhat similar to a model in a traditional MVC, but they manage the state of many objects — they do not represent a single record of data like ORM models do. Nor are they the same as Backbone’s collections. More than simply managing a collection of ORM-style objects, stores manage the application state for a particular domain within the application.” — https://facebook.github.io/flux/docs/overview.html

In very large apps and multiple development teams, this Store could become a high maintenance cost and a source of defects.

Non-React Store
For example of a reusable Store implementation see Redux. Amazing video: Dan Abramov – Live React: Hot Reloading with Time Travel at react-europe 2015

Interesting Java implementation of Redux: redux-java.

Maintenance
Today’s great application and shiny new framework are tomorrow’s maintenance nightmare. Thus, it makes sense to add in features that will aid this future support.

Example
A store has a JSON map of { foo : true, fee : false, fum : {…}, … }.

A particular flow in the application will update foo to false. Is that ok?

If foo and fee are in the same ‘context’, can they both be false? Note that the ‘application’ or maintenance developer may not know that there is a relationship between foo and fee. With annotations, dependency injection, and so forth, even perusal of the source could make this determination difficult.

Sure, in a small app and simple Store, it would be easy to trace the program and find out the implicit constraints. In reality, Stores grow complex over time, the app gets complex, new requirements mean many changes, and the developer culprit has left the company. Stores will mutate to resemble the catch-all Windows’ Registry.

To compound this, the control flows are hidden within the framework being used. No matter if its today’s MVC usurper, React, or some Observable liberator, there is spaghetti flow and implicit state somewhere.

“At some point, you no longer understand what happens in your app as you have lost control over the when, why, and how of its state. When a system is opaque and non-deterministic, it’s hard to reproduce bugs or add new features.” —
http://redux.js.org/docs/introduction/Motivation.html

Constraints
One way to reduce issues is to use the techniques from data design and use schema constraints. This does not necessarily mean the use of actual schemas as in XML’s XSD or its wannabe JSON equivalent. One alternative is that the Store has an API for constraint binding to content, new life cycle functions apply the constraints. The result of a constraint violation depends on dev or production deployment, log or throw of exceptions.

Afterword
Notice how in the development world we are going back in time? Central stores, Data flow diagrams, functional programming, FSM (obfuscated), etc. Maybe Object-Oriented Programming was a great distraction like Disco. Time for some real funk. “Maceo, I want you to Blow!

Wow, this synchronicity is weird. I’ve been thinking of this post’s contents for a while. Started to write it and my twitter app on phone rings. @brianloveswords tweets about a blog post by @jlongster: “Starters and Mainainers”. Not exactly the same subject, but was about maintenance.

Links

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Adaptive log level based on error context

The other day I was thinking about my companies’ application logging system, and wondered why we don’t increase the log output when there is a problem? I mean doing this automatically.

Problem
If a method in a class is logging at the ERROR level, and an exception occurs, the log output is useful at that level, it contains a stack-trace, for example. However, there are more levels below ERROR that contain much more info that could be useful in maintaining the system. Levels are used to control the logging output in logging systems. For example, in java.util.logging there are seven default levels: SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST.

Solution
One way of getting at this useful information is by the class with the detected exception setting the log level in that problem method or function to a more verbose level. The algorithm would probably be similar to the Circuit Breaker design pattern.

Like “First Failure Data Capture” this approach could be called Nth Failure Data Capture.

Issues
Of course, while this may be easy to do this programmatically, in practice, this is not simple approach. Many questions remain: performance; resources; is one error occurrence enough to trigger a change; are all threads effected; which target level; how much logging, how to reset the level, and so forth.

Funny, I’m sure this is not a new idea. A quick search makes it look like it is not a well-known approach.

Alternatives

  • Record everything instead of logging just some things. This is possible with some systems, for example Chronon?

Links

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

JSON as a configuration language

JSON as a configuration data file is already a given. I wrote about this before. Google has now made this even more powerful by open sourcing Jsonnet, a “mini-language”, domain specific language (DSL) on this data format. Jsonnet it supports inline comments. Nice!

If your scratching your head and wondering why, JSON is JavaScript, then you don’t understand what JSON is. JSON is a ‘data-interchange format’. It happens to be based on a subset of the JavaScript language, but it could have been in Python, Groovy, or any other scripting language. Undoubtedly, JavaScript’s ubiquitous use on the web is why JSON was optimal.

Links

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Relation generation rules from ER diagrams

A few general purpose purpose rules can help in creating relational database models. I found these rules years ago in a library and photocopied them. Of course, these are for very simple situations and not intended for a database professional’s use.

Rules

Rule 1

When the degree of a binary relationship is 1:1 with the membership class of both entities obligatory, only one relation is required. The primary key of this relation can be the entity key from either entity.

Rule 2

When the degree of a binary relationship is 1:1 with the membership class of one entity obligatory, and the other nonobligatory, two relations are required. There must be one relation for each entity for each entity, with the entity key serving as the primary key for the corresponding relation. Additionally, the entity key from the nonobligatory side must be added as an attribute in the relation on the obligatory side.

Rule 3

When the degree of a binary relations is 1:1 with the membership class of neither entity obligatory, three relations are required one for each entity, with the entity key serving as the primary key for the corresponding relation, and one for the relationship. The relationship will have among its attributes the entity keys from each entity.

Rule 4

When the degree of a binary relationship is 1:n with the membership class of the n-side obligatory, two relations are required: one for each entity, with the entity key from each entity serving as the primary
key for the corresponding relation. Additionally, the entity key from the 1-side must be added as an attribute in the relation on the n-side.

Rule 5

When the degree of a binary relationship is 1:n with the membership class of the n-side nonobligatory, three relations are required: one for each entity with the entity key from each entity serving as the
primary key for the corresponding relation, and one for the relationship. The relationship will have among its attributes the entity keys from each entity.

Rule 6

When the degree of a binary relationship is m:n, three relations are required: one for each entity, with the entity key from each entity serving as the primary key for the corresponding relation, and one
for the relationship. The relation from the relationship will have among its attributes the entity keys from each entity.

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Use dojo’s promise.all in non-failure mode

The “all” function “Takes multiple promises and returns a new promise that is fulfilled when all promises have been resolved or one has been rejected.” This makes a lot of sense. If you are invoking multiple asynchronous services in parallel and want to wait for all of them before continuing with a “reactive” function, you probably want to not run this function if one of the services fails.

In some scenarios you do want all the service invocations to complete and then deal with the results whether success or failure. Thus, it would be nice to have a version of ‘all’ that did this.

The now deprecated DeferredList may have supported this. See this reference.

Some() function implementation
Below in listing one I created a function ‘some’ that transforms the input to ‘all’ to accomplish this. This simply takes each promise argument (in array or object) and chains an always(…) Thenable. This Thenable promise link takes a handler that will be invoked whether the prior promise is resolved or rejected. It acts like a ‘finally’ in a try .. catch .. finally.

A better approach would have been to create an alternative to the ‘all’ function that did this.

/**
 * Takes an object or array of promises and creates a new array of 
 * promises that do not fail.
 * <p>
 * The Dojo/All function is fulfilled when all promises 
 * have been resolved or when one has been rejected.
 * In certain scenarios even if some promies
 * @author J. Betancourt 
 * @since 2014/11/04
 * @param objectOrArray  Object|Array?
 * @returns {Array} of promises.
 */
;function some(objectOrArray) {
    "use strict";
    
    var promises = [];
    require([ "dojo/_base/array", "dojo/Deferred", 'dojo/when' ],
      function(array, Deferred, when) {
        var origPromises = [];
        if (objectOrArray instanceof Array) {
            origPromises = objectOrArray;
        } else {
            for ( var key in objectOrArray) {
                if (Object.hasOwnProperty.call(objectOrArray, key)) {
                    origPromises.push(objectOrArray[key]);
                }
            }
        }
        // create array with each item a promise chain.
        array.forEach(origPromises, function(item){
           promises.push(when(item).always(function(res){return res;}));
        });
    });
    
    return promises;  // array of dojo/promise/Promise
    
} // end some(objectOrArray) function

Listing 1

Example
Below in Listing 2, this function is used. Available on jsFiddler.

<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/dojo.js"  
    data-dojo-config="async:false"></script>
<script src="scripts/some.js"></script>

<script>
    require([ "dojo/Deferred", "dojo/promise/all",
	 "dojo/dom", "dojo/on","dojo/domReady!" ], 
        function(Deferred, all, dom, on) {
        "use strict";    
        
        function show(msg){
            dom.byId('output').innerHTML += msg + '<br/>';
        }
        
        /**
         * Use setTimeout to simulate an async process.
         * @param {string} name the name of this async invoke
         * @param {boolean} fail if true fail the promise
         * @returns {Promise} dojo/promies/Promise
         */
        function async(name, fail){
            var deferred = new Deferred();
            setTimeout(function(){
                if(fail){
                    deferred.reject(name + "Failed!");
                }else{
                    deferred.resolve(name);
                }
            },1000);
            
            return deferred.promise;
        }
        
        /**
         * On click of 'StartButton' button 
		 * wait for an array of promises. 
         */
        on(dom.byId("startButton"), "click", function() {
            var multiples = [async('V0'),
			 async('V1',true),async('V2')];
			 
            var p = all(some(multiples))
            .then(function(result){
                show(result);
                console.log(result);
            },
            function(err){
                // this should not be reached.
                show(err);
                console.log(err);
            });
        });
    });
</script>
</head>
<body>
    <button type="button" id="startButton">Start</button><p/>
    <div id="output" style="border: 1px black solid;width:20em;margin-bottom:20px;">Ready<br/></div>
</body>
</html>

Listing 2

Further reading

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

JavaScript focus event has wrong target?

I had an amusing debugging experience. Well, now it’s funny, then not so much. A focus event handler was getting events that said the same field was generating them. Even if other fields were selected.

I am using Dojo’s event API. This, like most other frameworks, make JavaScript event handling very simple, and most importantly handle the cross-browser issues.

The event tracer
I put a listener on a field’s ‘change‘ event using dojo/on, example:

on( theNode,'change',
      function(evt){
          mode = 'rent';			
      }
);

The callback handler just set a state variable. I also attached a listener to the ‘focusin’ event on a few other fields using the ‘on‘ method of Dojo’s NodeList:

query.NodeList().concat([moeNode,larryNode,curlyNode]).on('focusin',function(evt){
	evt.stopPropagation(); // needed?
	if(mode == 'rent'){
	    doSomeRentyThings(evt);
        }
});

This second handler used the value of the state variable. That is, I wanted to know that the user went from a particular field ‘A’ to another group of fields ‘B’. Hopefully someone can tell me the correct way to do something like this. Yes, a kludge, but it had to be done immediately, not on a single ‘submit’ button.

What should happen is that when the mouse leaves the first field (or user tabs away) and lands on one of the second fields, the status variable would have the correct value and be used by the second handler. It works!

Since the field setting is very fast, very few users could be faster. I know, async stuff; the browser could have a delay, etc. Don’t try this at home. Hmmm, but the browser is single threaded, so how could …. Anyway, in this app that would not be a disaster.

It stopped working
But, then I was developing something else on the same page using the Chrome debugger, and the above kludge stopped working. Huh? Even if I clicked on empty space in the browser, the event captured would be from the last field that the mouse was on. I re-read the Dojo docs, went back to the W3C stuff on Events, etc. Could find no web site where someone experienced a similar issue. I started blaming the Dojo toolkit, maybe there is a bug or the docs are incorrect.

I asked a co-worker, but they didn’t want to solve the problem just tell me that the app requirements were wrong, it’s too complex, blub, blub, blub. Most of the time feedback like this is important. One can get stuck in fruitless paths or need to see a different view of the goals. Perhaps, but in this case something obvious was wrong and I will probably face the same debug problem in the future.

Solution
Then I noticed that when I went from the Debugger back to the browser and clicked on another field, a very brief underline appeared in the previously selected field. Ah, how dumbskevisky, when I click on the browser anywhere, the previously selected field regains the focus and the focus event is generated. Obviously. The switch from debugger window to the browser window was the real change.

How did I confirm my observation? I closed the debugger window, and added console logging, like: console.log(“focus event on: ” + evt.currentTarget.name);

Take away

  1. Blame the tools last.
  2. Was working now not, what really changed?
  3. If it is hard to find a similar problem on web, your doing something wrong.
  4. When you ask co-workers for input be mindful of changing the context.
  5. Debuggers, while useful, can cause problems. The console is your friend.
  6. Take a break and work on something else.

What’s next?
There just has to be a better way of satisfying my web page requirements. No app at any point in time wanted to know what was previously changed?

Links

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Groovy implementation of INIX file format, part 2

Continued experimentation with the INIX “ini” file format. I take the original post code and add an alias feature.

Background
In three prior posts I presented a very simple metadata file storage approach. Pretty much using the INI file format with the sections as “heredocs.” In original INI format, afaik, the data within the sections were properties only, x=y.

Updates

  • Dec 25, 2015: Just saw a mention of Tom’s Obvious, Minimal Language (TOML) This is not directly related to what I’m after with Inix, but interesting as an example of a simple markup language.
  • Alias
    Now I am working on adding the ability for a section of data to load data from another section. The sections to load are indicated by the ‘@’ symbol and then the section path. Multiple sections can be indicated. Though I’m using the term ‘alias’ for this, perhaps a better term is ‘importing’. So far, I can parse the alias from the tag string.

    I have not implemented the actual import. One complexity left to solve is recursion. If this section imports another section, what if that section imports others sections?

    Alias use case
    Since currently the Inix file format is being used for test data, aliasing allows reuse of data without duplication, i.e., DRY. This is problematic with hierarchical data like JSON or XML, but much easier with lists or maps. Further features like overriding and interpolation would be useful for Java Properties data. The goal would be to eventually support use of the Cascading Configuration Pattern.

    Example 1

    [>First]
    Data in first    
    [<]
    
    [>Second@First]
    Data in second
    [<]
    

    Now when the data in section “Second” is loaded, the data from the aliased section is prepended to the current section data:

    Data in first    
    Data in second
    

    Tag format
    The section tag format is now: [>path#fragment@aliases?querystring]. Note that unlike a URI, the fragment does not appear at the end of the string.

    The section ID is really the path#fragment. Thus, the end tag could be [<] or can use the section ID: [<path#fragment]. Example 2

    [>demo1/deploy#two@account897@policy253?enabled=true&owner=false]
    stuff here
    [<demo1/deploy#two]
    

    Grammar
    The start of a grammar follows, but has not been ‘checked’ by attempted use of a parser generator like Antlr.

    grammar Inix;
    section: start CRLF data end;
    start: '[>' path (fragment)?(alias)*('?' args)? ']';
    end: '[<' path? ']';
    path: NAME ('/' NAME)*;
    fragment: '#' NAME;
    alias: '@' NAME
    args: (NAME=NAME ('&' NAME=NAME)*)?;
    data: (ANYTHING CRLF)*;
    NAME: ('a'..'z' | 'A'..'Z')('a' .. 'z' | 'A'..'Z'|'0'..'9'|'_');
    
    TODO:

    1. Do the actual import of aliased section data.
    2. Allow multiple params per param key: ?measure=21,measure=34,measure=90. Or better yet, just allow array in arg string: measure=[21,34,90],color=red

     

    Implementation
    Source code available at Github: https://gist.github.com/josefbetancourt/7701645

    Listing 2, Implementation

    Test class
    Note that there are not enough tests and the implementation code has not been reviewed.

    Listing 3, Test class

    The test data is:

    Listing 4, data file

    Environment
    Groovy Version: 2.2.2 JVM: 1.7.0_25 Vendor: Oracle Corporation OS: Windows 7

    Further Reading

    1. The Evolution of Config Files from INI to TOML
    2. Groovy Object Notation using ConfigSlurper
    3. Configuration Files Are Just Another Form of Message Passing (or Maybe Vice Versa)
    4. INI file
    5. Data File Metaformats
    6. Here document
    7. JSON configuration file format
    8. Creating External DSLs using ANTLR and Java
    9. Groovy Object Notation (GrON) for Data
      Interchange
    10. Cloanto Implementation of INI File Format
    11. http://groovy.codehaus.org/Tutorial+5+-+Capturing+regex+groups
    12. URI
    13. Designing a simple file format
    14. The Universal Design Pattern
    Creative Commons License
    This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

    Design smell: Must run the app to configure the app

    The prevailing method of configuring an application is to run the application and then select various configuration screens or preferences. This is fine, until it is not.

    Sometimes you cannot run the application, so can’t configure it. An example would be the Eclipse IDE. It is possible to break Eclipse by loading a misbehaving plug-in or other means. If Eclipse cannot start, one can’t remove the offending plug-in or make other required changes.

    This brings up the main problem with relying on in-app configuration. Without its use, one must be skilled in the underlying configuration storage used by the app. Further, this storage may be minimally documented, complex, or in multiple places. In worse cases, this storage is non-textual. For instance, referring to Eclipse example above, I have yet to find via a web search how to easily use the OSGi Equinox run-time (that Eclipse builds upon) to remove a recently installed feature or plug-in. I’m sure it is possible, and probably minor if you know Equinox. But, how many users of Eclipse IDE have even heard of Equinox or OSGi?

    Issues

    • The app may be compromised or broken.
    • Configuring via configuration files or other apps requires a different skill set.
    • Attempts to repair via non-app UI can make things worse.

    Solutions

    • Allow a subset of an application to be used for configuration use.
    • Allow the running of the app in “safe” modes. Example, Browser without plugins.
    • Create a separate configuration application.
    • Allow easier means to roll back to previous configuration.

    The best solution is to create a secure application that can use the target application’s configuration storage systems. If the in-app configuration support can be modularized, this is optimal.


    Drawing Hands” by M. C. Escher, accessed at WikiPaintings
    © This artwork may be protected by copyright. It is posted on the site in accordance with fair use principles

    Creative Commons License
    This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

    Enum to Switch on Class types in Java and Groovy

    The Java Switch statement is usually considered a code smell since it’s use can be eliminated by better use of Object Oriented Programming (OOP) design. Nowhere is this more apparent than with a related technique: attempting to switch on Class types by using the instanceof operator.

    Real world
    Unfortunately, in the real world, OOP is sometimes lacking. The code may be using a minimal interface based design. Refactoring, redesigns, or sophisticated OO legerdemain cannot be used in such a project. What’s worse, these projects typically have no unit tests.

    In this situation, one must resort to use of ‘switch’ or nested “if else”. This is a situation I recently encountered with legacy code that used if-else conditionals and instanceof since the target classes had no commonality. I was curious at the alternatives, so wrote up this blog post.

    Important! The examples here do not reproduce the actual usage of the instanceof, wherein inheritance is taken account. See this Stackoverflow article for some info.

    Groovy approach
    In Groovy this is much easier since the switch statement supports much more types to switch on. In listing 1 below we simply use the classes directly. Note that this is not documented anywhere, afaik.

    Groovy Example source
    Listing 1

    package com.octodecillion.experiment
    
    class GroovySwithOnClass {
    
        static main(args) {
            
            switch(Class2.class){
                case Class1.class:
                    assert false
                    break
                case Class2.class:
                    assert true
                    break
                case Class2.class:
                    assert false
                    break
                default:
                    assert false
            }    
        }
        
        public static class Class1{}
    
        public static class Class2{}
    
        public static class Class3{}
    
    }
    

    Now that is sweet and to the point!

    Just to see if possible, one could explicitly switch on a Closure’s hashCode as follows:

    class SwithOnClosure {
    
        static main(args) {
            Closure cl1 = {}
            Closure cl2 = {}
            Closure cl3 = {}
            
            switch(cl2.hashCode()){
                case cl1.hashCode():
                    assert false
                    break
                case cl2.hashCode():
                    println "on cl2"
                    assert true
                    break
                case cl3.hashCode():
                    assert false
                    break
                default:
                    assert false
            }
        }
        
    }
    

    For some more Groovy Enum goodness, the reading list at end gives some more examples.

    Java Approach
    In contrast to the Groovy used above, in Java things get more wordy. Below in listing 2 a JUnit class illustrates two methods of using a switch that acts on Class types.

    Java 7
    The method “testOnJava7” shows that in Java 7 the switch can be on String values, so we just use the fully qualified class name (FQCN) as the case labels. This is not optimal, of course, any change to package or class names would break the switch.

    Unfortunately, you can’t use the class name found by, for example, Class1.class.getName(), to use for the case labels. The case labels must be “constant expressions“. Even creating String “constants” with private final String CLASS1 = …. would not work, afaik.

    Tip: In Java 7 the switch works with:
    • char
    • byte
    • short
    • int
    • Character
    • Byte
    • Short
    • Integer
    • String
    • Enum type
     

    Java 6
    In Java 6, the ‘switch’ is more limited. In method “testOnJava6” we create an Enum ‘Switcher’ that stores the FQCNs of the classes to switch on. To allow the conversion of class name to enum we have to implement the ‘fromString(String className)’ method (learned this in “Effective Java”).

    Java Example source
    Listing 2

    package com.octodecillion.experiment;
    
    import static org.junit.Assert.fail;
    import java.util.HashMap;
    import java.util.Map;
    import org.junit.Test;
    
    /**
     * @author josef betancourt
     */
    public class SwitchOnClass {    
        @Test
        public final void testOnJava7(){        
            switch(Class1.class.getName()){        
                case "com.octodecillion.experiment
                    .SwitchOnClass$Class1":
                    break;                
                case "com.octodecillion.experiment
                    .SwitchOnClass$Class2":
                    fail();
                    break;
                case "com.octodecillion.experiment
                    .SwitchOnClass$Class3":    
                    fail();
                    break;
                default:
                    fail();                    
            }        
        }
    
        @Test
        public final void testOnJava6() {
            switch(Switcher.fromString(Class1.class.getName())){            
                case CLASS1:
                    break;
                case CLASS2:
                    fail();                
                    break;
                case CLASS3:
                    fail();
                    break;                
                default:
                    fail();            
            }        
        }
    
        /** enum type that stores the class names as field */
        public static enum Switcher{        
            CLASS1(Class1.class),
            CLASS2(Class2.class),
            CLASS3(Class3.class);    
            
            private static final Map<String,Switcher>classNameToEnum = 
                 new HashMap<String, Switcher>();
            
            static{
               for(Switcher sw : values()){
                    classNameToEnum.put(sw.className, sw);
                }            
            }
            
            /** convert class name to the enum type */
            public static Switcher fromString(String className){
                return classNameToEnum.get(className);
            }
            
            private String className;
            
            // constructor
            Switcher(Class<?> klass){
                this.className = klass.getName();
            }
            
        } // end enum Switcher
        
        public static class Class1{}
    
        public static class Class2{}
    
        public static class Class3{}    
    }
    

    Alternatives
    1. Don’t do any of the above. Use instanceof to invoke a method specific to the target class. In this way future maintenance and possible OO refactoring can be done. This is possible with the Enum use too, but may be using the Enum for the wrong reason.

    2. An alternative is to change the classes in question to partake in the enum use as shown by Gaʀʀʏ in a Stackoverflow article. This, imho, is not a good approach since it mixes concerns.

    3. Still another approach was suggested by a colleague: switch on the hash code of a class, this would remove the maintenance of an Enum just for use of an instanceof replacement.

    4. An interesting approach is to forgo the use of a switch altogether and just use the enum to invoke type specific behavior. A state machine? See “Avoid switch! Use enum!

    5. Use the Visitor Pattern. However, this assumes you have or can modify the existing classes.

    Updates
    Feb 13, 2014: Changed the format of the post.
    Feb 15, 2014: added example with closures.
    Nov 7, 2015: Interesting discussion on the Guava project, Issue 562, IfElse and Switch Functions. The OP suggested something that would a Predicate and allow multiway conditionals. The commentators said it was not “Java”, so won’t fix.

    Environment

    • Windows 7
    • Eclipse 4.3
    • Java 7
    • JUnit 4
    • Groovy 2.2

    Further reading

    Creative Commons License
    This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.