/*
* Copyright 2011 Future Systems
*
* 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 org.krakenapps.logdb.query.command;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.krakenapps.codec.CustomCodec;
import org.krakenapps.codec.EncodedStringCache;
import org.krakenapps.codec.EncodingRule;
import org.krakenapps.codec.TypeMismatchException;
import org.krakenapps.codec.UnsupportedTypeException;
import org.krakenapps.logdb.sort.SortCodec;
public class FunctionCodec implements CustomCodec {
public final static FunctionCodec instance = new FunctionCodec();
private static Map<Class<?>, Byte> typeCode;
static {
typeCode = new HashMap<Class<?>, Byte>();
typeCode.put(Function.Average.class, (byte) 128);
typeCode.put(Function.Count.class, (byte) 129);
// typeCode.put(Function.DistinctCount.class, (byte) 130);
typeCode.put(Function.First.class, (byte) 131);
typeCode.put(Function.Last.class, (byte) 132);
// typeCode.put(Function.ValueList.class, (byte) 133);
typeCode.put(Function.Max.class, (byte) 134);
typeCode.put(Function.Min.class, (byte) 135);
// typeCode.put(Function.Mode.class, (byte) 136);
typeCode.put(Function.Range.class, (byte) 137);
typeCode.put(Function.Sum.class, (byte) 138);
// typeCode.put(Function.SumSquare.class, (byte) 139);
// typeCode.put(Function.Values.class, (byte) 140);
typeCode.put(Timechart.PerSecond.class, (byte) 141);
typeCode.put(Timechart.PerMinute.class, (byte) 142);
typeCode.put(Timechart.PerHour.class, (byte) 143);
typeCode.put(Timechart.PerDay.class, (byte) 144);
}
@Override
public void encode(ByteBuffer bb, Object value) {
Byte code = typeCode.get(value.getClass());
if (code == null)
throw new UnsupportedTypeException(value.toString());
List<Object> datas = getDatas(code, (Function) value);
int contentLength = 0;
for (Object data : datas) {
if (data instanceof String)
contentLength += EncodedStringCache.getEncodedString((String) data).length();
else
contentLength += EncodingRule.lengthOf(data, SortCodec.instance);
}
bb.put(code.byteValue());
EncodingRule.encodeRawNumber(bb, int.class, contentLength);
for (Object data : datas) {
if (data instanceof String) {
EncodedStringCache c = EncodedStringCache.getEncodedString((String) data);
bb.put(EncodingRule.STRING_TYPE);
EncodingRule.encodeRawNumber(bb, int.class, c.value().length);
bb.put(c.value());
} else
EncodingRule.encode(bb, data);
}
}
@Override
public int lengthOf(Object value) {
Byte code = typeCode.get(value.getClass());
if (code == null)
throw new UnsupportedTypeException(value.toString());
List<Object> datas = getDatas(code, (Function) value);
int contentLength = 0;
for (Object data : datas) {
if (data instanceof String)
contentLength += EncodedStringCache.getEncodedString((String) data).length();
else
contentLength += EncodingRule.lengthOf(data);
}
return 1 + EncodingRule.lengthOfRawNumber(int.class, contentLength) + contentLength;
}
private List<Object> getDatas(byte code, Function value) {
List<Object> datas = new ArrayList<Object>();
datas.add(value.getName());
datas.add(value.getTarget());
datas.add(value.getKeyName());
if (code == (byte) 128) {
datas.add(((Function.Average) value).getD());
datas.add(((Function.Average) value).getCount());
} else if (code == (byte) 129) {
datas.add(((Function.Count) value).getResult());
} else if (code == (byte) 130) {
// datas.add(((Function.DistinctCount) value).getObjs());
} else if (code == (byte) 131) {
datas.add(((Function.First) value).getFirst());
} else if (code == (byte) 132) {
datas.add(((Function.Last) value).getLast());
} else if (code == (byte) 133) {
// datas.add(((Function.ValueList) value).getObjs());
} else if (code == (byte) 134) {
datas.add(((Function.Max) value).getMax());
} else if (code == (byte) 135) {
datas.add(((Function.Min) value).getMin());
} else if (code == (byte) 136) {
// datas.add(((Function.Mode) value).getResult());
// datas.add(((Function.Mode) value).getMaxCount());
// datas.add(((Function.Mode) value).getNowCount());
} else if (code == (byte) 137) {
datas.add(((Function.Range) value).getMax());
datas.add(((Function.Range) value).getMin());
} else if (code == (byte) 138) {
datas.add(((Function.Sum) value).getSum());
} else if (code == (byte) 139) {
// datas.add(((Function.SumSquare) value).getSum());
} else if (code == (byte) 140) {
// datas.add(((Function.Values) value).getObjs());
} else if (code == (byte) 141 || code == (byte) 142 || code == (byte) 143 || code == (byte) 144) {
datas.add(((Timechart.PerTime) value).getAmount());
}
return datas;
}
@Override
public Object decode(ByteBuffer bb) {
int beginPosition = bb.position();
byte code = bb.get();
int length = (int) EncodingRule.decodeRawNumber(bb);
int limit = bb.limit();
bb.limit(bb.position() + length);
String name = (String) EncodingRule.decode(bb);
String target = (String) EncodingRule.decode(bb);
String keyName = (String) EncodingRule.decode(bb);
Function func = Function.getFunction(name, target, keyName, Timechart.func);
if (typeCode.get(func.getClass()) != code)
throw new TypeMismatchException(typeCode.get(func.getClass()), code, beginPosition);
if (code == (byte) 128) {
((Function.Average) func).setD((Double) EncodingRule.decode(bb));
((Function.Average) func).setCount((Integer) EncodingRule.decode(bb));
} else if (code == (byte) 129) {
((Function.Count) func).setResult((Long) EncodingRule.decode(bb));
} else if (code == (byte) 130) {
// ((Function.DistinctCount) func).setObjs((List<Object>)
// EncodingRule.decode(bb));
} else if (code == (byte) 131) {
((Function.First) func).setFirst(EncodingRule.decode(bb));
} else if (code == (byte) 132) {
((Function.Last) func).setLast(EncodingRule.decode(bb));
} else if (code == (byte) 133) {
// ((Function.ValueList) func).setObjs((List<Object>)
// EncodingRule.decode(bb));
} else if (code == (byte) 134) {
((Function.Max) func).setMax(EncodingRule.decode(bb));
} else if (code == (byte) 135) {
((Function.Min) func).setMin(EncodingRule.decode(bb));
} else if (code == (byte) 136) {
// ((Function.Mode) func).setResult(EncodingRule.decode(bb));
// ((Function.Mode) func).setMaxCount((Integer)
// EncodingRule.decode(bb));
// ((Function.Mode) func).setNowCount((Integer)
// EncodingRule.decode(bb));
} else if (code == (byte) 137) {
((Function.Range) func).setMax((Number) EncodingRule.decode(bb));
((Function.Range) func).setMin((Number) EncodingRule.decode(bb));
} else if (code == (byte) 138) {
((Function.Sum) func).setSum((Number) EncodingRule.decode(bb));
} else if (code == (byte) 139) {
// ((Function.SumSquare) func).setSum((Number)
// EncodingRule.decode(bb));
} else if (code == (byte) 140) {
// ((Function.Values) func).setObjs((List<Object>)
// EncodingRule.decode(bb));
} else if (code == (byte) 141 || code == (byte) 142 || code == (byte) 143 || code == (byte) 144) {
((Timechart.PerTime) func).setAmount((Long) EncodingRule.decode(bb));
}
bb.limit(limit);
return func;
}
@Override
public int getObjectLength(ByteBuffer bb) {
throw new UnsupportedOperationException();
}
}