/**
* Copyright 2013-2014 Recruit Technologies Co., Ltd. and contributors
* (see CONTRIBUTORS.md)
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. A copy of the
* License is distributed with this work in the LICENSE.md file. You may
* also obtain a copy of the License from
*
* 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.gennai.gungnir.ql.analysis;
import java.io.IOException;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import org.gennai.gungnir.GungnirManager;
import org.gennai.gungnir.UserEntity;
import org.gennai.gungnir.metastore.MetaStore;
import org.gennai.gungnir.metastore.MetaStoreException;
import org.gennai.gungnir.ql.FunctionEntity;
import org.gennai.gungnir.ql.FunctionEntity.FunctionType;
import org.gennai.gungnir.ql.FunctionEntity.ScriptType;
import org.gennai.gungnir.topology.udf.ArgumentException;
import org.gennai.gungnir.topology.udf.Average;
import org.gennai.gungnir.topology.udf.BaseFunction.Description;
import org.gennai.gungnir.topology.udf.Cast;
import org.gennai.gungnir.topology.udf.CollectList;
import org.gennai.gungnir.topology.udf.CollectSet;
import org.gennai.gungnir.topology.udf.Concat;
import org.gennai.gungnir.topology.udf.Cosine;
import org.gennai.gungnir.topology.udf.Count;
import org.gennai.gungnir.topology.udf.DateFormat;
import org.gennai.gungnir.topology.udf.Distance;
import org.gennai.gungnir.topology.udf.Function;
import org.gennai.gungnir.topology.udf.Ifnull;
import org.gennai.gungnir.topology.udf.InvokeAggregateFunction;
import org.gennai.gungnir.topology.udf.InvokeFunction;
import org.gennai.gungnir.topology.udf.ParseUrl;
import org.gennai.gungnir.topology.udf.RegexpExtract;
import org.gennai.gungnir.topology.udf.ScriptAggregateFunction;
import org.gennai.gungnir.topology.udf.ScriptFunction;
import org.gennai.gungnir.topology.udf.Sine;
import org.gennai.gungnir.topology.udf.Size;
import org.gennai.gungnir.topology.udf.Slice;
import org.gennai.gungnir.topology.udf.Split;
import org.gennai.gungnir.topology.udf.Sqrt;
import org.gennai.gungnir.topology.udf.Sum;
import org.gennai.gungnir.topology.udf.Tangent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Maps;
public class FunctionRegistry {
private static final Logger LOG = LoggerFactory.getLogger(FunctionRegistry.class);
private FileRegistry fileRegistry;
private Map<String, Function<?>> bifsMap = Maps.newHashMap();
private Map<String, Function<?>> udfsMap = Maps.newHashMap();
private MetaStore metaStore;
public FunctionRegistry(FileRegistry fileRegistry) {
this.fileRegistry = fileRegistry;
register(Count.class);
register(Average.class);
register(Sum.class);
register(Concat.class);
register(Ifnull.class);
register(Split.class);
register(RegexpExtract.class);
register(ParseUrl.class);
register(Cast.class);
register(DateFormat.class);
register(Distance.class);
register(Sqrt.class);
register(Sine.class);
register(Cosine.class);
register(Tangent.class);
register(Size.class);
register(Slice.class);
register(CollectList.class);
register(CollectSet.class);
}
private void register(Class<? extends Function<?>> funcClass) {
Description desc = funcClass.getAnnotation(Description.class);
try {
bifsMap.put(desc.name(), funcClass.newInstance());
} catch (InstantiationException e) {
LOG.error("Failed to create instance '{}' function", desc.name(), e);
} catch (IllegalAccessException e) {
LOG.error("Failed to create instance '{}' function", desc.name(), e);
}
}
public void load(UserEntity owner) throws MetaStoreException {
udfsMap.clear();
try {
fileRegistry.exportFiles(owner);
} catch (IOException e) {
LOG.error("Failed to load function", e);
}
String classPath = fileRegistry.getCacheDir();
if (metaStore == null) {
metaStore = GungnirManager.getManager().getMetaStore();
}
List<FunctionEntity> functions = metaStore.findFunctions(owner);
for (FunctionEntity function : functions) {
if (function.getLocation().endsWith(".class")) {
if (function.getType() == FunctionType.UDF) {
InvokeFunction invokeFunction = new InvokeFunction(function, classPath);
udfsMap.put(function.getName(), invokeFunction);
} else if (function.getType() == FunctionType.UDAF) {
InvokeAggregateFunction invokeFunction = new InvokeAggregateFunction(function, classPath);
udfsMap.put(function.getName(), invokeFunction);
}
} else {
ScriptType scriptType = null;
EnumSet<ScriptType> scriptTypes = EnumSet.allOf(ScriptType.class);
for (ScriptType script : scriptTypes) {
if (function.getLocation().endsWith(script.getExtension())) {
scriptType = script;
break;
}
}
if (function.getType() == FunctionType.UDF) {
ScriptFunction scriptFunction = new ScriptFunction(function, scriptType, classPath);
udfsMap.put(function.getName(), scriptFunction);
} else if (function.getType() == FunctionType.UDAF) {
ScriptAggregateFunction scriptFunction = new ScriptAggregateFunction(function, scriptType,
classPath);
udfsMap.put(function.getName(), scriptFunction);
}
}
}
}
public Function<?> create(String name, Object... parameters) throws SemanticAnalyzeException,
SemanticAnalyzeException, ArgumentException {
Function<?> func = udfsMap.get(name);
if (func == null) {
func = bifsMap.get(name);
}
if (func != null) {
if (parameters != null) {
return func.clone().create(parameters);
} else {
return func.clone().create();
}
} else {
throw new SemanticAnalyzeException(name + " isn't registered");
}
}
}