package org.cad.interruptus.rest;
import com.espertech.esper.client.dataflow.EPDataFlowState;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
import com.wordnik.swagger.annotations.ApiResponse;
import com.wordnik.swagger.annotations.ApiResponses;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cad.interruptus.core.EntityNotFoundException;
import org.cad.interruptus.core.esper.FlowConfiguration;
import org.cad.interruptus.entity.Flow;
import org.cad.interruptus.repository.FlowRepository;
import org.cad.interruptus.repository.zookeeper.listener.ConfigurationEventDispatcher;
@Singleton
@Path("/flow")
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
@Api(value = "/flow", description = "Flow operations")
public class FlowResource
{
@Inject
FlowRepository repository;
@Inject
FlowConfiguration configuration;
@Inject
ConfigurationEventDispatcher dispatcher;
Log logger = LogFactory.getLog(getClass());
@GET
@ApiOperation(
value = "List all flows",
notes = "List all flows, whether is runnig or not",
response = Flow.class,
responseContainer = "List"
)
public List<Flow> listFlows()
{
try {
return repository.findAll();
} catch (Exception ex) {
logger.error(this, ex);
throw new ResourceException(Response.Status.SERVICE_UNAVAILABLE, ex.getMessage());
}
}
@POST
@ApiOperation(
value = "Save a flow configuration",
notes = "Save a flow configuration, if the flow already exists will be overwritten",
response = Boolean.class
)
public Boolean saveFlow(Flow entity)
{
try {
configuration.save(entity);
repository.save(entity);
dispatcher.dispatchSave(entity);
return Boolean.TRUE;
} catch (Exception ex) {
logger.error(this, ex);
throw new ResourceException(Response.Status.SERVICE_UNAVAILABLE, ex.getMessage());
}
}
@GET
@Path("/{name}")
@ApiOperation(
value = "Retreives a flow configuration",
notes = "Retreives a flow configuration, throws exception if does not exists",
response = Flow.class
)
@ApiResponses({
@ApiResponse(code = 404, message = "Flow doesn't exists")
})
public Flow showFlow(@ApiParam(value = "Flow name to lookup for", required = true) @PathParam("name") String name)
{
try {
return repository.findById(name);
} catch (EntityNotFoundException ex) {
throw new ResourceException(ex);
} catch (Exception ex) {
logger.error(this, ex);
throw new ResourceException(Response.Status.SERVICE_UNAVAILABLE, ex.getMessage());
}
}
@DELETE
@Path("/{name}")
@ApiOperation(
value = "Removes a flow configuration",
notes = "Removes a flow configuration, throws exception if does not exists",
response = Flow.class
)
@ApiResponses({
@ApiResponse(code = 404, message = "Flow doesn't exists")
})
public Boolean removeFlow(@ApiParam(value = "Flow name to lookup for", required = true) @PathParam("name") String name)
{
try {
final Flow entity = repository.findById(name);
configuration.stop(name);
repository.remove(name);
dispatcher.dispatchDelete(entity);
return true;
} catch (EntityNotFoundException ex) {
throw new ResourceException(ex);
} catch (Exception ex) {
logger.error(this, ex);
throw new ResourceException(Response.Status.SERVICE_UNAVAILABLE, ex.getMessage());
}
}
@POST
@Path("/{name}/start")
@ApiOperation(
value = "Start a flow in esper",
notes = "Stop a existing in esper, throws exception if does not exists",
response = Flow.class
)
@ApiResponses({
@ApiResponse(code = 404, message = "Flow doesn't exists")
})
public Boolean startFlow(@ApiParam(value = "Flow name to lookup for", required = true) @PathParam("name") String name) throws Exception
{
final Flow entity = repository.findById(name);
entity.setStarted(true);
dispatcher.dispatchSave(entity);
repository.save(entity);
return true;
}
@POST
@Path("/{name}/stop")
@ApiOperation(
value = "Stop a flow in esper",
notes = "Stop a existing flow in esper, throws exception if does not exists",
response = Flow.class
)
@ApiResponses({
@ApiResponse(code = 404, message = "Flow doesn't exists")
})
public Boolean stopFlow(@ApiParam(value = "Flow name to lookup for", required = true) @PathParam("name") String name) throws Exception
{
final Flow entity = repository.findById(name);
if ( ! configuration.stop(name)) {
return false;
}
entity.setStarted(false);
repository.save(entity);
dispatcher.dispatchSave(entity);
return true;
}
@GET
@Path("/{name}/state")
@ApiOperation(
value = "Retrives the state for a flow",
notes = "Retrives the state for a flow, throws exception if does not exists",
response = Flow.class
)
@ApiResponses({
@ApiResponse(code = 404, message = "Flow doesn't exists")
})
public Map<String, String> state(@ApiParam(value = "Flow name to lookup for", required = true) @PathParam("name") String name) throws Exception
{
final Map<String, String> map = new HashMap<>();
final EPDataFlowState state = configuration.getFlowState(name);
map.put("name", name);
map.put("status", "STOPPED");
if (repository.findById(name) == null) {
throw new EntityNotFoundException(Flow.class, name);
}
if (state != null) {
map.put("status", state.toString());
}
return map;
}
}