All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.opentelemetry.javaagent.tooling.util.TrieImpl Maven / Gradle / Ivy

There is a newer version: 2.12.0-alpha
Show newest version
/*
 * Copyright The OpenTelemetry Authors
 * SPDX-License-Identifier: Apache-2.0
 */

package io.opentelemetry.javaagent.tooling.util;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.annotation.Nullable;

final class TrieImpl implements Trie {

  private final Node root;

  private TrieImpl(Node root) {
    this.root = root;
  }

  @Override
  public V getOrDefault(CharSequence str, V defaultValue) {
    Node node = root;
    V lastMatchedValue = defaultValue;

    for (int i = 0; i < str.length(); ++i) {
      char c = str.charAt(i);
      Node next = node.getNext(c);
      if (next == null) {
        return lastMatchedValue;
      }
      node = next;
      // next node matched, use its value if it's defined
      lastMatchedValue = next.value != null ? next.value : lastMatchedValue;
    }

    return lastMatchedValue;
  }

  static final class Node {
    final char[] chars;
    final Node[] children;
    final V value;

    Node(char[] chars, Node[] children, V value) {
      this.chars = chars;
      this.children = children;
      this.value = value;
    }

    @Nullable
    Node getNext(char c) {
      int index = Arrays.binarySearch(chars, c);
      if (index < 0) {
        return null;
      }
      return children[index];
    }
  }

  static final class BuilderImpl implements Builder {

    private final NodeBuilder root = new NodeBuilder<>();

    @Override
    @CanIgnoreReturnValue
    public Builder put(CharSequence str, V value) {
      put(root, str, 0, value);
      return this;
    }

    private void put(NodeBuilder node, CharSequence str, int i, V value) {
      if (str.length() == i) {
        node.value = value;
        return;
      }
      char c = str.charAt(i);
      NodeBuilder next = node.children.computeIfAbsent(c, k -> new NodeBuilder<>());
      put(next, str, i + 1, value);
    }

    @Override
    public Trie build() {
      return new TrieImpl<>(root.build());
    }
  }

  static final class NodeBuilder {
    final Map> children = new HashMap<>();
    V value;

    Node build() {
      int size = children.size();
      char[] chars = new char[size];
      @SuppressWarnings({"unchecked", "rawtypes"})
      Node[] nodes = new Node[size];

      int i = 0;
      Iterator>> it =
          this.children.entrySet().stream().sorted(Map.Entry.comparingByKey()).iterator();
      while (it.hasNext()) {
        Map.Entry> e = it.next();
        chars[i] = e.getKey();
        nodes[i++] = e.getValue().build();
      }

      return new Node<>(chars, nodes, value);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy