Package backtype.storm.tuple

Source Code of backtype.storm.tuple.Tuple$Seq

package backtype.storm.tuple;

import backtype.storm.utils.IndifferentAccessMap;
import backtype.storm.generated.GlobalStreamId;
import backtype.storm.task.TopologyContext;
import clojure.lang.Seqable;
import clojure.lang.Indexed;
import clojure.lang.Counted;
import clojure.lang.ISeq;
import clojure.lang.ASeq;
import clojure.lang.IPersistentMap;
import clojure.lang.PersistentArrayMap;
import clojure.lang.Obj;
import clojure.lang.IMeta;
import clojure.lang.Keyword;
import clojure.lang.Symbol;
import clojure.lang.MapEntry;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* The tuple is the main data structure in Storm. A tuple is a named list of values,
* where each value can be any type. Tuples are dynamically typed -- the types of the fields
* do not need to be declared. Tuples have helper methods like getInteger and getString
* to get field values without having to cast the result.
*
* Storm needs to know how to serialize all the values in a tuple. By default, Storm
* knows how to serialize the primitive types, strings, and byte arrays. If you want to
* use another type, you'll need to implement and register a serializer for that type.
* See {@link http://github.com/nathanmarz/storm/wiki/Serialization} for more info.
*/
public class Tuple extends IndifferentAccessMap implements Seqable, Indexed, IMeta {
    private List<Object> values;
    private int taskId;
    private String streamId;
    private TopologyContext context;
    private MessageId id;
    private IPersistentMap _meta = null;

    //needs to get taskId explicitly b/c could be in a different task than where it was created
    public Tuple(TopologyContext context, List<Object> values, int taskId, String streamId, MessageId id) {
        super();
        this.values = values;
        this.taskId = taskId;
        this.streamId = streamId;
        this.id = id;
        this.context = context;
       
        String componentId = context.getComponentId(taskId);
        Fields schema = context.getComponentOutputFields(componentId, streamId);
        if(values.size()!=schema.size()) {
            throw new IllegalArgumentException(
                    "Tuple created with wrong number of fields. " +
                    "Expected " + schema.size() + " fields but got " +
                    values.size() + " fields");
        }
    }

    public Tuple(TopologyContext context, List<Object> values, int taskId, String streamId) {
        this(context, values, taskId, streamId, MessageId.makeUnanchored());
    }

    /**
     * Returns the number of fields in this tuple.
     */
    public int size() {
        return values.size();
    }
   
    public int fieldIndex(String field) {
        return getFields().fieldIndex(field);
    }
   
    /**
     * Gets the field at position i in the tuple. Returns object since tuples are dynamically typed.
     */
    public Object getValue(int i) {
        return values.get(i);
    }

    /**
     * Returns the String at position i in the tuple. If that field is not a String,
     * you will get a runtime error.
     */
    public String getString(int i) {
        return (String) values.get(i);
    }

    /**
     * Returns the Integer at position i in the tuple. If that field is not an Integer,
     * you will get a runtime error.
     */
    public Integer getInteger(int i) {
        return (Integer) values.get(i);
    }

    /**
     * Returns the Long at position i in the tuple. If that field is not a Long,
     * you will get a runtime error.
     */
    public Long getLong(int i) {
        return (Long) values.get(i);
    }

    /**
     * Returns the Boolean at position i in the tuple. If that field is not a Boolean,
     * you will get a runtime error.
     */
    public Boolean getBoolean(int i) {
        return (Boolean) values.get(i);
    }

    /**
     * Returns the Short at position i in the tuple. If that field is not a Short,
     * you will get a runtime error.
     */
    public Short getShort(int i) {
        return (Short) values.get(i);
    }

    /**
     * Returns the Byte at position i in the tuple. If that field is not a Byte,
     * you will get a runtime error.
     */
    public Byte getByte(int i) {
        return (Byte) values.get(i);
    }

    /**
     * Returns the Double at position i in the tuple. If that field is not a Double,
     * you will get a runtime error.
     */
    public Double getDouble(int i) {
        return (Double) values.get(i);
    }

    /**
     * Returns the Float at position i in the tuple. If that field is not a Float,
     * you will get a runtime error.
     */
    public Float getFloat(int i) {
        return (Float) values.get(i);
    }

    /**
     * Returns the byte array at position i in the tuple. If that field is not a byte array,
     * you will get a runtime error.
     */
    public byte[] getBinary(int i) {
        return (byte[]) values.get(i);
    }
   
   
    public Object getValueByField(String field) {
        return values.get(fieldIndex(field));
    }

    public String getStringByField(String field) {
        return (String) values.get(fieldIndex(field));
    }

    public Integer getIntegerByField(String field) {
        return (Integer) values.get(fieldIndex(field));
    }

    public Long getLongByField(String field) {
        return (Long) values.get(fieldIndex(field));
    }

    public Boolean getBooleanByField(String field) {
        return (Boolean) values.get(fieldIndex(field));
    }

    public Short getShortByField(String field) {
        return (Short) values.get(fieldIndex(field));
    }

    public Byte getByteByField(String field) {
        return (Byte) values.get(fieldIndex(field));
    }

    public Double getDoubleByField(String field) {
        return (Double) values.get(fieldIndex(field));
    }

    public Float getFloatByField(String field) {
        return (Float) values.get(fieldIndex(field));
    }

    public byte[] getBinaryByField(String field) {
        return (byte[]) values.get(fieldIndex(field));
    }
   
    @Deprecated
    public List<Object> getTuple() {
        return values;
    }

    /**
     * Gets all the values in this tuple.
     */
    public List<Object> getValues() {
        return values;
    }
   
    /**
     * Gets the names of the fields in this tuple.
     */
    public Fields getFields() {
        return context.getComponentOutputFields(getSourceComponent(), getSourceStreamId());
    }

    /**
     * Returns a subset of the tuple based on the fields selector.
     */
    public List<Object> select(Fields selector) {
        return getFields().select(selector, values);
    }
   
   
    /**
     * Returns the global stream id (component + stream) of this tuple.
     */
    public GlobalStreamId getSourceGlobalStreamid() {
        return new GlobalStreamId(getSourceComponent(), streamId);
    }
   
    /**
     * Gets the id of the component that created this tuple.
     */
    public String getSourceComponent() {
        return context.getComponentId(taskId);
    }
   
    /**
     * Gets the id of the task that created this tuple.
     */
    public int getSourceTask() {
        return taskId;
    }
   
    /**
     * Gets the id of the stream that this tuple was emitted to.
     */
    public String getSourceStreamId() {
        return streamId;
    }
   
    public MessageId getMessageId() {
        return id;
    }
   
    @Override
    public String toString() {
        return "source: " + getSourceComponent() + ":" + taskId + ", stream: " + streamId + ", id: "+ id.toString() + ", " + values.toString();
    }
   
    @Override
    public boolean equals(Object other) {
        // for OutputCollector
        return this == other;
    }
   
    @Override
    public int hashCode() {
        // for OutputCollector
        return System.identityHashCode(this);
    }

    private final Keyword makeKeyword(String name) {
        return Keyword.intern(Symbol.create(name));
    }   

    /* ILookup */
    @Override
    public Object valAt(Object o) {
        try {
            if(o instanceof Keyword) {
                return getValueByField(((Keyword) o).getName());
            } else if(o instanceof String) {
                return getValueByField((String) o);
            }
        } catch(IllegalArgumentException e) {
        }
        return null;
    }

    /* Seqable */
    public ISeq seq() {
        if(values.size() > 0) {
            return new Seq(getFields().toList(), values, 0);
        }
        return null;
    }

    static class Seq extends ASeq implements Counted {
        final List<String> fields;
        final List<Object> values;
        final int i;

        Seq(List<String> fields, List<Object> values, int i) {
            this.fields = fields;
            this.values = values;
            this.i = i;
        }

        public Seq(IPersistentMap meta, List<String> fields, List<Object> values, int i) {
            super(meta);
            this.fields= fields;
            this.values = values;
            this.i = i;
        }

        public Object first() {
            return new MapEntry(fields.get(i), values.get(i));
        }

        public ISeq next() {
            if(i+1 < fields.size()) {
                return new Seq(fields, values, i+1);
            }
            return null;
        }

        public int count() {
            return fields.size();
        }

        public Obj withMeta(IPersistentMap meta) {
            return new Seq(meta, fields, values, i);
        }
    }

    /* Indexed */
    public Object nth(int i) {
        if(i < values.size()) {
            return values.get(i);
        } else {
            return null;
        }
    }

    public Object nth(int i, Object notfound) {
        Object ret = nth(i);
        if(ret==null) ret = notfound;
        return ret;
    }

    /* Counted */
    public int count() {
        return values.size();
    }
   
    /* IMeta */
    public IPersistentMap meta() {
        if(_meta==null) {
            _meta = new PersistentArrayMap( new Object[] {
            makeKeyword("stream"), getSourceStreamId(),
            makeKeyword("component"), getSourceComponent(),
            makeKeyword("task"), getSourceTask()});
        }
        return _meta;
    }

    private PersistentArrayMap toMap() {
        Object array[] = new Object[values.size()*2];
        List<String> fields = getFields().toList();
        for(int i=0; i < values.size(); i++) {
            array[i*2] = fields.get(i);
            array[(i*2)+1] = values.get(i);
        }
        return new PersistentArrayMap(array);
    }

    public IPersistentMap getMap() {
        if(_map==null) {
            setMap(toMap());
        }
        return _map;
    }
}
TOP

Related Classes of backtype.storm.tuple.Tuple$Seq

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.