static IntermediateOperation mapOperation(String opType,
                                              List<IntermediateOperation> inputs,
                                              String modelName,
                                              String nodeName,
                                              AttributeConverter attributes,
                                              int outputIndex) {
        switch (opType.toLowerCase()) {
            case "abs":         return new Map(modelName, nodeName, inputs, ScalarFunctions.abs());
            case "acos":        return new Map(modelName, nodeName, inputs, ScalarFunctions.acos());
            case "add":         return new Join(modelName, nodeName, inputs, ScalarFunctions.add());
            case "asin":        return new Map(modelName, nodeName, inputs, ScalarFunctions.asin());
            case "atan":        return new Map(modelName, nodeName, inputs, ScalarFunctions.atan());
            case "cast":        return new OnnxCast(modelName, nodeName, inputs, attributes);
            case "ceil":        return new Map(modelName, nodeName, inputs, ScalarFunctions.ceil());
            case "concat":      return new OnnxConcat(modelName, nodeName, inputs, attributes);
            case "constant":    return new OnnxConstant(modelName, nodeName, inputs, attributes);
            case "constantofshape": return new ConstantOfShape(modelName, nodeName, inputs, attributes);
            case "cos":         return new Map(modelName, nodeName, inputs, ScalarFunctions.cos());
            case "div":         return new Join(modelName, nodeName, inputs, ScalarFunctions.divide());
            case "elu":         return new Map(modelName, nodeName, inputs, ScalarFunctions.elu(attributes.get("alpha").orElse(eluAlpha).asDouble()));
            case "erf":         return new Map(modelName, nodeName, inputs, ScalarFunctions.erf());
            case "equal":       return new Join(modelName, nodeName, inputs, ScalarFunctions.equal());
            case "exp":         return new Map(modelName, nodeName, inputs, ScalarFunctions.exp());
            case "expand":      return new Expand(modelName, nodeName, inputs);
            case "floor":       return new Map(modelName, nodeName, inputs, ScalarFunctions.floor());
            case "gather":      return new Gather(modelName, nodeName, inputs, attributes);
            case "gemm":        return new Gemm(modelName, nodeName, inputs, attributes);
            case "greater":     return new Join(modelName, nodeName, inputs, ScalarFunctions.greater());
            case "identity":    return new Identity(modelName, nodeName, inputs);
            case "less":        return new Join(modelName, nodeName, inputs, ScalarFunctions.less());
            case "log":         return new Map(modelName, nodeName, inputs, ScalarFunctions.log());
            case "matmul":      return new MatMul(modelName, nodeName, inputs);
            case "max":         return new ConcatReduce(modelName, nodeName, inputs, com.yahoo.tensor.functions.Reduce.Aggregator.max);
            case "min":         return new ConcatReduce(modelName, nodeName, inputs, com.yahoo.tensor.functions.Reduce.Aggregator.min);
            case "mean":        return new ConcatReduce(modelName, nodeName, inputs, com.yahoo.tensor.functions.Reduce.Aggregator.avg);
            case "mul":         return new Join(modelName, nodeName, inputs, ScalarFunctions.multiply());
            case "neg":         return new Map(modelName, nodeName, inputs, ScalarFunctions.neg());
            case "pow":         return new Join(modelName, nodeName, inputs, ScalarFunctions.pow());
            case "range":       return new Range(modelName, nodeName, inputs);
            case "reshape":     return new Reshape(modelName, nodeName, inputs, attributes);
            case "reducel1":    return new Reduce(modelName, nodeName, inputs, attributes, com.yahoo.tensor.functions.Reduce.Aggregator.sum, ScalarFunctions.abs(), null);
            case "reducel2":    return new Reduce(modelName, nodeName, inputs, attributes, com.yahoo.tensor.functions.Reduce.Aggregator.sum, ScalarFunctions.square(), ScalarFunctions.sqrt());
            case "reducelogsum":return new Reduce(modelName, nodeName, inputs, attributes, com.yahoo.tensor.functions.Reduce.Aggregator.sum, null, ScalarFunctions.log());
            case "reducelogsumexp": return new Reduce(modelName, nodeName, inputs, attributes, com.yahoo.tensor.functions.Reduce.Aggregator.sum, ScalarFunctions.exp(), ScalarFunctions.log());
            case "reducemax":   return new Reduce(modelName, nodeName, inputs, attributes, com.yahoo.tensor.functions.Reduce.Aggregator.max);
            case "reducemean":  return new Reduce(modelName, nodeName, inputs, attributes, com.yahoo.tensor.functions.Reduce.Aggregator.avg);
            case "reducemin":   return new Reduce(modelName, nodeName, inputs, attributes, com.yahoo.tensor.functions.Reduce.Aggregator.min);
            case "reduceprod":  return new Reduce(modelName, nodeName, inputs, attributes, com.yahoo.tensor.functions.Reduce.Aggregator.prod);
            case "reducesum":   return new Reduce(modelName, nodeName, inputs, attributes, com.yahoo.tensor.functions.Reduce.Aggregator.sum);
            case "reducesumsquare": return new Reduce(modelName, nodeName, inputs, attributes, com.yahoo.tensor.functions.Reduce.Aggregator.sum, ScalarFunctions.square(), null);
            case "reciprocal":  return new Map(modelName, nodeName, inputs, ScalarFunctions.reciprocal());
            case "relu":        return new Map(modelName, nodeName, inputs, ScalarFunctions.relu());
            case "selu":        return new Map(modelName, nodeName, inputs, ScalarFunctions.selu(attributes.get("gamma").orElse(seluGamma).asDouble(), attributes.get("alpha").orElse(seluAlpha).asDouble()));
            case "leakyrelu":   return new Map(modelName, nodeName, inputs, ScalarFunctions.leakyrelu(attributes.get("alpha").orElse(leakyReluAlpha).asDouble()));
            case "shape":       return new Shape(modelName, nodeName, inputs);
            case "sigmoid":     return new Map(modelName, nodeName, inputs, ScalarFunctions.sigmoid());
            case "sin":         return new Map(modelName, nodeName, inputs, ScalarFunctions.sin());
            case "slice":       return new Slice(modelName, nodeName, inputs, attributes);
            case "softmax":     return new Softmax(modelName, nodeName, inputs, attributes);
            case "sub":         return new Join(modelName, nodeName, inputs, ScalarFunctions.subtract());
            case "split":       return new Split(modelName, nodeName, inputs, attributes, outputIndex);
            case "squeeze":     return new Squeeze(modelName, nodeName, inputs, attributes);
            case "sqrt":        return new Map(modelName, nodeName, inputs, ScalarFunctions.sqrt());
            case "square":      return new Map(modelName, nodeName, inputs, ScalarFunctions.square());
            case "where":       return new Select(modelName, nodeName, inputs);
            case "tan":         return new Map(modelName, nodeName, inputs, ScalarFunctions.tan());
            case "tanh":        return new Map(modelName, nodeName, inputs, ScalarFunctions.tanh());
            case "tile":        return new Tile(modelName, nodeName, inputs);
            case "transpose":   return new Transpose(modelName, nodeName, inputs, attributes);
            case "unsqueeze":   return new Unsqueeze(modelName, nodeName, inputs, attributes);
        }

        IntermediateOperation op = new NoOp(modelName, nodeName, inputs);
        op.warning("Operation '" + opType + "' is currently not implemented");
        return op;
    }
Converts an ONNX graph to a Vespa IntermediateGraph which is the basis
for generating Vespa ranking expressions.

@author lesters
model-integration/src/main/java/ai/vespa/rankingexpression/importer/onnx/GraphImporter.java