/*
# Licensed Materials - Property of IBM
# Copyright IBM Corp. 2015
*/
package com.ibm.streamsx.topology.spl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Type;
import java.util.concurrent.TimeUnit;
import com.ibm.json.java.JSONObject;
import com.ibm.streams.operator.StreamSchema;
import com.ibm.streams.operator.Tuple;
import com.ibm.streams.operator.encoding.CharacterEncoding;
import com.ibm.streams.operator.encoding.EncodingFactory;
import com.ibm.streamsx.topology.TStream;
import com.ibm.streamsx.topology.TopologyElement;
import com.ibm.streamsx.topology.builder.BOperatorInvocation;
import com.ibm.streamsx.topology.builder.BOutput;
import com.ibm.streamsx.topology.consistent.ConsistentRegionConfig;
import com.ibm.streamsx.topology.function.Function;
import com.ibm.streamsx.topology.function.Predicate;
import com.ibm.streamsx.topology.function.Supplier;
import com.ibm.streamsx.topology.function.UnaryOperator;
import com.ibm.streamsx.topology.internal.core.StreamImpl;
import com.ibm.streamsx.topology.internal.spljava.Schemas;
import com.ibm.streamsx.topology.json.JSONSchemas;
import com.ibm.streamsx.topology.json.JSONStreams.DeserializeJSON;
class SPLStreamImpl extends StreamImpl<Tuple> implements SPLStream {
public SPLStreamImpl(TopologyElement te, BOutput stream) {
super(te, stream, Tuple.class);
}
@Override
public SPLStream getStream() {
return this;
}
@Override
public StreamSchema getSchema() {
return output().schema();
}
@Override
public TStream<JSONObject> toJSON() {
return transform(
JSONSchemas.JSON.equals(getSchema()) ?
new JsonString2JSON() : new Tuple2JSON());
}
public static class Tuple2JSON implements Function<Tuple, JSONObject> {
private static final long serialVersionUID = 1L;
@Override
public JSONObject apply(Tuple tuple) {
return EncodingFactory
.getJSONEncoding().encodeTuple(tuple);
}
}
/**
* Deserialize from tuple<rstring jsonString>
*
*/
public static class JsonString2JSON implements Function<Tuple, JSONObject> {
private static final long serialVersionUID = 1L;
private final DeserializeJSON deserializer = new DeserializeJSON();
@Override
public JSONObject apply(Tuple tuple) {
return deserializer.apply(tuple.getString(0));
}
}
@Override
public <T> TStream<T> convert(Function<Tuple, T> convertor) {
return transform(convertor);
}
@Override
public TStream<String> toTupleString() {
return transform(new TupleToString(getSchema()));
}
@Override
public TStream<String> toStringStream() {
if (!Schemas.STRING.equals(getSchema()))
throw new IllegalStateException(getSchema().getLanguageType());
return new StreamImpl<String>(this, output(), String.class);
}
@Override
public SPLStream filter(Predicate<Tuple> filter) {
return asSPL(super.filter(filter));
}
@Override
public SPLStream isolate() {
return asSPL(super.isolate());
}
@Override
public SPLStream modify(UnaryOperator<Tuple> modifier) {
return asSPL(super.modify(modifier));
}
@Override
public SPLStream sample(double fraction) {
return asSPL(super.sample(fraction));
}
@Override
public SPLStream throttle(long delay, TimeUnit unit) {
return asSPL(super.throttle(delay, unit));
}
@Override
public SPLStream lowLatency() {
return asSPL(super.lowLatency());
}
@Override
public SPLStream endLowLatency() {
return asSPL(super.endLowLatency());
}
@Override
public SPLStream autonomous() {
return asSPL(super.autonomous());
}
@Override
public SPLStream setConsistent(ConsistentRegionConfig config) {
super.setConsistent(config);
return this;
}
private SPLStream asSPL(TStream<Tuple> tupleStream) {
// must have been created from addMatchingOutput or addMatchingStream
return (SPLStream) tupleStream;
}
protected SPLStream addMatchingOutput(BOperatorInvocation bop, Type tupleType) {
return new SPLStreamImpl(this, bop.addOutput(getSchema()));
}
protected SPLStream addMatchingStream(BOutput output) {
return new SPLStreamImpl(this, output);
}
@Override
public SPLStream parallel(int width) {
return asSPL(super.parallel(width));
}
@Override
public SPLStream parallel(Supplier<Integer> width,
com.ibm.streamsx.topology.TStream.Routing routing) {
if(routing != TStream.Routing.ROUND_ROBIN){
throw new IllegalArgumentException("Partitioning is not currently "
+ "supported with SPLStream.");
}
return asSPL(super.parallel(width, routing));
}
@Override
public SPLStream parallel(Supplier<Integer> width,
Function<Tuple, ?> keyer) {
throw new IllegalArgumentException("Partitioning is not currently "
+ "supported with SPLStream.");
}
@Override
public SPLStream endParallel() {
return asSPL(super.endParallel());
}
public static class TupleToString implements Function<Tuple, String> {
private static final long serialVersionUID = 1L;
private final StreamSchema schema;
private transient CharacterEncoding encoding;
TupleToString(StreamSchema schema) {
this.schema = schema;
setEncoding();
}
private void setEncoding() {
encoding = schema.newCharacterEncoding();
}
private void readObject(ObjectInputStream in)
throws ClassNotFoundException, IOException {
in.defaultReadObject();
setEncoding();
}
@Override
public String apply(Tuple tuple) {
return encoding.encodeTuple(tuple);
}
}
}