Skip to content

Commit

Permalink
[NU-7164] Add basic parser for fragment input definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
Piotr Rudnicki committed Nov 19, 2024
1 parent 580adec commit 204fd64
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,33 @@ export function useTypeOptions<Value = string>() {
};
}

export function useTypeOptionsV2<Value = string>() {
const definitionData = useSelector(getProcessDefinitionData);

const typeOptions = useMemo(
() =>
definitionData?.classes?.map((type) => ({
value: type.display,
label: ProcessUtils.humanReadableType(type),
})),
[definitionData?.classes],
);

const orderedTypeOptions = useMemo(() => orderBy(typeOptions, (item) => [item.label, item.value], ["asc"]), [typeOptions]);

const defaultTypeOption = useMemo(() => find(typeOptions, { label: "String" }) || head(typeOptions), [typeOptions]);
return {
orderedTypeOptions,
defaultTypeOption,
};
}

export default function FragmentInputDefinition(props: Props): JSX.Element {
const { removeElement, addElement, variableTypes, ...passProps } = props;
const { node, setProperty, isEditMode, showValidation } = passProps;

const readOnly = !isEditMode;
const { orderedTypeOptions, defaultTypeOption } = useTypeOptions();
const { orderedTypeOptions, defaultTypeOption } = useTypeOptionsV2();

const addField = useCallback(() => {
addElement("parameters", getDefaultFields(defaultTypeOption.value));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ object ProcessValidator {

val nodeCompiler = new NodeCompiler(
modelDefinition,
new FragmentParametersDefinitionExtractor(classLoader),
new FragmentParametersDefinitionExtractor(classLoader, definitionWithTypes.classDefinitions.all),
expressionCompiler,
classLoader,
Seq.empty,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ class NodeDataValidator(modelData: ModelData) {

private val compiler = new NodeCompiler(
modelData.modelDefinition,
new FragmentParametersDefinitionExtractor(modelData.modelClassLoader.classLoader),
new FragmentParametersDefinitionExtractor(
modelData.modelClassLoader.classLoader,
modelData.modelDefinitionWithClasses.classDefinitions.all
),
expressionCompiler,
modelData.modelClassLoader.classLoader,
Seq.empty,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import pl.touk.nussknacker.engine.api.definition._
import pl.touk.nussknacker.engine.api.parameter.ValueInputWithDictEditor
import pl.touk.nussknacker.engine.api.typed.typing.{Typed, TypingResult, Unknown}
import pl.touk.nussknacker.engine.compile.nodecompilation.FragmentParameterValidator
import pl.touk.nussknacker.engine.definition.clazz.{ClassDefinition, ClassDefinitionSet}
import pl.touk.nussknacker.engine.definition.component.parameter.ParameterData
import pl.touk.nussknacker.engine.definition.component.parameter.defaults.{
DefaultValueDeterminerChain,
Expand All @@ -28,11 +29,16 @@ import pl.touk.nussknacker.engine.graph.expression.Expression.Language
import pl.touk.nussknacker.engine.graph.node.FragmentInputDefinition.FragmentParameter
import pl.touk.nussknacker.engine.graph.node.{FragmentInput, FragmentInputDefinition}

import scala.util.Try

/*
* This class doesn't validate the parameters' initialValue and valueEditor (e.g. values can be of incorrect type), as it would require ExpressionCompiler, ValidationContext and declared dictionaries.
* They are validated separately when creating fragment in NodeCompiler.compileSource, but if they are not validated it is not a breaking issue anyway as a process using these incorrect values will fail validation.
*/
class FragmentParametersDefinitionExtractor(classLoader: ClassLoader) {
class FragmentParametersDefinitionExtractor(
classLoader: ClassLoader,
classDefinitions: Set[ClassDefinition] = Set.empty
) {

def extractParametersDefinition(
fragmentInput: FragmentInput
Expand All @@ -54,7 +60,7 @@ class FragmentParametersDefinitionExtractor(classLoader: ClassLoader) {
): WriterT[Id, List[PartSubGraphCompilationError], List[Id[Parameter]]] = {
parameters
.map(p =>
getParamTypingResult(p)
getParamTypingResultV2(p)
.mapBoth { (written, typ) =>
val param = toParameter(typ, p)
(written ++ param.written, param.value)
Expand Down Expand Up @@ -131,6 +137,52 @@ class FragmentParametersDefinitionExtractor(classLoader: ClassLoader) {
.tell(validationErrors)
}

private def parse(className: String): Try[TypingResult] = {
def resolveInnerClass(simpleClassName: String): TypingResult =
classDefinitions
.find(classDefinition => classDefinition.clazzName.display == simpleClassName)
.fold(
throw new ClassNotFoundException(
s"Class $simpleClassName was not found in the class definitions set: ${classDefinitions.map(_.clazzName.display)}"
)
) { classDefinition =>
classDefinition.clazzName
}

val mapPattern = "Map\\[(.+),(.+)\\]".r
val listPattern = "List\\[(.+)\\]".r
val setPattern = "Set\\[(.+)\\]".r

Try(className match {
case mapPattern(x, y) =>
val resolvedFirstTypeParam = resolveInnerClass(x)
val resolvedSecondTypeParam = resolveInnerClass(y)
Typed.genericTypeClass[java.util.Map[_, _]](List(resolvedFirstTypeParam, resolvedSecondTypeParam))
case listPattern(x) =>
val resolvedTypeParam = resolveInnerClass(x)
Typed.genericTypeClass[java.util.List[_]](List(resolvedTypeParam))
case setPattern(x) =>
val resolvedTypeParam = resolveInnerClass(x)
Typed.genericTypeClass[java.util.Set[_]](List(resolvedTypeParam))
case simpleClassName => resolveInnerClass(simpleClassName)
})
}

private def getParamTypingResultV2(
fragmentParameter: FragmentParameter
)(implicit nodeId: NodeId): Writer[List[PartSubGraphCompilationError], TypingResult] =
parse(
fragmentParameter.typ.refClazzName
)
.map(Writer.value[List[PartSubGraphCompilationError], TypingResult])
.getOrElse(
Writer
.value[List[PartSubGraphCompilationError], TypingResult](Unknown)
.tell(
List(FragmentParamClassLoadError(fragmentParameter.name, fragmentParameter.typ.refClazzName, nodeId.id))
)
)

private def getParamTypingResult(
fragmentParameter: FragmentParameter
)(implicit nodeId: NodeId): Writer[List[PartSubGraphCompilationError], TypingResult] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ class ModelDataTestInfoProvider(modelData: ModelData) extends TestInfoProvider w

private lazy val nodeCompiler = new NodeCompiler(
modelData.modelDefinition,
new FragmentParametersDefinitionExtractor(modelData.modelClassLoader.classLoader),
new FragmentParametersDefinitionExtractor(
modelData.modelClassLoader.classLoader,
modelData.modelDefinitionWithClasses.classDefinitions.all
),
expressionCompiler,
modelData.modelClassLoader.classLoader,
Seq.empty,
Expand Down

0 comments on commit 204fd64

Please sign in to comment.