Skip to content

Commit

Permalink
Merge pull request #1413 from aml-org/W-11187481-semex-same-branch
Browse files Browse the repository at this point in the history
W-11187481 - Added default shape to SemEx CustomDomainProperty
  • Loading branch information
looseale authored May 24, 2022
2 parents 039aacd + 401e6f6 commit 3cdcd54
Show file tree
Hide file tree
Showing 15 changed files with 226 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package amf.apicontract.internal.validation.payload.collector

import amf.aml.client.scala.model.domain.DialectDomainElement
import amf.core.client.scala.model.document.PayloadFragment
import amf.core.client.scala.model.domain.extensions.{DomainExtension, Extension, ShapeExtension}
import amf.core.client.scala.model.domain.{AmfElement, AmfScalar}
Expand All @@ -23,7 +24,7 @@ object ExtensionsCollector extends ValidationCandidateCollector {
element match {
case extension: DomainExtension if Option(extension.definedBy).exists(definition => {
Option(definition.schema).isDefined && resolveAnnotation(s"(${definition.name.value()})").isDefined
}) =>
}) && !isSemanticExtension(extension) =>
Seq(extension)
case shapeExtension: ShapeExtension
if Option(shapeExtension.definedBy).isDefined && Option(shapeExtension.obtainSchema).isDefined =>
Expand All @@ -35,4 +36,8 @@ object ExtensionsCollector extends ValidationCandidateCollector {
}
case _ => Nil
}

// If it is a SemEx I don't want to validate the candidates
private def isSemanticExtension(extension: DomainExtension) =
extension.fields.fields().exists(_.value.value.isInstanceOf[DialectDomainElement])
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#%RAML 1.0
title: Something

annotationTypes:
pagination: any

/sample:
(pagination):
pageSize: 15
get:
(pagination):
pageSize: 10
responses:
200:
description: A Response
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#%Dialect 1.0
dialect: Pagination Test
version: 1.0

external:
apiContract: http://a.ml/vocabularies/apiContract#
aml: http://a.ml/vocab#

documents: {}

annotationMappings:
PaginationAnnotation:
domain:
- apiContract.EndPoint
- apiContract.Operation
propertyTerm: aml.pagination
range: Pagination

nodeMappings:
Pagination:
classTerm: aml.Pagination
mapping:
pageSize:
propertyTerm: aml.PageSize
range: integer
mandatory: true

extensions:
pagination: PaginationAnnotation
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#%RAML 1.0
title: something

annotationTypes:
something:
type: string

/test:
(other): 44
get:
responses:
(something): blablabla
200:
body:
application/json:
(something): sarasa
type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#%RAML 1.0
title: something

annotationTypes:
other:
type: any

/test:
(other): 44
get:
responses:
(something): blablabla
200:
body:
application/json:
(something): sarasa
type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#%RAML 1.0
title: something

annotationTypes:
something:
type: string
other:
type: any

/test:
(other): 44
get:
responses:
(something): blablabla
200:
body:
application/json:
(something): sarasa
type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#%RAML 1.0
title: something

annotationTypes:
something:
type: string

/test:
get:
responses:
200:
body:
application/json:
(something): sarasa
type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#%RAML 1.0
title: something

/test:
get:
responses:
200:
body:
application/json:
(something): sarasa
type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
ModelId: file://amf-cli/shared/src/test/resources/validations/raml/annotation-mixed-1.raml
Profile: RAML 1.0
Conforms: false
Number of results: 1

Level: Violation

- Constraint: http://a.ml/vocabularies/amf/parser#DomainProperty-schema-minCount
Message: type is mandatory for a RAML annotationType
Severity: Violation
Target: file://amf-cli/shared/src/test/resources/validations/raml/annotation-mixed-1.raml#/web-api/endpoint/%2Ftest/customDomainProperties/other/other
Property: http://a.ml/vocabularies/shapes#schema
Range: [(9,2)-(10,0)]
Location: file://amf-cli/shared/src/test/resources/validations/raml/annotation-mixed-1.raml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
ModelId: file://amf-cli/shared/src/test/resources/validations/raml/annotation-mixed-2.raml
Profile: RAML 1.0
Conforms: false
Number of results: 1

Level: Violation

- Constraint: http://a.ml/vocabularies/amf/parser#DomainProperty-schema-minCount
Message: type is mandatory for a RAML annotationType
Severity: Violation
Target: file://amf-cli/shared/src/test/resources/validations/raml/annotation-mixed-2.raml#/web-api/endpoint/%2Ftest/supportedOperation/get/returns/resp/200/payload/application%2Fjson/scalar/schema/customDomainProperties/something/something
Property: http://a.ml/vocabularies/shapes#schema
Range: [(16,12)-(17,0)]
Location: file://amf-cli/shared/src/test/resources/validations/raml/annotation-mixed-2.raml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
ModelId: file://amf-cli/shared/src/test/resources/validations/raml/annotation-without-definition.raml
Profile: RAML 1.0
Conforms: false
Number of results: 1

Level: Violation

- Constraint: http://a.ml/vocabularies/amf/parser#DomainProperty-schema-minCount
Message: type is mandatory for a RAML annotationType
Severity: Violation
Target: file://amf-cli/shared/src/test/resources/validations/raml/annotation-without-definition.raml#/web-api/endpoint/%2Ftest/supportedOperation/get/returns/resp/200/payload/application%2Fjson/scalar/schema/customDomainProperties/something/something
Property: http://a.ml/vocabularies/shapes#schema
Range: [(10,12)-(11,0)]
Location: file://amf-cli/shared/src/test/resources/validations/raml/annotation-without-definition.raml
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
package amf.semantic

import amf.aml.client.scala.model.document.Dialect
import amf.aml.client.scala.{AMLConfiguration, AMLDialectResult}
import amf.apicontract.client.scala.{AMFConfiguration, AMFLibraryResult, APIConfiguration}
import amf.apicontract.client.scala.model.domain.api.Api
import amf.core.client.scala.config.{CachedReference, UnitCache}
import amf.core.client.scala.errorhandling.UnhandledErrorHandler
import amf.core.client.scala.model.document.Document
import amf.core.client.scala.model.domain.extensions.DomainExtension
import amf.core.internal.annotations.LexicalInformation
import amf.core.internal.parser.domain.Value
import amf.core.internal.remote.{AsyncApi20, Oas20, Oas30, Raml10, Spec}
import org.mulesoft.antlrast.unsafe.PlatformSecrets
import org.scalatest.Assertion
import amf.core.internal.remote.{AsyncApi20, Oas20, Oas30, Raml10}
import org.scalatest.funsuite.AsyncFunSuite
import org.scalatest.matchers.should.Matchers
import amf.core.client.scala.model.document.Module

import scala.concurrent.{ExecutionContext, Future}
import scala.concurrent.ExecutionContext

class SemanticExtensionTest extends AsyncFunSuite with SemanticExtensionParseTest with Matchers {

Expand Down Expand Up @@ -48,10 +37,24 @@ class SemanticExtensionTest extends AsyncFunSuite with SemanticExtensionParseTes
}
}

test("Apply same SemEx to Endpoint and Operation") {
assertModel("dialect-endpoint-operation.yaml", "api-endpoint-operation.raml", Raml10) { doc =>
lookupEndpoint(doc)
lookupOperation(doc)
}
}

private def lookupOperation(document: Document) = {
val extension =
document.encodes.asInstanceOf[Api].endPoints.head.operations.head.customDomainProperties.head

assertPaginationExtension(extension, 10)
}

private def lookupEndpoint(document: Document) = {
val extension =
document.encodes.asInstanceOf[Api].endPoints.head.customDomainProperties.head

assertPaginationExtension(extension, 15)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,17 @@ class SemanticExtensionValidationTest extends MultiPlatformReportGenTest {
}
}

test("Validate valid multiple SemEx in the same branch at a RAML 1.0") {
getConfig("../dialect-endpoint-operation.yaml", RAMLConfiguration.RAML10()).flatMap { config =>
validate(
"../api-endpoint-operation.raml",
None,
overridedHint = Some(Raml10YamlHint),
configOverride = Some(config)
)
}
}

private def getConfig(
dialect: String,
baseConfig: AMFConfiguration = APIConfiguration.API()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -729,4 +729,25 @@ class RamlModelUniquePlatformReportTest extends UniquePlatformReportGenTest {
test("json with object as key throws violation") {
validate("/raml/json-example-with-object-as-key.raml", Some("json-example-with-object-as-key.report"))
}

test("annotation without definition") {
validate("/raml/annotation-without-definition.raml", Some("annotation-without-definition.report"))
}

test("annotation with definition") {
validate("/raml/annotation-with-definition.raml", None)
}

test("multiple annotations with definition in the same branch") {
validate("/raml/annotation-with-definition-multiple.raml", None)
}

test("multiple annotations without definition 1") {
validate("/raml/annotation-mixed-1.raml", Some("annotation-mixed-1.report"))
}

// TODO this should show 2 errors and is showing only 1
test("multiple annotations without definition 2") {
validate("/raml/annotation-mixed-2.raml", Some("annotation-mixed-2.report"))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import amf.aml.internal.semantic.{SemanticExtensionsFacade, SemanticExtensionsFa
import amf.core.client.scala.model.domain.extensions.{CustomDomainProperty, DomainExtension}
import amf.core.client.scala.model.domain.{AmfArray, AmfObject}
import amf.core.client.scala.parse.document.{ErrorHandlingContext, ParserContext}
import amf.core.internal.annotations.{LexicalInformation, SourceAST}
import amf.core.internal.datanode.{DataNodeParser, DataNodeParserContext}
import amf.core.internal.metamodel.domain.DomainElementModel
import amf.core.internal.metamodel.domain.DomainElementModel.CustomDomainProperties
import amf.core.internal.metamodel.domain.extensions.DomainExtensionModel
import amf.core.internal.parser.domain._
import amf.core.internal.parser.{LimitedParseConfig, YMapOps}
import amf.shapes.client.scala.model.domain.AnyShape
import amf.shapes.internal.annotations.OrphanOasExtension
import amf.shapes.internal.spec.ShapeParserContext
import amf.shapes.internal.spec.common.parser.AnnotationParser.parseExtensions
Expand Down Expand Up @@ -76,12 +76,15 @@ object AnnotationParser {
semanticParser: Option[SemanticExtensionsFacade]
)(implicit ctx: ErrorHandlingContext): Option[DomainExtension] = {
semanticParser.flatMap { parser =>
val nextCtx = ParserContext(config = LimitedParseConfig(ctx.eh, parser.registry))
parser.parse(elementTypes, entry, nextCtx, "nonImportantId")
val nextCtx = ParserContext(config = LimitedParseConfig(ctx.eh, parser.registry))
val maybeExtension = parser.parse(elementTypes, entry, nextCtx, "nonImportantId")
// Inject and anyShape inside the SemEx to avoid validation of annotationType definition
maybeExtension.foreach(_.definedBy.withSchema(AnyShape()))
maybeExtension
}
}

private def entryKey(entry: YMapEntry) = {
private def entryKey(entry: YMapEntry): String = {
entry.key.asOption[YScalar].map(_.text).getOrElse(entry.key.toString)
}
}
Expand Down

0 comments on commit 3cdcd54

Please sign in to comment.