/*
# Licensed Materials - Property of IBM
# Copyright IBM Corp. 2011, 2012
*/
package com.ibm.streamsx.inet.rest.servlets;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ibm.json.java.JSON;
import com.ibm.json.java.JSONArray;
import com.ibm.json.java.JSONObject;
import com.ibm.json.java.OrderedJSONObject;
import com.ibm.streams.operator.Attribute;
import com.ibm.streams.operator.StreamSchema;
import com.ibm.streams.operator.Tuple;
import com.ibm.streams.operator.Type;
import com.ibm.streams.operator.encoding.EncodingFactory;
import com.ibm.streams.operator.encoding.JSONEncoding;
import com.ibm.streams.operator.types.RString;
import com.ibm.streamsx.inet.window.WindowContentsAtTrigger;
public class AccessWindowContents extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = -5897438813664075070L;
private final WindowContentsAtTrigger<Tuple> windowContents;
private final StreamSchema schema;
// Is the schema tuple<rstring jsonString> which is JSON_SCHEMA
private final boolean isPureJson;
private final JSONEncoding<JSONObject,JSONArray> jsonEncoding = EncodingFactory.getJSONEncoding();
public AccessWindowContents(WindowContentsAtTrigger<Tuple> windowContents) {
this.windowContents = windowContents;
schema = windowContents.getInput().getStreamSchema();
isPureJson = JSON_SCHEMA.equals(schema);
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
action(request, response);
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
action(request, response);
}
private void action(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Object partition = getPartitionObject(request);
Iterable<Attribute> attributes = null;
// If the input type is pure JSON (rstring jsonString)
// then return the JSON object as-is, not as
// an attribute with key jsonString.
if (!isPureJson) {
String[] selectAttributesA = request
.getParameterValues("attribute");
if (selectAttributesA == null) {
attributes = schema;
} else {
List<Attribute> la = new ArrayList<Attribute>(
selectAttributesA.length);
for (String name : selectAttributesA) {
if (schema.getAttributeIndex(name) != -1)
la.add(schema.getAttribute(name));
}
attributes = la;
}
String[] suppressA = request.getParameterValues("suppress");
if (suppressA != null) {
Set<String> suppress = new HashSet<String>();
Collections.addAll(suppress, suppressA);
List<Attribute> la = new ArrayList<Attribute>(
schema.getAttributeCount());
for (Attribute attr : attributes) {
if (!suppress.contains(attr.getName()))
la.add(attr);
}
attributes = la;
}
}
final List<Tuple> tuples = windowContents.getWindowContents(partition);
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
// Need the list of headers
final List<String> headers = windowContents.getContext().getParameterValues("headers");
for (String header: headers)
{
String[] splitheader = header.split(":");
if (splitheader.length == 2)
response.setHeader(splitheader[0], splitheader[1]);
}
response.setHeader("Cache-Control",
"no-cache, no-store, must-revalidate");
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("application/json");
if (request.getParameter("callback") != null)
{
out.print(request.getParameter("callback"));
out.print("(");
}
if (isPureJson)
formatPureJSON(out, tuples);
else
formatJSON(out, tuples, attributes);
if (request.getParameter("callback") != null)
out.println(");");
out.flush();
out.close();
}
private Object getPartitionObject(HttpServletRequest request) throws ServletException {
final List<Attribute> pa = windowContents.getPartitionAttributes();
// Not partitioned.
if (pa.size() == 0)
return 0;
String[] partitionValues = request.getParameterValues("partition");
if (partitionValues == null)
return null; // partitioned but no partition given, return all the data.
if (pa.size() == 1)
return getAttributeObject(pa.get(0), partitionValues[0]);
List<Object> partitionList = new ArrayList<Object>(pa.size());
for (int i = 0; i < pa.size(); i++){
partitionList.add(getAttributeObject(pa.get(i), partitionValues[i]));
}
return partitionList;
}
private static Object getAttributeObject(Attribute attribute, String value) throws ServletException {
switch (attribute.getType().getMetaType()) {
case USTRING:
return value;
case BSTRING:
case RSTRING:
return new RString(value);
case BOOLEAN:
return new RString(value);
case INT8:
return Byte.valueOf(value);
case INT16:
return Short.valueOf(value);
case INT32:
return Integer.valueOf(value);
case INT64:
return Long.valueOf(value);
case UINT8:
return Short.valueOf(value).byteValue();
case UINT16:
return Integer.valueOf(value).shortValue();
case UINT32:
return Long.valueOf(value).intValue();
case UINT64:
return new BigInteger(value).longValue();
default:
throw new ServletException("Unsupported partition type for attribute: " + attribute.getName());
}
}
protected void formatJSON(PrintWriter out, List<Tuple> tuples, Iterable<Attribute> attributes) throws IOException {
JSONArray jsonTuples = new JSONArray(tuples.size());
for (Tuple tuple : tuples) {
JSONObject jsonTuple = tuple2JSON(jsonEncoding, attributes, tuple);
jsonTuples.add(jsonTuple);
}
out.println(jsonTuples.serialize());
}
protected void formatPureJSON(PrintWriter out, List<Tuple> tuples) throws IOException {
assert isPureJson;
JSONArray jsonTuples = new JSONArray(tuples.size());
for (Tuple tuple : tuples) {
jsonTuples.add(JSON.parse(tuple.getString(0)));
}
out.println(jsonTuples.serialize());
}
public static JSONObject tuple2JSON(JSONEncoding<JSONObject,JSONArray> encoding, Tuple tuple) throws IOException {
return tuple2JSON(encoding, tuple.getStreamSchema(), tuple);
}
// Standard SPL JSON schema
private static final StreamSchema JSON_SCHEMA = Type.Factory.getStreamSchema("tuple<rstring jsonString>");
// Standard SPL JSON attribute
private static final Attribute JSON_ATTR = JSON_SCHEMA.getAttribute(0);
/**
* Convert the set of attributes to JSON.
* If any attribute is rstring jsonString then assume
* it is serialized JSON and add it in as JSON (not a string value).
*/
public static JSONObject tuple2JSON(JSONEncoding<JSONObject,JSONArray> encoding, Iterable<Attribute> attributes, Tuple tuple)
throws IOException
{
JSONObject jsonTuple = new OrderedJSONObject();
for (Attribute attr : attributes) {
Object o;
if (JSON_ATTR.same(attr))
o = JSON.parse(tuple.getString(attr.getIndex()));
else
o = encoding.getAttributeObject(tuple, attr);
jsonTuple.put(attr.getName(), o);
}
return jsonTuple;
}
}