+ return inference instanceof DefaultSchemaTreeInference ? ofInference((DefaultSchemaTreeInference) inference)
+ : of(inference.getEffectiveModelContext(), inference.toSchemaNodeIdentifier());
+ }
+
+ /**
+ * Create a new stack from an {@link DefaultSchemaTreeInference}. The argument is nominally trusted to be an
+ * accurate representation of the schema tree.
+ *
+ * <p>
+ * Run-time verification of {@code inference} can be enabled by setting the
+ * {@value #VERIFY_DEFAULT_SCHEMA_TREE_INFERENCE_PROP} system property to {@code true}.
+ *
+ * @param inference DefaultSchemaTreeInference to use for initialization
+ * @return A new stack
+ * @throws NullPointerException if {@code inference} is null
+ * @throws IllegalArgumentException if {@code inference} refers to a missing module or when verification is enabled
+ * and it does not match its context's scheam tree
+ */
+ public static @NonNull SchemaInferenceStack ofInference(final DefaultSchemaTreeInference inference) {
+ return VERIFY_DEFAULT_SCHEMA_TREE_INFERENCE ? ofUntrusted(inference) : ofTrusted(inference);
+ }
+
+ private static @NonNull SchemaInferenceStack ofTrusted(final DefaultSchemaTreeInference inference) {
+ final var path = inference.statementPath();
+ final var ret = new SchemaInferenceStack(inference.getEffectiveModelContext(), path.size());
+ ret.currentModule = ret.getModule(path.get(0).argument());
+ ret.deque.addAll(path);
+ return ret;
+ }
+
+ @VisibleForTesting
+ static @NonNull SchemaInferenceStack ofUntrusted(final DefaultSchemaTreeInference inference) {
+ final var ret = of(inference.getEffectiveModelContext(), inference.toSchemaNodeIdentifier());
+ if (!Iterables.elementsEqual(ret.deque, inference.statementPath())) {
+ throw new IllegalArgumentException("Provided " + inference + " is not consistent with resolved path "
+ + ret.toSchemaTreeInference());
+ }
+ return ret;