Commit dadf706e authored by Günter Hipler's avatar Günter Hipler
Browse files

first getRequests against dummy index

enhanced error handling for wrong verbs based on algebraic data types
parent 89cef8b7
Pipeline #12652 passed with stage
in 2 minutes and 10 seconds
package controllers
import javax.inject.Inject
import modules.{ElasticsearchComponent, OaiRepository}
import org.swissbib.memobase.oai.request.OaiRequest
import modules.OaiRepository
import org.swissbib.memobase.oai.request.{OaiRequest, OaiRequestIllegalVerb}
import org.swissbib.memobase.oai.common.verb.OaiVerb
import org.swissbib.memobase.oai.common.verb.OaiVerb.{OaiVerb, WRONGVERB, getVerb}
import play.api.Configuration
import play.api.mvc.{AbstractController, Action, AnyContent, ControllerComponents, Rendering}
import scala.util.{Failure, Success, Try}
class OaiController @Inject()(cc: ControllerComponents,
config: Configuration,
repository:OaiRepository,
) extends AbstractController(cc) with Rendering {
......@@ -26,20 +28,32 @@ class OaiController @Inject()(cc: ControllerComponents,
resumptionToken: Option[String]): Action[AnyContent] =
Action { implicit request =>
//Todo has to be wrapped with Try because verb might be wrong
val enumVerb = OaiVerb.withName(verb)
val t = repository
val request = OaiRequest(enumVerb,
metadataPrefix,
set,
from,
until,
identifier,
resumptionToken
)
val oaiRequest = Try[OaiVerb]( OaiVerb.withName(verb)) match {
//only allowed are the OAI defined verb values
//additionally we have to exclude the WRONGVERB value which is used in the Failure pattern to instantiate
//the OaiRequestIllegalVerb type
case Success(v) if v != WRONGVERB => OaiRequest(
v,
metadataPrefix,
set,
from,
until,
identifier,
resumptionToken
)
case _ => OaiRequestIllegalVerb(
//seems to be that Enumeration value and val identifier have to be written in a case sensitive equal way
OaiVerb.withName("WRONGVERB"),
metadataPrefix,
set,
from,
until,
identifier,
resumptionToken
)
}
val response = request.execute(config, repository).createResponse
val response = oaiRequest.execute(config, repository).createResponse
/*
todo: make Writable for Node[Seq]
[info] Compiling 4 Scala sources to /home/swissbib/environment/code/swissbib.repositories/memoriav/gitlab/services/oai/target/scala-2.13/classes ...
......
package modules
import java.util
import com.typesafe.config.Config
import org.elasticsearch.action.get.GetRequest
import org.elasticsearch.client.{RequestOptions, RestHighLevelClient}
......@@ -7,6 +9,7 @@ import org.swissbib.memobase.oai.common.util.ResumptionToken
import play.Environment
import play.api.libs.json.Json
import utilities.Json2XML
import scala.xml.Node
trait ElasticsearchComponent extends OaiRepository {
......@@ -17,18 +20,26 @@ trait ElasticsearchComponent extends OaiRepository {
//to do: another solution necessary in case we decide to use several indices for OAI
val index: String
override def listRecords(from: Option[String], until: Option[String], set: Option[String], resumptionToken: Option[ResumptionToken], metadataPrefix: String): Seq[Node] = ???
override def listRecords(from: Option[String],
until: Option[String],
set: Option[String],
resumptionToken: Option[ResumptionToken],
metadataPrefix: String): Seq[Node] = ???
override def listIdentiers(from: Option[String], until: Option[String], set: Option[String], resumptionToken: Option[ResumptionToken], metadataPrefix: String): Seq[Node] = ???
override def listIdentiers(from: Option[String],
until: Option[String],
set: Option[String],
resumptionToken: Option[ResumptionToken],
metadataPrefix: String): Seq[Node] = ???
override def getRecord(identifier: String, metadataPrefix: String): Option[Node] = {
override def getRecord(identifier: String,
metadataPrefix: String): Option[Node] = {
val getRequest = new GetRequest(index, identifier)
val getResponse = client.get.get(getRequest, RequestOptions.DEFAULT)
//todo: what if response is empty?
val sourceMap = getResponse.getSourceAsMap
Option(Json2XML.singleJsonDoc2Xml(Json.parse(play.libs.Json.toJson(sourceMap).toString)))
val sM : Option[util.Map[String, AnyRef]] = Option(getResponse.getSourceAsMap)
sM.map(hash => Json2XML.singleJsonDoc2Xml(Json.parse(play.libs.Json.toJson(hash).toString)))
}
}
package modules
import com.google.inject.AbstractModule
import com.google.inject.AbstractModule
class ElasticsearchModule extends AbstractModule{
......
......@@ -17,6 +17,7 @@ object OaiVerb extends Enumeration {
val GetRecord: OaiVal = OaiVal("GetRecord")
val ListMetadataFormats: OaiVal = OaiVal("ListMetadataFormats")
val Identify: OaiVal = OaiVal("Identify")
val WRONGVERB: OaiVal = OaiVal("WRONGVERB")
......
......@@ -4,17 +4,34 @@ import modules.OaiRepository
import org.swissbib.memobase.oai.response.OaiResponse
import org.swissbib.memobase.oai.common.verb.OaiVerb
import org.swissbib.memobase.oai.common.verb.OaiVerb.OaiVerb
import org.swissbib.memobase.oai.runner.{GetRecordRunner, IdentifyRunner,
ListIdentifiersRunner, ListMetadataFormatsRunner, ListRecordsRunner, ListSetsRunner}
import org.swissbib.memobase.oai.runner.{GetExceptionRunner, GetRecordRunner, IdentifyRunner, ListIdentifiersRunner, ListMetadataFormatsRunner, ListRecordsRunner, ListSetsRunner}
import play.api.Configuration
case class OaiRequest(verb:OaiVerb,
metadataPrefix: Option[String],
set: Option[String],
from:Option[String],
until:Option[String],
identifier: Option[String],
resumptionToken: Option[String]) {
sealed abstract class UserRequest(val verb:OaiVerb,
val metadataPrefix: Option[String],
val set: Option[String],
val from:Option[String],
val until:Option[String],
val identifier: Option[String],
val resumptionToken: Option[String]) {
def execute(config: Configuration, repository:OaiRepository): OaiResponse
}
case class OaiRequest(override val verb:OaiVerb,
override val metadataPrefix: Option[String],
override val set: Option[String],
override val from:Option[String],
override val until:Option[String],
override val identifier: Option[String],
override val resumptionToken: Option[String]) extends UserRequest(verb,
metadataPrefix,
set,
from,
until,
identifier,
resumptionToken) {
def hasNecessaryArguments:Boolean = {
......@@ -162,7 +179,7 @@ case class OaiRequest(verb:OaiVerb,
//todo: validation for supplied argument
def areArgumentsValid: Boolean = true
def execute(config: Configuration, repository:OaiRepository): OaiResponse = {
override def execute(config: Configuration, repository:OaiRepository): OaiResponse = {
//todo: too much imperative programming, make it more functional!
if (hasNecessaryArguments && areArgumentsValid) {
......@@ -188,3 +205,23 @@ case class OaiRequest(verb:OaiVerb,
}
case class OaiRequestIllegalVerb(override val verb:OaiVerb,
override val metadataPrefix: Option[String],
override val set: Option[String],
override val from:Option[String],
override val until:Option[String],
override val identifier: Option[String],
override val resumptionToken: Option[String]) extends UserRequest(
verb,
metadataPrefix,
set,
from,
until,
identifier,
resumptionToken) {
override def execute(config: Configuration, repository:OaiRepository): OaiResponse =
GetExceptionRunner(config, repository, this).run()
}
\ No newline at end of file
package org.swissbib.memobase.oai.runner
import modules.OaiRepository
import org.swissbib.memobase.oai.request.OaiRequest
import org.swissbib.memobase.oai.response.{GetRecordResponse, IdentifyResponse, ListIdentifiersResponse, ListMetadaFormatsResponse, ListRecordsResponse, ListSetsResponse, OaiResponse}
import org.swissbib.memobase.oai.request.{OaiRequest, UserRequest}
import org.swissbib.memobase.oai.response.{GetRecordResponse, IdentifyResponse, ListIdentifiersResponse,
ListMetadaFormatsResponse, ListRecordsResponse, ListSetsResponse, OaiResponse}
import play.api.Configuration
import scala.xml.Node
abstract class OaiRequestRunner (val config: Configuration,
val repository: OaiRepository,
val request: OaiRequest){
val request: UserRequest){
var result: Option[Node] = None
def run(): OaiResponse
}
//todo: this is wrong!
sealed case class IdentifyRunner(override val config: Configuration,
override val repository: OaiRepository,
override val request: OaiRequest) extends OaiRequestRunner( config,
......@@ -33,7 +38,8 @@ case class GetRecordRunner(override val config: Configuration,
override def run(): OaiResponse = {
//Identify doesnit need any action on repository
val node = repository.getRecord(request.identifier.get,request.metadataPrefix.get)
result = repository.getRecord(request.identifier.get,request.metadataPrefix.get)
GetRecordResponse(this)
}
......@@ -83,6 +89,15 @@ case class ListSetsRunner(override val config: Configuration,
}
case class GetExceptionRunner(override val config: Configuration,
override val repository: OaiRepository,
override val request: UserRequest) extends OaiRequestRunner( config,
repository,
request) {
override def run(): OaiResponse = ???
}
/*
I think we do not need it any more...
*/
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.19-->
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key for="graphml" id="d7" yfiles.type="resources"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d0"/>
<node id="n0">
<data key="d4" xml:space="preserve"/>
<data key="d5"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="91.0" width="158.0" x="152.0" y="131.0"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="107.568359375" x="25.2158203125" xml:space="preserve" y="25.96875">OaiRepository<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="&lt;&lt;trait&gt;&gt;" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve">listRecords
listIdentifiers
getRecord</y:MethodLabel>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n1">
<data key="d4" xml:space="preserve"/>
<data key="d5"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="68.0" width="248.0" x="107.0" y="314.0"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="184.7177734375" x="31.64111328125" xml:space="preserve" y="25.96875">ElasticsearchComponent<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="&lt;&lt;trait&gt;&gt;" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n2">
<data key="d4" xml:space="preserve"/>
<data key="d5"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="28.0" width="248.0" x="433.0" y="324.0"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="205.24609375" x="21.376953125" xml:space="preserve" y="3.0">com.typesafe.config.Config<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n3">
<data key="d4" xml:space="preserve"/>
<data key="d5"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="28.0" width="248.0" x="439.0" y="372.0"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="133.44140625" x="57.279296875" xml:space="preserve" y="3.0">play.Environment<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n4">
<data key="d4" xml:space="preserve"/>
<data key="d5"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="34.0" width="248.0" x="107.0" y="468.0"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="143.6611328125" x="52.16943359375" xml:space="preserve" y="3.0">ElasticsearchClient<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n5">
<data key="d4" xml:space="preserve"/>
<data key="d5"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="34.0" width="248.0" x="433.5" y="532.0"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="154.62353515625" x="46.688232421875" xml:space="preserve" y="3.0">ElasticsearchModule<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n6">
<data key="d4" xml:space="preserve"/>
<data key="d5"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="34.0" width="259.0" x="428.0" y="468.0"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="255.7734375" x="1.61328125" xml:space="preserve" y="3.0">com.google.inject.AbstractModule<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n7">
<data key="d4" xml:space="preserve"/>
<data key="d5"/>
<data key="d6">
<y:UMLClassNode>
<y:Geometry height="91.0" width="248.0" x="107.0" y="665.0"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="101.703125" x="73.1484375" xml:space="preserve" y="3.0">OaiController<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve">handleRequest</y:MethodLabel>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<edge id="e0" source="n1" target="n0">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n1" target="n2">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n1" target="n3">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n4" target="n1">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n5" target="n6">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n5" target="n4">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="332.0" y="549.0"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="88.826171875" x="-137.19988495254114" xml:space="preserve" y="-38.984375">&lt;&lt;creates&gt;&gt;<y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.8328809211504608" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n7" target="n4">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d7">
<y:Resources/>
</data>
</graphml>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment