Skip to content

Commit

Permalink
Support for remarks in let statements (#216)
Browse files Browse the repository at this point in the history
* Added support for remarks in let statements. resolves #169.
  • Loading branch information
david-waltermire authored Oct 27, 2024
1 parent 37089cd commit 98a2c53
Show file tree
Hide file tree
Showing 14 changed files with 319 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ private static ISequence<IStringItem> executeOneArg(@NonNull IFunction function,
return ISequence.of(arguments.get(0).isEmpty()
? IStringItem.valueOf("")
: fnUpperCase(FunctionUtils.asType(ObjectUtils.notNull(arguments.get(0).getFirstItem(true)))));

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@

package gov.nist.secauto.metaschema.core.model.constraint;

import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.MetapathExpression;
import gov.nist.secauto.metaschema.core.model.constraint.impl.DefaultLet;

import javax.xml.namespace.QName;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

/**
* Represents a variable assignment for use in Metaschema module constraints.
*/
@SuppressWarnings("PMD.ShortClassName")
public interface ILet {
/**
Expand All @@ -25,16 +30,23 @@ public interface ILet {
* a Metapath expression string representing the variable value
* @param source
* the source descriptor for the resource containing the constraint
* @param remarks
* remarks about the let statement
* @return the original let statement with the same name or {@code null}
*/
@SuppressWarnings("PMD.ShortMethodName")
@NonNull
static ILet of(
@NonNull QName name,
@NonNull String valueExpression,
@NonNull ISource source) {
@NonNull ISource source,
@Nullable MarkupMultiline remarks) {
try {
return of(name, MetapathExpression.compile(valueExpression, source.getStaticContext()), source);
return of(
name,
MetapathExpression.compile(valueExpression, source.getStaticContext()),
source,
remarks);
} catch (MetapathException ex) {
throw new MetapathException(
String.format("Unable to compile the let expression '%s=%s'%s. %s",
Expand All @@ -55,15 +67,18 @@ static ILet of(
* a Metapath expression representing the variable value
* @param source
* the source descriptor for the resource containing the constraint
* @param remarks
* remarks about the let statement
* @return the original let statement with the same name or {@code null}
*/
@SuppressWarnings("PMD.ShortMethodName")
@NonNull
static ILet of(
@NonNull QName name,
@NonNull MetapathExpression valueExpression,
@NonNull ISource source) {
return new DefaultLet(name, valueExpression, source);
@NonNull ISource source,
@Nullable MarkupMultiline remarks) {
return new DefaultLet(name, valueExpression, source, remarks);
}

/**
Expand All @@ -89,4 +104,12 @@ static ILet of(
*/
@NonNull
ISource getSource();

/**
* Get the remarks associated with the let statement.
*
* @return the remark or {@code null} if no remarks are defined
*/
@Nullable
MarkupMultiline getRemarks();
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ static ISource modelSource(@NonNull IModule module) {
* Get the descriptor for a
* {@link gov.nist.secauto.metaschema.core.model.constraint.ISource.SourceType#EXTERNAL}
* source with as associated resource.
* <p>
* The provided static context idenfies the location of this source based on the
* {@link StaticContext#getBaseUri()} method.
*
* @param staticContext
* the static Metapath context to use for compiling Metapath
Expand All @@ -57,6 +60,9 @@ static ISource modelSource(@NonNull IModule module) {
*/
@NonNull
static ISource externalSource(@NonNull StaticContext staticContext) {
if (staticContext.getBaseUri() == null) {
throw new IllegalArgumentException("The static content must define a baseUri identifing the source resource.");
}
return ExternalSource.instance(staticContext);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,30 @@

package gov.nist.secauto.metaschema.core.model.constraint.impl;

import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
import gov.nist.secauto.metaschema.core.metapath.MetapathExpression;
import gov.nist.secauto.metaschema.core.model.constraint.ILet;
import gov.nist.secauto.metaschema.core.model.constraint.ISource;

import javax.xml.namespace.QName;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

/**
* A variable assignment for use in Metaschema module constraints.
* <p>
* This class is immutable.
*/
public class DefaultLet implements ILet {
@NonNull
private final QName name;
@NonNull
private final MetapathExpression valueExpression;
@NonNull
private final ISource source;
@Nullable
private final MarkupMultiline remarks;

/**
* Construct a new let statement.
Expand All @@ -30,14 +39,18 @@ public class DefaultLet implements ILet {
* the Metapath expression used to query the value
* @param source
* the source of the let statement
* @param remarks
* remarks about the let statement
*/
public DefaultLet(
@NonNull QName name,
@NonNull MetapathExpression metapath,
@NonNull ISource source) {
@NonNull ISource source,
@Nullable MarkupMultiline remarks) {
this.name = name;
this.valueExpression = metapath;
this.source = source;
this.remarks = remarks;
}

@Override
Expand All @@ -55,4 +68,9 @@ public MetapathExpression getValueExpression() {
public ISource getSource() {
return source;
}

@Override
public MarkupMultiline getRemarks() {
return remarks;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -471,10 +471,14 @@ public static ICardinalityConstraint newCardinalityConstraint(
public static ILet newLet(
@NonNull ConstraintLetType xmlObject,
@NonNull ISource source) {

// TODO: figure out how to resolve the namespace prefix on var
return ILet.of(
new QName(xmlObject.getVar()),
ObjectUtils.notNull(xmlObject.getExpression()),
source);
source,
xmlObject.isSetRemarks()
? remarks(ObjectUtils.notNull(xmlObject.getRemarks()))
: null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: none
* SPDX-License-Identifier: CC0-1.0
*/

package gov.nist.secauto.metaschema.core.model.xml.impl;

import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;

import gov.nist.secauto.metaschema.core.metapath.StaticContext;
import gov.nist.secauto.metaschema.core.model.constraint.ILet;
import gov.nist.secauto.metaschema.core.model.constraint.ISource;
import gov.nist.secauto.metaschema.core.model.xml.xmlbeans.ConstraintLetType;
import gov.nist.secauto.metaschema.core.model.xml.xmlbeans.RemarksType;

import org.apache.xmlbeans.XmlException;
import org.junit.jupiter.api.Test;

import java.net.URI;

import javax.xml.namespace.QName;

class ModelFactoryTest {

@SuppressWarnings("null")
@Test
void letTest() throws XmlException {
ISource source = ISource.externalSource(StaticContext.builder()
.baseUri(URI.create("https://example.com/"))
.build());

String variable = "var1";
String expression = "1 + 1";
RemarksType remarks = RemarksType.Factory.parse("<p>Test</p>");

ConstraintLetType letObj = ConstraintLetType.Factory.newInstance();
letObj.setExpression(expression);
letObj.setVar(variable);
letObj.setRemarks(remarks);

ILet let = ModelFactory.newLet(letObj, source);
assertAll(
() -> assertEquals(new QName(variable), let.getName()),
() -> assertEquals(expression, let.getValueExpression().getPath()),
() -> assertEquals(source, let.getSource()),
() -> assertEquals("Test", let.getRemarks().toMarkdown()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
<context>
<metapath target="/(computer|vendor)/@id"/>
<constraints>
<matches target="." datatype="uuid"/>
<matches target="." datatype="uuid">
<remarks>
<p>This matches the id of child computer and vendor elements.</p>
</remarks>
</matches>
</constraints>
</context>
</metaschema-meta-constraints>
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,10 @@ private static void applyLetAssignments(
letAnnotation.addMember("name", "$S", let.getName());
letAnnotation.addMember("target", "$S", let.getValueExpression().getPath());

// TODO: Support remarks
// MarkupMultiline remarks = let.getRemarks();
// if (remarks != null) {
// constraintAnnotation.addMember("remarks", "$S",
// remarks.toMarkdown());
// }
MarkupMultiline remarks = let.getRemarks();
if (remarks != null) {
letAnnotation.addMember("remarks", "$S", remarks.toMarkdown());
}

annotation.addMember("lets", "$L", letAnnotation.build());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

import edu.umd.cs.findbugs.annotations.NonNull;

/**
* Represents a constraint let statement used to assign the result of a Metapath
* expression to a variable.
*/
@Documented
@Retention(RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

@SuppressWarnings("PMD.CouplingBetweenObjects")
final class ConstraintFactory {
private ConstraintFactory() {
// disable
Expand Down Expand Up @@ -324,6 +325,14 @@ static ICardinalityConstraint newCardinalityConstraint(@NonNull HasCardinality c

@NonNull
static ILet newLetExpression(@NonNull Let annotation, @NonNull ISource source) {
return ILet.of(new QName(annotation.name()), annotation.target(), source);
String remarkMarkdown = annotation.remarks();
MarkupMultiline remarks = remarkMarkdown.isBlank()
? null
: MarkupMultiline.fromMarkdown(remarkMarkdown);
return ILet.of(
new QName(annotation.name()),
annotation.target(),
source,
remarks);
}
}
Loading

0 comments on commit 98a2c53

Please sign in to comment.