nstream.adapter.common.relay.Directive Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nstream-adapter-common Show documentation
Show all versions of nstream-adapter-common Show documentation
General server-side data flow templates with Swim
// Copyright 2015-2024 Nstream, inc.
//
// Licensed under the Redis Source Available License 2.0 (RSALv2) Agreement;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://redis.com/legal/rsalv2-agreement/
//
// 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 nstream.adapter.common.relay;
import swim.api.agent.AgentContext;
import swim.structure.Item;
import swim.structure.Value;
import swim.util.Log;
/**
* An environment frame from an in-progress interpretation of a program written
* in the message relay domain-specific language (DSL).
* {@code Directive} evaluation may create "child" {@code Directives}
* or require state from "ancestor" frames.
*
*
Illustrative Example
*
* Consider the following DSL snippet:
*
* {@code
* {
* @command($code) {
* nodeUri: "/healthcheck",
* laneUri: "payloadStatusCode"
* },
* @foreach($rates.*) {
* @command {
* complexNodeUri: {
* "/currency/",
* @substring($*:){lower:3}
* },
* laneUri:"addEvent",
* value: $:*
* }
* }
* }
* }
*
* and the following top-level input (JSON):
*
* {@code
* {
* "code": 200,
* "rates": {
* "USDEUR": {
* "rate": 0.967715,
* "timestamp": 1660235884
* },
* "USDJPY": {
* "rate": 132.716501,
* "timestamp": 1660235884
* }
* }
* }
* }
*
* Evaluating the snippet against the input yields two top-level actions to
* evaluate sequentially:
*
* - Send a WARP command with {@code nodeUri="/healthcheck"}, {@code
* laneUri="payloadStatusCode", value=200}
*
- For each {@code Item} {@code rate} in {@code input.get("rates")}, send
* a WARP command with {@code nodeUri="/currency/"+rate.key().substring(3)},
* {@code laneUri="addEvent", value=rate.value()}
*
* These correspond the following directives:
*
* - A {@link Take} that trims {@code input} to {@code 200} before
* passing it to its child directive, which is a {@code Command}
*
- A {@code Take} that trims {@code input} to {@code input.get("rates")}
* before passing it to its child directive, which is a {@link ForEach} that
* passes on each of the two items in the aforementioned truncation to a
* different child directive, each of which is a {@link Command} whose {@code
* complexNodeUri} can only be evaluated with a {@link Substring}'s help
*
* for a total of 8 directives spawned.
*
* @param the possibly-Absent return type of {@code evaluate}-ing this {@code
* Directive}
*/
public abstract class Directive {
protected final Directive> parent;
protected final AgentContext context;
protected final Log log;
protected final Item scope;
public Directive(Directive> parent, AgentContext context, Log log, Item scope) {
this.parent = parent;
this.context = context;
this.log = log;
this.scope = scope;
}
/**
* Evaluates this {@code Directive} against {@link #scope}, possibly spawning
* and recursively evaluating more {@code Directives}.
*
* @return the result of evaluating this {@code Directive}
*/
public abstract T evaluate() throws InterpretException;
final String hintOrLiteralToString(Value hint, Value literal, String prefix) {
return hintOrLiteralToString(hint, literal, prefix, false);
}
final String hintOrLiteralToString(Value hint, Value literal, String prefix, boolean isFirst) {
if (isFirst) {
boolean didFindHint = false;
String result = "";
if (hint != null && !hint.isDefined()) {
didFindHint = true;
result += (prefix + "=" + hint);
}
result += (literal == null || !literal.isDefined() ? ""
: ((didFindHint ? ", " : "") + prefix + "Literal=" + literal));
return result;
} else {
return (hint != null && hint.isDefined() ? (", " + prefix + "=" + hint) : "")
+ (literal != null && literal.isDefined() ? (", " + prefix + "Literal=" + literal) : "");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy