net.intelie.pipes.PipePropertySource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pipes-api Show documentation
Show all versions of pipes-api Show documentation
Intelie Pipes' API classes and interfaces
package net.intelie.pipes;
import net.intelie.pipes.filters.ObjectSink;
import net.intelie.pipes.types.*;
import net.intelie.pipes.util.GetUtils;
import net.intelie.pipes.util.Iterables;
import net.intelie.pipes.util.Levenshtein;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
public class PipePropertySource implements PropertySource {
private static final long serialVersionUID = 1L;
private final RowFields fields;
private final int offset;
private final Metadata metadata;
public PipePropertySource(Metadata metadata) {
this.metadata = metadata;
this.fields = metadata.getRowFields();
this.offset = fields.timestamp().size() + fields.group().size();
}
@Override
public Property timestamp() throws PipeException {
if (fields.indexOf(Row.TIMESTAMP) < 0)
return new PipeProperty(Type.NUMBER, Row.TIMESTAMP, -1);
return property(Type.NUMBER, Row.TIMESTAMP);
}
@Override
public Property property() throws PipeException {
return new PipeProperty(defineTypeFor(offset), fields.name(offset), offset);
}
@Override
public Property property(String name) throws PipeException {
return property(null, name);
}
Property property(Type declared, String name) throws PipeException {
int index = fields.indexOf(name);
if (index < 0)
throw Levenshtein.makeExc(name, fields.names(), "Cannot resolve property '%s'.%s");
return new PipeProperty(declared == null ? defineTypeFor(index) : declared, name, index);
}
@Override
public List defaultProperties() {
return Collections.emptyList();
}
@Override
public Metadata metadata() {
return metadata;
}
@Override
public PropertyReplacer makeReplacer(ClauseInfo fields) {
return new PipePropertyReplacer(this.fields, fields);
}
@Override
public PropertySource newSource(Metadata metadata) {
throw new UnsupportedOperationException("Can't use newSource on a PipePropertySource");
}
private Type defineTypeFor(int index) throws PipeException {
return fields.type(index);
}
public static class PipeProperty implements Property {
private final Type originalType;
private final Type type;
private final String identifier;
private final int index;
private final Scalar[] args;
public PipeProperty(Type type, String identifier, int index, Scalar... args) throws PipeException {
this(type, type, identifier, index, args);
}
public PipeProperty(Type originalType, Type type, String identifier, int index, Scalar... args) throws PipeException {
this.originalType = originalType;
this.type = type != null ? type : Type.OBJECT;
this.identifier = identifier;
this.index = index;
this.args = args;
}
@Override
public Object eval(Scope parent, Object obj) {
if (index == -1) return null;
Row row = castRow(obj);
if (row == null) return null;
Object value = row.get(index);
for (Scalar arg : args) {
value = GetUtils.get(value, arg.eval(parent, obj));
}
return type.cast(value);
}
@Override
public boolean sameProperty(Property other) {
if (!(other instanceof PipeProperty))
return false;
PipeProperty that = (PipeProperty) other;
return Objects.equals(this.identifier, that.identifier) &&
Objects.equals(this.index, that.index) &&
Objects.equals(this.type, that.type) &&
sameScalars(this.args, that.args);
}
@Override
public boolean requiresObjectFix() {
return false;
}
private boolean sameScalars(Scalar[] thisNth, Scalar[] thatNth) {
if (thisNth.length != thatNth.length)
return false;
for (int i = 0; i < thisNth.length; i++) {
if (!Level.CONSTANT.accepts(thatNth[i]) ||
!Level.CONSTANT.accepts(thisNth[i]) ||
!Objects.equals(Level.asScalar(thisNth[i]).eval(null, null), Level.asScalar(thatNth[i]).eval(null, null)))
return false;
}
return true;
}
private Row castRow(Object obj) {
if (!(obj instanceof Row)) return null;
Row row = (Row) obj;
if (index >= row.size()) return null;
return row;
}
@Override
public Type type() {
return type;
}
@Override
public String name() {
return identifier;
}
@Override
public Iterable args() {
return Arrays.asList(args);
}
@Override
public Property indexed(Scalar... args) throws PipeException {
return new PipeProperty(originalType, GetUtils.inferType(originalType, args), identifier, index, args);
}
@Override
public Property hint(Type type) throws PipeException {
return new PipeProperty(type, identifier, index, args);
}
@Override
public void evalRaw(Scope parent, Object obj, ObjectSink sink) {
if (index == -1) return;
Row row = castRow(obj);
if (row == null) return;
Object o = row.get(index);
for (Scalar scalar : args)
o = GetUtils.get(o, scalar.eval(parent, obj));
sink.onSingle(o);
}
@Override
public PropertyVisitor visit(Scope parent, PropertyVisitor visitor) {
for (Scalar scalar : args)
scalar.visit(parent, visitor);
return visitor.property(this);
}
@Override
public String toString() {
return "pipe:" + identifier + "[" + Iterables.join(", ", Arrays.asList(args)) + "]@" + type;
}
}
public static class PipePropertyReplacer implements PropertyReplacer {
private static final long serialVersionUID = 1L;
private final RowType type;
public PipePropertyReplacer(RowFields originalFields, ClauseInfo newFields) {
this.type = new RowType(new RowFields(
originalFields.timestamp(),
originalFields.group(),
new ClauseInfo(Stream.concat(
originalFields.select().stream(),
newFields.stream()).toArray(FieldInfo[]::new))
));
}
@Override
public Type type() {
return type;
}
@Override
public Object replaceValues(Object obj, Row row) {
if (!(obj instanceof Row)) return obj;
return ArrayRow.concat((Row) obj, row);
}
}
}