Skip to content
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

W-11187481 - Added default shape to SemEx CustomDomainProperty #1413

Merged
merged 2 commits into from
May 24, 2022
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
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