/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.tajo.catalog;
import com.google.common.base.Objects;
import com.google.gson.annotations.Expose;
import org.apache.tajo.json.GsonObject;
import org.apache.tajo.catalog.function.Function;
import org.apache.tajo.catalog.json.CatalogGsonHelper;
import org.apache.tajo.catalog.proto.CatalogProtos.FunctionDescProto;
import org.apache.tajo.catalog.proto.CatalogProtos.FunctionType;
import org.apache.tajo.common.ProtoObject;
import org.apache.tajo.common.TajoDataTypes.DataType;
import org.apache.tajo.exception.InternalException;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.List;
public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable, GsonObject {
private FunctionDescProto.Builder builder = FunctionDescProto.newBuilder();
@Expose private String signature;
@Expose private Class<? extends Function> funcClass;
@Expose private FunctionType funcType;
@Expose private DataType returnType;
@Expose private DataType [] params;
@Expose private String description;
@Expose private String detail;
@Expose private String example;
public FunctionDesc() {
}
public FunctionDesc(String signature, Class<? extends Function> clazz,
FunctionType funcType, DataType retType,
DataType [] params) {
this.signature = signature.toLowerCase();
this.funcClass = clazz;
this.funcType = funcType;
this.returnType = retType;
this.params = params;
}
public FunctionDesc(FunctionDescProto proto) throws ClassNotFoundException {
this(proto.getSignature(), proto.getClassName(), proto.getType(),
proto.getReturnType(),
proto.getParameterTypesList().toArray(new DataType[proto.getParameterTypesCount()]));
if (proto.hasDescription()) {
this.description = proto.getDescription();
}
if (proto.hasDetail()) {
this.detail = proto.getDetail();
}
if (proto.hasExample()) {
this.example = proto.getExample();
}
}
public FunctionDesc(String signature, String className, FunctionType type,
DataType retType,
DataType... argTypes) throws ClassNotFoundException {
this(signature, (Class<? extends Function>) Class.forName(className), type, retType, argTypes);
}
/**
*
* @return Function Instance
* @throws org.apache.tajo.exception.InternalException
*/
public Function newInstance() throws InternalException {
try {
Constructor<? extends Function> cons = getFuncClass().getConstructor();
return cons.newInstance();
} catch (Exception ioe) {
throw new InternalException("Cannot initiate function " + signature);
}
}
public String getSignature() {
return this.signature;
}
@SuppressWarnings("unchecked")
public Class<? extends Function> getFuncClass() throws InternalException {
return this.funcClass;
}
public FunctionType getFuncType() {
return this.funcType;
}
public DataType [] getParamTypes() {
return this.params;
}
public DataType getReturnType() {
return this.returnType;
}
public String getDescription() {
return description;
}
public String getDetail() {
return detail;
}
public String getExample() {
return example;
}
public void setDescription(String description) {
this.description = description;
}
public void setDetail(String detail) {
this.detail = detail;
}
public void setExample(String example) {
this.example = example;
}
@Override
public int hashCode() {
return Objects.hashCode(signature, Objects.hashCode(params));
}
@Override
public boolean equals(Object obj) {
if (obj instanceof FunctionDesc) {
FunctionDesc other = (FunctionDesc) obj;
if(this.getProto().equals(other.getProto()))
return true;
}
return false;
}
@Override
public Object clone() throws CloneNotSupportedException{
FunctionDesc desc = (FunctionDesc)super.clone();
desc.signature = this.signature;
desc.params = params.clone();
desc.description = this.description;
desc.example = this.example;
desc.detail = this.detail;
desc.returnType = this.returnType;
desc.funcClass = this.funcClass;
return desc;
}
@Override
public FunctionDescProto getProto() {
if (builder == null) {
builder = FunctionDescProto.newBuilder();
} else {
builder.clear();
}
builder.setSignature(this.signature);
builder.setClassName(this.funcClass.getName());
builder.setType(this.funcType);
builder.setReturnType(this.returnType);
if(this.description != null) {
builder.setDescription(this.description);
}
if (this.detail != null) {
builder.setDetail(this.detail);
}
if (this.example != null) {
builder.setExample(this.example);
}
if (this.params != null) { // repeated field
builder.addAllParameterTypes(Arrays.asList(params));
}
return builder.build();
}
@Override
public String toString() {
return getProto().toString();
}
public String toJson() {
return CatalogGsonHelper.toJson(this, FunctionDesc.class);
}
public String getHelpSignature() {
return returnType.getType() + " " + CatalogUtil.getCanonicalName(signature, getParamTypes());
}
public static String dataTypesToStr(List<DataType> parameterTypesList) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < parameterTypesList.size(); i++) {
DataType eachType = parameterTypesList.get(i);
if (i > 0) {
result.append(",");
}
result.append(eachType.getType().toString());
}
return result.toString();
}
}