package de.axone.web.rest; import java.io.PrintWriter; import java.util.Map; import javax.servlet.http.HttpServletResponse; import de.axone.web.Method; import de.axone.web.SuperURL; public abstract class AbstractCrudFunction<ID, DATA, REQUEST extends RestRequest> extends AbstractRestFunction<DATA,REQUEST> implements CrudFunction<ID, DATA,REQUEST> { private static final String A_CONFIG = "__CONFIG__"; private static final String A_NEW = "new"; private static final String A_HELP = "help"; protected static final String P_ID = "id"; public enum Actions{ CREATE, READ, UPDATE, DELETE, LIST, OTHER, CONFIG, HELP }; private final RestFunctionDescription description; //private final String name; public AbstractCrudFunction( String name, boolean hasConfig ) { //this.name = name; super( name ); this.description = makeDescription( name, hasConfig ); } /* @Override public String name(){ return name; } */ @Override public RestFunctionDescription description() { return description; } private static RestFunctionDescription makeDescription( String name, boolean hasConfig ) { RestFunctionDescription description = new RestFunctionDescription( name, "crud functions" ); description.addMethod( "GET /" + name , "Return a list of " + name ) .addParameter( "start", "start index" ) .addParameter( "count", "amount of objects to return" ) .addParameter( "sort", "name of sorter/field to sort by" ) .addParameter( "filter", "filter value" ) .setReturnValue( "list", "list of " + name ) ; description.addMethod( "GET /" + name + "/:id", "return one " + name + " identified by id" ) .setReturnValue( "object", "the found instance of " + name ); description.addMethod( "GET /" + name + "/new", "return one new " + name + " object" ) .setReturnValue( "object", "a new instance of " + name + " initialized by default values" ); if( hasConfig ){ description.addMethod( "GET /" + name + "/__CONFIG__", "return the configuration and default values" ) .setReturnValue( "object", "a map of key/value config values" ); } description.addMethod( "POST /" + name + "/:id", "save one " + name + " identified by id" ) .setReturnValue( "object", "the saved instance of " + name + " or the posted object if fatal errors occur" ); description.addMethod( "DELETE /" + name + "/:id", "delete one " + name + " identified by id" ) .setReturnValue( "object", "the deleted instance of " + name ); return description; } @Override public void registerMe( RestFunctionRegistry<DATA, REQUEST> registry ) { registry.register( new RestFunctionRoute.Simple( "/" + name() + "/:id.*" ), this ); registry.register( new RestFunctionRoute.Simple( "/" + name() + ".*" ), this ); } @Override public void doRun( DATA data, Method method, Map<String, String> parameters, SuperURL url, PrintWriter out, REQUEST req, HttpServletResponse resp ) throws Exception { String idStr = parameters.get( P_ID ); Actions action = ACTION( data, method, idStr, parameters, url, out, req, resp ); doAction( data, method, action, idStr, parameters, url, out, req, resp ); /* if( object != null ){ ResultWriter.writeValue( req.mapper(), out, object ); } else if( list != null ){ ResultWriter.writeValue( req.mapper(), out, list ); } else { throw new IllegalStateException( "No result" ); } */ } protected Actions ACTION( DATA data, Method method, String idStr, Map<String, String> parameters, SuperURL url, PrintWriter out, REQUEST req, HttpServletResponse resp ) throws Exception { Actions action = Actions.OTHER; switch( method ){ case GET: if( A_NEW.equals( url.getPath().getLast() ) ){ action = Actions.CREATE; } else if( A_HELP.equals( url.getPath().getLast() ) ){ action = Actions.HELP; } else if( A_CONFIG.equals( url.getPath().getLast() ) ){ action = Actions.CONFIG; } else if( url.getPath().length() == 1 && idStr != null ){ action = Actions.READ; } else if( url.getPath().length() == 0 ) { action = Actions.LIST; } break; case POST: case PUT: action = Actions.UPDATE; break; case DELETE: action = Actions.DELETE; break; default: throw new IllegalArgumentException( "Unsupported Method: " + method ); } return action; } protected void doAction( DATA data, Method method, Actions action, String idStr, Map<String, String> parameters, SuperURL url, PrintWriter out, REQUEST req, HttpServletResponse resp ) throws Exception { ID id; switch( action ){ case CREATE: doCreate( data, method, parameters, out, req, resp ); break; case READ: id = parseId( data, method, idStr, parameters, req ); doRead( data, method, id, parameters, out, req, resp ); break; case UPDATE: id = parseId( data, method, idStr, parameters, req ); doUpdate( data, method, id, parameters, out, req, resp ); break; case DELETE: id = parseId( data, method, idStr, parameters, req ); doDelete( data, method, id, parameters, out, req, resp ); break; case LIST: doList( data, method, parameters, out, req, resp ); break; case CONFIG: doConfig( data, method, parameters, out, req, resp ); break; case OTHER: doOther( data, method, parameters, url, out, req, resp ); break; case HELP: doHelp( data, method, parameters, url, out, req, resp ); break; default: throw new IllegalArgumentException( "Unknown action: " + action ); } } @Override public void doConfig( DATA data, Method method, Map<String, String> parameters, PrintWriter out, REQUEST req, HttpServletResponse resp ) throws Exception { throw new UnsupportedOperationException(); } @Override public void doOther( DATA data, Method method, Map<String, String> parameters, SuperURL url, PrintWriter out, REQUEST req, HttpServletResponse resp ) throws Exception { throw new UnsupportedOperationException(); } @Override public void doHelp( DATA data, Method method, Map<String, String> parameters, SuperURL url, PrintWriter out, REQUEST req, HttpServletResponse resp ) throws Exception { resp.setContentType( "text/html" ); out.println( description().toHtml( true ) ); } protected interface M<DATA,REQUEST> { public void run( DATA data, Method method, Map<String, String> parameters, SuperURL url, PrintWriter out, REQUEST req, HttpServletResponse resp ) throws Exception; } /* protected static class RestFunctionToMethod<ID, DATA, REQUEST> implements RestFunction<DATA,REQUEST> { final java.lang.reflect.Method call; final Object self; @Override public void run( DATA data, Method method, Map<String, String> parameters, SuperURL url, PrintWriter out, REQUEST req, HttpServletResponse resp ) throws Exception { call.invoke( self, data, method, parameters, url, out, req, resp ); } @Override public String name() { return null; } @Override public RestFunctionDescription description() { return null; } } */ }