Skip to content

Publish 5.0.0-RC.2 #357

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ name := "amf-core"
//
// if (branch.contains("master")) s"$major.$minor.$build" else s"$major.${minor + 1}.0-SNAPSHOT"
//}
ThisBuild / version := "5.0.0-RC.1"
ThisBuild / version := "5.0.0-RC.2"

publish := {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ object AMFEventNames {
val FoundReferences = "FoundReferences"
val SelectedParsePlugin = "SelectedParsePlugin"
val DetectedSyntaxMediaType = "DetectedSyntaxMediaType"
val SkippedValidationPlugin = "SkippedValidationPlugin"
}

object AMFEventConverter {
Expand All @@ -68,6 +69,7 @@ object AMFEventConverter {
case e: config.SelectedParsePluginEvent => SelectedParsePluginEvent(e)
case e: config.StartedTransformationStepEvent => StartedTransformationStepEvent(e)
case e: config.StartingRenderToWriterEvent => StartingRenderToWriterEvent(e)
case e: config.SkippedValidationPluginEvent => SkippedValidationPluginEvent(e)
}
}

Expand Down Expand Up @@ -241,3 +243,7 @@ case class DetectedSyntaxMediaTypeEvent(private val _internal: config.DetectedSy
@JSExportAll
case class StartedTransformationStepEvent(private val _internal: config.StartedTransformationStepEvent)
extends ClientEvent(_internal) {}

@JSExportAll
case class SkippedValidationPluginEvent(private val _internal: config.SkippedValidationPluginEvent)
extends ClientEvent(_internal) {}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ case class Graph(private[amf] val _internal: InternalGraph) {

def scalarByProperty(uri: String): ClientList[Any] = _internal.scalarByProperty(uri).asClient

def removeField(uri: String): this.type = {
_internal.removeField(uri)
this
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import amf.core.internal.plugins.render.{AMFGraphRenderPlugin, DefaultRenderConf
import amf.core.internal.plugins.syntax.{SyamlSyntaxParsePlugin, SyamlSyntaxRenderPlugin}
import amf.core.internal.registries.AMFRegistry
import amf.core.internal.resource.AMFResolvers
import amf.core.internal.validation.ValidationConfiguration
import amf.core.internal.validation.{EffectiveValidations, ValidationConfiguration}
import amf.core.internal.validation.core.ValidationProfile

import scala.concurrent.ExecutionContext
Expand Down Expand Up @@ -119,6 +119,11 @@ class AMFGraphConfiguration private[amf] (override private[amf] val resolvers: A
private[amf] def withValidationProfile(profile: ValidationProfile): AMFGraphConfiguration =
super._withValidationProfile(profile)

// Keep AMF internal, done to avoid recomputing validations every time a config is requested
private[amf] def withValidationProfile(profile: ValidationProfile,
effective: EffectiveValidations): AMFGraphConfiguration =
super._withValidationProfile(profile, effective)

def withTransformationPipeline(pipeline: TransformationPipeline): AMFGraphConfiguration =
super._withTransformationPipeline(pipeline)

Expand Down Expand Up @@ -204,6 +209,9 @@ sealed abstract class BaseAMFConfigurationSetter(private[amf] val resolvers: AMF
protected def _withValidationProfile[T](profile: ValidationProfile): T =
copy(registry = registry.withConstraints(profile)).asInstanceOf[T]

protected def _withValidationProfile[T](profile: ValidationProfile, effectiveValidations: EffectiveValidations): T =
copy(registry = registry.withConstraints(profile, effectiveValidations)).asInstanceOf[T]

protected def _withTransformationPipeline[T](pipeline: TransformationPipeline): T =
copy(registry = registry.withTransformationPipeline(pipeline)).asInstanceOf[T]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,7 @@ case class FinishedRenderingSyntaxEvent(unit: BaseUnit) extends AMFEvent with Gr
override val name: String = FinishedSyntaxRender
override val groupKey: String = unit.id
}

case class SkippedValidationPluginEvent(pluginName: String, reason: String) extends AMFEvent {
override val name: String = SkippedValidationPlugin
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ trait AMFErrorHandler {

/** Report an [[AMFValidationResult]] */
def report(result: AMFValidationResult): Unit = synchronized {
if (!results.contains(result)) { // TODO ARM check this assertion
if (!results.contains(result)) {
results += result
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ import amf.core.internal.parser.domain.{Annotations, FieldEntry, Value}

case class Graph(e: DomainElement) {

private[amf] def removeField(uri: String): this.type = {
e.fields.remove(uri)
this
}

private[amf] def scalarByField(field: Field): Seq[Any] = scalarByProperty(field.value.iri())

private[amf] def containsField(f: Field): Boolean = properties().contains(f.toString)
Expand Down Expand Up @@ -67,4 +62,9 @@ case class Graph(e: DomainElement) {
case None => List()
}
}

def removeField(uri: String): this.type = {
e.fields.remove(uri)
this
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ abstract class Shape extends DomainElement with Linkable with NamedDomainElement

// @todo should be memoize this?
def collectCustomShapePropertyDefinitions(onlyInherited: Boolean = false,
traversed: mutable.Set[String] = mutable.Set()): Seq[FacetsMap] = {
traversed: mutable.Set[Shape] = mutable.Set()): Seq[FacetsMap] = {
// Facet properties for the current shape
val accInit: FacetsMap = Map.empty
val initialSequence = if (onlyInherited) {
Expand All @@ -103,8 +103,8 @@ abstract class Shape extends DomainElement with Linkable with NamedDomainElement
// initial facets maps computed for this shape. This multiplies the number of
// final facets maps
effectiveInherits.foldLeft(initialSequence) { (acc: Seq[FacetsMap], baseShape: Shape) =>
if (!traversed.contains(baseShape.id)) {
baseShape.collectCustomShapePropertyDefinitions(onlyInherited = false, traversed += baseShape.id).flatMap {
if (!traversed.contains(baseShape)) {
baseShape.collectCustomShapePropertyDefinitions(onlyInherited = false, traversed += baseShape).flatMap {
facetsMap: FacetsMap =>
acc.map { accFacetsMap =>
accFacetsMap ++ facetsMap
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package amf.core.client.scala.validation

import amf._
import amf.core.internal.validation.ValidationConfiguration
import amf.core.client.common.validation._
import amf.core.client.scala.AMFGraphConfiguration
import amf.core.client.scala.model.document.BaseUnit
import amf.core.client.common.validation.{AmfProfile, Async20Profile, Oas20Profile, Oas30Profile, ProfileName, Raml08Profile, Raml10Profile}
import amf.core.internal.plugins.validation.{ValidationInfo, ValidationOptions}
import amf.core.internal.remote.{AmlDialectSpec, Spec}
import amf.core.internal.validation.core.ValidationProfile
import amf.core.internal.validation.FailFastValidationRunner
import amf.core.internal.plugins.validation.{ValidationInfo, ValidationOptions}
import amf.core.internal.validation.{EffectiveValidations, FailFastValidationRunner, ValidationConfiguration}

import scala.concurrent.Future
Expand Down Expand Up @@ -36,30 +33,13 @@ object VendorToProfile {
object AMFValidator {

def validate(baseUnit: BaseUnit, conf: AMFGraphConfiguration): Future[AMFValidationReport] = {
// TODO ARM: ValidationProfile election shouldn't be done here.
val profileName = baseUnit.sourceSpec.map(VendorToProfile.mapOrDefault).getOrElse(AmfProfile)
val plugins = conf.registry.plugins.validatePlugins.filter(_.applies(ValidationInfo(baseUnit, profileName))).sorted
val constraints = computeApplicableConstraints(profileName, conf.registry.constraintsRules)
val options = ValidationOptions(profileName, constraints, ValidationConfiguration(conf))
val plugins = computeApplicablePlugins(baseUnit, conf)
val options = ValidationOptions(ValidationConfiguration(conf))
val runner = FailFastValidationRunner(plugins, options)
runner.run(baseUnit)(conf.getExecutionContext)
}

private def computeApplicableConstraints(profileName: ProfileName, constraints: Map[ProfileName, ValidationProfile]): EffectiveValidations = {
val profiles = findProfileHierarchy(profileName, constraints)
val applicable = EffectiveValidations()
profiles.foldLeft(applicable) { (acc, curr) => acc.someEffective(curr) }
}

private def findProfileHierarchy(profileName: ProfileName, constraints: Map[ProfileName, ValidationProfile], seen: Set[ProfileName] = Set.empty): Seq[ValidationProfile] = {
if (seen.contains(profileName)) return Seq.empty
constraints.map {
case (key, value) => key.p -> value
}.get(profileName.p)
.map { profile =>
profile.baseProfile
.map(base => findProfileHierarchy(base, constraints, seen + profile.name))
.getOrElse(Seq.empty) ++ Seq(profile)
}.getOrElse(Seq.empty)
private def computeApplicablePlugins(baseUnit: BaseUnit, conf: AMFGraphConfiguration) = {
conf.registry.plugins.validatePlugins.filter(_.applies(ValidationInfo(baseUnit))).sorted
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package amf.core.client.scala.validation

import amf.core.client.common.validation.ProfileName
import amf.core.internal.validation.EffectiveValidations
import amf.core.internal.validation.core.ValidationProfile

object EffectiveValidationsCompute {

def build(profile: ProfileName, constraints: Map[ProfileName, ValidationProfile]): Option[EffectiveValidations] = {
computeApplicableConstraints(profile, constraints)
}

def buildAll(constraints: Map[ProfileName, ValidationProfile]): Map[ProfileName, EffectiveValidations] = {
constraints.keySet.foldLeft(Map[ProfileName, EffectiveValidations]()) { (acc, curr) =>
build(curr, constraints).map(eff => acc + (curr -> eff)).getOrElse(acc)
}
}

private def computeApplicableConstraints(
profileName: ProfileName,
constraints: Map[ProfileName, ValidationProfile]): Option[EffectiveValidations] = {
val profiles = findProfileHierarchy(profileName, constraints)
if (profiles.isEmpty) return None

val applicable = EffectiveValidations()
profiles.foldLeft(applicable) { (acc, curr) =>
acc.someEffective(curr)
}
Some(applicable)
}

private def findProfileHierarchy(profileName: ProfileName,
constraints: Map[ProfileName, ValidationProfile],
seen: Set[ProfileName] = Set.empty): Seq[ValidationProfile] = {
if (seen.contains(profileName)) return Seq.empty
constraints
.map {
case (key, value) => key.p -> value
}
.get(profileName.p)
.map { profile =>
profile.baseProfile
.map(base => findProfileHierarchy(base, constraints, seen + profile.name))
.getOrElse(Seq.empty) ++ Seq(profile)
}
.getOrElse(Seq.empty)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ trait AMFShapePayloadValidationPlugin extends AMFPlugin[ValidatePayloadRequest]

override def applies(element: ValidatePayloadRequest): Boolean

// TODO ARM we can remove the validation mode and handle it on different plugins, o we can put the mode into the options
def validator(shape: Shape,
mediaType: String,
config: ShapeValidationConfiguration,
Expand Down
14 changes: 10 additions & 4 deletions shared/src/main/scala/amf/core/internal/parser/domain/Fields.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package amf.core.internal.parser.domain

import amf.core.client.scala.model._
import amf.core.client.scala.model.domain._
import amf.core.client.scala.vocabulary.ValueType
import amf.core.internal.metamodel.Type._
import amf.core.internal.metamodel.{Field, Obj, Type}
import amf.core.internal.annotations.{Inferred, SynthesizedField}
Expand Down Expand Up @@ -75,6 +76,11 @@ class Fields {
/** Return [[Value]] associated to given Field. */
def getValue(field: Field): Value = fs.get(field).orNull

def getValueAsOption(iri: String): Option[Value] = {
val constructedField = Field(Type.Any, ValueType(iri)) // valueType iri is the only relevant value
getValueAsOption(constructedField)
}

/** Return [[Value]] associated to given Field. */
def getValueAsOption(field: Field): Option[Value] = fs.get(field)

Expand Down Expand Up @@ -262,10 +268,10 @@ class Value(var value: AmfElement, val annotations: Annotations) {
value = resolved
} else {
value = resolved.resolveUnreferencedLink(
linkable.refName,
linkable.annotations,
linkable,
linkable.supportsRecursion.option().getOrElse(false)) // mutation of the field value
linkable.refName,
linkable.annotations,
linkable,
linkable.supportsRecursion.option().getOrElse(false)) // mutation of the field value
}
val syntax = value match {
case s: Shape => Some(s.ramlSyntaxKey)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,18 @@ import scala.collection.mutable.ListBuffer
/**
* AMF Graph parser
*/
class EmbeddedGraphParser()(implicit val ctx: GraphParserContext) extends GraphParser(ctx.config) {
class EmbeddedGraphParser()(implicit val ctx: GraphParserContext) extends GraphParserHelpers {

override def canParse(document: SyamlParsedDocument): Boolean = EmbeddedGraphParser.canParse(document)
def canParse(document: SyamlParsedDocument): Boolean = EmbeddedGraphParser.canParse(document)

override def parse(document: YDocument, location: String): BaseUnit = {
def parse(document: YDocument, location: String): BaseUnit = {
val parser = Parser(Map())
parser.parse(document, location)
}

def annotations(nodes: Map[String, AmfElement], sources: SourceMap, key: String): Annotations =
ctx.config.serializableAnnotationsFacade.retrieveAnnotation(nodes, sources, key)

case class Parser(var nodes: Map[String, AmfElement]) {
private val unresolvedReferences = mutable.Map[String, Seq[DomainElement]]()
private val unresolvedExtReferencesMap =
Expand Down Expand Up @@ -68,7 +71,8 @@ class EmbeddedGraphParser()(implicit val ctx: GraphParserContext) extends GraphP
stringTypes.find(findType(_).isDefined) match {
case Some(t) => findType(t)
case None =>
ctx.eh.violation(UnableToParseNode, id, s"Error parsing JSON-LD node, unknown @types $stringTypes", map.location)
ctx.eh
.violation(UnableToParseNode, id, s"Error parsing JSON-LD node, unknown @types $stringTypes", map.location)
None
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ class FlattenedGraphParser(startingPoint: String)(implicit val ctx: GraphParserC
parser.parse(document)
}

// TODO ARM duplicated
def annotations(nodes: Map[String, AmfElement], sources: SourceMap, key: String): Annotations =
ctx.config.serializableAnnotationsFacade.retrieveAnnotation(nodes, sources, key)

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ trait AMFValidatePlugin extends AMFPlugin[ValidationInfo] with PlatformSecrets {
implicit executionContext: ExecutionContext): Future[ValidationResult]
}

case class ValidationOptions(profile: ProfileName,
effectiveValidations: EffectiveValidations,
config: ValidationConfiguration)
case class ValidationOptions(config: ValidationConfiguration)

case class ValidationInfo(val baseUnit: BaseUnit, val profile: ProfileName)
case class ValidationInfo(baseUnit: BaseUnit)

case class ValidationResult(unit: BaseUnit, report: AMFValidationReport)
Loading