Skip to content

Publish 5.4.1 #619

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 17 commits into from
Jul 26, 2023
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
5 changes: 3 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ val ivyLocal = Resolver.file("ivy", file(Path.userHome.absolutePath + "/.ivy2/lo

name := "amf-core"
ThisBuild / scalaVersion := "2.12.15"
ThisBuild / version := "5.4.0"
ThisBuild / version := "5.4.1"

publish := {}

Expand All @@ -29,7 +29,7 @@ lazy val workspaceDirectory: File =
case _ => Path.userHome / "mulesoft"
}

val syamlVersion = "2.0.332"
val syamlVersion = "2.0.334"

lazy val syamlJVMRef = ProjectRef(workspaceDirectory / "syaml", "syamlJVM")
lazy val syamlJSRef = ProjectRef(workspaceDirectory / "syaml", "syamlJS")
Expand Down Expand Up @@ -62,6 +62,7 @@ lazy val core = crossProject(JSPlatform, JVMPlatform)
Compile / fullOptJS / artifactPath := baseDirectory.value / "target" / "artifact" / "amf-core-module.js"
)
.disablePlugins(SonarPlugin)
.settings(AutomaticModuleName.settings("amf.core"))

lazy val coreJVM = core.jvm
.in(file("./jvm"))
Expand Down
11 changes: 11 additions & 0 deletions project/AutomaticModuleName.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import sbt.*
import sbt.Keys.*

object AutomaticModuleName {
def settings(name: String): Seq[Def.Setting[_]] = {
val pair = ("Automatic-Module-Name" -> name)
Seq(
Compile / packageBin / packageOptions += Package.ManifestAttributes(pair)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package amf.core.client.common

import amf.core.internal.remote.AmfException

import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}

@JSExportTopLevel("ExceptionUtil")
@JSExportAll
object ExceptionUtil {

/** Checks if some AmfObject is of an specific type
*
* @param exception
* AmfObject to validate the type
* @param exceptionCode
* IRI of the type wanted to validate. It could be one of the IRIs defined in [[AmfExceptionCode]] or other
* @return
* a boolean value indicating if the AmfElement is of that type (true if it is, false if not)
*/
def isExceptionType(exception: AmfException, exceptionCode: String): Boolean = {
exception.code == exceptionCode
}

}

@JSExportTopLevel("AmfExceptionCode")
@JSExportAll
object AmfExceptionCode {

val ResourceNotFound: String = "resource-not-found"
val PathResolutionError: String = "path-resolution-error"
val UnsupportedUrlScheme: String = "unsupported-url-scheme"
val UnexpectedStatusCode: String = "unexpected-status-code"
val NetworkError: String = "network-error"
val SocketTimeout: String = "socket-timeout"
val FileNotFound: String = "file-not-found"

}

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import amf.core.client.platform.reference.UnitCache
import amf.core.client.platform.resource.ResourceLoader
import amf.core.client.platform.transform.TransformationPipeline
import amf.core.client.platform.validation.payload.AMFShapePayloadValidationPlugin
import amf.core.client.platform.adoption.{IdAdopter, IdAdopterProvider}
import amf.core.client.scala.{AMFGraphConfiguration => InternalGraphConfiguration}
import amf.core.internal.convert.ClientErrorHandlerConverter._
import amf.core.internal.convert.CoreClientConverters._
Expand Down Expand Up @@ -56,6 +57,9 @@ class AMFGraphConfiguration private[amf] (private[amf] val _internal: InternalGr
def withShapePayloadPlugin(plugin: AMFShapePayloadValidationPlugin): AMFGraphConfiguration =
_internal.withPlugin(PayloadValidationPluginMatcher.asInternal(plugin))

def withIdAdopterProvider(idAdopterProvider: IdAdopterProvider): AMFGraphConfiguration =
_internal.withIdAdopterProvider(idAdopterProvider)

private[amf] def getExecutionContext: ExecutionContext = _internal.getExecutionContext

}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package amf.core.client.platform.adoption

import amf.core.client.platform.model.AmfObjectWrapper
import amf.core.client.scala.adoption.{IdAdopter => InternalIdAdopter}
import amf.core.internal.convert.CoreClientConverters._

import scala.scalajs.js.annotation.JSExportAll

@JSExportAll
class IdAdopter(private[amf] val _internal: InternalIdAdopter) {

def this(initialId: String) = this(new InternalIdAdopter(initialId))
def this(initialId: String, idMaker: IdMaker) = this(new InternalIdAdopter(initialId, idMaker))

def adoptFromRoot(initialElem: AmfObjectWrapper): Unit = _internal.adoptFromRoot(initialElem)
def adoptFromRelative(initialElem: AmfObjectWrapper): Unit = _internal.adoptFromRoot(initialElem)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package amf.core.client.platform.adoption

import scala.scalajs.js.annotation.JSExportAll

@JSExportAll
trait IdAdopterProvider {
def idAdopter(initialId: String): IdAdopter

def idAdopter(initialId: String, idMaker: IdMaker): IdAdopter
}

class DefaultIdAdopterProvider extends IdAdopterProvider {
override def idAdopter(initialId: String) = new IdAdopter(initialId)
override def idAdopter(initialId: String, idMaker: IdMaker) =
new IdAdopter(initialId, idMaker) // Shall we expose the idmaker?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package amf.core.client.platform.adoption

import scala.scalajs.js.annotation.JSExportAll

@JSExportAll
trait IdMaker {
def makeId(parent: String, element: String): String
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package amf.core.client.platform.resource

import amf.core.client.common.AmfExceptionCode
import amf.core.internal.remote.FileLoaderException

import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}

@JSExportAll
@JSExportTopLevel("ResourceNotFound")
class ResourceNotFound(val msj: String) extends FileLoaderException(msj, new Throwable(msj))
class ResourceNotFound(val msj: String)
extends FileLoaderException(AmfExceptionCode.ResourceNotFound, msj, new Throwable(msj))
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package amf.core.client.scala

import amf.core.client.scala.model.document.BaseUnit
import amf.core.client.scala.model.domain.AmfObject
import amf.core.client.scala.parse.AMFParser
import amf.core.client.scala.parse.document.ParsedDocument
import amf.core.client.scala.render.AMFRenderer
import amf.core.client.scala.transform.AMFTransformer
import amf.core.client.scala.validation.{AMFValidationReport, AMFValidator}
import amf.core.internal.adoption.IdAdopter
import org.yaml.builder.DocBuilder

import scala.concurrent.{ExecutionContext, Future}
Expand Down Expand Up @@ -125,5 +123,5 @@ class AMFGraphBaseUnitClient private[amf] (protected val configuration: AMFGraph
def validate(baseUnit: BaseUnit): Future[AMFValidationReport] = AMFValidator.validate(baseUnit, configuration)

/** defines base uri of the BaseUnit, adopting ids of all nested nodes. */
def setBaseUri(unit: BaseUnit, base: String): Unit = new IdAdopter(unit, base).adoptFromRoot()
def setBaseUri(unit: BaseUnit, base: String): Unit = configuration.idAdopterProvider.adoptFromRoot(unit, base)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package amf.core.client.scala

import amf.core.client.common.validation.ProfileName
import amf.core.client.scala.adoption.{DefaultIdAdopterProvider, IdAdopterProvider}
import amf.core.client.scala.config._
import amf.core.client.scala.errorhandling.{AMFErrorHandler, DefaultErrorHandlerProvider, ErrorHandlerProvider}
import amf.core.client.scala.execution.ExecutionEnvironment
Expand Down Expand Up @@ -36,7 +37,8 @@ object AMFGraphConfiguration {
DefaultErrorHandlerProvider,
AMFRegistry.empty,
Set.empty,
AMFOptions.default()
AMFOptions.default(),
new DefaultIdAdopterProvider()
)
}

Expand All @@ -55,7 +57,8 @@ object AMFGraphConfiguration {
.withEntities(CoreEntities.entities ++ DataNodeEntities.entities)
.withAnnotations(CoreSerializableAnnotations.annotations),
Set.empty,
AMFOptions.default()
AMFOptions.default(),
new DefaultIdAdopterProvider()
).withRootParsePlugin(AMFGraphParsePlugin())
.withPlugins(List(AMFGraphRenderPlugin, SyamlSyntaxParsePlugin, SyamlSyntaxRenderPlugin))
.withTransformationPipeline(BasicTransformationPipeline())
Expand Down Expand Up @@ -84,8 +87,9 @@ class AMFGraphConfiguration private[amf] (
override private[amf] val errorHandlerProvider: ErrorHandlerProvider,
override private[amf] val registry: AMFRegistry,
override private[amf] val listeners: Set[AMFEventListener],
override private[amf] val options: AMFOptions
) extends BaseAMFConfigurationSetter(resolvers, errorHandlerProvider, registry, listeners, options) { // break platform into more specific classes?
override private[amf] val options: AMFOptions,
override private[amf] val idAdopterProvider: IdAdopterProvider
) extends BaseAMFConfigurationSetter(resolvers, errorHandlerProvider, registry, listeners, options, idAdopterProvider) { // break platform into more specific classes?

/** Contains common AMF graph operations associated to documents */
def baseUnitClient(): AMFGraphBaseUnitClient = new AMFGraphBaseUnitClient(this)
Expand Down Expand Up @@ -164,16 +168,20 @@ class AMFGraphConfiguration private[amf] (
def withExecutionEnvironment(executionEnv: ExecutionEnvironment): AMFGraphConfiguration =
super._withExecutionEnvironment(executionEnv)

def withIdAdopterProvider(idAdopterProvider: IdAdopterProvider): AMFGraphConfiguration =
super._withIdAdopterProvider(idAdopterProvider)

protected[amf] def emptyPlugins(): AMFGraphConfiguration = copy(registry = registry.emptyPlugins())

protected def copy(
resolvers: AMFResolvers = resolvers,
errorHandlerProvider: ErrorHandlerProvider = errorHandlerProvider,
registry: AMFRegistry = registry,
listeners: Set[AMFEventListener] = Set.empty,
options: AMFOptions = options
options: AMFOptions = options,
idAdopterProvider: IdAdopterProvider = idAdopterProvider
): AMFGraphConfiguration = {
new AMFGraphConfiguration(resolvers, errorHandlerProvider, registry, listeners, options)
new AMFGraphConfiguration(resolvers, errorHandlerProvider, registry, listeners, options, idAdopterProvider)
}

private[amf] def emptyEntities(): AMFGraphConfiguration = super._emptyEntities()
Expand All @@ -194,7 +202,8 @@ sealed abstract class BaseAMFConfigurationSetter(
private[amf] val errorHandlerProvider: ErrorHandlerProvider,
private[amf] val registry: AMFRegistry,
private[amf] val listeners: Set[AMFEventListener],
private[amf] val options: AMFOptions
private[amf] val options: AMFOptions,
private[amf] val idAdopterProvider: IdAdopterProvider
) {
protected def _withParsingOptions[T](parsingOptions: ParsingOptions): T =
copy(options = options.copy(parsingOptions = parsingOptions)).asInstanceOf[T]
Expand Down Expand Up @@ -266,12 +275,16 @@ sealed abstract class BaseAMFConfigurationSetter(
protected def _withExecutionEnvironment[T](executionEnv: ExecutionEnvironment): T =
copy(resolvers = resolvers.withExecutionEnvironment(executionEnv)).asInstanceOf[T]

protected def _withIdAdopterProvider[T](idAdopterProvider: IdAdopterProvider): T =
copy(idAdopterProvider = idAdopterProvider).asInstanceOf[T]

protected def copy(
resolvers: AMFResolvers = resolvers,
errorHandlerProvider: ErrorHandlerProvider = errorHandlerProvider,
registry: AMFRegistry = registry,
listeners: Set[AMFEventListener] = Set.empty,
options: AMFOptions = options
options: AMFOptions = options,
idAdopterProvider: IdAdopterProvider = idAdopterProvider
): BaseAMFConfigurationSetter

}
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
package amf.core.internal.adoption
package amf.core.client.scala.adoption

import amf.core.client.scala.model.document.BaseUnit
import amf.core.client.scala.model.domain.{AmfArray, AmfElement, AmfObject, AmfScalar}
import amf.core.internal.adoption.{AdoptionDependantCalls, BaseUnitFieldAdoptionOrdering, GenericFieldAdoptionOrdering}
import amf.core.internal.annotations.DomainExtensionAnnotation
import amf.core.internal.metamodel.Field
import amf.core.internal.parser.domain.FieldEntry
import amf.core.internal.utils.{AmfStrings, IdCounter}
import org.mulesoft.common.collections.FilterType
import org.mulesoft.common.core.CachedFunction
import org.mulesoft.common.functional.MonadInstances.{Identity, identityMonad}

import scala.collection.mutable


class IdAdopter(
initialElem: AmfObject,
initialId: String,
private val adopted: mutable.Map[String, AmfObject] = mutable.Map.empty
) {
initialId: String,
private val idMaker: IdMaker = new DefaultIdMaker(),
private val adopted: mutable.Map[String, AmfObject] = mutable.Map.empty
) {

def adoptFromRoot(initialElem: AmfObject): Unit = adopt(initialElem, isRoot = true)

def adoptFromRoot(): Unit = adopt(isRoot = true)
def adoptFromRelative(): Unit = adopt(isRoot = false)
def adoptFromRelative(initialElem: AmfObject): Unit = adopt(initialElem, isRoot = false)

private def adopt(isRoot: Boolean): Unit = {
adoptElement(isRoot)
private[amf] def adopt(initialElem: AmfObject, isRoot: Boolean): Unit = {
adoptElement(initialElem, isRoot)
adopted.values.filterType[AdoptionDependantCalls].foreach(_.run())
}

/** adopts the initial element and all of its nested element in a BFS manner
* @param isRoot:
* if the initialElement is the root base unit, used to place fragment in id.
*/
private def adoptElement(isRoot: Boolean): Unit = {
*
* @param isRoot :
* if the initialElement is the root base unit, used to place fragment in id.
*/
private def adoptElement(initialElem: AmfObject, isRoot: Boolean): Unit = {
val adoptionQueue: mutable.Queue[PendingAdoption] = new mutable.Queue()
adoptionQueue.enqueue(PendingAdoption(initialElem, initialId, isRoot))
adoptQueue(adoptionQueue)
Expand Down Expand Up @@ -59,59 +59,33 @@ class IdAdopter(

private def traverseArrayValues(array: AmfArray, id: String): Seq[PendingAdoption] = {
array.values.zipWithIndex.map { case (item, i) =>
val element = componentId(item).getOrElse(i.toString)
val generatedId = makeId(id, element)
val generatedId = idMaker.makeArrayElementId(id, i, item)
PendingAdoption(item, generatedId)
}
}

private def traverseObjFields(obj: AmfObject, isRoot: Boolean): Seq[PendingAdoption] = {
getOrderedFields(obj).map { field =>
val generatedId = makeId(obj.id + withFragment(isRoot), relativeName(field))
val generatedId = idMaker.makeId(obj, field, isRoot)
PendingAdoption(field.element, generatedId)
}.toList
}

/** this is done specifically because of RAML scalar valued nodes, extension is only stored in annotation contained in
* AmfScalar and needs to have id defined due to potential validations
*/
* AmfScalar and needs to have id defined due to potential validations
*/
private def traverseDomainExtensionAnnotation(scalar: AmfScalar, id: String): Seq[PendingAdoption] = {
scalar.annotations.collect[PendingAdoption] { case domainAnnotation: DomainExtensionAnnotation =>
val extension = domainAnnotation.extension
val generatedId = makeId(id, extension.componentId)
val extension = domainAnnotation.extension
val generatedId = idMaker.makeId(id, extension.componentId)
PendingAdoption(extension, generatedId)
}
}

private def withFragment(isRoot: Boolean) = if (isRoot) "#" else ""

private def relativeName(field: FieldEntry): String =
componentId(field.element).getOrElse(fieldDisplayName.runCached(field.field))

val fieldDisplayName: CachedFunction[Field, String, Identity] = CachedFunction.from[Field, String] { field =>
field.doc.displayName.urlComponentEncoded
}

private def componentId(element: AmfElement): Option[String] = element match {
case obj: AmfObject if obj.componentId.nonEmpty => Some(obj.componentId.stripPrefix("/"))
case _ => None
}

val createdIds: mutable.Set[String] = mutable.Set.empty
val idGenerator = new IdCounter()

private def makeId(parent: String, element: String): String = {
val newId = parent + "/" + element
val finalId =
if (createdIds.contains(newId)) idGenerator.genId(newId) else newId // ensures no duplicate ids will be created
createdIds.add(finalId)
finalId
}

private def getOrderedFields(obj: AmfObject): Iterable[FieldEntry] = {
val criteria = obj match {
case _: BaseUnit => BaseUnitFieldAdoptionOrdering
case _ => GenericFieldAdoptionOrdering
case _ => GenericFieldAdoptionOrdering
}
criteria.fields(obj)
}
Expand Down
Loading