Suggest optimization for apache camel cartridge code
06:17 15 Jan 2026
CartridgeException.java
package com.example.transformation.cartridge;

public class CartridgeException extends RuntimeException {
  public CartridgeException(String message) {
    super(message);
  }

  public CartridgeException(String message, Throwable cause) {
    super(message, cause);
  }
}

CartridgeYamlRouteRegistrar.java

package com.example.transformation.cartridge;

import java.io.InputStream;
import org.apache.camel.CamelContext;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.dsl.yaml.YamlRoutesBuilderLoader;
import org.apache.camel.support.ResourceHelper;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Component;

/**
 * Ensures cartridge YAML routes are loaded at runtime.
 *
 * We intentionally do not rely on Spring Boot property-based route discovery here,
 * because it's easy to misconfigure and then "direct:" endpoints won't exist.
 *
 * Plug-and-play rule remains:
 * - add `cartridges//-route.yaml` and `cartridges//-mapping.yaml`
 * - the route must start with `direct:`
 */
@Component
public class CartridgeYamlRouteRegistrar implements ApplicationRunner {
  private final CamelContext camelContext;

  public CartridgeYamlRouteRegistrar(CamelContext camelContext) {
    this.camelContext = camelContext;
  }

  @Override
  @SuppressWarnings("resource")
  public void run(ApplicationArguments args) throws Exception {
    Resource[] cartridgeResources = new PathMatchingResourcePatternResolver()
        .getResources("classpath*:cartridges/*/*-route.yaml");
    Resource[] sharedResources = new PathMatchingResourcePatternResolver()
        .getResources("classpath*:routes/*.yaml");

    if (cartridgeResources.length == 0 && sharedResources.length == 0) {
      return;
    }

    YamlRoutesBuilderLoader loader = new YamlRoutesBuilderLoader();
    loader.setCamelContext(camelContext);
    loader.start();
    try {
    for (Resource r : concat(sharedResources, cartridgeResources)) {
        try (InputStream is = r.getInputStream()) {
          byte[] bytes = is.readAllBytes();
          org.apache.camel.spi.Resource camelResource = ResourceHelper.fromBytes(r.getDescription(), bytes);
          RoutesBuilder rb = (RoutesBuilder) loader.loadRoutesBuilder(camelResource);
          camelContext.addRoutes(rb);
        }
      }
    } finally {
      loader.stop();
    }
  }

  private static Resource[] concat(Resource[] a, Resource[] b) {
    Resource[] out = new Resource[a.length + b.length];
    System.arraycopy(a, 0, out, 0, a.length);
    System.arraycopy(b, 0, out, a.length, b.length);
    return out;
  }
}
src/main/java/com/example/transformation/cartridge/JsonPathMini.java
package com.example.transformation.cartridge;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Minimal JSONPath-ish accessor with optimized path parsing.
 *
 * Supported:
 * - $.a.b.c (maps)
 * - $.a.0.b (lists by numeric segment)
 *
 * Not supported: filters, wildcards, predicates.
 *
 * Performance optimizations:
 * - Pre-parsed path segments are cached
 * - Integer indices are pre-parsed for list access
 * - No regex compilation at runtime
 */
public final class JsonPathMini {
  private JsonPathMini() {}

  // Cache for parsed JSONPath segments (source paths like $.a.b.c)
  private static final ConcurrentHashMap SOURCE_PATH_CACHE = new ConcurrentHashMap<>(64);
  
  // Cache for parsed dot-path segments (target paths like a.b.c)
  private static final ConcurrentHashMap TARGET_PATH_CACHE = new ConcurrentHashMap<>(64);

  /**
   * Pre-parsed path representation for fast traversal.
   */
  private static final class ParsedPath {
    final String[] segments;
    final int[] indices; // Pre-parsed integer indices, -1 if not numeric

    ParsedPath(String[] segments) {
      this.segments = segments;
      this.indices = new int[segments.length];
      for (int i = 0; i < segments.length; i++) {
        this.indices[i] = parseIndex(segments[i]);
      }
    }

    private static int parseIndex(String seg) {
      if (seg.isEmpty()) return -1;
      // Fast path: check if all chars are digits
      for (int i = 0; i < seg.length(); i++) {
        char c = seg.charAt(i);
        if (c < '0' || c > '9') return -1;
      }
      try {
        return Integer.parseInt(seg);
      } catch (NumberFormatException e) {
        return -1;
      }
    }
  }

  private static ParsedPath parsePath(String path) {
    return SOURCE_PATH_CACHE.computeIfAbsent(path, JsonPathMini::doParseSourcePath);
  }

  private static ParsedPath doParseSourcePath(String path) {
    if (path == null || path.isEmpty()) {
      return new ParsedPath(new String[0]);
    }
    String p = path.charAt(0) == ' ' ? path.trim() : path;
    if ("$".equals(p)) {
      return new ParsedPath(new String[0]);
    }
    if (p.length() < 3 || p.charAt(0) != '$' || p.charAt(1) != '.') {
      throw new IllegalArgumentException("Only paths starting with '$.' are supported. Got: " + path);
    }
    // Manual split for performance (avoids regex)
    return new ParsedPath(splitByDot(p, 2));
  }

  private static String[] parseTargetPath(String dotPath) {
    return TARGET_PATH_CACHE.computeIfAbsent(dotPath, JsonPathMini::doParseTargetPath);
  }

  private static String[] doParseTargetPath(String dotPath) {
    if (dotPath == null || dotPath.isEmpty()) {
      return new String[0];
    }
    return splitByDot(dotPath, 0);
  }

  /**
   * Split string by '.' starting from given offset. Avoids regex overhead.
   */
  private static String[] splitByDot(String s, int startOffset) {
    // Count dots first
    int dotCount = 0;
    for (int i = startOffset; i < s.length(); i++) {
      if (s.charAt(i) == '.') dotCount++;
    }
    
    String[] result = new String[dotCount + 1];
    int segStart = startOffset;
    int segIdx = 0;
    
    for (int i = startOffset; i < s.length(); i++) {
      if (s.charAt(i) == '.') {
        result[segIdx++] = s.substring(segStart, i);
        segStart = i + 1;
      }
    }
    result[segIdx] = s.substring(segStart);
    return result;
  }

  public static Object get(Object root, String path) {
    if (path == null || path.isEmpty()) {
      return null;
    }
    // Fast path for blank check without creating new string
    if (isBlank(path)) {
      return null;
    }
    
    ParsedPath parsed = parsePath(path);
    if (parsed.segments.length == 0) {
      return root;
    }
    
    Object cur = root;
    String[] segments = parsed.segments;
    int[] indices = parsed.indices;
    
    for (int i = 0; i < segments.length; i++) {
      if (cur == null) {
        return null;
      }
      if (cur instanceof Map m) {
        cur = m.get(segments[i]);
      } else if (cur instanceof List list) {
        int idx = indices[i];
        if (idx < 0) {
          // Not a valid index - try map lookup failed
          return null;
        }
        cur = (idx < list.size()) ? list.get(idx) : null;
      } else {
        return null;
      }
    }
    return cur;
  }

  @SuppressWarnings("unchecked")
  public static void put(Map root, String dotPath, Object value) {
    if (dotPath == null || dotPath.isEmpty()) {
      return;
    }
    
    String[] segments = parseTargetPath(dotPath);
    if (segments.length == 0) {
      return;
    }
    
    Map cur = root;
    int lastIdx = segments.length - 1;
    
    for (int i = 0; i < lastIdx; i++) {
      String seg = segments[i];
      Object existing = cur.get(seg);
      if (existing instanceof Map) {
        cur = (Map) existing;
      } else {
        Map next = new java.util.LinkedHashMap<>(4);
        cur.put(seg, next);
        cur = next;
      }
    }
    cur.put(segments[lastIdx], value);
  }

  private static boolean isBlank(String s) {
    for (int i = 0; i < s.length(); i++) {
      if (s.charAt(i) > ' ') return false;
    }
    return true;
  }
}

src/main/java/com/example/transformation/cartridge/MappingDefinition.java

package com.example.transformation.cartridge;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * YAML model for a cartridge mapping definition.
 *
 * Example:
 * cartridgeId: cjson-to-rest
 * output:
 *   type: json
 * validations:
 *   - path: $.msgId
 *     required: true
 * mappings:
 *   - source: $.msgId
 *     target: messageId
 */
public class MappingDefinition {
  public String cartridgeId;
  public Output output = new Output();
  public List validations = new ArrayList<>();
  public List mappings = new ArrayList<>();
  public Map metadata = new LinkedHashMap<>();

  public static class Output {
    /** json or xml */
    public String type = "json";
    /** Only used for xml. */
    public String root = "message";
  }

  public static class ValidationRule {
    /** JSONPath-like: $.a.b.c */
    public String path;
    public boolean required = false;
    /** Optional: if set, the field must equal this value (string compare). */
    public String equals;
    /** Optional: minimum string length (applied to String.valueOf(value)). */
    public Integer minLength;
    /** Optional: maximum string length (applied to String.valueOf(value)). */
    public Integer maxLength;
    /** Optional: regex pattern (Java Pattern). Applied to String.valueOf(value). */
    public String pattern;
    /** Optional: numeric minimum (applied if value is numeric or numeric string). */
    public Double min;
    /** Optional: numeric maximum (applied if value is numeric or numeric string). */
    public Double max;
  }

  public static class MappingRule {
    /** JSONPath-like: $.a.b.c */
    public String source;
    /** Output field path using dot-notation: a.b.c */
    public String target;
    /** If true and source missing/blank => fail. */
    public boolean required = false;
    /** Default string to use when source missing (and not required). */
    public String defaultValue;
  }
}

/Users/dtale/Documents/transformationlayer/src/main/java/com/example/transformation/cartridge/MappingEngine.java

package com.example.transformation.cartridge;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import org.springframework.stereotype.Component;

@Component
public class MappingEngine {
  private final XmlMapper xmlMapper = new XmlMapper();
  
  // Cache compiled regex patterns to avoid recompilation on every validation
  private static final ConcurrentHashMap PATTERN_CACHE = new ConcurrentHashMap<>(32);

  public Result transform(Object input, MappingDefinition def) {
    validate(input, def);
    
    // Pre-size map based on number of mappings for better performance
    Map out = new LinkedHashMap<>(Math.max(def.mappings.size(), 4));

    for (MappingDefinition.MappingRule rule : def.mappings) {
      Object v = JsonPathMini.get(input, rule.source);

      if (v == null || (v instanceof String s && s.isEmpty()) || (v instanceof String s2 && isBlank(s2))) {
        if (rule.required) {
          throw new CartridgeException("Required mapping source missing: " + rule.source + " -> " + rule.target);
        }
        if (rule.defaultValue != null) {
          v = rule.defaultValue;
        } else {
          continue;
        }
      }

      JsonPathMini.put(out, rule.target, v);
    }

    String type = (def.output != null && def.output.type != null) ? def.output.type : "json";
    if ("xml".equalsIgnoreCase(type)) {
      String root = (def.output.root != null && !def.output.root.isEmpty() && !isBlank(def.output.root)) 
          ? def.output.root : "message";
      try {
        String xml = xmlMapper.writer().withRootName(root).writeValueAsString(out);
        return Result.xml(xml);
      } catch (Exception e) {
        throw new CartridgeException("Failed to serialize XML output", e);
      }
    }

    return Result.json(out);
  }

  private void validate(Object input, MappingDefinition def) {
    if (def.validations == null || def.validations.isEmpty()) {
      return;
    }
    for (MappingDefinition.ValidationRule v : def.validations) {
      Object value = JsonPathMini.get(input, v.path);
      if (v.required) {
        if (value == null || (value instanceof String s && isBlank(s))) {
          throw new CartridgeException("Validation failed: required field missing at " + v.path);
        }
      }
      if (v.equals != null) {
        String actual = (value == null) ? null : String.valueOf(value);
        if (!v.equals.equals(actual)) {
          throw new CartridgeException("Validation failed: " + v.path + " must equal '" + v.equals + "' but was '" + actual + "'");
        }
      }

      if (value != null) {
        // String validations
        if (v.minLength != null || v.maxLength != null || v.pattern != null) {
          String s = String.valueOf(value);
          int len = s.length();
          if (v.minLength != null && len < v.minLength) {
            throw new CartridgeException("Validation failed: " + v.path + " length must be >= " + v.minLength);
          }
          if (v.maxLength != null && len > v.maxLength) {
            throw new CartridgeException("Validation failed: " + v.path + " length must be <= " + v.maxLength);
          }
          if (v.pattern != null) {
            Pattern p = getCompiledPattern(v.pattern);
            if (!p.matcher(s).matches()) {
              throw new CartridgeException("Validation failed: " + v.path + " must match pattern " + v.pattern);
            }
          }
        }

        // Numeric validations
        if (v.min != null || v.max != null) {
          Double n = toNumberOrNull(value);
          if (n == null) {
            throw new CartridgeException("Validation failed: " + v.path + " must be a number");
          }
          double nv = n; // Unbox once
          if (v.min != null && nv < v.min) {
            throw new CartridgeException("Validation failed: " + v.path + " must be >= " + v.min);
          }
          if (v.max != null && nv > v.max) {
            throw new CartridgeException("Validation failed: " + v.path + " must be <= " + v.max);
          }
        }
      }
    }
  }

  /**
   * Get cached compiled pattern, compiling only once per unique pattern string.
   */
  private static Pattern getCompiledPattern(String regex) {
    return PATTERN_CACHE.computeIfAbsent(regex, Pattern::compile);
  }

  private static Double toNumberOrNull(Object value) {
    if (value instanceof Number n) {
      return n.doubleValue();
    }
    if (value instanceof String s) {
      int len = s.length();
      if (len == 0) return null;
      
      // Fast trim check - avoid creating new string if not needed
      int start = 0;
      int end = len;
      while (start < end && s.charAt(start) <= ' ') start++;
      while (end > start && s.charAt(end - 1) <= ' ') end--;
      if (start == end) return null;
      
      String t = (start == 0 && end == len) ? s : s.substring(start, end);
      try {
        return Double.parseDouble(t);
      } catch (NumberFormatException ignored) {
        return null;
      }
    }
    return null;
  }

  /**
   * Fast blank check without creating new string objects.
   */
  private static boolean isBlank(String s) {
    for (int i = 0; i < s.length(); i++) {
      if (s.charAt(i) > ' ') return false;
    }
    return true;
  }

  public record Result(String contentType, Object body) {
    public static Result json(Object body) {
      return new Result("application/json", body);
    }

    public static Result xml(String xml) {
      return new Result("application/xml", xml);
    }
  }
}

/Users/dtale/Documents/transformationlayer/src/main/java/com/example/transformation/cartridge/MappingLoader.java

package com.example.transformation.cartridge;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;

@Component
public class MappingLoader {
  private final ResourceLoader resourceLoader;
  private final Yaml yaml;
  private final ConcurrentMap cache = new ConcurrentHashMap<>();

  public MappingLoader(ResourceLoader resourceLoader) {
    this.resourceLoader = resourceLoader;
    LoaderOptions options = new LoaderOptions();
    options.setAllowDuplicateKeys(false);
    this.yaml = new Yaml(new Constructor(MappingDefinition.class, options));
  }

  public MappingDefinition load(String mappingResourcePath) {
    return cache.computeIfAbsent(mappingResourcePath, this::readYaml);
  }

  private MappingDefinition readYaml(String mappingResourcePath) {
    Resource resource = resourceLoader.getResource(mappingResourcePath);
    if (!resource.exists()) {
      throw new CartridgeException("Mapping YAML not found: " + mappingResourcePath);
    }
    try (InputStream is = resource.getInputStream()) {
      MappingDefinition def = yaml.loadAs(new String(is.readAllBytes(), StandardCharsets.UTF_8), MappingDefinition.class);
      if (def == null) {
        throw new CartridgeException("Empty mapping YAML: " + mappingResourcePath);
      }
      return def;
    } catch (Exception e) {
      throw new CartridgeException("Failed to read mapping YAML: " + mappingResourcePath, e);
    }
  }
}

spring-boot apache-camel