diff --git a/pom.xml b/pom.xml
index 96a649a5120..70f7b7f56c1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,6 +61,8 @@
cannot share a single property. -->
2.22.42.22
+
+ 2.2.3033.7.2-jre3.1.8
@@ -1989,6 +1991,13 @@
jackson-annotations${jackson2.annotations.version}
+
+
+
+ io.swagger.core.v3
+ swagger-annotations-jakarta
+ ${swagger.version}
+ com.fasterxml.jackson.datatype
diff --git a/src/prerna/openapi/Internal.java b/src/prerna/openapi/Internal.java
new file mode 100644
index 00000000000..1d9d6b7dd5f
--- /dev/null
+++ b/src/prerna/openapi/Internal.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
+package prerna.openapi;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a REST operation or a reactor as internal: it is published in the
+ * OpenAPI document as {@code "x-internal": true}, and every SDK generated from
+ * the document tags it so its users know not to rely on it. It still works for
+ * everyone; this is a warning, not access control.
+ *
+ * Put it on a resource method, on a resource class (every operation in it), or on
+ * a reactor class. To leave something out of the document and
+ * the SDKs entirely, use swagger-core's {@code @Hidden} instead.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE, ElementType.METHOD })
+public @interface Internal {
+
+ /**
+ * Why it is internal, such as "Used by the admin console only". It is shown to
+ * SDK users next to the internal tag.
+ */
+ String value() default "";
+}
diff --git a/src/prerna/openapi/PixelInput.java b/src/prerna/openapi/PixelInput.java
new file mode 100644
index 00000000000..8788d804c03
--- /dev/null
+++ b/src/prerna/openapi/PixelInput.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
+package prerna.openapi;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Refines what is inferred for one of a reactor's inputs. Every input in
+ * {@code keysToGet} is published without it; use it where the inferred type,
+ * description or requiredness is not good enough.
+ *
+ *
{@code
+ * @PixelInput(name = "value", type = Object.class)
+ * @PixelInput(name = "limit", type = Integer.class, required = Requirement.OPTIONAL)
+ * public class EchoReactor extends AbstractReactor {
+ * }
+ *
+ * Naming a key the reactor does not declare fails the OpenAPI export.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Repeatable(PixelInputs.class)
+public @interface PixelInput {
+
+ /** Whether an input must be passed. */
+ enum Requirement {
+ /** As {@code keyRequired} says. */
+ INFERRED,
+ /** It must be passed. */
+ REQUIRED,
+ /** It may be left out. */
+ OPTIONAL
+ }
+
+ /** The input's key, as in {@code keysToGet} (the canonical name, before any alias). */
+ String name();
+
+ /**
+ * Its type: {@code String}, {@code Integer}, {@code Long}, {@code Double},
+ * {@code Boolean}, an enum, {@code Map}, {@code List} (with {@link #items()}),
+ * or {@code Object} for any value. {@code Void}, the default, keeps the
+ * type inferred from {@code getKeyTypeForMCP}.
+ */
+ Class> type() default Void.class;
+
+ /** The element type when {@link #type()} is {@code List}. */
+ Class> items() default Void.class;
+
+ /** Its description. Empty, the default, keeps {@code getDescriptionForKey}. */
+ String description() default "";
+
+ /** Whether it must be passed. {@code INFERRED}, the default, follows {@code keyRequired}. */
+ Requirement required() default Requirement.INFERRED;
+}
diff --git a/src/prerna/openapi/PixelInputs.java b/src/prerna/openapi/PixelInputs.java
new file mode 100644
index 00000000000..464031c6ac5
--- /dev/null
+++ b/src/prerna/openapi/PixelInputs.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
+package prerna.openapi;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Holds repeated {@link PixelInput} annotations. */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface PixelInputs {
+ PixelInput[] value();
+}
diff --git a/src/prerna/openapi/PixelOutput.java b/src/prerna/openapi/PixelOutput.java
new file mode 100644
index 00000000000..a3b63764ade
--- /dev/null
+++ b/src/prerna/openapi/PixelOutput.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
+package prerna.openapi;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Declares what a reactor returns, so the SDKs can type its output. Without it
+ * the output is published as any value: a reactor's code does not say what it
+ * returns, so it cannot be inferred.
+ *
+ *
{@code
+ * @PixelOutput(value = String.class, description = "The id of the current insight")
+ * public class GetCurrentInsightIdReactor extends AbstractReactor {
+ * }
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface PixelOutput {
+
+ /**
+ * The type of the output: {@code String}, {@code Integer}, {@code Long},
+ * {@code Double}, {@code Boolean}, an enum, {@code Map}, {@code List} (with
+ * {@link #items()}), a record, or {@code Object} for any value.
+ */
+ Class> value();
+
+ /** The element type when {@link #value()} is {@code List}. */
+ Class> items() default Void.class;
+
+ /** What the output is. */
+ String description() default "";
+}
diff --git a/src/prerna/reactor/EchoReactor.java b/src/prerna/reactor/EchoReactor.java
index ef0d35fa01f..3a57ce4be4a 100644
--- a/src/prerna/reactor/EchoReactor.java
+++ b/src/prerna/reactor/EchoReactor.java
@@ -27,11 +27,13 @@
*******************************************************************************/
package prerna.reactor;
+import prerna.openapi.PixelInput;
import prerna.sablecc2.om.GenRowStruct;
import prerna.sablecc2.om.PixelDataType;
import prerna.sablecc2.om.ReactorKeysEnum;
import prerna.sablecc2.om.nounmeta.NounMetadata;
+@PixelInput(name = "value", type = Object.class)
public class EchoReactor extends AbstractReactor {
public EchoReactor() {
diff --git a/src/prerna/reactor/ReactorContract.java b/src/prerna/reactor/ReactorContract.java
new file mode 100644
index 00000000000..59718f9ef35
--- /dev/null
+++ b/src/prerna/reactor/ReactorContract.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
+package prerna.reactor;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import prerna.openapi.Internal;
+import prerna.openapi.PixelInput;
+import prerna.openapi.PixelOutput;
+
+/**
+ * What a reactor declares about itself, read for the OpenAPI document the SDKs
+ * are generated from.
+ *
+ * Everything is inferred from what reactors already declare, so no reactor has
+ * to change to be published:
+ *
+ *
inputs from {@code keysToGet} (the canonical name before any alias);
+ *
requiredness from {@code keyRequired}: with none, nothing is required,
+ * the way {@code organizeKeys()} checks at runtime;
+ *
input types from {@code getKeyTypeForMCP};
+ *
descriptions from {@code getDescriptionForKey} and
+ * {@code getReactorDescription}.
+ *
+ * {@link PixelInput} refines one input and {@link PixelOutput} declares the
+ * output, which cannot be inferred. Reading a contract constructs the reactor,
+ * since its constructor sets {@code keysToGet}; it never runs it.
+ *
+ * @param name the name it is called by in Pixel
+ * @param description its description, or a placeholder
+ * @param descriptionInferred whether the description is a placeholder
+ * @param inputs its inputs, in {@code keysToGet} order
+ * @param output its declared output, or null when undeclared
+ * @param internal its {@link Internal}, or null
+ */
+public record ReactorContract(String name, String description, boolean descriptionInferred, List inputs,
+ Output output, Internal internal) {
+
+ /**
+ * One input.
+ *
+ * @param type {@code String}, {@code Integer}, {@code Double},
+ * {@code Boolean}, {@code List}, {@code Map}, an enum, or
+ * {@code Object} for any value
+ * @param items the element type of a {@code List}, or {@code Void}
+ * @param typeInferred whether the type came from {@code getKeyTypeForMCP}
+ * rather than a {@link PixelInput}
+ */
+ public record Input(String name, Class> type, Class> items, String description, boolean required,
+ boolean typeInferred, boolean descriptionInferred) {
+ }
+
+ /** A declared output, from {@link PixelOutput}. */
+ public record Output(Class> type, Class> items, String description) {
+ }
+
+ /** Whether anything in the contract is inferred rather than declared. */
+ public boolean inferred() {
+ return this.descriptionInferred || this.output == null
+ || this.inputs.stream().anyMatch(i -> i.typeInferred() || i.descriptionInferred());
+ }
+
+ /** The name a reactor class is called by in Pixel. */
+ public static String pixelName(Class> reactorClass) {
+ return ReactorNames.pixelName(reactorClass.getSimpleName());
+ }
+
+ /** Whether a reactor class is a general one rather than specific to one frame type. */
+ public static boolean isGeneral(Class> reactorClass) {
+ return ReactorNames.frameType(reactorClass.getPackageName()) == null;
+ }
+
+ /**
+ * Reads a reactor's contract.
+ *
+ * @throws ReflectiveOperationException when the reactor cannot be constructed
+ * @throws IllegalArgumentException when it is not an {@code AbstractReactor},
+ * or declares a key twice
+ * @throws IllegalStateException when a {@link PixelInput} names a key
+ * the reactor does not declare
+ */
+ public static ReactorContract of(Class> reactorClass) throws ReflectiveOperationException {
+ if (!AbstractReactor.class.isAssignableFrom(reactorClass)) {
+ throw new IllegalArgumentException(reactorClass.getName() + " is not an AbstractReactor");
+ }
+ AbstractReactor reactor = (AbstractReactor) reactorClass.getDeclaredConstructor().newInstance();
+ String name = pixelName(reactorClass);
+
+ Map overrides = new LinkedHashMap<>();
+ for (PixelInput input : reactorClass.getAnnotationsByType(PixelInput.class)) {
+ overrides.put(input.name(), input);
+ }
+
+ List inputs = new ArrayList<>();
+ Set seen = new LinkedHashSet<>();
+ String[] keys = reactor.keysToGet == null ? new String[0] : reactor.keysToGet;
+ for (int i = 0; i < keys.length; i++) {
+ String key = keys[i] == null ? "" : keys[i].split(",", -1)[0].trim();
+ if (key.isEmpty()) {
+ throw new IllegalArgumentException(name + " has an empty key at position " + i + " of keysToGet");
+ }
+ if (!seen.add(key)) {
+ throw new IllegalArgumentException(name + " declares the key \"" + key + "\" twice");
+ }
+ boolean required = reactor.keyRequired != null && i < reactor.keyRequired.length
+ && reactor.keyRequired[i] == 1;
+
+ Class> type = typeOf(reactor.getKeyTypeForMCP(key));
+ Class> items = Void.class;
+ boolean typeInferred = true;
+ String description = reactor.getDescriptionForKey(key);
+ boolean descriptionInferred = description == null || description.isBlank();
+ if (descriptionInferred) {
+ description = "The " + key + " input";
+ }
+
+ PixelInput override = overrides.remove(key);
+ if (override != null) {
+ if (override.type() != Void.class) {
+ type = override.type();
+ items = override.items();
+ typeInferred = false;
+ }
+ if (!override.description().isBlank()) {
+ description = override.description();
+ descriptionInferred = false;
+ }
+ if (override.required() == PixelInput.Requirement.REQUIRED) {
+ required = true;
+ } else if (override.required() == PixelInput.Requirement.OPTIONAL) {
+ required = false;
+ }
+ }
+ inputs.add(new Input(key, type, items, description, required, typeInferred, descriptionInferred));
+ }
+ if (!overrides.isEmpty()) {
+ throw new IllegalStateException(reactorClass.getName() + " has @PixelInput for " + overrides.keySet()
+ + ", which are not in its keysToGet");
+ }
+
+ String description = reactor.getReactorDescription();
+ boolean descriptionInferred = description == null || description.isBlank();
+ if (descriptionInferred) {
+ description = name + " reactor";
+ }
+
+ PixelOutput declared = reactorClass.getAnnotation(PixelOutput.class);
+ Output output = declared == null ? null
+ : new Output(declared.value(), declared.items(), declared.description());
+
+ return new ReactorContract(name, description, descriptionInferred, List.copyOf(inputs), output,
+ reactorClass.getAnnotation(Internal.class));
+ }
+
+ /** Maps the type a reactor reports for MCP to a Java type. */
+ private static Class> typeOf(IReactor.MCP_KEY_TYPE type) {
+ if (type == null) {
+ return String.class;
+ }
+ return switch (type) {
+ case INTEGER -> Integer.class;
+ case NUMBER -> Double.class;
+ case BOOLEAN -> Boolean.class;
+ case ARRAY -> List.class;
+ case OBJECT -> Map.class;
+ default -> String.class;
+ };
+ }
+}
diff --git a/src/prerna/reactor/ReactorFactory.java b/src/prerna/reactor/ReactorFactory.java
index 13fd7baddc7..d44d5dd25da 100644
--- a/src/prerna/reactor/ReactorFactory.java
+++ b/src/prerna/reactor/ReactorFactory.java
@@ -501,44 +501,25 @@ private static void loadFromCP(String... packages) {
// ignore abstract and engines
if (!Modifier.isAbstract(actualClass.getModifiers())
&& !Arrays.asList(actualClass.getInterfaces()).contains(IEngine.class)) {
- String[] packagePaths = packageName.split("\\.");
- // System.out.println("Package name " + packageName);
- packageName = packagePaths[packagePaths.length - 1];
- boolean frame = false;
- if (packagePaths.length > 2) {
- frame = packagePaths[packagePaths.length - 2].equalsIgnoreCase("frame");
- }
- // we will allow for 1 more level
- // i.e. things of the form so *.frame.r.?
- if (!frame && packagePaths.length > 3) {
- packageName = packagePaths[packagePaths.length - 2];
- frame = packagePaths[packagePaths.length - 3].equalsIgnoreCase("frame");
- }
- String reactorName = name;
- final String REACTOR_KEY = "REACTOR";
- if (reactorName.toUpperCase().endsWith(REACTOR_KEY)) {
- reactorName = reactorName.substring(0, reactorName.length() - REACTOR_KEY.length());
- }
+ // ReactorNames holds these rules so the OpenAPI export reads reactors the same way
+ String reactorName = ReactorNames.pixelName(name);
+ String frameType = ReactorNames.frameType(packageName);
- if (frame) {
- if (packageName.equalsIgnoreCase("rdbms")) {
+ if (frameType != null) {
+ if (frameType.equalsIgnoreCase("rdbms")) {
h2FrameHash.put(reactorName, actualClass);
- } else if (packageName.equalsIgnoreCase("r")) {
+ } else if (frameType.equalsIgnoreCase("r")) {
rFrameHash.put(reactorName, actualClass);
- } else if (packageName.equalsIgnoreCase("py")) {
+ } else if (frameType.equalsIgnoreCase("py")) {
pandasFrameHash.put(reactorName, actualClass);
- } else if (packageName.equalsIgnoreCase("tinker") || packageName.equalsIgnoreCase("graph")) {
+ } else {
+ // tinker or graph
tinkerFrameHash.put(reactorName, actualClass);
- } else {// nullify the package name
- packageName = null;
- // general reactor
- // example - frame filters
- reactorHash.put(reactorName, actualClass);
- }
- if (packageName != null) {
- reactorName = packageName + "_" + reactorName;
}
+ reactorName = frameType + "_" + reactorName;
} else {
+ // general reactor, including those under a frame package that is
+ // not a frame type, such as frame filters
reactorHash.put(reactorName, actualClass);
}
nmList.add(reactorName);
diff --git a/src/prerna/reactor/ReactorNames.java b/src/prerna/reactor/ReactorNames.java
new file mode 100644
index 00000000000..9629a8cfbae
--- /dev/null
+++ b/src/prerna/reactor/ReactorNames.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
+package prerna.reactor;
+
+import java.util.Set;
+
+/**
+ * How a reactor class is named in Pixel and whether it belongs to one frame
+ * type. {@link ReactorFactory} registers reactors with these rules, and the
+ * OpenAPI export reads contracts with them, so both always agree.
+ */
+public final class ReactorNames {
+
+ private static final String REACTOR_SUFFIX = "REACTOR";
+ private static final Set FRAME_TYPES = Set.of("rdbms", "r", "py", "tinker", "graph");
+
+ private ReactorNames() {
+ }
+
+ /** The name a reactor is called by in Pixel: its class name without "Reactor". */
+ public static String pixelName(String simpleClassName) {
+ if (simpleClassName.toUpperCase().endsWith(REACTOR_SUFFIX)) {
+ return simpleClassName.substring(0, simpleClassName.length() - REACTOR_SUFFIX.length());
+ }
+ return simpleClassName;
+ }
+
+ /**
+ * The frame type a reactor in this package is specific to, as written in the
+ * package (such as {@code r} for {@code prerna.reactor.frame.r}), or null for
+ * a general reactor. A package one level below {@code frame}, or two
+ * ({@code *.frame.r.util}), names its frame type.
+ */
+ public static String frameType(String packageName) {
+ String[] packagePaths = packageName.split("\\.");
+ String last = packagePaths[packagePaths.length - 1];
+ boolean frame = false;
+ if (packagePaths.length > 2) {
+ frame = packagePaths[packagePaths.length - 2].equalsIgnoreCase("frame");
+ }
+ // we will allow for 1 more level
+ // i.e. things of the form so *.frame.r.?
+ if (!frame && packagePaths.length > 3) {
+ last = packagePaths[packagePaths.length - 2];
+ frame = packagePaths[packagePaths.length - 3].equalsIgnoreCase("frame");
+ }
+ if (frame && FRAME_TYPES.contains(last.toLowerCase())) {
+ return last;
+ }
+ // not under frame, or a general reactor under it (such as frame filters)
+ return null;
+ }
+}
diff --git a/src/prerna/reactor/StopPixelExecutionReactor.java b/src/prerna/reactor/StopPixelExecutionReactor.java
index af9a740fdb7..c2c92307281 100644
--- a/src/prerna/reactor/StopPixelExecutionReactor.java
+++ b/src/prerna/reactor/StopPixelExecutionReactor.java
@@ -29,6 +29,7 @@
import java.util.Objects;
+import prerna.openapi.PixelOutput;
import prerna.auth.User;
import prerna.auth.utils.SecurityAdminUtils;
import prerna.reactor.agent.AgentCancelHook;
@@ -42,6 +43,7 @@
import prerna.sablecc2.om.nounmeta.NounMetadata;
import prerna.tcp.client.SocketClient;
+@PixelOutput(value = String.class, description = "Whether the job was not found, asked to cancel, or already completed")
public class StopPixelExecutionReactor extends AbstractReactor {
public StopPixelExecutionReactor() {
diff --git a/src/prerna/reactor/insights/GetCurrentInsightIdReactor.java b/src/prerna/reactor/insights/GetCurrentInsightIdReactor.java
index 1ea0fb933d5..7abd704dfb2 100644
--- a/src/prerna/reactor/insights/GetCurrentInsightIdReactor.java
+++ b/src/prerna/reactor/insights/GetCurrentInsightIdReactor.java
@@ -27,10 +27,12 @@
*******************************************************************************/
package prerna.reactor.insights;
+import prerna.openapi.PixelOutput;
import prerna.reactor.AbstractReactor;
import prerna.sablecc2.om.PixelDataType;
import prerna.sablecc2.om.nounmeta.NounMetadata;
+@PixelOutput(value = String.class, description = "The id of the current insight")
public class GetCurrentInsightIdReactor extends AbstractReactor {
@Override
diff --git a/test/prerna/auth/utils/ModelUsageLimitColumnMigrationUnitTests.java b/test/prerna/auth/utils/ModelUsageLimitColumnMigrationUnitTests.java
index c0e01e895d0..c240113fad8 100644
--- a/test/prerna/auth/utils/ModelUsageLimitColumnMigrationUnitTests.java
+++ b/test/prerna/auth/utils/ModelUsageLimitColumnMigrationUnitTests.java
@@ -1,3 +1,30 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
package prerna.auth.utils;
import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/test/prerna/collaboration/WorkRoutineDocumentsUnitTests.java b/test/prerna/collaboration/WorkRoutineDocumentsUnitTests.java
index 803b8a60b50..b703f6c434b 100644
--- a/test/prerna/collaboration/WorkRoutineDocumentsUnitTests.java
+++ b/test/prerna/collaboration/WorkRoutineDocumentsUnitTests.java
@@ -1,3 +1,30 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
package prerna.collaboration;
import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/test/prerna/ds/py/PandasCompatibilityTests.java b/test/prerna/ds/py/PandasCompatibilityTests.java
index d41bcafdbda..13611a4fe03 100644
--- a/test/prerna/ds/py/PandasCompatibilityTests.java
+++ b/test/prerna/ds/py/PandasCompatibilityTests.java
@@ -1,3 +1,30 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
package prerna.ds.py;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
diff --git a/test/prerna/engine/impl/model/ModelRouterEngineTurnRoutingUnitTests.java b/test/prerna/engine/impl/model/ModelRouterEngineTurnRoutingUnitTests.java
index 0ff29188c7e..7fa9205c17b 100644
--- a/test/prerna/engine/impl/model/ModelRouterEngineTurnRoutingUnitTests.java
+++ b/test/prerna/engine/impl/model/ModelRouterEngineTurnRoutingUnitTests.java
@@ -1,3 +1,30 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
package prerna.engine.impl.model;
import static org.junit.jupiter.api.Assertions.*;
diff --git a/test/prerna/engine/impl/model/ModelRouterEngineTypeSafeUnitTests.java b/test/prerna/engine/impl/model/ModelRouterEngineTypeSafeUnitTests.java
index cb46278ebd8..1db02e9cf31 100644
--- a/test/prerna/engine/impl/model/ModelRouterEngineTypeSafeUnitTests.java
+++ b/test/prerna/engine/impl/model/ModelRouterEngineTypeSafeUnitTests.java
@@ -1,3 +1,30 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
package prerna.engine.impl.model;
import static org.junit.jupiter.api.Assertions.*;
diff --git a/test/prerna/engine/impl/model/usage/ModelUsageBilledToUnitTests.java b/test/prerna/engine/impl/model/usage/ModelUsageBilledToUnitTests.java
index 151987bd7a5..6a484322daa 100644
--- a/test/prerna/engine/impl/model/usage/ModelUsageBilledToUnitTests.java
+++ b/test/prerna/engine/impl/model/usage/ModelUsageBilledToUnitTests.java
@@ -1,3 +1,30 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
/*******************************************************************************
' * Copyright 2015 Defense Health Agency (DHA)
*
diff --git a/test/prerna/reactor/ReactorContractTest.java b/test/prerna/reactor/ReactorContractTest.java
new file mode 100644
index 00000000000..1556f09fe3e
--- /dev/null
+++ b/test/prerna/reactor/ReactorContractTest.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
+package prerna.reactor;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import prerna.openapi.Internal;
+import prerna.openapi.PixelInput;
+import prerna.openapi.PixelOutput;
+import prerna.reactor.insights.GetCurrentInsightIdReactor;
+import prerna.sablecc2.om.ReactorKeysEnum;
+import prerna.sablecc2.om.nounmeta.NounMetadata;
+
+class ReactorContractTest {
+
+ /** Declares keys the way most reactors do, with no annotations. */
+ static class PlainReactor extends AbstractReactor {
+ PlainReactor() {
+ this.keysToGet = new String[] { "name,alias", ReactorKeysEnum.LIMIT.getKey(), "notes" };
+ this.keyRequired = new int[] { 1, 0, 0 };
+ }
+
+ @Override
+ public NounMetadata execute() {
+ return null;
+ }
+
+ @Override
+ protected String getDescriptionForKey(String key) {
+ return key.equals("notes") ? null : super.getDescriptionForKey(key);
+ }
+ }
+
+ /** No keyRequired: organizeKeys() requires nothing. */
+ static class NoRequiredReactor extends AbstractReactor {
+ NoRequiredReactor() {
+ this.keysToGet = new String[] { "a", "b" };
+ }
+
+ @Override
+ public NounMetadata execute() {
+ return null;
+ }
+
+ @Override
+ public String getReactorDescription() {
+ return "Has no required keys";
+ }
+ }
+
+ @PixelInput(name = "a", type = List.class, items = String.class, description = "Some names", required = PixelInput.Requirement.REQUIRED)
+ @PixelInput(name = "b", required = PixelInput.Requirement.OPTIONAL)
+ @PixelOutput(value = List.class, items = Integer.class, description = "Some counts")
+ @Internal("Testing only")
+ static class AnnotatedReactor extends NoRequiredReactor {
+ }
+
+ @PixelInput(name = "missing", type = String.class)
+ static class BadOverrideReactor extends NoRequiredReactor {
+ }
+
+ static class TwiceReactor extends AbstractReactor {
+ TwiceReactor() {
+ this.keysToGet = new String[] { "a", "a,alias" };
+ }
+
+ @Override
+ public NounMetadata execute() {
+ return null;
+ }
+ }
+
+ private static ReactorContract.Input input(ReactorContract contract, String name) {
+ return contract.inputs().stream().filter(i -> i.name().equals(name)).findFirst().orElseThrow();
+ }
+
+ @Test
+ void infersInputsFromKeysRequirednessTypesAndDescriptions() throws Exception {
+ ReactorContract contract = ReactorContract.of(PlainReactor.class);
+
+ assertEquals("Plain", contract.name());
+ assertEquals(List.of("name", "limit", "notes"), contract.inputs().stream().map(ReactorContract.Input::name).toList());
+ assertTrue(input(contract, "name").required());
+ assertFalse(input(contract, "limit").required());
+ assertEquals(Integer.class, input(contract, "limit").type(), "LIMIT is an integer for MCP");
+ assertEquals(String.class, input(contract, "name").type());
+ assertTrue(input(contract, "name").typeInferred());
+
+ assertEquals("The notes input", input(contract, "notes").description());
+ assertTrue(input(contract, "notes").descriptionInferred());
+ assertEquals("Plain reactor", contract.description());
+ assertTrue(contract.descriptionInferred());
+ assertNull(contract.output());
+ assertTrue(contract.inferred());
+ }
+
+ @Test
+ void treatsMissingKeyRequiredAsNothingRequiredLikeOrganizeKeys() throws Exception {
+ ReactorContract contract = ReactorContract.of(NoRequiredReactor.class);
+
+ assertFalse(input(contract, "a").required());
+ assertFalse(input(contract, "b").required());
+ assertEquals("Has no required keys", contract.description());
+ assertFalse(contract.descriptionInferred());
+ }
+
+ @Test
+ void appliesPixelInputPixelOutputAndInternal() throws Exception {
+ ReactorContract contract = ReactorContract.of(AnnotatedReactor.class);
+
+ ReactorContract.Input a = input(contract, "a");
+ assertEquals(List.class, a.type());
+ assertEquals(String.class, a.items());
+ assertEquals("Some names", a.description());
+ assertTrue(a.required());
+ assertFalse(a.typeInferred());
+
+ ReactorContract.Input b = input(contract, "b");
+ assertFalse(b.required());
+ assertTrue(b.typeInferred(), "a @PixelInput without a type keeps the inferred one");
+
+ assertEquals(List.class, contract.output().type());
+ assertEquals(Integer.class, contract.output().items());
+ assertEquals("Some counts", contract.output().description());
+ assertEquals("Testing only", contract.internal().value());
+ }
+
+ @Test
+ void rejectsAPixelInputForAKeyTheReactorDoesNotDeclare() {
+ IllegalStateException error = assertThrows(IllegalStateException.class,
+ () -> ReactorContract.of(BadOverrideReactor.class));
+ assertTrue(error.getMessage().contains("[missing]"), error.getMessage());
+ }
+
+ @Test
+ void rejectsAKeyDeclaredTwice() {
+ assertThrows(IllegalArgumentException.class, () -> ReactorContract.of(TwiceReactor.class));
+ }
+
+ @Test
+ void namesAndFrameTypesFollowReactorFactory() {
+ assertEquals("StopPixelExecution", ReactorNames.pixelName("StopPixelExecutionReactor"));
+ assertEquals("Plain", ReactorNames.pixelName("Plain"));
+ assertEquals("r", ReactorNames.frameType("prerna.reactor.frame.r"));
+ assertEquals("py", ReactorNames.frameType("prerna.reactor.frame.py.util"));
+ assertEquals("rdbms", ReactorNames.frameType("prerna.reactor.frame.rdbms"));
+ assertNull(ReactorNames.frameType("prerna.reactor.frame.filter"), "frame filters are general");
+ assertNull(ReactorNames.frameType("prerna.reactor.insights"));
+ assertTrue(ReactorContract.isGeneral(GetCurrentInsightIdReactor.class));
+ }
+
+ @Test
+ void readsThePilotReactors() throws Exception {
+ ReactorContract stop = ReactorContract.of(StopPixelExecutionReactor.class);
+ assertEquals(List.of("id"), stop.inputs().stream().map(ReactorContract.Input::name).toList());
+ assertTrue(input(stop, "id").required());
+ assertEquals(String.class, input(stop, "id").type());
+ assertEquals(String.class, stop.output().type());
+ assertEquals("Stop the current execution of a pixel job", stop.description());
+
+ ReactorContract echo = ReactorContract.of(EchoReactor.class);
+ assertEquals(Object.class, input(echo, "value").type());
+ assertFalse(input(echo, "value").required());
+ assertNull(echo.output());
+
+ ReactorContract insight = ReactorContract.of(GetCurrentInsightIdReactor.class);
+ assertTrue(insight.inputs().isEmpty());
+ assertEquals(String.class, insight.output().type());
+ }
+}
diff --git a/test/prerna/reactor/collaboration/WorkShowItemReactorUnitTests.java b/test/prerna/reactor/collaboration/WorkShowItemReactorUnitTests.java
index fba17b350ce..734be95daaa 100644
--- a/test/prerna/reactor/collaboration/WorkShowItemReactorUnitTests.java
+++ b/test/prerna/reactor/collaboration/WorkShowItemReactorUnitTests.java
@@ -1,3 +1,30 @@
+/*******************************************************************************
+ * Copyright 2015 Defense Health Agency (DHA)
+ *
+ * If your use of this software does not include any GPLv2 components:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ * If your use of this software includes any GPLv2 components:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *******************************************************************************/
package prerna.reactor.collaboration;
import static org.junit.jupiter.api.Assertions.assertEquals;