/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.addthis.hydra.data.query;
import java.io.IOException;
import java.util.List;
import com.addthis.basis.util.MemoryCounter;
import com.addthis.basis.util.LessStrings;
import com.addthis.bundle.core.Bundle;
import com.addthis.bundle.core.BundleField;
import com.addthis.bundle.core.BundleFormatted;
import com.addthis.bundle.table.DataTable;
import com.addthis.bundle.util.BundleColumnBinder;
import com.addthis.bundle.util.ValueUtil;
import com.addthis.bundle.value.ValueFactory;
import com.addthis.bundle.value.ValueLong;
import com.addthis.bundle.value.ValueString;
import io.netty.channel.ChannelProgressivePromise;
public abstract class AbstractQueryOp implements QueryOp {
public static final ValueLong ZERO = ValueFactory.create(0);
public static final ValueString EMPTY_STRING = ValueFactory.create("");
@MemoryCounter.Mem(estimate = false)
private QueryOp next;
@MemoryCounter.Mem(estimate = false)
private QueryMemTracker memTracker;
private BundleColumnBinder sourceBinder;
@MemoryCounter.Mem(estimate = false)
protected final ChannelProgressivePromise opPromise;
protected AbstractQueryOp(ChannelProgressivePromise opPromise) {
this.opPromise = opPromise;
}
public BundleColumnBinder getSourceColumnBinder(BundleFormatted row) {
return getSourceColumnBinder(row, null);
}
public BundleColumnBinder getSourceColumnBinder(BundleFormatted row, String[] fields) {
if (sourceBinder == null) {
sourceBinder = new BundleColumnBinder(row, fields);
}
return sourceBinder;
}
@Override public ChannelProgressivePromise getOpPromise() {
return opPromise;
}
@Override
public void close() throws IOException {
// sub-classes should implement for any clean-up they need
}
@Override
public void sendTable(DataTable table) {
for (Bundle row : table) {
if (opPromise.isDone()) {
break;
} else {
send(row);
}
}
sendComplete();
}
@Override
public void send(List<Bundle> bundles) {
if (bundles != null && !bundles.isEmpty()) {
for (Bundle bundle : bundles) {
send(bundle);
}
}
}
@Override
public QueryMemTracker getMemTracker() {
return memTracker;
}
@Override
public void setNext(QueryMemTracker memTracker, QueryOp next) {
this.memTracker = memTracker;
this.next = next;
}
@Override
public QueryOp getNext() {
return next;
}
@Override
public String getSimpleName() {
return getClass().getSimpleName().toString();
}
@Override
public String toString() {
QueryOp op = this;
StringBuffer sb = new StringBuffer();
while (op != null) {
if (op != this) {
sb.append(" > ");
}
sb.append(op.getSimpleName());
op = op.getNext();
}
return sb.toString();
}
public static int[] csvToInts(String args) {
String[] sv = LessStrings.splitArray(args, ",");
int[] ov = new int[sv.length];
for (int i = 0; i < ov.length; i++) {
ov[i] = Integer.parseInt(sv[i]);
}
return ov;
}
public static float[] csvToFloats(String args) {
String[] sv = LessStrings.splitArray(args, ",");
float[] ov = new float[sv.length];
for (int i = 0; i < ov.length; i++) {
ov[i] = Float.parseFloat(sv[i]);
}
return ov;
}
/**
* @param field array of BundleField
* @param row source row
* @return a compound key
*/
public static String createCompoundKey(BundleField[] field, Bundle row) {
String key = null;
for (BundleField kc : field) {
String kv = ValueUtil.asNativeString(row.getValue(kc));
if (kv == null) {
continue;
}
if (key == null) {
key = kv;
} else {
key = key.concat(kv);
}
}
return key;
}
}