io.atomicbits.scraml.parser.model.Resource.scala Maven / Gradle / Ivy
/*
* (C) Copyright 2015 Atomic BITS (http://atomicbits.io).
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Affero General Public License
* (AGPL) version 3.0 which accompanies this distribution, and is available in
* the LICENSE file or at http://www.gnu.org/licenses/agpl-3.0.en.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* Contributors:
* Peter Rigole
*
*/
package io.atomicbits.scraml.parser.model
import scala.collection.JavaConverters._
/**
* Created by peter on 17/05/15, Atomic BITS bvba (http://atomicbits.io).
*/
case class Resource(urlSegment: String,
urlParameter: Option[Parameter] = None,
actions: List[Action] = List.empty,
resources: List[Resource] = List.empty,
parent: Option[Resource] = None)
object Resource {
def apply(resource: org.raml.model.Resource): Resource = {
val relativeUri = resource.getRelativeUri
val uriParameters: Map[String, Parameter] =
Transformer.transformMap[org.raml.model.parameter.UriParameter, Parameter](Parameter(_))(resource.getUriParameters)
val oldActionsList: List[org.raml.model.Action] = resource.getActions.values().asScala.toSet.toList
val newActionList = oldActionsList.map(a => Action(a))
val allSubResources: List[Resource] =
Transformer.transformMap[org.raml.model.Resource, Resource](Resource(_))(resource.getResources).values.toList
val (emptySubResources, nonEmptySubResources) = allSubResources.partition(_.urlSegment.isEmpty)
val actionList = newActionList ++ emptySubResources.flatMap(_.actions)
// Group all subresources with the same urlSegment and urlParameter
val groupedSubResources: List[List[Resource]] =
nonEmptySubResources.groupBy(resource => (resource.urlSegment, resource.urlParameter)).values.toList
// Merge all actions and subresources of all resources that have the same (urlSegment, urlParameter)
def mergeResources(resources: List[Resource]): Resource = {
resources.reduce { (resourceA, resourceB) =>
resourceA.copy(actions = resourceA.actions ++ resourceB.actions, resources = resourceA.resources ++ resourceB.resources)
}
}
val subResources = groupedSubResources.map(mergeResources)
/**
* Resources in the Java RAML model can have relative URLs that consist of multiple segments in a single Resource,
* e.g.: /rest/some/path/to/{param}/a/resource
* Our DSL generation would benefit form a breakdown of this path into nested resources. The all resulting
* resources would just be path elements to the last resource, which then contains the actions and sub
* resources of the original resource.
*/
/**
* Breakdown of the url segments into nested resources.
* @param urlSegments The URL segments.
*/
def breakdownResourceUrl(urlSegments: List[String]): Resource = {
def buildResourceSegment(segment: String): Resource = {
if (segment.startsWith("{") && segment.endsWith("}")) {
val pathParameterName = segment.stripPrefix("{").stripSuffix("}")
val pathParameterMeta = uriParameters.get(pathParameterName)
Resource(pathParameterName, pathParameterMeta)
} else {
Resource(segment)
}
}
def connectParentChildren(parent: Resource, children: List[Resource]): Resource = {
val childrenWithUpdatedParent = children.map(_.copy(parent = Some(parent)))
parent.copy(resources = childrenWithUpdatedParent)
}
urlSegments match {
case segment :: Nil =>
val resource: Resource = buildResourceSegment(segment)
val connectedResource: Resource = connectParentChildren(resource, subResources)
connectedResource.copy(actions = actionList)
case segment :: segs =>
val resource: Resource = buildResourceSegment(segment)
connectParentChildren(resource, List(breakdownResourceUrl(segs)))
// Todo: handle the case Nil without introducing an extra 'root' path
case Nil =>
val resource: Resource = buildResourceSegment("")
val connectedResource: Resource = connectParentChildren(resource, subResources)
connectedResource.copy(actions = actionList)
}
}
// Make sure we can handle the root segment as wel
if (relativeUri == "/")
breakdownResourceUrl(Nil)
else
breakdownResourceUrl(relativeUri.split('/').toList.filter(!_.isEmpty))
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy