text:
using namespace impala;
using namespace impala_udf;
using namespace std;
using namespace strings;

ScalarFnCall::ScalarFnCall(const TExprNode& node)
  : Expr(node),
    vararg_start_idx_(node.__isset.vararg_start_idx ?
        node.vararg_start_idx : -1),
    scalar_fn_wrapper_(NULL),
    prepare_fn_(NULL),
    close_fn_(NULL),
    scalar_fn_(NULL) {
  DCHECK_NE(fn_.binary_type, TFunctionBinaryType::HIVE);
}

Status ScalarFnCall::Prepare(RuntimeState* state, const RowDescriptor& desc,
                             ExprContext* context) {
  RETURN_IF_ERROR(Expr::Prepare(state, desc, context));

  if (fn_.scalar_fn.symbol.empty()) {
    // This path is intended to only be used during development to test FE
    // code before the BE has implemented the function.
    // Having the failure in the BE (rather than during analysis) allows for
    // better FE testing.
    DCHECK_EQ(fn_.binary_type, TFunctionBinaryType::BUILTIN);
    stringstream ss;
    ss << "Function " << fn_.name.function_name << " is not implemented.";
    return Status(ss.str());
  }

  FunctionContext::TypeDesc return_type = AnyValUtil::ColumnTypeToTypeDesc(type_);
  vector<FunctionContext::TypeDesc> arg_types;
  bool char_arg = false;
  for (int i = 0; i < children_.size(); ++i) {
    arg_types.push_back(AnyValUtil::ColumnTypeToTypeDesc(children_[i]->type_));
    char_arg = char_arg || (children_[i]->type_.type == TYPE_CHAR);
  }

  // Compute buffer size for varargs
  int varargs_buffer_size = 0;
  if (vararg_start_idx_ != -1) {
    DCHECK_GT(GetNumChildren(), vararg_start_idx_);
    for (int i = vararg_start_idx_; i < GetNumChildren(); ++i) {
      varargs_buffer_size += AnyValUtil::AnyValSize(children_[i]->type());
    }
  }

  context_index_ = context->Register(state, return_type, arg_types, varargs_buffer_size);

  // If the codegen object hasn't been created yet and we're calling a builtin or native
  // UDF with <= 8 non-variadic arguments, we can use the interpreted path and call the
  // builtin without codegen. This saves us the overhead of creating the codegen object
  // when it's not necessary (i.e., in plan fragments with no codegen-enabled operators).
  // In addition, we can never codegen char arguments.
  // TODO: codegen for char arguments
  if (char_arg || (!state->codegen_created() && NumFixedArgs() <= 8 &&
                   (fn_.binary_type == TFunctionBinaryType::BUILTIN ||
                    fn_.binary_type == TFunctionBinaryType::NATIVE))) {
    // Builtins with char arguments must still have <= 8 arguments.
    // TODO: delete when we have codegen for char arguments
    if (char_arg) {
      DCHECK(NumFixedArgs() <= 8 && fn_.binary_type == TFunctionBinaryType::BUILTIN);
    }
    Status status = LibCache::instance()->GetSoFunctionPtr(
        fn_.hdfs_location, fn_.scalar_fn.symbol, &scalar_fn_, &cache_entry_);
    if (!status.ok()) {
      if (fn_.binary_type == TFunctionBinaryType::BUILTIN) {
        // Builtins symbols should exist unless there is a version mismatch.
        status.AddErrorMsg(Substitute(
            "Builtin '$0' with symbol '$1' does not exist. Verify that all your impalads "
            "are the same version.", fn_.name.function_name, fn_.scalar_fn.symbol));
        return status;
      } else {
        DCHECK_EQ(fn_.binary_type, TFunctionBinaryType::NATIVE);
        return Status(Substitute("Problem loading UDF '$0':\n$1",
            fn_.name.function_name, status.GetErrorMsg()));
        return status;
      }
    }
  } else {
    // If we got here, either codegen is enabled or we need codegen to run this function.
    LlvmCodeGen* codegen;
    RETURN_IF_ERROR(state->GetCodegen(&codegen));

    if (fn_.binary_type == TFunctionBinaryType::IR) {
      string local_path;
      RETURN_IF_ERROR(LibCache::instance()->GetLocalLibPath(
          fn_.hdfs_location, LibCache::TYPE_IR, &local_path));
      // Link the UDF module into this query's main module (essentially copy the UDF
      // module into the main module) so the UDF's functions are available in the main
      // module.
      RETURN_IF_ERROR(codegen->LinkModule(local_path));
    }

    llvm::Function* ir_udf_wrapper;
    RETURN_IF_ERROR(GetCodegendComputeFn(state, &ir_udf_wrapper));
    // TODO: don't do this for child exprs
    codegen->AddFunctionToJit(ir_udf_wrapper, &scalar_fn_wrapper_);
  }

  if (fn_.scalar_fn.__isset.prepare_fn_symbol) {
    RETURN_IF_ERROR(GetFunction(state, fn_.scalar_fn.prepare_fn_symbol,
        reinterpret_cast<void**>(&prepare_fn_)));
  }
  if (fn_.scalar_fn.__isset.close_fn_symbol) {
    RETURN_IF_ERROR(GetFunction(state, fn_.scalar_fn.close_fn_symbol,
        reinterpret_cast<void**>(&close_fn_)));
  }

  return Status::OK;
}

Status ScalarFnCall::Open(RuntimeState* state, ExprContext* ctx,
                          FunctionContext::FunctionStateScope scope) {
  // Opens and inits children
  RETURN_IF_ERROR(Expr::Open(state, ctx, scope));
  FunctionContext* fn_ctx = ctx->fn_context(context_index_);

  if (scalar_fn_ != NULL) {
    // We're in the interpreted path (i.e. no JIT). Populate our FunctionContext's
    // staging_input_vals, which will be reused across calls to scalar_fn_.
    DCHECK(scalar_fn_wrapper_ == NULL);
    ObjectPool* obj_pool = state->obj_pool();
    vector<AnyVal*>* input_vals = fn_ctx->impl()->staging_input_vals();
    for (int i = 0; i < NumFixedArgs(); ++i) {
      input_vals->push_back(CreateAnyVal(obj_pool, children_[i]->type()));
    }
  }

  // Only evaluate constant arguments once per fragment
  if (scope == FunctionContext::FRAGMENT_LOCAL) {
    vector<AnyVal*> constant_args;
    for (int i = 0; i < children_.size(); ++i) {
      constant_args.push_back(children_[i]->GetConstVal(ctx));
    }
    fn_ctx->impl()->SetConstantArgs(constant_args);
  }

  if (prepare_fn_ != NULL) {
    if (scope == FunctionContext::FRAGMENT_LOCAL) {
      prepare_fn_(fn_ctx, FunctionContext::FRAGMENT_LOCAL);
      if (fn_ctx->has_error()) return Status(fn_ctx->error_msg());
    }
    prepare_fn_(fn_ctx, FunctionContext::THREAD_LOCAL);
    if (fn_ctx->has_error()) return Status(fn_ctx->error_msg());
  }

  // If we're calling MathFunctions::RoundUpTo(), we need to set output_scale_, which
  // determines how many decimal places are printed.
  // TODO: revisit this. We should be able to do this if the scale argument is
  // non-constant.
  if (fn_.name.function_name == "round" && type_.type == TYPE_DOUBLE) {
    DCHECK_EQ(children_.size(), 2);
    if (children_[1]->IsConstant()) {
      IntVal scale_arg = children_[1]->GetIntVal(ctx, NULL);
      output_scale_ = scale_arg.val;
    }
  }

  return Status::OK;
}

void ScalarFnCall::Close(RuntimeState* state, ExprContext* context,
                         FunctionContext::FunctionStateScope scope) {
  if (context_index_ != -1 && close_fn_ != NULL) {
    FunctionContext* fn_ctx = context->fn_context(context_index_);

    close_fn_(fn_ctx, FunctionContext::THREAD_LOCAL);
    if (scope == FunctionContext::FRAGMENT_LOCAL) {
      close_fn_(fn_ctx, FunctionContext::FRAGMENT_LOCAL);
    }
  }
  Expr::Close(state, context, scope);
}

bool ScalarFnCall::IsConstant() const {
  if (fn_.name.function_name == "rand") return false;
  return Expr::IsConstant();
}

// Dynamically loads the pre-compiled UDF and codegens a function that calls each child's
// codegen'd function, then passes those values to the UDF and returns the result.
// Example generated IR for a UDF with signature
//    create function Udf(double, int...) returns double
//    select Udf(1.0, 2, 3, 4, 5)
// define { i8, double } @UdfWrapper(i8* %context, %"class.impala::TupleRow"* %row) {
// entry:
//   %arg_val = call { i8, double }
//      @ExprWrapper(i8* %context, %"class.impala::TupleRow"* %row)
//   %arg_ptr = alloca { i8, double }
//   store { i8, double } %arg_val, { i8, double }* %arg_ptr
//   %arg_val1 = call i64 @ExprWrapper1(i8* %context, %"class.impala::TupleRow"* %row)
//   store i64 %arg_val1, i64* inttoptr (i64 89111072 to i64*)
//   %arg_val2 = call i64 @ExprWrapper2(i8* %context, %"class.impala::TupleRow"* %row)
//   store i64 %arg_val2, i64* inttoptr (i64 89111080 to i64*)
//   %arg_val3 = call i64 @ExprWrapper3(i8* %context, %"class.impala::TupleRow"* %row)
//   store i64 %arg_val3, i64* inttoptr (i64 89111088 to i64*)
//   %arg_val4 = call i64 @ExprWrapper4(i8* %context, %"class.impala::TupleRow"* %row)
//   store i64 %arg_val4, i64* inttoptr (i64 89111096 to i64*)
//   %result = call { i8, double }
//      @_Z14VarSumMultiplyPN10impala_udf15FunctionContextERKNS_9DoubleValEiPKNS_6IntValE(
//        %"class.impala_udf::FunctionContext"* inttoptr
//            (i64 37522464 to %"class.impala_udf::FunctionContext"*),
//        {i8, double }* %arg_ptr,
//        i32 4,
//        i64* inttoptr (i64 89111072 to i64*))
//   ret { i8, double } %result
Status ScalarFnCall::GetCodegendComputeFn(RuntimeState* state, llvm::Function** fn) {
  if (ir_compute_fn_ != NULL) {
    *fn = ir_compute_fn_;
    return Status::OK;
  }
  for (int i = 0; i < GetNumChildren(); ++i) {
    if (children_[i]->type().type == TYPE_CHAR) {
      *fn = NULL;
      return Status("ScalarFnCall Codegen not supported for CHAR");
    }
  }

  LlvmCodeGen* codegen;
  RETURN_IF_ERROR(state->GetCodegen(&codegen));
  llvm::Function* udf;
  RETURN_IF_ERROR(GetUdf(state, &udf));

  // Create wrapper that computes args and calls UDF
  stringstream fn_name;
  fn_name << SymbolsUtil::DemangleNameOnly(udf->getName().str()) << "Wrapper";

  llvm::Value* args[2];
  *fn = CreateIrFunctionPrototype(codegen, fn_name.str(), &args);
  llvm::Value* expr_ctx = args[0];
  llvm::Value* row = args[1];
  llvm::BasicBlock* block = llvm::BasicBlock::Create(codegen->context(), "entry", *fn);
  LlvmCodeGen::LlvmBuilder builder(block);

  // Populate UDF arguments
  vector<llvm::Value*> udf_args;

  // First argument is always FunctionContext*.
  // Index into our registered offset in the ExprContext.
  llvm::Value* expr_ctx_gep = builder.CreateStructGEP(expr_ctx, 1, "expr_ctx_gep");
  llvm::Value* fn_ctxs_base = builder.CreateLoad(expr_ctx_gep, "fn_ctxs_base");
  // Use GEP to add our index to the base pointer
  llvm::Value* fn_ctx_ptr =
      builder.CreateConstGEP1_32(fn_ctxs_base, context_index_, "fn_ctx_ptr");
  llvm::Value* fn_ctx = builder.CreateLoad(fn_ctx_ptr, "fn_ctx");
  udf_args.push_back(fn_ctx);

  // Get IR i8* pointer to varargs buffer from FunctionContext* argument
  // (if there are varargs)
  llvm::Value* varargs_buffer = NULL;
  if (vararg_start_idx_ != -1) {
    // FunctionContextImpl is first field of FunctionContext
    // fn_ctx_impl_ptr has type FunctionContextImpl**
    llvm::Value* fn_ctx_impl_ptr = builder.CreateStructGEP(fn_ctx, 0, "fn_ctx_impl_ptr");
    llvm::Value* fn_ctx_impl = builder.CreateLoad(fn_ctx_impl_ptr, "fn_ctx_impl");
    // varargs_buffer is first field of FunctionContextImpl
    // varargs_buffer_ptr has type i8**
    llvm::Value* varargs_buffer_ptr =
        builder.CreateStructGEP(fn_ctx_impl, 0, "varargs_buffer");
    varargs_buffer = builder.CreateLoad(varargs_buffer_ptr);
  }
  // Tracks where to write the next vararg to
  int varargs_buffer_offset = 0;

  // Call children to populate remaining arguments
  for (int i = 0; i < GetNumChildren(); ++i) {
    llvm::Function* child_fn = NULL;
    vector<llvm::Value*> child_fn_args;
    if (state->codegen_enabled()) {
      // Set 'child_fn' to the codegen'd function, sets child_fn = NULL if codegen fails
      children_[i]->GetCodegendComputeFn(state, &child_fn);
    }
    if (child_fn == NULL) {
      // Set 'child_fn' to the interpreted function
      child_fn = GetStaticGetValWrapper(children_[i]->type(), codegen);
      // First argument to interpreted function is children_[i]
      llvm::Type* expr_ptr_type = codegen->GetPtrType(Expr::LLVM_CLASS_NAME);
      child_fn_args.push_back(codegen->CastPtrToLlvmPtr(expr_ptr_type, children_[i]));
    }
    child_fn_args.push_back(expr_ctx);
    child_fn_args.push_back(row);

    // Call 'child_fn', adding the result to either 'udf_args' or 'varargs_buffer'
    DCHECK(child_fn != NULL);
    llvm::Type* arg_type = CodegenAnyVal::GetUnloweredType(codegen, children_[i]->type());
    llvm::Value* arg_val_ptr;
    if (vararg_start_idx_ == -1 || i < vararg_start_idx_) {
      // Either no varargs or arguments before varargs begin. Allocate space to store
      // 'child_fn's result so we can pass the pointer to the UDF.
      arg_val_ptr = codegen->CreateEntryBlockAlloca(builder, arg_type, "arg_val_ptr");

      if (children_[i]->type().type == TYPE_DECIMAL) {
        // UDFs may manipulate DecimalVal arguments via SIMD instructions such as 'movaps'
        // that require 16-byte memory alignment. LLVM uses 8-byte alignment by default,
        // so explicitly set the alignment for DecimalVals.
        llvm::cast<llvm::AllocaInst>(arg_val_ptr)->setAlignment(16);
      }
      udf_args.push_back(arg_val_ptr);
     } else {
      // Store the result of 'child_fn' in varargs_buffer + varargs_buffer_offset
      arg_val_ptr =
          builder.CreateConstGEP1_32(varargs_buffer, varargs_buffer_offset, "arg_val_ptr");
      varargs_buffer_offset += AnyValUtil::AnyValSize(children_[i]->type());
      // Cast arg_val_ptr from i8* to AnyVal pointer type
      arg_val_ptr =
          builder.CreateBitCast(arg_val_ptr, arg_type->getPointerTo(), "arg_val_ptr");
    }
    DCHECK_EQ(arg_val_ptr->getType(), arg_type->getPointerTo());
    // The result of the call must be stored in a lowered AnyVal
    llvm::Value* lowered_arg_val_ptr = builder.CreateBitCast(
        arg_val_ptr, CodegenAnyVal::GetLoweredPtrType(codegen, children_[i]->type()),
        "lowered_arg_val_ptr");
    CodegenAnyVal::CreateCall(
        codegen, &builder, child_fn, child_fn_args, "arg_val", lowered_arg_val_ptr);
  }

  if (vararg_start_idx_ != -1) {
    // We've added the FunctionContext argument plus any non-variadic arguments
    DCHECK_EQ(udf_args.size(), vararg_start_idx_ + 1);
    DCHECK_GE(GetNumChildren(), 1);
    // Add the number of varargs
    udf_args.push_back(codegen->GetIntConstant(
        TYPE_INT, GetNumChildren() - vararg_start_idx_));
    // Add all the accumulated vararg inputs as one input argument.
    llvm::PointerType* vararg_type = codegen->GetPtrType(
        CodegenAnyVal::GetUnloweredType(codegen, children_.back()->type()));
    udf_args.push_back(builder.CreateBitCast(varargs_buffer, vararg_type, "varargs"));
  }

  // Call UDF
  llvm::Value* result_val =
      CodegenAnyVal::CreateCall(codegen, &builder, udf, udf_args, "result");
  builder.CreateRet(result_val);

  *fn = codegen->FinalizeFunction(*fn);
  DCHECK(*fn != NULL);
  ir_compute_fn_ = *fn;
  return Status::OK;
}

Status ScalarFnCall::GetUdf(RuntimeState* state, llvm::Function** udf) {
  LlvmCodeGen* codegen;
  RETURN_IF_ERROR(state->GetCodegen(&codegen));

  // from_utc_timestamp and to_utc_timestamp have inline ASM that cannot be JIT'd.
  // TimestampFunctions::DateAddSub() contains a try/catch which doesn't work in JIT'd
  // code.  Always use the statically compiled versions of these functions so the
  // xcompiled versions are not included in the final module to be JIT'd.
  // TODO: fix this
  bool broken_builtin = fn_.name.function_name == "from_utc_timestamp" ||
                        fn_.name.function_name == "to_utc_timestamp" ||
                        fn_.scalar_fn.symbol.find("DateAddSub") != string::npos;
  if (fn_.binary_type == TFunctionBinaryType::NATIVE ||
      (fn_.binary_type == TFunctionBinaryType::BUILTIN &&
       (!state->codegen_enabled() || broken_builtin))) {
    // In this path, we are code that has been statically compiled to assembly.
    // This can either be a UDF implemented in a .so or a builtin using the UDF
    // interface with the code in impalad.
    void* fn_ptr;
    Status status = LibCache::instance()->GetSoFunctionPtr(
        fn_.hdfs_location, fn_.scalar_fn.symbol, &fn_ptr, &cache_entry_);
    if (!status.ok() && fn_.binary_type == TFunctionBinaryType::BUILTIN) {
      // Builtins symbols should exist unless there is a version mismatch.
      stringstream ss;
      ss << "Builtin '" << fn_.name.function_name << "' with symbol '"
         << fn_.scalar_fn.symbol << "' does not exist. "
         << "Verify that all your impalads are the same version.";
      status.AddErrorMsg(ss.str());
    }
    RETURN_IF_ERROR(status);
    DCHECK(fn_ptr != NULL);

    // Convert UDF function pointer to llvm::Function*
    // First generate the llvm::FunctionType* corresponding to the UDF.
    llvm::Type* return_type = CodegenAnyVal::GetLoweredType(codegen, type());
    vector<llvm::Type*> arg_types;

    if (type().type == TYPE_DECIMAL) {
      // Per the x64 ABI, DecimalVals are returned via a DecmialVal* output argument
      return_type = codegen->void_type();
      arg_types.push_back(
          codegen->GetPtrType(CodegenAnyVal::GetUnloweredType(codegen, type())));
    }

    arg_types.push_back(codegen->GetPtrType("class.impala_udf::FunctionContext"));
    for (int i = 0; i < NumFixedArgs(); ++i) {
      llvm::Type* arg_type = codegen->GetPtrType(
          CodegenAnyVal::GetUnloweredType(codegen, children_[i]->type()));
      arg_types.push_back(arg_type);
    }

    if (vararg_start_idx_ >= 0) {
      llvm::Type* vararg_type = CodegenAnyVal::GetUnloweredPtrType(
          codegen, children_[vararg_start_idx_]->type());
      arg_types.push_back(codegen->GetType(TYPE_INT));
      arg_types.push_back(vararg_type);
    }
    llvm::FunctionType* udf_type = llvm::FunctionType::get(return_type, arg_types, false);

    // Create a llvm::Function* with the generated type. This is only a function
    // declaration, not a definition, since we do not create any basic blocks or
    // instructions in it.
    *udf = llvm::Function::Create(
        udf_type, llvm::GlobalValue::ExternalLinkage,
        fn_.scalar_fn.symbol, codegen->module());

    // Associate the dynamically loaded function pointer with the Function* we
    // defined. This tells LLVM where the compiled function definition is located in
    // memory.
    codegen->execution_engine()->addGlobalMapping(*udf, fn_ptr);
  } else if (fn_.binary_type == TFunctionBinaryType::BUILTIN) {
    // In this path, we're running a builtin with the UDF interface. The IR is
    // in the llvm module.
    DCHECK(state->codegen_enabled());
    *udf = codegen->module()->getFunction(fn_.scalar_fn.symbol);
    if (*udf == NULL) {
      // Builtins symbols should exist unless there is a version mismatch.
      stringstream ss;
      ss << "Builtin '" << fn_.name.function_name << "' with symbol '"
         << fn_.scalar_fn.symbol << "' does not exist. "
         << "Verify that all your impalads are the same version.";
      return Status(ss.str());
    }
  } else {
    // We're running a IR UDF.
    DCHECK_EQ(fn_.binary_type, TFunctionBinaryType::IR);
    *udf = codegen->module()->getFunction(fn_.scalar_fn.symbol);
    if (*udf == NULL) {
      stringstream ss;
      ss << "Unable to locate function " << fn_.scalar_fn.symbol
         << " from LLVM module " << fn_.hdfs_location;
      return Status(ss.str());
    }
  }
  (*udf)->addFnAttr(llvm::Attribute::AlwaysInline);
  return Status::OK;
}

Status ScalarFnCall::GetFunction(RuntimeState* state, const string& symbol, void** fn) {
  if (fn_.binary_type == TFunctionBinaryType::NATIVE ||
      fn_.binary_type == TFunctionBinaryType::BUILTIN) {
    return LibCache::instance()->GetSoFunctionPtr(fn_.hdfs_location, symbol, fn,
                                                  &cache_entry_);
  } else {
    DCHECK_EQ(fn_.binary_type, TFunctionBinaryType::IR);
    LlvmCodeGen* codegen;
    RETURN_IF_ERROR(state->GetCodegen(&codegen));
    llvm::Function* ir_fn = codegen->module()->getFunction(symbol);
    if (ir_fn == NULL) {
      stringstream ss;
      ss << "Unable to locate function " << symbol
         << " from LLVM module " << fn_.hdfs_location;
      return Status(ss.str());
    }
    codegen->AddFunctionToJit(ir_fn, fn);
    return Status::OK;
  }
}

void ScalarFnCall::EvaluateChildren(ExprContext* context, TupleRow* row,
                                    vector<AnyVal*>* input_vals) {
  DCHECK_EQ(input_vals->size(), NumFixedArgs());
  FunctionContext* fn_ctx = context->fn_context(context_index_);
  uint8_t* varargs_buffer = fn_ctx->impl()->varargs_buffer();
  for (int i = 0; i < children_.size(); ++i) {
    void* src_slot = context->GetValue(children_[i], row);
    AnyVal* dst_val;
    if (vararg_start_idx_ == -1 || i < vararg_start_idx_) {
      dst_val = (*input_vals)[i];
    } else {
      dst_val = reinterpret_cast<AnyVal*>(varargs_buffer);
      varargs_buffer += AnyValUtil::AnyValSize(children_[i]->type());
    }
    AnyValUtil::SetAnyVal(src_slot, children_[i]->type(), dst_val);
  }
}

template<typename RETURN_TYPE>
RETURN_TYPE ScalarFnCall::InterpretEval(ExprContext* context, TupleRow* row) {
  DCHECK(scalar_fn_ != NULL);
  FunctionContext* fn_ctx = context->fn_context(context_index_);
  vector<AnyVal*>* input_vals = fn_ctx->impl()->staging_input_vals();
  EvaluateChildren(context, row, input_vals);

  if (vararg_start_idx_ == -1) {
    switch (children_.size()) {
      case 0:
        typedef RETURN_TYPE (*ScalarFn0)(FunctionContext*);
        return reinterpret_cast<ScalarFn0>(scalar_fn_)(fn_ctx);
      case 1:
        typedef RETURN_TYPE (*ScalarFn1)(FunctionContext*, const AnyVal& a1);
        return reinterpret_cast<ScalarFn1>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0]);
      case 2:
        typedef RETURN_TYPE (*ScalarFn2)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2);
        return reinterpret_cast<ScalarFn2>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0], *(*input_vals)[1]);
      case 3:
        typedef RETURN_TYPE (*ScalarFn3)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, const AnyVal& a3);
        return reinterpret_cast<ScalarFn3>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0], *(*input_vals)[1], *(*input_vals)[2]);
      case 4:
        typedef RETURN_TYPE (*ScalarFn4)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, const AnyVal& a3, const AnyVal& a4);
        return reinterpret_cast<ScalarFn4>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0], *(*input_vals)[1], *(*input_vals)[2], *(*input_vals)[3]);
      case 5:
        typedef RETURN_TYPE (*ScalarFn5)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, const AnyVal& a3, const AnyVal& a4, const AnyVal& a5);
        return reinterpret_cast<ScalarFn5>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0], *(*input_vals)[1], *(*input_vals)[2], *(*input_vals)[3],
            *(*input_vals)[4]);
      case 6:
        typedef RETURN_TYPE (*ScalarFn6)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, const AnyVal& a3, const AnyVal& a4, const AnyVal& a5,
            const AnyVal& a6);
        return reinterpret_cast<ScalarFn6>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0], *(*input_vals)[1], *(*input_vals)[2], *(*input_vals)[3],
            *(*input_vals)[4], *(*input_vals)[5]);
      case 7:
        typedef RETURN_TYPE (*ScalarFn7)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, const AnyVal& a3, const AnyVal& a4, const AnyVal& a5,
            const AnyVal& a6, const AnyVal& a7);
        return reinterpret_cast<ScalarFn7>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0], *(*input_vals)[1], *(*input_vals)[2], *(*input_vals)[3],
            *(*input_vals)[4], *(*input_vals)[5], *(*input_vals)[6]);
      case 8:
        typedef RETURN_TYPE (*ScalarFn8)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, const AnyVal& a3, const AnyVal& a4, const AnyVal& a5,
            const AnyVal& a6, const AnyVal& a7, const AnyVal& a8);
        return reinterpret_cast<ScalarFn8>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0], *(*input_vals)[1], *(*input_vals)[2], *(*input_vals)[3],
            *(*input_vals)[4], *(*input_vals)[5], *(*input_vals)[6], *(*input_vals)[7]);
      default:
        DCHECK(false) << "Interpreted path not implemented. We should have "
                      << "codegen'd the wrapper";
    }
   } else {
    int num_varargs = children_.size() - NumFixedArgs();
    const AnyVal* varargs = reinterpret_cast<AnyVal*>(fn_ctx->impl()->varargs_buffer());
    switch (NumFixedArgs()) {
      case 0:
        typedef RETURN_TYPE (*VarargFn0)(FunctionContext*, int num_varargs,
            const AnyVal* varargs);
        return reinterpret_cast<VarargFn0>(scalar_fn_)(fn_ctx, num_varargs, varargs);
      case 1:
        typedef RETURN_TYPE (*VarargFn1)(FunctionContext*, const AnyVal& a1,
            int num_varargs, const AnyVal* varargs);
        return reinterpret_cast<VarargFn1>(scalar_fn_)(fn_ctx, *(*input_vals)[0],
            num_varargs, varargs);
      case 2:
        typedef RETURN_TYPE (*VarargFn2)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, int num_varargs, const AnyVal* varargs);
        return reinterpret_cast<VarargFn2>(scalar_fn_)(fn_ctx, *(*input_vals)[0],
            *(*input_vals)[1], num_varargs, varargs);
      case 3:
        typedef RETURN_TYPE (*VarargFn3)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, const AnyVal& a3, int num_varargs, const AnyVal* varargs);
        return reinterpret_cast<VarargFn3>(scalar_fn_)(fn_ctx, *(*input_vals)[0],
            *(*input_vals)[1], *(*input_vals)[2], num_varargs, varargs);
      case 4:
        typedef RETURN_TYPE (*VarargFn4)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, const AnyVal& a3, const AnyVal& a4, int num_varargs,
            const AnyVal* varargs);
        return reinterpret_cast<VarargFn4>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0], *(*input_vals)[1], *(*input_vals)[2], *(*input_vals)[3],
            num_varargs, varargs);
      case 5:
        typedef RETURN_TYPE (*VarargFn5)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, const AnyVal& a3, const AnyVal& a4, const AnyVal& a5,
            int num_varargs, const AnyVal* varargs);
        return reinterpret_cast<VarargFn5>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0], *(*input_vals)[1], *(*input_vals)[2], *(*input_vals)[3],
            *(*input_vals)[4], num_varargs, varargs);
      case 6:
        typedef RETURN_TYPE (*VarargFn6)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, const AnyVal& a3, const AnyVal& a4, const AnyVal& a5,
            const AnyVal& a6, int num_varargs, const AnyVal* varargs);
        return reinterpret_cast<VarargFn6>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0], *(*input_vals)[1], *(*input_vals)[2], *(*input_vals)[3],
            *(*input_vals)[4], *(*input_vals)[5], num_varargs, varargs);
      case 7:
        typedef RETURN_TYPE (*VarargFn7)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, const AnyVal& a3, const AnyVal& a4, const AnyVal& a5,
            const AnyVal& a6, const AnyVal& a7, int num_varargs, const AnyVal* varargs);
        return reinterpret_cast<VarargFn7>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0], *(*input_vals)[1], *(*input_vals)[2], *(*input_vals)[3],
            *(*input_vals)[4], *(*input_vals)[5], *(*input_vals)[6], num_varargs, varargs);
      case 8:
        typedef RETURN_TYPE (*VarargFn8)(FunctionContext*, const AnyVal& a1,
            const AnyVal& a2, const AnyVal& a3, const AnyVal& a4, const AnyVal& a5,
            const AnyVal& a6, const AnyVal& a7, const AnyVal& a8, int num_varargs,
            const AnyVal* varargs);
        return reinterpret_cast<VarargFn8>(scalar_fn_)(fn_ctx,
            *(*input_vals)[0], *(*input_vals)[1], *(*input_vals)[2], *(*input_vals)[3],
            *(*input_vals)[4], *(*input_vals)[5], *(*input_vals)[6], *(*input_vals)[7],
            num_varargs, varargs);
      default:
        DCHECK(false) << "Interpreted path not implemented. We should have "
                      << "codegen'd the wrapper";
    }
  }
  return RETURN_TYPE::null();
}

typedef BooleanVal (*BooleanWrapper)(ExprContext*, TupleRow*);
typedef TinyIntVal (*TinyIntWrapper)(ExprContext*, TupleRow*);
typedef SmallIntVal (*SmallIntWrapper)(ExprContext*, TupleRow*);
typedef IntVal (*IntWrapper)(ExprContext*, TupleRow*);
typedef BigIntVal (*BigIntWrapper)(ExprContext*, TupleRow*);
typedef FloatVal (*FloatWrapper)(ExprContext*, TupleRow*);
typedef DoubleVal (*DoubleWrapper)(ExprContext*, TupleRow*);
typedef StringVal (*StringWrapper)(ExprContext*, TupleRow*);
typedef TimestampVal (*TimestampWrapper)(ExprContext*, TupleRow*);
typedef DecimalVal (*DecimalWrapper)(ExprContext*, TupleRow*);

// TODO: macroify this?
BooleanVal ScalarFnCall::GetBooleanVal(ExprContext* context, TupleRow* row) {
  DCHECK_EQ(type_.type, TYPE_BOOLEAN);
  DCHECK(context != NULL);
  if (scalar_fn_wrapper_ == NULL) return InterpretEval<BooleanVal>(context, row);
  BooleanWrapper fn = reinterpret_cast<BooleanWrapper>(scalar_fn_wrapper_);
  return fn(context, row);
}

TinyIntVal ScalarFnCall::GetTinyIntVal(ExprContext* context, TupleRow* row) {
  DCHECK_EQ(type_.type, TYPE_TINYINT);
  DCHECK(context != NULL);
  if (scalar_fn_wrapper_ == NULL) return InterpretEval<TinyIntVal>(context, row);
  TinyIntWrapper fn = reinterpret_cast<TinyIntWrapper>(scalar_fn_wrapper_);
  return fn(context, row);
}

SmallIntVal ScalarFnCall::GetSmallIntVal(ExprContext* context, TupleRow* row) {
  DCHECK_EQ(type_.type, TYPE_SMALLINT);
  DCHECK(context != NULL);
  if (scalar_fn_wrapper_ == NULL) return InterpretEval<SmallIntVal>(context, row);
  SmallIntWrapper fn = reinterpret_cast<SmallIntWrapper>(scalar_fn_wrapper_);
  return fn(context, row);
}

IntVal ScalarFnCall::GetIntVal(ExprContext* context, TupleRow* row) {
  DCHECK_EQ(type_.type, TYPE_INT);
  DCHECK(context != NULL);
  if (scalar_fn_wrapper_ == NULL) return InterpretEval<IntVal>(context, row);
  IntWrapper fn = reinterpret_cast<IntWrapper>(scalar_fn_wrapper_);
  return fn(context, row);
}

BigIntVal ScalarFnCall::GetBigIntVal(ExprContext* context, TupleRow* row) {
  DCHECK_EQ(type_.type, TYPE_BIGINT);
  DCHECK(context != NULL);
  if (scalar_fn_wrapper_ == NULL) return InterpretEval<BigIntVal>(context, row);
  BigIntWrapper fn = reinterpret_cast<BigIntWrapper>(scalar_fn_wrapper_);
  return fn(context, row);
}

FloatVal ScalarFnCall::GetFloatVal(ExprContext* context, TupleRow* row) {
  DCHECK_EQ(type_.type, TYPE_FLOAT);
  DCHECK(context != NULL);
  if (scalar_fn_wrapper_ == NULL) return InterpretEval<FloatVal>(context, row);
  FloatWrapper fn = reinterpret_cast<FloatWrapper>(scalar_fn_wrapper_);
  return fn(context, row);
}

DoubleVal ScalarFnCall::GetDoubleVal(ExprContext* context, TupleRow* row) {
  DCHECK_EQ(type_.type, TYPE_DOUBLE);
  DCHECK(context != NULL);
  if (scalar_fn_wrapper_ == NULL) return InterpretEval<DoubleVal>(context, row);
  DoubleWrapper fn = reinterpret_cast<DoubleWrapper>(scalar_fn_wrapper_);
  return fn(context, row);
}

StringVal ScalarFnCall::GetStringVal(ExprContext* context, TupleRow* row) {
  DCHECK(type_.IsStringType());
  DCHECK(context != NULL);
  if (scalar_fn_wrapper_ == NULL) return InterpretEval<StringVal>(context, row);
  StringWrapper fn = reinterpret_cast<StringWrapper>(scalar_fn_wrapper_);
  return fn(context, row);
}

TimestampVal ScalarFnCall::GetTimestampVal(ExprContext* context, TupleRow* row) {
  DCHECK_EQ(type_.type, TYPE_TIMESTAMP);
  DCHECK(context != NULL);
  if (scalar_fn_wrapper_ == NULL) return InterpretEval<TimestampVal>(context, row);
  TimestampWrapper fn = reinterpret_cast<TimestampWrapper>(scalar_fn_wrapper_);
  return fn(context, row);
}

DecimalVal ScalarFnCall::GetDecimalVal(ExprContext* context, TupleRow* row) {
  DCHECK_EQ(type_.type, TYPE_DECIMAL);
  DCHECK(context != NULL);
  if (scalar_fn_wrapper_ == NULL) return InterpretEval<DecimalVal>(context, row);
  DecimalWrapper fn = reinterpret_cast<DecimalWrapper>(scalar_fn_wrapper_);
  return fn(context, row);
}

string ScalarFnCall::DebugString() const {
  stringstream out;
  out << "ScalarFnCall(udf_type=" << fn_.binary_type
      << " location=" << fn_.hdfs_location
      << " symbol_name=" << fn_.scalar_fn.symbol << Expr::DebugString() << ")";
  return out.str();
}


text:
(function checkMoreTypes(check) {
  'use strict';

  if (!check) {
    if (typeof require === 'undefined') {
      throw new Error('Cannot find check-types library, has it been loaded?');
    }
    check = require('check-types');
  }

  if (typeof Function.prototype.bind !== 'function') {
    throw new Error('Missing Function.prototype.bind, please load es5-shim first');
  }

  /**
    Checks if argument is defined or not

    This method now is part of the check-types.js
    @method defined
  */
  function defined(value) {
    return typeof value !== 'undefined';
  }

  /**
    Checks if argument is a valid Date instance

    @method validDate
  */
  function validDate(value) {
    return check.date(value) &&
      check.number(Number(value));
  }

  /**
    Returns true if the argument is primitive JavaScript type

    @method primitive
  */
  function primitive(value) {
    var type = typeof value;
    return type === 'number' ||
      type === 'boolean' ||
      type === 'string';
  }

  /**
    Returns true if the value is a number 0

    @method zero
  */
  function zero(x) {
    return typeof x === 'number' && x === 0;
  }

  /**
    same as ===

    @method same
  */
  function same(a, b) {
    return a === b;
  }

  /**
    Returns true if the index is valid for give string / array

    @method index
  */
  function index(list, k) {
    return defined(list) &&
      has(list, 'length') &&
      k >= 0 &&
      k < list.length;
  }

  /**
    Returns true if both objects are the same type and have same length property

    @method sameLength
  */
  function sameLength(a, b) {
    return typeof a === typeof b &&
      a && b &&
      a.length === b.length;
  }

  /**
    Returns true if all items in an array are the same reference

    @method allSame
  */
  function allSame(arr) {
    if (!check.array(arr)) {
      return false;
    }
    if (!arr.length) {
      return true;
    }
    var first = arr[0];
    return arr.every(function (item) {
      return item === first;
    });
  }

  /**
    Returns true if given item is in the array

    @method oneOf
  */
  function oneOf(arr, x) {
    check.verify.array(arr, 'expected an array');
    return arr.indexOf(x) !== -1;
  }

  /**
    Returns true for urls of the format `git@....git`

    @method git
  */
  function git(url) {
    return check.unemptyString(url) &&
      /^git@/.test(url);
  }

  /**
    Checks if given value is 0 or 1

    @method bit
  */
  function bit(value) {
    return value === 0 || value === 1;
  }

  /**
    Checks if given value is true of false

    @method bool
  */
  function bool(value) {
    return typeof value === 'boolean';
  }

  /**
    Checks if given object has a property
    @method has
  */
  function has(o, property) {
    if (arguments.length !== 2) {
      throw new Error('Expected two arguments to check.has, got only ' + arguments.length);
    }
    return Boolean(o && property &&
      typeof property === 'string' &&
      typeof o[property] !== 'undefined');
  }

  /**
  Checks if given string is already in lower case
  @method lowerCase
  */
  function lowerCase(str) {
    return check.string(str) &&
      str.toLowerCase() === str;
  }

  /**
  Returns true if the argument is an array with at least one value
  @method unemptyArray
  */
  function unemptyArray(a) {
    return check.array(a) && a.length > 0;
  }

  /**
  Returns true if each item in the array passes the predicate
  @method arrayOf
  @param rule Predicate function
  @param a Array to check
  */
  function arrayOf(rule, a) {
    return check.array(a) && a.every(rule);
  }

  /**
  Returns items from array that do not passes the predicate
  @method badItems
  @param rule Predicate function
  @param a Array with items
  */
  function badItems(rule, a) {
    check.verify.array(a, 'expected array to find bad items');
    return a.filter(notModifier(rule));
  }

  /**
  Returns true if given array only has strings
  @method arrayOfStrings
  @param a Array to check
  @param checkLowerCase Checks if all strings are lowercase
  */
  function arrayOfStrings(a, checkLowerCase) {
    var v = check.array(a) && a.every(check.string);
    if (v && check.bool(checkLowerCase) && checkLowerCase) {
      return a.every(check.lowerCase);
    }
    return v;
  }

  /**
  Returns true if given argument is array of arrays of strings
  @method arrayOfArraysOfStrings
  @param a Array to check
  @param checkLowerCase Checks if all strings are lowercase
  */
  function arrayOfArraysOfStrings(a, checkLowerCase) {
    return check.array(a) && a.every(function (arr) {
      return check.arrayOfStrings(arr, checkLowerCase);
    });
  }

  /**
    Checks if object passes all rules in predicates.

    check.all({ foo: 'foo' }, { foo: check.string }, 'wrong object');

    This is a composition of check.every(check.map ...) calls
    https://github.com/philbooth/check-types.js#batch-operations

    @method all
    @param {object} object object to check
    @param {object} predicates rules to check. Usually one per property.
    @public
    @returns true or false
  */
  function all(obj, predicates) {
    check.verify.object(obj, 'missing object to check');
    check.verify.object(predicates, 'missing predicates object');
    Object.keys(predicates).forEach(function (property) {
      check.verify.fn(predicates[property], 'not a predicate function for ' + property);
    });
    return check.every(check.map(obj, predicates));
  }

  /**
    Checks given object against predicates object
    @method schema
  */
  function schema(predicates, obj) {
    return all(obj, predicates);
  }

  /** Checks if given function raises an error

    @method raises
  */
  function raises(fn, errorValidator) {
    check.verify.fn(fn, 'expected function that raises');
    try {
      fn();
    } catch (err) {
      if (typeof errorValidator === 'undefined') {
        return true;
      }
      if (typeof errorValidator === 'function') {
        return errorValidator(err);
      }
      return false;
    }
    // error has not been raised
    return false;
  }

  /**
    Returns true if given value is ''
    @method emptyString
  */
  function emptyString(a) {
    return a === '';
  }

  /**
    Returns true if given value is [], {} or ''
    @method empty
  */
  function empty(a) {
    var hasLength = typeof a === 'string' ||
      Array.isArray(a);
    if (hasLength) {
      return !a.length;
    }
    if (a instanceof Object) {
      return !Object.keys(a).length;
    }
    return false;
  }

  /**
    Returns true if given value has .length and it is not zero, or has properties
    @method unempty
  */
  function unempty(a) {
    var hasLength = typeof a === 'string' ||
      Array.isArray(a);
    if (hasLength) {
      return a.length;
    }
    if (a instanceof Object) {
      return Object.keys(a).length;
    }
    return true;
  }

  /**
    Returns true if 0 <= value <= 1
    @method unit
  */
  function unit(value) {
    return check.number(value) &&
      value >= 0.0 && value <= 1.0;
  }

  var rgb = /^#(?:[0-9a-fA-F]{3}){1,2}$/;
  /**
    Returns true if value is hex RGB between '#000000' and '#FFFFFF'
    @method hexRgb
  */
  function hexRgb(value) {
    return check.string(value) &&
      rgb.test(value);
  }

  // typical git SHA commit id is 40 digit hex string, like
  // 3b819803cdf2225ca1338beb17e0c506fdeedefc
  var shaReg = /^[0-9a-f]{40}$/;

  /**
    Returns true if the given string is 40 digit SHA commit id
    @method commitId
  */
  function commitId(id) {
    return check.string(id) &&
      id.length === 40 &&
      shaReg.test(id);
  }

  // when using git log --oneline short ids are displayed, first 7 characters
  var shortShaReg = /^[0-9a-f]{7}$/;

  /**
    Returns true if the given string is short 7 character SHA id part
    @method shortCommitId
  */
  function shortCommitId(id) {
    return check.string(id) &&
      id.length === 7 &&
      shortShaReg.test(id);
  }

  //
  // helper methods
  //

  if (!check.defend) {
    var checkPredicates = function checksPredicates(fn, predicates, args) {
      check.verify.fn(fn, 'expected a function');
      check.verify.array(predicates, 'expected list of predicates');
      check.verify.defined(args, 'missing args');

      var k = 0, // iterates over predicates
        j = 0, // iterates over arguments
        n = predicates.length;

      for (k = 0; k < n; k += 1) {
        var predicate = predicates[k];
        if (!check.fn(predicate)) {
          continue;
        }

        if (!predicate.call(null, args[j])) {
          var msg = 'Argument ' + (j + 1) + ': ' + args[j] + ' does not pass predicate';
          if (check.unemptyString(predicates[k + 1])) {
            msg += ': ' + predicates[k + 1];
          }
          throw new Error(msg);
        }

        j += 1;
      }
      return fn.apply(null, args);
    };

    check.defend = function defend(fn) {
      var predicates = Array.prototype.slice.call(arguments, 1);
      return function () {
        return checkPredicates(fn, predicates, arguments);
      };
    };
  }

  /**
    Combines multiple predicate functions to produce new OR predicate
    @method or
  */
  function or() {
    var predicates = Array.prototype.slice.call(arguments, 0);
    if (!predicates.length) {
      throw new Error('empty list of arguments to or');
    }

    return function orCheck() {
      var values = Array.prototype.slice.call(arguments, 0);
      return predicates.some(function (predicate) {
        try {
          return check.fn(predicate) ?
            predicate.apply(null, values) : Boolean(predicate);
        } catch (err) {
          // treat exceptions as false
          return false;
        }
      });
    };
  }

  /**
    Combines multiple predicate functions to produce new AND predicate
    @method or
  */
  function and() {
    var predicates = Array.prototype.slice.call(arguments, 0);
    if (!predicates.length) {
      throw new Error('empty list of arguments to or');
    }

    return function orCheck() {
      var values = Array.prototype.slice.call(arguments, 0);
      return predicates.every(function (predicate) {
        return check.fn(predicate) ?
          predicate.apply(null, values) : Boolean(predicate);
      });
    };
  }

  /**
  * Public modifier `not`.
  *
  * Negates `predicate`.
  * copied from check-types.js
  */
  function notModifier(predicate) {
    return function () {
      return !predicate.apply(null, arguments);
    };
  }

  if (!check.mixin) {
    /** Adds new predicate to all objects
    @method mixin */
    check.mixin = function mixin(fn, name) {
      if (check.string(fn) && check.fn(name)) {
        var tmp = fn;
        fn = name;
        name = tmp;
      }

      check.verify.fn(fn, 'expected predicate function');
      if (!check.unemptyString(name)) {
        name = fn.name;
      }
      check.verify.unemptyString(name, 'predicate function missing name\n' + fn.toString());

      function registerPredicate(obj, name, fn) {
        check.verify.object(obj, 'missing object');
        check.verify.unemptyString(name, 'missing name');
        check.verify.fn(fn, 'missing function');

        if (!obj[name]) {
          obj[name] = fn;
        }
      }

      /**
       * Public modifier `maybe`.
       *
       * Returns `true` if `predicate` is  `null` or `undefined`,
       * otherwise propagates the return value from `predicate`.
       * copied from check-types.js
       */
      function maybeModifier(predicate) {
        return function () {
          if (!check.defined(arguments[0]) || check.nulled(arguments[0])) {
            return true;
          }
          return predicate.apply(null, arguments);
        };
      }

      /**
       * Public modifier `verify`.
       *
       * Throws if `predicate` returns `false`.
       * copied from check-types.js
       */
      function verifyModifier(predicate, defaultMessage) {
        return function () {
          var message;
          if (predicate.apply(null, arguments) === false) {
            message = arguments[arguments.length - 1];
            throw new Error(check.unemptyString(message) ? message : defaultMessage);
          }
        };
      }

      registerPredicate(check, name, fn);
      registerPredicate(check.maybe, name, maybeModifier(fn));
      registerPredicate(check.not, name, notModifier(fn));
      registerPredicate(check.verify, name, verifyModifier(fn, name + ' failed'));
    };
  }

  if (!check.then) {
    /**
      Executes given function only if condition is truthy.
      @method then
    */
    check.then = function then(condition, fn) {
      return function () {
        var ok = typeof condition === 'function' ?
          condition.apply(null, arguments) : condition;
        if (ok) {
          return fn.apply(null, arguments);
        }
      };
    };
  }

  var promiseSchema = {
    then: check.fn
  };

  // work around reserved keywords checks
  promiseSchema['catch'] = check.fn;
  promiseSchema['finally'] = check.fn;

  var hasPromiseApi = schema.bind(null, promiseSchema);

  /**
    Returns true if argument implements promise api (.then, .catch, .finally)
    @method promise
  */
  function isPromise(p) {
    return check.object(p) && hasPromiseApi(p);
  }

  /**
    Shallow strict comparison
    @method equal
  */
  function equal(a, b) {
    if (arguments.length === 2) {
      return a === b;
    } else if (arguments.length === 1) {
      return function equalTo(b) {
        return a === b;
      };
    } else {
      throw new Error('Expected at least 1 or 2 arguments to check.equal');
    }
  }

  // new predicates to be added to check object. Use object to preserve names
  var predicates = {
    defined: defined,
    same: same,
    allSame: allSame,
    bit: bit,
    bool: bool,
    has: has,
    lowerCase: lowerCase,
    unemptyArray: unemptyArray,
    arrayOfStrings: arrayOfStrings,
    arrayOfArraysOfStrings: arrayOfArraysOfStrings,
    all: all,
    schema: schema,
    raises: raises,
    empty: empty,
    emptyString: emptyString,
    unempty: unempty,
    unit: unit,
    hexRgb: hexRgb,
    sameLength: sameLength,
    commitId: commitId,
    shortCommitId: shortCommitId,
    index: index,
    git: git,
    arrayOf: arrayOf,
    badItems: badItems,
    oneOf: oneOf,
    promise: isPromise,
    validDate: validDate,
    equal: equal,
    or: or,
    and: and,
    primitive: primitive,
    zero: zero
  };

  Object.keys(predicates).forEach(function (name) {
    check.mixin(predicates[name], name);
  });

  if (typeof module === 'object') {
    module.exports = check;
  }
}(typeof window === 'object' ? window.check : global.check));

redpajama_set_name: RedPajamaGithub


text:
package org.ovirt.engine.core.dao;

import java.util.List;

import org.ovirt.engine.core.common.businessentities.roles;
import org.ovirt.engine.core.compat.Guid;

/**
 * RoleDAO defines a type for performing CRUD operations on instances of {@link roles}.
 *
 *
 */
public interface RoleDAO extends GenericDao<roles, Guid> {

    /**
     * Retrieves the role with the specified name.
     *
     * @param name
     *            the role name
     * @return the role
     */
    roles getByName(String name);

    /**
     * Retrieves all roles for the specified Ad element.
     *
     * @param id
     *            the Ad element
     * @return the list of roles
     */
    List<roles> getAllForAdElement(Guid id);

    /**
     * This seems to be a redundant method, but the stored procedure is different from the one for
     * {@link #getAllForAdElement(Guid)}.
     *
     * @param id
     *            the Ad element
     * @return the list of roles
     */
    List<roles> getForAdElement(Guid id);

    /**
     * This method gets the Roles for the given user and its groups. The purpose of this method is to be able to get
     * roles even if the user is not already added to DB, by getting the roles for his groups
     *
     * @param userId
     *            ID of the user to obtain roles for
     * @param groupIds
     *            comma delimited list of group IDs of the user
     * @return the list of the roles
     */
    List<roles> getAllForUserAndGroups(Guid userId, String groupIds);
}


text:
/**
 * Typescript definition tests for d3/d3-format module
 *
 * Note: These tests are intended to test the definitions only
 * in the sense of typing and call signature consistency. They
 * are not intended as functional tests.
 */

import * as d3Format from 'd3-format';

// ----------------------------------------------------------------------
// Preparatory Steps
// ----------------------------------------------------------------------

let num: number;

let formatFn: (n: number) => string;

let specifier: d3Format.FormatSpecifier;

let localeDef: d3Format.FormatLocaleDefinition;

let localeObj: d3Format.FormatLocaleObject;

// ----------------------------------------------------------------------
// Test Format and FormatPrefix
// ----------------------------------------------------------------------

formatFn = d3Format.format('.0%');

formatFn = d3Format.formatPrefix(',.0', 1e-6);

// ----------------------------------------------------------------------
// Test Format Specifier
// ----------------------------------------------------------------------

specifier = d3Format.formatSpecifier('.0%');

let fill: string = specifier.fill;
let align: '>' | '<' | '^' | '=' = specifier.align;
let sign: '-' | '+' | '(' | ' ' = specifier.sign;
let symbol: '$' | '#' | '' = specifier.symbol;
let zero: boolean = specifier.zero;
let width: number | undefined = specifier.width;
let comma: boolean = specifier.comma;
let precision: number = specifier.precision;
let type: 'e' | 'f' | 'g' | 'r' | 's' | '%' | 'p' | 'b' | 'o' | 'd' | 'x' | 'X' | 'c' | '' | 'n' = specifier.type;

let formatString: string = specifier.toString();

// ----------------------------------------------------------------------
// Test Precision Suggestors
// ----------------------------------------------------------------------

num = d3Format.precisionFixed(0.0005);

num = d3Format.precisionPrefix(0.0005, 1000);

num = d3Format.precisionRound(0.0005, 3000);

// ----------------------------------------------------------------------
// Test Locale Definition
// ----------------------------------------------------------------------

localeDef = {
    decimal: ',',
    thousands: '.',
    grouping: [3],
    currency: ['EUR', '']
};

localeDef = {
  decimal: "\u066b",
  thousands: "\u066c",
  grouping: [3],
  currency: ["", ""],
  numerals : ["\u0660", "\u0661", "\u0662", "\u0663", "\u0664", "\u0665", "\u0666", "\u0667", "\u0668", "\u0669"]
};

localeDef = {
  decimal: "\u066b",
  thousands: "\u066c",
  grouping: [3],
  currency: ["", ""],
  percent : "\u202f%"
};

let decimal: string = localeDef.decimal;
let thousands: string = localeDef.thousands;
let grouping: number[] = localeDef.grouping;
let currency: [string, string] = localeDef.currency;
let numerals: string[] | undefined = localeDef.numerals;
let percent: string | undefined = localeDef.percent;

localeObj = d3Format.formatLocale(localeDef);

localeObj = d3Format.formatDefaultLocale(localeDef);

let formatFactory: (specifier: string) => ((n: number) => string) = localeObj.format;
let formatPrefixFactory: (specifier: string, value: number) => ((n: number) => string) = localeObj.formatPrefix;


text:
import os
from twilio.rest import Client

# Your Account Sid and Auth Token from twilio.com/user/account
# To set up environmental variables, see http://twil.io/secure
account_sid = os.environ['TWILIO_ACCOUNT_SID']
auth_token = os.environ['TWILIO_AUTH_TOKEN']
client = Client(account_sid, auth_token)

# A list of participant objects with the properties described above
participants = client.conferences('CFbbe4632a3c49700934481addd5ce1659') \
                     .participants \
                     .list()

for participant in participants:
    print(participant.muted)


text:
//********************************************************************
//*
//* Warning: This file was generated by ecore4CPP Generator
//*
//********************************************************************

#ifndef UML_STRUCTUREDCLASSIFIERSTRUCTUREDCLASSIFIERIMPL_HPP
#define UML_STRUCTUREDCLASSIFIERSTRUCTUREDCLASSIFIERIMPL_HPP

//*********************************
// generated Includes

// namespace macro header include
#include "uml/uml.hpp"

// model includes
#include "../StructuredClassifier.hpp"

#include "uml/impl/ClassifierImpl.hpp"

//*********************************
namespace uml
{
	class UML_API StructuredClassifierImpl : virtual public ClassifierImpl, virtual public StructuredClassifier
	{
		public:
			StructuredClassifierImpl(const StructuredClassifierImpl & obj);
			virtual std::shared_ptr<ecore::EObject> copy() const = 0;
			StructuredClassifierImpl& operator=(StructuredClassifierImpl const&);

		protected:
			friend class umlFactoryImpl;
			StructuredClassifierImpl();
			virtual std::shared_ptr<uml::StructuredClassifier> getThisStructuredClassifierPtr() const;
			virtual void setThisStructuredClassifierPtr(std::weak_ptr<uml::StructuredClassifier> thisStructuredClassifierPtr);

			//Additional constructors for the containments back reference
			StructuredClassifierImpl(std::weak_ptr<uml::Namespace> par_namespace);
			//Additional constructors for the containments back reference
			StructuredClassifierImpl(std::weak_ptr<uml::Element> par_owner);
			//Additional constructors for the containments back reference
			StructuredClassifierImpl(std::weak_ptr<uml::Package> par_Package, const int reference_id);
			//Additional constructors for the containments back reference
			StructuredClassifierImpl(std::weak_ptr<uml::TemplateParameter> par_owningTemplateParameter);
			//Additional constructors for the containments back reference

		public:
			//destructor
			virtual ~StructuredClassifierImpl() = 0;

			//*********************************
			// Operations
			//*********************************
			/*!
			All features of type ConnectableElement, equivalent to all direct and inherited roles.
			result = (allFeatures()->select(oclIsKindOf(ConnectableElement))->collect(oclAsType(ConnectableElement))->asSet())

From package UML::StructuredClassifiers.

			*/

			virtual std::shared_ptr<Bag<uml::ConnectableElement> > allRoles() ;
			/*!
			Creates a property with the specified name, type, lower bound, and upper bound as an owned attribute of this structured classifier.
			*/

			virtual std::shared_ptr<uml::Property> createOwnedAttribute(std::string name,std::shared_ptr<uml::Type> type,int lower,int upper) ;
			/*!
			Derivation for StructuredClassifier::/part
			result = (ownedAttribute->select(isComposite)->asSet())

From package UML::StructuredClassifiers.

			*/

			virtual std::shared_ptr<Bag<uml::Property> > getParts() ;

			//*********************************
			// Attribute Getters & Setters
			//*********************************

			//*********************************
			// Reference Getters & Setters
			//*********************************
			/*!
			The Properties owned by the StructuredClassifier.

From package UML::StructuredClassifiers.

			*/

			virtual std::shared_ptr<SubsetUnion<uml::Property, uml::ConnectableElement, uml::NamedElement, uml::Property>> getOwnedAttribute() const ;
			/*!
			The connectors owned by the StructuredClassifier.

From package UML::StructuredClassifiers.

			*/

			virtual std::shared_ptr<Subset<uml::Connector, uml::Feature, uml::NamedElement>> getOwnedConnector() const ;
			/*!
			The Properties specifying instances that the StructuredClassifier owns by composition. This collection is derived, selecting those owned Properties where isComposite is true.

From package UML::StructuredClassifiers.

			*/

			virtual std::shared_ptr<Bag<uml::Property>> getPart() const ;

			//*********************************
			// Union Reference Getters
			//*********************************
			/*!
			All of the Properties that are direct (i.e., not inherited or imported) attributes of the Classifier.

From package UML::Classification.

			*/

			virtual std::shared_ptr<SubsetUnion<uml::Property, uml::Feature>> getAttribute() const ;
			/*!
			Specifies each Feature directly defined in the classifier. Note that there may be members of the Classifier that are of the type Feature but are not included, e.g., inherited features.

From package UML::Classification.

			*/

			virtual std::shared_ptr<SubsetUnion<uml::Feature, uml::NamedElement>> getFeature() const ;
			/*!
			A collection of NamedElements identifiable within the Namespace, either by being owned or by being introduced by importing or inheritance.

From package UML::CommonStructure.

			*/

			virtual std::shared_ptr<Union<uml::NamedElement>> getMember() const ;
			/*!
			Specifies the Namespace that owns the NamedElement.

From package UML::CommonStructure.

			*/

			virtual std::weak_ptr<uml::Namespace> getNamespace() const ;
			/*!
			The Elements owned by this Element.

From package UML::CommonStructure.

			*/

			virtual std::shared_ptr<Union<uml::Element>> getOwnedElement() const ;
			/*!
			A collection of NamedElements owned by the Namespace.

From package UML::CommonStructure.

			*/

			virtual std::shared_ptr<SubsetUnion<uml::NamedElement, uml::Element, uml::NamedElement>> getOwnedMember() const ;
			/*!
			The Element that owns this Element.

From package UML::CommonStructure.

			*/

			virtual std::weak_ptr<uml::Element> getOwner() const ;
			/*!
			The RedefinableElement that is being redefined by this element.

From package UML::Classification.

			*/

			virtual std::shared_ptr<Union<uml::RedefinableElement>> getRedefinedElement() const ;
			/*!
			The roles that instances may play in this StructuredClassifier.

From package UML::StructuredClassifiers.

			*/

			virtual std::shared_ptr<SubsetUnion<uml::ConnectableElement, uml::NamedElement>> getRole() const ;

			//*********************************
			// Container Getter
			//*********************************
			virtual std::shared_ptr<ecore::EObject> eContainer() const ;

			//*********************************
			// Persistence Functions
			//*********************************
			virtual void load(std::shared_ptr<persistence::interfaces::XLoadHandler> loadHandler) ;
			virtual void loadAttributes(std::shared_ptr<persistence::interfaces::XLoadHandler> loadHandler, std::map<std::string, std::string> attr_list);
			virtual void loadNode(std::string nodeName, std::shared_ptr<persistence::interfaces::XLoadHandler> loadHandler);
			virtual void resolveReferences(const int featureID, std::vector<std::shared_ptr<ecore::EObject> > references) ;
			virtual void save(std::shared_ptr<persistence::interfaces::XSaveHandler> saveHandler) const ;
			virtual void saveContent(std::shared_ptr<persistence::interfaces::XSaveHandler> saveHandler) const;

		protected:
			virtual std::shared_ptr<ecore::EClass> eStaticClass() const;

			//*********************************
			// EStructuralFeature Get/Set/IsSet
			//*********************************
			virtual Any eGet(int featureID, bool resolve, bool coreType) const ;
			virtual bool eSet(int featureID, Any newValue) ;
			virtual bool internalEIsSet(int featureID) const ;

			//*********************************
			// EOperation Invoke
			//*********************************
			virtual Any eInvoke(int operationID, std::shared_ptr<std::list<Any>> arguments) ;

		private:
			std::weak_ptr<uml::StructuredClassifier> m_thisStructuredClassifierPtr;
	};
}
#endif /* end of include guard: UML_STRUCTUREDCLASSIFIERSTRUCTUREDCLASSIFIERIMPL_HPP */


text:
<?xml version="1.0" ?>
<!--
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.
-->
<Root>
  <TestCase name="testRemoveRedundantLocalHashAgg_ShuffleKeyFromJoin">
    <Resource name="sql">
      <![CDATA[
WITH r AS (SELECT * FROM x, y WHERE a = d AND c LIKE 'He%')
SELECT SUM(b) FROM r GROUP BY a
      ]]>
    </Resource>
    <Resource name="planBefore">
      <![CDATA[
LogicalProject(EXPR$0=[$1])
+- LogicalAggregate(group=[{0}], EXPR$0=[SUM($1)])
   +- LogicalProject(a=[$0], b=[$1])
      +- LogicalFilter(condition=[AND(=($0, $3), LIKE($2, _UTF-16LE'He%'))])
         +- LogicalJoin(condition=[true], joinType=[inner])
            :- LogicalTableScan(table=[[default_catalog, default_database, x, source: [TestTableSource(a, b, c)]]])
            +- LogicalTableScan(table=[[default_catalog, default_database, y, source: [TestTableSource(d, e, f)]]])
]]>
    </Resource>
    <Resource name="planAfter">
      <![CDATA[
Calc(select=[EXPR$0])
+- HashAggregate(isMerge=[false], groupBy=[a], select=[a, SUM(b) AS EXPR$0])
   +- Calc(select=[a, b])
      +- HashJoin(joinType=[InnerJoin], where=[=(a, d)], select=[a, b, d], build=[left])
         :- Exchange(distribution=[hash[a]])
         :  +- Calc(select=[a, b], where=[LIKE(c, _UTF-16LE'He%')])
         :     +- TableSourceScan(table=[[default_catalog, default_database, x, source: [TestTableSource(a, b, c)]]], fields=[a, b, c])
         +- Exchange(distribution=[hash[d]])
            +- Calc(select=[d])
               +- TableSourceScan(table=[[default_catalog, default_database, y, source: [TestTableSource(d, e, f)]]], fields=[d, e, f])
]]>
    </Resource>
  </TestCase>
  <TestCase name="testRemoveRedundantLocalHashAgg_ShuffleKeyFromRank">
    <Resource name="sql">
      <![CDATA[
SELECT a, SUM(b) FROM (
 SELECT * FROM (
   SELECT a, b, c, RANK() OVER (PARTITION BY a, c ORDER BY b) rk FROM x)
 WHERE rk <= 10
) GROUP BY a
      ]]>
    </Resource>
    <Resource name="planBefore">
      <![CDATA[
LogicalAggregate(group=[{0}], EXPR$1=[SUM($1)])
+- LogicalProject(a=[$0], b=[$1])
   +- LogicalFilter(condition=[<=($3, 10)])
      +- LogicalProject(a=[$0], b=[$1], c=[$2], rk=[RANK() OVER (PARTITION BY $0, $2 ORDER BY $1 NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)])
         +- LogicalTableScan(table=[[default_catalog, default_database, x, source: [TestTableSource(a, b, c)]]])
]]>
    </Resource>
    <Resource name="planAfter">
      <![CDATA[
HashAggregate(isMerge=[false], groupBy=[a], select=[a, SUM(b) AS EXPR$1])
+- Calc(select=[a, b])
   +- Rank(rankType=[RANK], rankRange=[rankStart=1, rankEnd=10], partitionBy=[a, c], orderBy=[b ASC], global=[true], select=[a, b, c])
      +- Sort(orderBy=[a ASC, c ASC, b ASC])
         +- Exchange(distribution=[hash[a]])
            +- Rank(rankType=[RANK], rankRange=[rankStart=1, rankEnd=10], partitionBy=[a, c], orderBy=[b ASC], global=[false], select=[a, b, c])
               +- Sort(orderBy=[a ASC, c ASC, b ASC])
                  +- TableSourceScan(table=[[default_catalog, default_database, x, source: [TestTableSource(a, b, c)]]], fields=[a, b, c])
]]>
    </Resource>
  </TestCase>
</Root>


text:
require "pathname"
require "active_support"
require "rails/command/helpers/editor"
require "rails/command/environment_argument"

module Rails
  module Command
    class CredentialsCommand < Rails::Command::Base # :nodoc:
      include Helpers::Editor
      include EnvironmentArgument

      require_relative "credentials_command/diffing"
      include Diffing

      self.environment_desc = "Uses credentials from config/credentials/:environment.yml.enc encrypted by config/credentials/:environment.key key"

      no_commands do
        def help
          say "Usage:\n  #{self.class.banner}"
          say ""
          say self.class.desc
        end
      end

      def edit
        extract_environment_option_from_argument(default_environment: nil)
        require_application!

        ensure_editor_available(command: "bin/rails credentials:edit") || (return)

        ensure_encryption_key_has_been_added if credentials.key.nil?
        ensure_credentials_have_been_added
        ensure_rails_credentials_driver_is_set

        catch_editing_exceptions do
          change_credentials_in_system_editor
        end

        say "File encrypted and saved."
      rescue ActiveSupport::MessageEncryptor::InvalidMessage
        say "Couldn't decrypt #{content_path}. Perhaps you passed the wrong key?"
      end

      def show
        extract_environment_option_from_argument(default_environment: nil)
        require_application!

        say credentials.read.presence || missing_credentials_message
      end

      option :enroll, type: :boolean, default: false,
        desc: "Enrolls project in credential file diffing with `git diff`"

      def diff(content_path = nil)
        if @content_path = content_path
          extract_environment_option_from_argument(default_environment: extract_environment_from_path(content_path))
          require_application!

          say credentials.read.presence || credentials.content_path.read
        else
          require_application!
          enroll_project_in_credentials_diffing if options[:enroll]
        end
      rescue ActiveSupport::MessageEncryptor::InvalidMessage
        say credentials.content_path.read
      end

      private
        def credentials
          Rails.application.encrypted(content_path, key_path: key_path)
        end

        def ensure_encryption_key_has_been_added
          encryption_key_file_generator.add_key_file(key_path)
          encryption_key_file_generator.ignore_key_file(key_path)
        end

        def ensure_credentials_have_been_added
          if options[:environment]
            encrypted_file_generator.add_encrypted_file_silently(content_path, key_path)
          else
            credentials_generator.add_credentials_file_silently
          end
        end

        def change_credentials_in_system_editor
          credentials.change do |tmp_path|
            system("#{ENV["EDITOR"]} #{tmp_path}")
          end
        end

        def missing_credentials_message
          if credentials.key.nil?
            "Missing '#{key_path}' to decrypt credentials. See `rails credentials:help`"
          else
            "File '#{content_path}' does not exist. Use `rails credentials:edit` to change that."
          end
        end

        def content_path
          @content_path ||= options[:environment] ? "config/credentials/#{options[:environment]}.yml.enc" : "config/credentials.yml.enc"
        end

        def key_path
          options[:environment] ? "config/credentials/#{options[:environment]}.key" : "config/master.key"
        end

        def extract_environment_from_path(path)
          available_environments.find { |env| path.include? env } if path.match?(/\.yml\.enc$/)
        end

        def encryption_key_file_generator
          require "rails/generators"
          require "rails/generators/rails/encryption_key_file/encryption_key_file_generator"

          Rails::Generators::EncryptionKeyFileGenerator.new
        end

        def encrypted_file_generator
          require "rails/generators"
          require "rails/generators/rails/encrypted_file/encrypted_file_generator"

          Rails::Generators::EncryptedFileGenerator.new
        end

        def credentials_generator
          require "rails/generators"
          require "rails/generators/rails/credentials/credentials_generator"

          Rails::Generators::CredentialsGenerator.new
        end
    end
  end
end


text:
<template name="frontpage">

    {{> masthead}}

    {{> about}}

</template>

<template name="masthead">

                    HipLearn

                    Learning has never been more  easy  or more  fun !

                Get started with HipLearn (or login)

</template>

<template name="about">

                    Why HipLearn?

                    HipLearn is designed for you, with the sole purpose of making your student life a little bit
                    easier.
                    As students ourselves, we often experience that we use a lot of time each day just to figure
                    what to read,
                    where to start, and how to get the best control of the curriculum. Sometimes you have read some
                    pages here, and a chapter
                    there, which makes you lose control of where in the book you should read this time. Our goal is
                    to help you reach you goals with HipLearn.
                    HipLearn makes your learning process a little easier.

                How does HipLearn work?

                HipLearn is an application designed to give you full control of exactly how much of your
                curriculum you have been through, so that you always know how to use your own time best
                possible.
                HipLearn gives you the opportunity to register your subjects, and then fetches the chapters in
                your book. When you have read a chapter or a subchapter of a book in a subject, you cross it of
                the list so that next time, you remember how far you got.

                Who are we?

                We are a team of engaged students of technology. From left: Ingeborg Lianes, Håkon Ringdal and
                Janne Nesse.
                As students, we know the challenges students usually encounter, and we try to use our technical
                competence
                to solve those problems. Many students have a lot to do, and it can be hard to keep track of
                everything during a
                hectic semester. We cannot solve everything for you, but we can make it easier for you to keep
                track of your studies.

"Because of HipLearn, I have saved many hours every week! Finally, I can keep track of
                        my study life in a tidy way."

                         -Ragnhild Frøhaug, m.sc
                        industrial engineering with data technology, NTNU

"HipLearn is both fun and educational! It keeps me motivated during the
                        semester."

                         - Øyvor Haldorsen, m.sc industrial
                        engineering with data technology, NTNU

</template>


text:
package xworker.app.view.extjs.xworker.thingEditor;

import org.xmeta.Action;
import org.xmeta.ActionContext;
import org.xmeta.Thing;
import org.xmeta.World;

import xworker.http.HttpRequestBean;

public class XWorker_ThingAddChildWindowActions {
    public static Object httpDo(ActionContext actionContext){
        //Thing self = actionContext.getObject("self");
        World world = World.getInstance();
        HttpRequestBean requestBean = actionContext.getObject("requestBean");

        //获取事物
        Thing thing = world.getThing((String) requestBean.get("thingPath"));

        actionContext.getScope(0).put("thing", thing);
        actionContext.getScope(0).put("descriptor", thing.getDescriptor());

        //执行RemoteWidget的方法
        Action action = world.getAction("xworker.html.extjs.xw.remote.RemoteWidget/@actions/@httpDo");

        return action.run(actionContext);
    }

}


text:
package example

object Hello extends App {
  println("Hello World")
  sys.props.get("java.runtime.version") foreach { version =>
    println(s"Java runtime version: $version")
  }
  println("Goodbye")
}


text:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:color="@color/colorPurple"
           />
    <size
        android:width="45dp"
        android:height="45dp"/>
</shape>


text:
package com.amazonaws.services.elasticloadbalancing.model;

import java.io.Serializable;

/**
 *
 */
public class DeregisterInstancesFromLoadBalancerResult implements Serializable, Cloneable {

    /**
     * The remaining instances registered with the load balancer.
     */
    private com.amazonaws.internal.ListWithAutoConstructFlag<Instance> instances;

    /**
     * The remaining instances registered with the load balancer.
     *
     * @return The remaining instances registered with the load balancer.
     */
    public java.util.List<Instance> getInstances() {
        if (instances == null) {
              instances = new com.amazonaws.internal.ListWithAutoConstructFlag<Instance>();
              instances.setAutoConstruct(true);
        }
        return instances;
    }

    /**
     * The remaining instances registered with the load balancer.
     *
     * @param instances The remaining instances registered with the load balancer.
     */
    public void setInstances(java.util.Collection<Instance> instances) {
        if (instances == null) {
            this.instances = null;
            return;
        }
        com.amazonaws.internal.ListWithAutoConstructFlag<Instance> instancesCopy = new com.amazonaws.internal.ListWithAutoConstructFlag<Instance>(instances.size());
        instancesCopy.addAll(instances);
        this.instances = instancesCopy;
    }

    /**
     * The remaining instances registered with the load balancer.
     *

     * NOTE: This method appends the values to the existing list (if
     * any). Use {@link #setInstances(java.util.Collection)} or {@link
     * #withInstances(java.util.Collection)} if you want to override the
     * existing values.
     *

     * Returns a reference to this object so that method calls can be chained together.
     *
     * @param instances The remaining instances registered with the load balancer.
     *
     * @return A reference to this updated object so that method calls can be chained
     *         together.
     */
    public DeregisterInstancesFromLoadBalancerResult withInstances(Instance... instances) {
        if (getInstances() == null) setInstances(new java.util.ArrayList<Instance>(instances.length));
        for (Instance value : instances) {
            getInstances().add(value);
        }
        return this;
    }

    /**
     * The remaining instances registered with the load balancer.
     *

     * Returns a reference to this object so that method calls can be chained together.
     *
     * @param instances The remaining instances registered with the load balancer.
     *
     * @return A reference to this updated object so that method calls can be chained
     *         together.
     */
    public DeregisterInstancesFromLoadBalancerResult withInstances(java.util.Collection<Instance> instances) {
        if (instances == null) {
            this.instances = null;
        } else {
            com.amazonaws.internal.ListWithAutoConstructFlag<Instance> instancesCopy = new com.amazonaws.internal.ListWithAutoConstructFlag<Instance>(instances.size());
            instancesCopy.addAll(instances);
            this.instances = instancesCopy;
        }

        return this;
    }

    /**
     * Returns a string representation of this object; useful for testing and
     * debugging.
     *
     * @return A string representation of this object.
     *
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        if (getInstances() != null) sb.append("Instances: " + getInstances() );
        sb.append("}");
        return sb.toString();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int hashCode = 1;

        hashCode = prime * hashCode + ((getInstances() == null) ? 0 : getInstances().hashCode());
        return hashCode;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;

        if (obj instanceof DeregisterInstancesFromLoadBalancerResult == false) return false;
        DeregisterInstancesFromLoadBalancerResult other = (DeregisterInstancesFromLoadBalancerResult)obj;

        if (other.getInstances() == null ^ this.getInstances() == null) return false;
        if (other.getInstances() != null && other.getInstances().equals(this.getInstances()) == false) return false;
        return true;
    }

    @Override
    public DeregisterInstancesFromLoadBalancerResult clone() {
        try {
            return (DeregisterInstancesFromLoadBalancerResult) super.clone();

        } catch (CloneNotSupportedException e) {
            throw new IllegalStateException(
                    "Got a CloneNotSupportedException from Object.clone() "
                    + "even though we're Cloneable!",
                    e);
        }

    }

}


text:
namespace caffe2 {
namespace {

REGISTER_CPU_OPERATOR(FunHash, FunHashOp<float, CPUContext>);
REGISTER_CPU_OPERATOR(FunHashGradient, FunHashGradientOp<float, CPUContext>);

OPERATOR_SCHEMA(FunHash)
    .NumInputs(4, 5)
    .NumOutputs(1)
    .SetDoc(R"DOC(
This layer compresses a fully-connected layer for sparse inputs
via hashing.
It takes four required inputs and an optional fifth input.
The first three inputs `scalars`, `indices`, and `segment_ids` are
the sparse segmented representation of sparse data, which are the
same as the last three inputs of the `SparseSortedSegmentWeightedSum`
operator. If the argument `num_segments` is specified, it would be used
as the first dimension for the output; otherwise it would be derived
from the maximum segment ID.

The fourth input is a 1D weight vector. Each entry of the fully-connected
layer would be randomly mapped from one of the entries in this vector.

When the optional fifth input vector is present, each weight of the
fully-connected layer would be the linear combination of K entries
randomly mapped from the weight vector, provided the input
(length-K vector) serves as the coefficients.
)DOC")
    .Input(0, "scalars", "Values of the non-zero entries of the sparse data.")
    .Input(1, "indices", "Indices to the non-zero valued features.")
    .Input(2, "segment_ids",
        "Segment IDs corresponding to the non-zero entries.")
    .Input(3, "weight", "Weight vector")
    .Input(4, "alpha",
        "Optional coefficients for linear combination of hashed weights.")
    .Output(0, "output",
        "Output tensor with the first dimension equal to the number "
        "of segments.")
    .Arg("num_outputs", "Number of outputs")
    .Arg("num_segments", "Number of segments");

OPERATOR_SCHEMA(FunHashGradient)
    .NumInputs(5, 6)
    .NumOutputs(1, 2);

class GetFunHashGradient : public GradientMakerBase {
  using GradientMakerBase::GradientMakerBase;
  vector<OperatorDef> GetGradientDefs() override {
    if (def_.input_size() == 4) {
      return SingleGradientDef(
          "FunHashGradient", "",
          vector<string>{GO(0), I(0), I(1), I(2), I(3)},
          vector<string>{GI(3)});
    }
    // def_.input_size() == 5
    return SingleGradientDef(
        "FunHashGradient", "",
        vector<string>{GO(0), I(0), I(1), I(2), I(3), I(4)},
        vector<string>{GI(3), GI(4)});
  }
};

REGISTER_GRADIENT(FunHash, GetFunHashGradient);

} // namespace
} // namespace caffe2


text:
/* ###
 * IP: GHIDRA
 *
 * 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 agent.gdb.manager.evt;

import agent.gdb.manager.breakpoint.GdbBreakpointInfo;
import agent.gdb.manager.impl.GdbManagerImpl;
import agent.gdb.manager.parsing.GdbParsingUtils.GdbParseError;

/**
 * The event corresponding with "{@code =breakpoint-created}"
 */
public class GdbBreakpointCreatedEvent extends AbstractGdbEventWithFields {
	private final GdbBreakpointInfo bkptInfo;

	/**
	 * Construct a new event by parsing the tail for information
	 *
	 * The breakpoint information must be specified by GDB.
	 *
	 * @param tail the text following the event type in the GDB/MI event record
	 * @throws GdbParseError if the tail cannot be parsed
	 */
	public GdbBreakpointCreatedEvent(CharSequence tail, GdbManagerImpl manager)
			throws GdbParseError {
		super(tail);
		this.bkptInfo = GdbBreakpointInfo.parse(getInfo(), manager.currentInferior().getId());
	}

	/**
	 * Get the breakpoint information
	 *
	 * @return the parsed, but not processed, breakpoint information
	 */
	public GdbBreakpointInfo getBreakpointInfo() {
		return bkptInfo;
	}
}


text:
/**
 *
 */
package de.evoila.cfmc.api.model;

import java.util.UUID;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
 * @author Johannes Hiemer.
 *
 */
public class Domain {

	@JsonProperty("name")
	private String name;

	@JsonProperty("owning_organization_guid")
	private UUID owningOrganizationGuid;

	@JsonProperty("owning_organization_url")
	private String owningOrganizationUrl;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public UUID getOwningOrganizationGuid() {
		return owningOrganizationGuid;
	}

	public void setOwningOrganizationGuid(UUID owningOrganizationGuid) {
		this.owningOrganizationGuid = owningOrganizationGuid;
	}

	public String getOwningOrganizationUrl() {
		return owningOrganizationUrl;
	}

	public void setOwningOrganizationUrl(String owningOrganizationUrl) {
		this.owningOrganizationUrl = owningOrganizationUrl;
	}

}


text:
package net.catchpole.web.site.pages;

//   Copyright 2014 catchpole.net
//
//   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.

import net.catchpole.web.site.model.Backing;
import net.catchpole.web.site.model.cart.Catalog;
import net.catchpole.web.site.model.cart.Item;

public class CatalogHandler implements PathHandler {
    public boolean handle(Backing backing, String[] path) {
        if (path.length < 3) {
            return false;
        }

        Catalog catalog = backing.getCatalog();
        if (catalog.getItems().containsKey(path[1])) {
            Item item = catalog.getSku(path[2]);
            if (item != null) {
                backing.setSelectedItem(item);
            }
        }
        return true;
    }
}


text:
using namespace std;

template <class generic>
class Priority_queue
{
  public:
    Priority_queue();
    ~Priority_queue();
    void push( generic x );
    void pop();
    generic & top();
    void clear();
    bool empty();
    unsigned int size();

  protected:
    void swap(Bsn<generic> * x, Bsn<generic> * y);

    void relocate_m_pop();

    void relocate_m_push();

  private:
    //Pointer to the root of the tree
    Bsn<generic> * m_root;

    //Pointer to where to next push onto the tree at
    Bsn<generic> * m_push;

    //Pointer to where to use when popping the tree
    Bsn<generic> * m_pop;

    //The size of the tree
    unsigned int m_size;
};

#include "priority_queue.hpp"
#endif


text:
#include <boost/python.hpp>

#include <CLucene.h>

#include "typeconversion.h"

using namespace boost::python;
using namespace lucene::queryParser;

/* CLucene provides a way to directly instantiate a QueryParser (and
   MultiQueryParser), but we only expose the static parse method
   provided by QueryParser. */

lucene::search::Query* queryparser_parse(wstring query, wstring field,
					 lucene::analysis::Analyzer *analyzer)
{
  std::auto_ptr<TCHAR> scoped_query(wstring_to_tchar(query));
  std::auto_ptr<TCHAR> scoped_field(wstring_to_tchar(field));

  return QueryParser::parse(scoped_query.get(),
			    scoped_field.get(),
			    analyzer);
}

void init_queryparser(){
  class_<QueryParser>("QueryParser",
		      no_init);
  def("parse", queryparser_parse,
      return_value_policy<manage_new_object>());
}


text:
title:  El Daniel actual
date:   09/04/2018
---

**Testimonio  >** Isaías 43:10

"Así como el Señor cooperó con Daniel y sus compañeros, cooperará con todos los que se esfuercen por hacer su voluntad. Mediante la impartición de su Espíritu fortalecerá todo propósito fiel, toda resolución noble. Los que anden en la senda de la obediencia encontrarán muchos obstáculos. Pueden ligarlos al mundo influencias poderosas y sutiles; pero el Señor puede inutilizar todo agente que obre para derrotar a sus escogidos. En su fuerza, pueden ellos vencer toda tentación y toda dificultad".1

"En la vida del verdadero cristiano no hay cosas que no sean esenciales; a la vista del Omnipotente, todo deber es importante. El Señor mide con exactitud toda posibilidad de servir. Las capacidades que no se usan se tienen en cuenta tanto como las que se usan. Seremos juzgados por lo que deberíamos haber hecho y no hicimos, porque no usamos nuestras facultades para glorificar a Dios.

"Un carácter noble no es el resultado de la casualidad; no se debe a favores o dones especiales de la Providencia. Es el resultado de la autodisciplina, de la sujeción de la naturaleza inferior a la superior, de la entrega del yo al servicio de Dios y de los hombres.

"Dios habla a los jóvenes de hoy por medio de la fidelidad que los jóvenes hebreos manifestaron hacia los principios de temperancia. Se necesitan hombres que, como Daniel, sean activos y audaces para la causa del bien. Se necesitan corazones puros, manos fuertes, valor intrépido; porque la guerra entre el vicio y la virtud exige una vigilancia incesante".2

"Los jóvenes de hoy pueden tener el espíritu que dominó a Daniel; pueden sacar fuerza de la misma fuente, poseer el mismo poder de dominio propio y revelar la misma gracia en su vida, aun en circunstancias tan desfavorables como las que predominaban entonces. Aunque rodeados por tentaciones a satisfacer sus apetitos, especialmente en nuestras grandes ciudades, donde resulta fácil y atrayente toda complacencia sensual, pueden permanecer por la gracia de Dios firmes en su propósito de honrar a Dios. Mediante una determinación enérgica y una vigilancia constante, pueden resistir toda tentación que asalte el alma. Pero solo podrá obtener la victoria el que resuelva hacer lo correcto porque es correcto".3

"Un estudio cuidadoso de cómo se cumple el propósito de Dios en la historia de las naciones y en la revelación de las cosas venideras nos ayudará a estimar en su verdadero valor las cosas que se ven y las que no se ven, y a comprender cuál es el verdadero objeto de la vida".4

1 Profetas y reyes,p.357.

2 Ibíd,p.358

3 Ibíd,p.360

4 Ibíd, p. 403.

**Para pensar y debatir**

`¿En qué situaciones tenemos que aplicar el ejemplo de Daniel, ya sea como iglesia o como individuos?`

_Rose Ndanu. Makueni, Kenia_


text:
require 'zlib'

module Flipper
  module Gates
    class PercentageOfActors < Gate
      # Internal: The name of the gate. Used for instrumentation, etc.
      def name
        :percentage_of_actors
      end

      # Internal: Name converted to value safe for adapter.
      def key
        :percentage_of_actors
      end

      def data_type
        :integer
      end

      def enabled?(value)
        value > 0
      end

      # Internal: Checks if the gate is open for a thing.
      #
      # Returns true if gate open for thing, false if not.
      def open?(context)
        percentage = context.values[key]

        if Types::Actor.wrappable?(context.thing)
          actor = Types::Actor.wrap(context.thing)
          id = "#{context.feature_name}#{actor.value}"
          # this is to support up to 3 decimal places in percentages
          scaling_factor = 1_000
          Zlib.crc32(id) % (100 * scaling_factor) < percentage * scaling_factor
        else
          false
        end
      end

      def protects?(thing)
        thing.is_a?(Types::PercentageOfActors)
      end
    end
  end
end


text:
The MAC-NET core of i.MX 6SoloX, in conjunction with a 10/100 MAC, implements layer 3 network acceleration functions. These functions are designed to accelerate the processing of various common networking protocols, such as IP, TCP, UDP, and ICMP, providing wire speed services to client applications.
A physical layer is implemented by KSZ8091RNA chip.

The KSZ8091RNA is a single-supply 10Base-T/100Base-TX Ethernet physical-layer transceiver for transmission and reception of data over standard CAT-5 unshielded twisted pair (UTP) cable.

### Reference
[Datasheet](http://www.micrel.com/_PDF/Ethernet/datasheets/KSZ8091RNA-RND.pdf)


text:
Ext.define('Ext.theme.touchsizing.grid.column.RowNumberer', {
    override: 'Ext.grid.column.RowNumberer',

    width: 50
});


text:
action :download do
  new_resource.assume_defaults!
  directory(::File.dirname(new_resource.release_file)) do
    mode        '0755'
    action      :create
    recursive   true
  end

  remote_file new_resource.release_file do
    source      new_resource.release_url
    mode        "0644"
    action      :create
    checksum    new_resource.checksum if new_resource.checksum
    not_if{     ::File.exists?(new_resource.release_file) }
  end
end

action :unpack do
  action_download
  directory(::File.dirname(new_resource.install_dir)) do
    mode      '0755'
    action    :create
    recursive true
  end

  bash "unpack #{new_resource.name} release" do
    user        new_resource.user
    cwd         ::File.dirname(new_resource.install_dir)
    code        new_resource.expand_cmd
    creates     new_resource.install_dir
    environment new_resource.environment
  end
end

action :configure do
  action_unpack

  link new_resource.home_dir do
    to          new_resource.install_dir
    action      :create
  end
end

action :build do
  action_configure
end

action :install do
  action_build
  action_install_binaries
end

action :build_with_ant do
  action_build
  bash "build #{new_resource.name} with ant" do
    user        new_resource.user
    cwd         new_resource.install_dir
    code        "ant"
    environment new_resource.environment
  end
end

action :configure_with_autoconf do
  action_configure
  bash "configure #{new_resource.name} with configure" do
    user        new_resource.user
    cwd         new_resource.install_dir
    code        "./configure #{new_resource.autoconf_opts.join(' ')}"
    environment new_resource.environment
    not_if{     ::File.exists?(::File.join(new_resource.install_dir, 'config.status')) }
  end
end

action :build_with_make do
  action_build
  bash "build #{new_resource.name} with make" do
    user        new_resource.user
    cwd         new_resource.install_dir
    code        "make"
    environment new_resource.environment
  end
end

action :install_binaries do
  new_resource.has_binaries.each do |bin|
    link ::File.join(new_resource.prefix_root, 'bin', ::File.basename(bin)) do
      to        ::File.join(new_resource.home_dir, bin)
      action    :create
    end
  end
end

action :install_python do
  action_install

  bash "install #{new_resource.name} with python" do
    code "python setup.py install"
    cwd           new_resource.install_dir
  end
end

action :install_with_make do
  action_build_with_make
  action_install
  bash "install #{new_resource.name} with make" do
    user        new_resource.user
    cwd         new_resource.install_dir
    code        "make install"
    environment new_resource.environment
  end
end


text:
libraryinit()

#include <roundrobin.h>

#include <service_common.h>

#include <srv_common.h>

//eg 60 60 60 DOS EMAILS.DAT
//means window of 60*60 seconds rolling every 60 seconds
//max events 60 and store in DOS EMAILS.DAT file so per installation
//could be DEFINITIONS EMAILS.ROUNDROBIN to be per database
// clang-format off
#define secsperperiod_      params.f(1)
#define periodsperwindow_   params.f(2)
#define maxeventsperwindow_ params.f(3)
#define roundrobinfilename_ params.f(4)
#define roundrobinkey_      params.f(5)
	// clang-format on

	var errormsg;

function main(in mode, in params, io result, io msg) {

	// output:
	// empty = ok
	// result
	// msg if any error

	result = "";
	msg	   = "";

	// roundrobin
	// minutes are the number of minutes since 1/1/1970 provided by date()/time()
	// field 1 = the last minute that was updated
	// field 2 = 60 multivalues for minutes of the hour

	if (mode == "TEST") {

		// here we have maximum of 6 events per last 6x6 seconds
		var params2 = "";
		params2(1)	= 6;
		params2(2)	= 6;
		params2(3)	= 6;
		params2(4)	= "DOS";
		params2(5)	= "TEST.DAT";
		// osremove params2<5>

		printl();
		while (true) {
			// /BREAK;
			if (not(not(esctoexit())))
				break;
			call ossleep(1000 * var(3).rnd());
			call roundrobin("ONEVENT", params2, result, errormsg);
		}  // loop;

	} else if (mode == "ONEVENT") {

		var voc;
		if (not(voc.open("VOC", ""))) {
			msg = "ROUNDROBIN: CANNOT OPEN VOC";
			return 0;
		}

		var roundrobinfile;
		if (not(roundrobinfile.open(roundrobinfilename_, ""))) {
			msg = "ROUNDROBIN: CANNOT OPEN " ^ roundrobinfilename_;
			return 0;
		}

		let roundrobinlock = "ROUNDROBIN*" ^ roundrobinfilename_ ^ "*" ^ roundrobinkey_;

		// try to lock for 9 seconds since other locks should be brief
		if (not(lockrecord("VOC", voc, roundrobinlock, "", 9))) {
			msg = "ROUNDROBIN: CANNOT LOCK VOC," ^ roundrobinlock;
			return 0;
		}

		// get the round robin data
		var roundrobin;
		if (not(roundrobin.read(roundrobinfile, roundrobinkey_))) {
			roundrobin = "";
		}
		if (roundrobin.contains(chr(0))) {
			roundrobin.converter(chr(0), "");
			//var(date() ^ FM ^ time()).oswrite("rrobin");
			if (not var(date() ^ FM ^ time()).oswrite("rrobin")) {
				loglasterror();
			}
		}

		// determine current and last timeperiod
		// currentperiodn=date()*24*secsperperiod+mod(time(),secsperperiod)
		let currentperiodn = ((date() * 24 * 60 * 60 + time()) / secsperperiod_).floor();
		var lastperiodn	   = roundrobin.f(1);

		// prevent catch up longer than periodsperwindow (add 2 for safety)
		if (currentperiodn - lastperiodn > periodsperwindow_ + 2) {
			lastperiodn = currentperiodn - periodsperwindow_ - 2;
		}

		// clear any skipped periods since last update
		// nb start from lastperiodn+1 to avoid clearing current period multiple times
		// ie clear only on the first time that we arrive in it
		for (const var periodn : range(lastperiodn + 1, currentperiodn)) {
			roundrobin(2, periodn.mod(periodsperwindow_) + 1) = "";
		}  // periodn;

		// record the current period as the last period so that in the next call
		// we can clear skipped periods (but not the current period again)
		roundrobin(1)	  = currentperiodn;
		let currentbreakn = currentperiodn.mod(periodsperwindow_) + 1;

		if (roundrobin.f(2).sum() < maxeventsperwindow_) {

			result = 1;

			// increment the current number of events in the current period
			roundrobin(2, currentbreakn) = roundrobin.f(2, currentbreakn) + 1;

		} else {
			result = 0;
		}

		if (roundrobin.contains(chr(0))) {
			roundrobin.converter(chr(0), "");
			//var(date() ^ FM ^ time()).oswrite("RRW");
			if (not var(date() ^ FM ^ time()).oswrite("RRW")) {
				loglasterror();
			}
		}
		roundrobin.write(roundrobinfile, roundrobinkey_);

		// for testing
		// print lastperiodn,currentperiodn,currentbreakn,result,roundrobin<2>

		call unlockrecord("VOC", voc, roundrobinlock);
	}

	return 0;
}

libraryexit()


text:
package com.github.steveash.bushwhacker.rules;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;

import com.github.steveash.bushwhacker.CompositeExceptionHandler;
import com.github.steveash.bushwhacker.RuleExceptionHandler;
import com.github.steveash.bushwhacker.exception.IllegalBushwhackerRulesException;

import org.apache.commons.lang3.BooleanUtils;

import static com.github.steveash.bushwhacker.rules.ActionMaker.makeAddHint;
import static com.github.steveash.bushwhacker.rules.ActionMaker.makeLog;
import static com.github.steveash.bushwhacker.rules.ActionMaker.makeReplace;
import static com.google.common.base.Functions.compose;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

/**
 * @author Steve Ash
 */
public class HandlerMaker {

  // translate the xml rules in to specific predicates to return RuleExceHandler
  public CompositeExceptionHandler buildHandlersFor(XmlRules rules) {
    ImmutableList.Builder<RuleExceptionHandler> builder = ImmutableList.builder();
    for (XmlRules.ExceptionRule rule : rules.getExceptionRules()) {
      builder.add(buildHandlerFor(rule));
    }
    return new CompositeExceptionHandler(builder.build());
  }

  public RuleExceptionHandler buildHandlerFor(XmlRules.ExceptionRule rule) {
    try {
      return new RuleExceptionHandler(makePredicate(rule), makeAction(rule));
    } catch (RuntimeException e) {
      throw new IllegalBushwhackerRulesException("Cannot build handler for bushwhacker rule " + rule, e);
    }
  }

  private Predicate<Throwable> makePredicate(XmlRules.ExceptionRule rule) {
    XmlRules.ExceptionMatch matches = rule.getMatches();
    ImmutableList.Builder<Predicate<Throwable>> builder = ImmutableList.builder();

    if (isNotBlank(matches.getCalledFrom())) {
      builder.add(PredicateMaker.makeCalledFrom(matches.getCalledFrom()));
    }
    if (isNotBlank(matches.getExceptionClass())) {
      builder.add(PredicateMaker.makeExceptionClass(matches.getExceptionClass()));
    }
    if (isNotBlank(matches.getMessageMatches())) {
      builder.add(PredicateMaker.makeMessageMatches(matches.getMessageMatches()));
    }
    if (isNotBlank(matches.getCustom())) {
      builder.add(PredicateMaker.makeCustom(matches.getCustom()));
    }
    if (isNotBlank(matches.getThrownFrom())) {
      builder.add(PredicateMaker.makeThrownFrom(matches.getThrownFrom()));
    }
    return Predicates.and(builder.build());
  }

  private Function<Throwable, ?> makeAction(XmlRules.ExceptionRule rule) {
    Function<Throwable,Throwable> result = Functions.identity();

    XmlRules.ExceptionAction action = rule.getAction();
    if (isNotBlank(action.getReplaceMessage())) {
      result = compose(makeReplace(action.getReplaceMessage()), result);
    }
    if (isNotBlank(action.getAddHint())) {
      result = compose(makeAddHint(action.getAddHint()), result);
    }
    if (BooleanUtils.isTrue(action.isWriteToLog())) {
      result = compose(makeLog(), result);
    }

    return result;
  }
}