DataModel.scala 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  1. /*
  2. * Copyright (C) 2020 Prasoon Joshi
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. */
  17. package models
  18. import utils.FileUtils
  19. import java.util.UUID
  20. import play.api.data._
  21. import com.lucidchart.open.xtract.{XmlReader, __}
  22. import com.lucidchart.open.xtract.XmlReader._
  23. import com.lucidchart.open.xtract._
  24. import play.api.libs.functional.syntax._
  25. import cats.syntax.all._
  26. import org.apache.tinkerpop.gremlin.structure.Vertex
  27. import java.{util => ju}
  28. import scala.xml.NodeSeq
  29. import scala.xml.Node
  30. import java.time.LocalDate
  31. //Start --- Infrastructure models
  32. /**
  33. * These set of classes hold state of execution to be
  34. * passed around from/to the client. These are not persisted.
  35. * No `graphId` is needed, they are not a subtype of `NiosxEntity`.
  36. */
  37. case class Page(edges: Seq[PageEdge], pageInfo: PageInfo)
  38. case class PageEdge(
  39. node: MilliEntity,
  40. cursor: String,
  41. offset: Long,
  42. isDirectMatch: Boolean,
  43. annotationMatchCount: Int)
  44. import graphql.SchemaInputObjects._
  45. case class PageInfo(
  46. pageNumber: Int,
  47. endCursor: String,
  48. hasNextPage: Boolean,
  49. filters: EntityFilter)
  50. //import graphql.SchemaInputObjects.GraphId
  51. //case class EntityFilterAlt(
  52. // blob: String,
  53. // lang: Option[Seq[GraphId]] = None,
  54. // dateRange: Option[DateRange] = None,
  55. // subjects: Option[Seq[GraphId]] = None,
  56. // people: Option[Seq[GraphId]] = None,
  57. // places: Option[Seq[GraphId]] = None,
  58. // partners: Option[Seq[GraphId]] = None)
  59. case class EntityFilter(
  60. blob: String,
  61. lang: Option[Seq[Language]] = None,
  62. dateRange: Option[DateRange] = None,
  63. subjects: Option[Seq[Subject]] = None,
  64. people: Option[Seq[Person]] = None,
  65. places: Option[Seq[Place]] = None,
  66. partners: Option[Seq[Partner]] = None)
  67. //object EntityFilter {
  68. // def fromFilterInput(in: EntityFilterInput) =
  69. // new EntityFilter(
  70. // blob = in.blob,
  71. // lang = in.lang,
  72. // dateRange = in.dateRange.map(DateRange.fromDateRangeInput(_)),
  73. // subjects = in.subjects,
  74. // people = in.people,
  75. // places = in.places,
  76. // partners = in.partners)
  77. // }
  78. // mediaTypes: Seq[MediaType.Value] = Nil,
  79. // resultCount: FilterResultCount)
  80. case class FilterResultCount(
  81. lang: Long,
  82. date: Long,
  83. subjects: Long,
  84. people: Long,
  85. places: Long,
  86. partners: Long,
  87. mediaTypes: Long)
  88. //End --- Infrastructure models
  89. trait WebResource {
  90. def iri: String
  91. }
  92. /** Typeclass that converts a metadata type to a NiosxEntity
  93. *
  94. * Provide implicit instances to convert between different metadata types
  95. * and NiosxEntity types.
  96. */
  97. trait Metadata[M, N] {
  98. def toEntity(m: M): N
  99. }
  100. object Metadata {
  101. def apply[M, N](implicit m: Metadata[M, N]): Metadata[M, N] = m
  102. def instance[M, N](f: M => N): Metadata[M, N] =
  103. new Metadata[M, N] {
  104. def toEntity(m: M): N = f(m)
  105. }
  106. implicit val Ead3Instance: Metadata[Ead, MilliEntity] =
  107. instance({ e: Ead =>
  108. MilliEntity(
  109. graphId = FileUtils.getNewGraphId,
  110. agencyCode = e.control.maintenanceAgency.agencyCode.fold("")(_.text),
  111. recordId = e.control.recordId.text,
  112. unitId = "",
  113. title = "",
  114. creator = "",
  115. dateOfCreation = "",
  116. extent = "",
  117. level = e.archDesc.attributes.level,
  118. partner = Partner.mockPartner)
  119. //None)
  120. })
  121. }
  122. trait Level
  123. object Level extends Enumeration {
  124. val Item, Series, SubSeries = Value
  125. }
  126. trait Collection {
  127. def level: Level
  128. }
  129. object EntityType extends Enumeration {
  130. type Typ = Value
  131. val Subject, Place, Language, MilliEntity, Annotation,
  132. Person, Partner, User, Ni, Client, Software, LocalResource,
  133. TextualBody, SpecificResource,
  134. Dataset, Image, Video, Sound, Text = Value
  135. }
  136. import models.EntityType.{Typ => Typ}
  137. import models.{EntityType => ET}
  138. import sangria.macros.derive._
  139. object SangriaMiter {
  140. implicit val typEnumType = deriveEnumType[models.EntityType.Value]()
  141. }
  142. trait NiosxEntity {
  143. def graphId: String
  144. def typ: Typ
  145. def freeNode: Boolean = true
  146. }
  147. case class Ni(graphId: String = FileUtils.getNewGraphId,
  148. typ: Typ = ET.Ni,
  149. title: String,
  150. image: String,
  151. IRI: String) extends NiosxEntity
  152. case class Subject(graphId: String = FileUtils.getNewGraphId,
  153. typ: Typ = ET.Subject,
  154. prefLabel: String,
  155. inScheme: String,
  156. id: String,
  157. isSelected: Boolean = true) extends NiosxEntity
  158. import repository.UserRole
  159. case class NiosxUser(graphId: String = FileUtils.getNewGraphId,
  160. typ: Typ = ET.User,
  161. username: String,
  162. passHash: String,
  163. role: UserRole,
  164. permissions: List[String]) extends NiosxEntity
  165. case class AuthPayload(token: String,
  166. user: NiosxUser)
  167. object MediaType extends Enumeration {
  168. val IMAGE, VIDEO, TEXT = Value
  169. }
  170. object ImageSize extends Enumeration {
  171. val SMALL, MEDIUM, LARGE = Value
  172. }
  173. case class Image(graphId: String = FileUtils.getNewGraphId,
  174. typ: Typ = ET.Image,
  175. src: String,
  176. alt: Option[String] = None,
  177. size: ImageSize.Value) extends NiosxEntity
  178. case class MilliEntity(graphId: String = FileUtils.getNewGraphId,
  179. typ: Typ = ET.MilliEntity,
  180. agencyCode: String,
  181. recordId: String,
  182. unitId: String,
  183. title: String,
  184. creator: String,
  185. dateOfCreation: String,
  186. extent: String,
  187. level: String,
  188. partner: Partner,
  189. subjects: Seq[Subject] = Nil,
  190. images: Seq[Image] = Nil,
  191. description: Option[String] = None,
  192. location: Option[String] = None,
  193. accessRestrict: Option[String] = None,
  194. useRestrict: Option[String] = None,
  195. language: Option[String] = None, //TODO: Change to Language type
  196. unitType: Option[String] = None,
  197. format: Option[String] = None,
  198. annotations: Seq[Annotation] = Nil) extends NiosxEntity
  199. trait FilterLike {
  200. val isSelected: Boolean = true
  201. }
  202. case class Language(graphId: String = FileUtils.getNewGraphId,
  203. typ: Typ = ET.Language,
  204. langId: String,
  205. displayName: String,
  206. isSelected: Boolean = true ) extends NiosxEntity
  207. case class DateRange(from: LocalDate, to: LocalDate)
  208. object DateRange {
  209. def fromDateRangeInput(in: DateRangeInput) =
  210. new DateRange(
  211. from = LocalDate.parse(in.from),
  212. to = LocalDate.parse(in.to)
  213. )
  214. }
  215. //TODO: Person trait with `LegalPerson`, etc.
  216. case class Person(graphId: String,
  217. typ: Typ = ET.Person,
  218. displayName: String,
  219. isSelected: Boolean = true) extends Agent
  220. case class Place(graphId: String = FileUtils.getNewGraphId,
  221. typ: Typ = ET.Place,
  222. lat: Double,
  223. lon: Double,
  224. displayName: String,
  225. isSelected: Boolean = true) extends NiosxEntity
  226. case class Partner(graphId: String = FileUtils.getNewGraphId,
  227. typ: Typ = ET.Partner,
  228. displayName: String,
  229. isSelected: Boolean = true) extends NiosxEntity
  230. object Partner {
  231. def mockPartner: Partner =
  232. Partner(displayName = "Mock Partner")
  233. }
  234. //Begin: Annotation types
  235. sealed trait NiosxConcept {
  236. def name: String
  237. }
  238. object NiosxConcept {
  239. def apply(name: String): NiosxConcept = name match {
  240. case "ScopeContent" => ScopeContent
  241. case "comment" => Comment
  242. case "subjectHeading" => SubjectHeading
  243. case c => UserDefinedConcept(c)
  244. case _ => GenericConcept
  245. }
  246. }
  247. //This case class can be enriched to include desired properties
  248. //for the edge that this user defined concept defines the annotation
  249. //object to be.
  250. case class UserDefinedConcept(name: String) extends NiosxConcept
  251. case object GenericConcept extends NiosxConcept {
  252. def name = "annotation"
  253. }
  254. case object ScopeContent extends NiosxConcept {
  255. def name = "ScopeContent"
  256. }
  257. case object Comment extends NiosxConcept {
  258. def name = "comment"
  259. }
  260. case object SubjectHeading extends NiosxConcept {
  261. def name = "subjectHeading"
  262. }
  263. case class Annotation(graphId: String,
  264. context: String = "http://www.w3.org/ns/anno.jsonld",
  265. identity: String,
  266. typ: Typ = ET.Annotation,
  267. motivation: String,
  268. creator: AnnoCreator,
  269. created: String,
  270. generator: AnnoGenerator,
  271. generated: String,
  272. body: Option[Seq[BodyType]],
  273. target: Seq[TargetType]) extends NiosxEntity
  274. object Annotation {
  275. def apply(motivation: String,
  276. id: String,
  277. body: Option[Seq[BodyType]],
  278. target: Seq[TargetType]): Annotation = {
  279. val graphId: String = FileUtils.getNewGraphId
  280. val identity = id + graphId
  281. new Annotation(graphId = graphId,
  282. identity = identity,
  283. motivation = motivation,
  284. creator = Agent.mockCreator,
  285. created = ju.Calendar.getInstance().toString(),
  286. generator = Agent.mockGenerator,
  287. generated = ju.Calendar.getInstance().toString,
  288. body = body,
  289. target = target)
  290. }
  291. }
  292. trait Agent extends NiosxEntity
  293. object Agent {
  294. val mockCreator: AnnoCreator =
  295. AnnoCreator(
  296. graphId = "creator_test_" + FileUtils.getNewGraphId,
  297. typ = ET.Software,
  298. name = "Mr. Mock Agent",
  299. nickname = "niosX")
  300. def mockGenerator: AnnoGenerator =
  301. AnnoGenerator(
  302. graphId = "generator_test_" + FileUtils.getNewGraphId,
  303. typ = ET.Software,
  304. name = "Mr. Mock Generator",
  305. homepage = "niosX dot awesome")
  306. }
  307. case class AnnoCreator(graphId: String = FileUtils.getNewGraphId,
  308. typ: Typ,
  309. name: String,
  310. nickname: String) extends NiosxEntity with Agent
  311. case class Client(graphId: String = FileUtils.getNewGraphId,
  312. typ: Typ = ET.Client,
  313. name: String,
  314. homepage: String) extends Agent
  315. case class AnnoGenerator(graphId: String = FileUtils.getNewGraphId,
  316. //override val label: String = "anno_generator",
  317. typ: Typ,
  318. name: String,
  319. homepage: String) extends NiosxEntity with Agent
  320. /*
  321. trait BodyResource
  322. object BodyResource {
  323. def typ: String
  324. def purpose: String
  325. def items: Seq[BodyResource]
  326. def value: String
  327. def format: String
  328. def language: String
  329. def creator: String
  330. def source: String //TODO: define Source type
  331. }
  332. trait TargetResource
  333. object TargetResource {
  334. def typ: String
  335. def styleClass: String
  336. def source: String
  337. //TODO: def state
  338. //TODO: def selector
  339. }
  340. */
  341. trait BodyType extends WebResource {
  342. /**
  343. * "type" of the Body. From https://www.w3.org/TR/annotation-model/#classes :
  344. * """The type of the Body or Target resource.
  345. * The Body or Target MAY have 1 or more types, and if so,
  346. * the value SHOULD be drawn from the list of classes below,
  347. * but MAY come from other vocabularies."""
  348. *
  349. * TODO: Limit to these with custom vocalubaries:
  350. * [Dataset, Image, Video, Sound, Text]
  351. */
  352. def typ: Typ
  353. def concept: NiosxConcept
  354. def entity: Option[NiosxEntity] = None
  355. }
  356. object BodyType {
  357. def apply(typ: Typ,
  358. purpose: String,
  359. value: String,
  360. format: String,
  361. language: String,
  362. creator: String,
  363. concept: NiosxConcept): BodyType = typ match {
  364. case ET.TextualBody => {
  365. val graphId = FileUtils.getNewGraphId
  366. TextualBody(
  367. graphId = graphId,
  368. typ,
  369. iri = "iri of text",
  370. purpose, value, format, language, creator,
  371. concept = concept)
  372. }
  373. }
  374. }
  375. case class ExternalWebResource(graphId: String,
  376. typ: Typ, // = "AUDIO|VIDEO|DATASET",
  377. concept: NiosxConcept,
  378. iri: String) extends NiosxEntity with BodyType
  379. case class LocalResource(
  380. graphId: String,
  381. iri: String,
  382. typ: Typ = ET.LocalResource,
  383. source: String, //TODO: Change to Source type which has iri of the LocalResource
  384. concept: NiosxConcept,
  385. //While the `entity` is an optional field, it is important
  386. //to understand that an edge from `LocalResource` to a
  387. //`NiosxEntity` is always created when it is persisted on
  388. //the data graph.
  389. override val entity: Option[NiosxEntity]
  390. ) extends NiosxEntity with BodyType
  391. case class TextualBody(graphId: String,
  392. typ: Typ = ET.TextualBody,
  393. iri: String,
  394. purpose: String,
  395. value: String,
  396. format: String,
  397. language: String,
  398. creator: String,
  399. concept: NiosxConcept) extends NiosxEntity with BodyType
  400. trait TargetType {
  401. def typ: Typ
  402. def graphId: String
  403. }
  404. object TargetType {
  405. def apply(
  406. typ: Typ,
  407. source: String,
  408. targetId: String): TargetType = typ match {
  409. case ET.SpecificResource =>
  410. SpecificResource(graphId = FileUtils.getNewGraphId,
  411. typ, source, targetId)
  412. }
  413. }
  414. case class SpecificResource(graphId: String,
  415. typ: Typ = ET.SpecificResource,
  416. source: String,
  417. targetId: String) extends NiosxEntity with TargetType
  418. // End: Annotation types
  419. object Audience extends Enumeration {
  420. val INTERNAL, EXTERNAL, OTHER = Value
  421. }
  422. sealed trait Attributes {
  423. def vertex: Option[Vertex]
  424. }
  425. case class AmCommonAttrbs(id: Option[String],
  426. altRender: Option[String],
  427. audience: Option[Audience.Value],
  428. lang: Option[String],
  429. script: Option[String])
  430. object AmCommonAttrbs {
  431. implicit val reader: XmlReader[AmCommonAttrbs] = {
  432. for {
  433. id <- attribute[String]("id").optional
  434. altRender <- attribute[String]("altrender").optional
  435. audience <- attribute[String]("audience").optional.map(v => v match {
  436. case Some("internal") => Some(Audience.INTERNAL)
  437. case Some("external") => Some(Audience.EXTERNAL)
  438. case _ => None })
  439. lang <- attribute[String]("lang").optional
  440. script <- attribute[String]("script").optional
  441. } yield AmCommonAttrbs(id, altRender, audience, lang, script)
  442. }
  443. }
  444. case class CommonAttributes(id: Option[String],
  445. altRender: Option[String],
  446. audience: Option[Audience.Value],
  447. lang: Option[String],
  448. script: Option[String])
  449. object CommonAttributes {
  450. implicit val reader: XmlReader[CommonAttributes] = {
  451. for {
  452. id <- attribute[String]("id").optional
  453. altRender <- attribute[String]("altrender").optional
  454. audience <- attribute[String]("audience").optional.map(v => v match {
  455. case Some("internal") => Some(Audience.INTERNAL)
  456. case Some("external") => Some(Audience.EXTERNAL)
  457. case None => None
  458. case _ => None })
  459. lang <- attribute[String]("lang").optional
  460. script <- attribute[String]("script").optional
  461. } yield CommonAttributes(id, altRender, audience, lang, script)
  462. }
  463. }
  464. case class EadAttributes(
  465. id: Option[String],
  466. altRender: Option[String],
  467. audience: Option[Audience.Value],
  468. lang: Option[String],
  469. script: Option[String],
  470. relatedEncoding: Option[String],
  471. base: Option[String],
  472. vertex: Option[Vertex]) extends Attributes
  473. object EadAttributes {
  474. implicit val reader: XmlReader[EadAttributes] = {
  475. for {
  476. id <- attribute[String]("id").optional
  477. altRender <- attribute[String]("altrender").optional
  478. audience <- attribute[String]("audience").optional.map(v => v match {
  479. case Some("internal") => Some(Audience.INTERNAL)
  480. case Some("external") => Some(Audience.EXTERNAL)
  481. case None => None })
  482. lang <- attribute[String]("lang").optional
  483. script <- attribute[String]("script").optional
  484. relatedEncoding <- attribute[String]("relatedencoding").optional
  485. base <- attribute[String]("base").optional
  486. } yield
  487. EadAttributes(
  488. id,
  489. altRender,
  490. audience,
  491. lang,
  492. script,
  493. relatedEncoding,
  494. base,
  495. None)
  496. }
  497. }
  498. case class Ead(attributes: EadAttributes,
  499. control: Control,
  500. archDesc: ArchDesc)
  501. object Ead {
  502. implicit val reader: XmlReader[Ead] = (
  503. EadAttributes.reader,
  504. (__ \ "control").read[Control],
  505. (__ \ "archdesc").read[ArchDesc]
  506. ).mapN(apply _)
  507. }
  508. object LangEncoding extends Enumeration {
  509. val iso639_1, iso639_2b, iso639_3, OtherLangEncoding = Value
  510. }
  511. object ScriptEncoding extends Enumeration {
  512. val iso15924, OtherScriptEncoding = Value
  513. }
  514. object DateEncoding extends Enumeration {
  515. val iso8601, OtherDateEncoding = Value
  516. }
  517. object CountryEncoding extends Enumeration {
  518. val iso3166_1, OtherCountryEncoding = Value
  519. }
  520. object RepositoryEncoding extends Enumeration {
  521. val iso15511, OtherRepositoryEncoding = Value
  522. }
  523. case class ControlAttrbs(graphId: Option[String],
  524. encodingAnalog: Option[String],
  525. relatedEncoding: Option[String],
  526. base: Option[String],
  527. langEncoding: Option[LangEncoding.Value],
  528. scriptEncoding: Option[ScriptEncoding.Value],
  529. dateEncoding: Option[DateEncoding.Value],
  530. countryEncoding: Option[CountryEncoding.Value],
  531. repositoryEncoding: Option[RepositoryEncoding.Value],
  532. vertex: Option[Vertex]) extends Attributes
  533. object ControlAttrbs {
  534. implicit val reader: XmlReader[ControlAttrbs] = {
  535. for {
  536. encodingAnalog <- attribute[String]("encodinganalog").optional
  537. relatedEncoding <- attribute[String]("relatedencoding").optional
  538. base <- attribute[String]("base").optional
  539. langEncoding <- attribute[String]("langencoding").optional.map( v => v match {
  540. case Some("iso639-1") => LangEncoding.iso639_1
  541. case Some("iso639-2b") => LangEncoding.iso639_2b
  542. case Some("iso639-3") => LangEncoding.iso639_3
  543. case Some("otherlangencoding") => LangEncoding.OtherLangEncoding })
  544. scriptEncoding <- attribute[String]("scriptencoding").optional.map( v => v match {
  545. case Some("iso15924") => ScriptEncoding.iso15924
  546. case Some("otherscriptencoding") => ScriptEncoding.OtherScriptEncoding })
  547. dateEncoding <- attribute[String]("dateencoding").optional.map( v => v match {
  548. case Some("iso8601") => DateEncoding.iso8601
  549. case Some("otherdateencoding") => DateEncoding.OtherDateEncoding })
  550. countryEncoding <- attribute[String]("countryencoding").optional.map( v => v match {
  551. case Some("iso3166-1") => CountryEncoding.iso3166_1
  552. case Some("othercountryencoding") => CountryEncoding.OtherCountryEncoding })
  553. repositoryEncoding <- attribute[String]("repositoryencoding")
  554. .optional
  555. .map(v => v match {
  556. case Some("iso15511") => RepositoryEncoding.iso15511
  557. case Some("otherrepositoryencoding") =>
  558. RepositoryEncoding.OtherRepositoryEncoding })
  559. } yield
  560. ControlAttrbs(None,
  561. encodingAnalog,
  562. relatedEncoding,
  563. base,
  564. Some(langEncoding),
  565. Some(scriptEncoding),
  566. Some(dateEncoding),
  567. Some(countryEncoding),
  568. Some(repositoryEncoding),
  569. None)
  570. }
  571. }
  572. case class Control(attributes: ControlAttrbs,
  573. recordId: RecordId,
  574. otherRecordId: Option[Seq[OtherRecordId]],
  575. representation: Option[Seq[Representation]],
  576. // fileDesc: FileDesc)
  577. // maintenanceStatus: MaintenanceStatus,
  578. // publicationStatus: Option[PublicationStatus],
  579. maintenanceAgency: MaintenanceAgency
  580. // languageDeclaration: Seq[LanguageDeclaration] = Nil,
  581. // conventionDeclaration: Seq[ConventionDeclaration] = Nil,
  582. // rightsDeclaration: Seq[RightsDeclaration] = Nil,
  583. // localTypeDeclaration: Seq[LocalTypeDeclaration] = Nil,
  584. // localControl: Seq[LocalControl] = Nil,
  585. // maintenanceHistory: Seq[MaintenanceHistory] = Nil,
  586. // sources: Option[Sources]
  587. )
  588. object Control {
  589. implicit val reader: XmlReader[Control] = (
  590. ControlAttrbs.reader,
  591. (__ \ "recordid").read[RecordId],
  592. (__ \ "otherrecordid").read(XmlReader.seq[OtherRecordId]).optional,
  593. (__ \ "representation").read(XmlReader.seq[Representation]).optional,
  594. // (__ \ "filedesc").read[FileDesc]).mapN(apply _)
  595. // (__ \ "maintenancestatus").read[MaintenanceStatus],
  596. // (__ \ "publicationstatus").read[PublicationStatus].optional,
  597. (__ \ "maintenanceagency").read[MaintenanceAgency]).mapN(apply _)
  598. // (__ \ "languagedeclaration").read(Seq[LanguageDeclaration]),
  599. // (__ \ "conventiondeclaration").read(Seq[ConventionDeclaration]),
  600. // (__ \ "rightsdeclaration").read(Seq[RightsDeclaration]),
  601. // (__ \ "localtypedeclaration").read(Seq[LocalTypeDeclaration]),
  602. // (__ \ "localcontrol").read(Seq[LocalControl]),
  603. // (__ \ "maintenancehistory").read[MaintenanceHistory],
  604. // (__ \ "sources").read[Sources].optional
  605. // ).mapN(apply _)
  606. }
  607. case class RecordId(graphID: Option[String],
  608. amCommonAttrbs: AmCommonAttrbs,
  609. encodingAnalog: Option[String],
  610. instanceUrl: Option[String], //TODO: Change to ForgiveableUrl
  611. text: String)
  612. object RecordId {
  613. implicit val reader: XmlReader[RecordId] = (
  614. attribute[String]("graphID").optional,
  615. AmCommonAttrbs.reader,
  616. attribute[String]("encodinganalog").optional,
  617. attribute[String]("instanceurl").optional,
  618. (__).read[String]
  619. ).mapN(apply _)
  620. }
  621. case class OtherRecordId(graphID: Option[String] = None,
  622. amCommonAttrbs: AmCommonAttrbs,
  623. encodingAnalog: Option[String],
  624. aLocalType: Option[String],
  625. text: String)
  626. object OtherRecordId {
  627. implicit val reader: XmlReader[OtherRecordId] = (
  628. attribute[String]("graphID").optional,
  629. AmCommonAttrbs.reader,
  630. attribute[String]("encodinganalog").optional,
  631. attribute[String]("localtype").optional,
  632. (__).read[String]
  633. ).mapN(apply _)
  634. }
  635. case class Representation(graphID: Option[String] = None,
  636. amCommonAttrbs: AmCommonAttrbs,
  637. encodingAnalog: Option[String],
  638. simpleLink: SimpleLink,
  639. localType: Option[String],
  640. text: String)
  641. object Representation {
  642. implicit val reader: XmlReader[Representation] = (
  643. attribute[String]("graphID").optional,
  644. AmCommonAttrbs.reader,
  645. attribute[String]("encodinganalog").optional,
  646. SimpleLink.reader,
  647. attribute[String]("localtype").optional,
  648. (__).read[String]
  649. ).mapN(apply _)
  650. }
  651. case class MaintenanceAgencyAttrbs(id: Option[String])
  652. object MaintenanceAgencyAttrbs {
  653. implicit val reader: XmlReader[MaintenanceAgencyAttrbs] = {
  654. for {
  655. id <- attribute[String]("id").optional
  656. } yield MaintenanceAgencyAttrbs(id)
  657. }
  658. }
  659. case class MaintenanceAgency(graphID: Option[String] = None,
  660. attributes: MaintenanceAgencyAttrbs,
  661. agencyCode: Option[AgencyCode])
  662. object MaintenanceAgency {
  663. implicit val reader: XmlReader[MaintenanceAgency] = (
  664. attribute[String]("graphID").optional,
  665. MaintenanceAgencyAttrbs.reader,
  666. (__ \ "agencycode").read[AgencyCode].optional
  667. ).mapN(apply _)
  668. }
  669. case class AgencyCodeAttrbs(id: Option[String],
  670. altRender: Option[String],
  671. audience: Option[Audience.Value],
  672. lang: Option[String],
  673. script: Option[String],
  674. encodingAnalog: Option[String],
  675. localType: Option[String],
  676. vertex: Option[Vertex])
  677. object AgencyCodeAttrbs {
  678. implicit val reader: XmlReader[AgencyCodeAttrbs] = {
  679. for {
  680. id <- attribute[String]("id").optional
  681. altRender <- attribute[String]("altrender").optional
  682. audience <- attribute[String]("audience").optional.map(v => v match {
  683. case Some("internal") => Some(Audience.INTERNAL)
  684. case Some("external") => Some(Audience.EXTERNAL)
  685. case None => None })
  686. lang <- attribute[String]("lang").optional
  687. script <- attribute[String]("script").optional
  688. encodingAnalog <- attribute[String]("encodinganalog").optional
  689. localType <- attribute[String]("localtype").optional
  690. } yield
  691. AgencyCodeAttrbs(id,
  692. altRender,
  693. audience,
  694. lang,
  695. script,
  696. encodingAnalog,
  697. localType,
  698. None)
  699. }
  700. }
  701. case class AgencyCode(graphID: Option[String] = None,
  702. attributes: AgencyCodeAttrbs,
  703. text: String)
  704. object AgencyCode {
  705. implicit val reader: XmlReader[AgencyCode] = (
  706. attribute[String]("graphID").optional,
  707. AgencyCodeAttrbs.reader,
  708. (__).read[String]
  709. ).mapN(apply _)
  710. }
  711. object LinkShow extends Enumeration {
  712. val NEW, REPLACE, EMBED, OTHER, NONE = Value
  713. }
  714. object Actuate extends Enumeration {
  715. val ONLOAD, ONREQUEST, OTHER, NONE = Value
  716. }
  717. case class SimpleLink(graphID: Option[String] = None,
  718. href: Option[String],
  719. role: Option[String],
  720. arcrole: Option[String],
  721. title: Option[String],
  722. show: Option[LinkShow.Value],
  723. actuate: Option[Actuate.Value])
  724. object SimpleLink {
  725. implicit val reader: XmlReader[SimpleLink] = (
  726. attribute[String]("graphID").optional,
  727. attribute[String]("href").optional,
  728. attribute[String]("linkrole").optional,
  729. attribute[String]("arcrole").optional,
  730. attribute[String]("linktitle").optional,
  731. attribute[String]("show").optional.map(v => v match {
  732. case Some("new") => Some(LinkShow.NEW)
  733. case Some("replace") => Some(LinkShow.REPLACE)
  734. case Some("embed") => Some(LinkShow.EMBED)
  735. case Some("other") => Some(LinkShow.OTHER)
  736. case Some("none") => Some(LinkShow.NONE)
  737. }),
  738. attribute[String]("actuate").optional.map(v => v match {
  739. case Some("onload") => Some(Actuate.ONLOAD)
  740. case Some("onrequest") => Some(Actuate.ONREQUEST)
  741. case Some("other") => Some(Actuate.OTHER)
  742. case Some("none") => Some(Actuate.NONE)
  743. })
  744. ).mapN(apply _)
  745. }
  746. sealed trait ArchDescOption
  747. object ArchDescOption {
  748. implicit val reader: XmlReader[Seq[ArchDescOption]] = {
  749. for {
  750. dsc <- (__ \ "dsc").read[Dsc]
  751. } yield Seq(dsc)
  752. }
  753. }
  754. case class ArchDescAttrbs(id: Option[String],
  755. level: String)
  756. object ArchDescAttrbs {
  757. implicit val reader: XmlReader[ArchDescAttrbs] = {
  758. for {
  759. id <- attribute[String]("id").optional
  760. level <- attribute[String]("level")
  761. } yield ArchDescAttrbs(id,
  762. level)
  763. }
  764. }
  765. case class ArchDesc(graphID: Option[String] = None,
  766. attributes: ArchDescAttrbs,
  767. did: Did,
  768. archDescOptions: Seq[ArchDescOption] = Nil)
  769. object ArchDesc {
  770. implicit val reader: XmlReader[ArchDesc] = (
  771. attribute[String]("graphID").optional,
  772. ArchDescAttrbs.reader,
  773. (__ \ "did").read[Did],
  774. ArchDescOption.reader
  775. ).mapN(apply _)
  776. }
  777. case class DidAttrbs(id: Option[String],
  778. audience: Option[String])
  779. object DidAttrbs {
  780. implicit val reader: XmlReader[DidAttrbs] = {
  781. for {
  782. id <- attribute[String]("id").optional
  783. audience <- attribute[String]("audience").optional
  784. } yield DidAttrbs(id,
  785. audience)
  786. }
  787. }
  788. sealed trait DidOption
  789. object DidOption {
  790. implicit val reader: XmlReader[Seq[DidOption]] = {
  791. for {
  792. unitId <- (__ \ "unitid").read[UnitId]
  793. unitTitle <- (__ \ "unittitle").read[UnitTitle]
  794. } yield Seq(unitId, unitTitle)
  795. }
  796. }
  797. case class Did(graphID: Option[String] = None,
  798. attributes: DidAttrbs,
  799. didOptions: Seq[DidOption])
  800. // unitId: UnitId,
  801. // unitTitle: UnitTitle,
  802. // origination: Origination,
  803. // unitDate: UnitDate,
  804. // unitDateStructured: UnitDateStructured,
  805. // physDesc: PhysDesc,
  806. // physDescSet: PhysDescSet,
  807. // physDescStructured: PhysDescStructured)
  808. object Did {
  809. implicit val reader: XmlReader[Did] = (
  810. attribute[String]("graphID").optional,
  811. DidAttrbs.reader,
  812. DidOption.reader
  813. // (__ \ "unitid").read[UnitId],
  814. // (__ \ "unittitle").read[UnitTitle],
  815. // (__ \ "origination").read[Origination],
  816. // (__ \ "unitdate").read[UnitDate],
  817. // (__ \ "unitdatestructured").read[UnitDateStructured],
  818. // (__ \ "physdesc").read[PhysDesc],
  819. // (__ \ "physdescset").read[PhysDescSet],
  820. // (__ \ "physdescstructured").read[PhysDescStructured]
  821. ).mapN(apply _)
  822. }
  823. case class UnitIdAttrbs(countryCode: Option[String],
  824. repositoryCode: Option[String])
  825. object UnitIdAttrbs {
  826. implicit val reader: XmlReader[UnitIdAttrbs] = {
  827. for {
  828. countryCode <- attribute[String]("countrycode").optional
  829. repositoryCode <- attribute[String]("repositorycode").optional
  830. } yield UnitIdAttrbs(countryCode,
  831. repositoryCode)
  832. }
  833. }
  834. case class UnitId(graphID: Option[String] = None,
  835. attributes: UnitIdAttrbs,
  836. text: String) extends DidOption
  837. object UnitId {
  838. implicit val reader: XmlReader[UnitId] = (
  839. attribute[String]("graphID").optional,
  840. UnitIdAttrbs.reader,
  841. (__).read[String]
  842. ).mapN(apply _)
  843. }
  844. case class UnitTitle(graphID: Option[String] = None,
  845. text: String) extends DidOption
  846. object UnitTitle {
  847. implicit val reader: XmlReader[UnitTitle] = (
  848. attribute[String]("graphID").optional,
  849. (__).read[String]).mapN(apply _)
  850. }
  851. trait OriginationAgent
  852. case class CorpName(graphID: Option[String] = None,
  853. parts: Seq[Part]) extends OriginationAgent
  854. case class PersName(graphID: Option[String] = None,
  855. parts: Seq[Part]) extends OriginationAgent
  856. // A graph Key with properties
  857. case class Origination(origin: Seq[OriginationAgent])
  858. case class Part(text: String)
  859. case class Dsc(dummy: Option[String]) extends ArchDescOption//c: Option[Seq[C]]
  860. // c01: Option[Seq[C01]]) extends ArchDescOption
  861. object Dsc {
  862. implicit val reader: XmlReader[Dsc] = (
  863. attribute[String]("id").optional
  864. ).map(apply _)
  865. }
  866. case class CAttrbs(level: String)
  867. object CAttrbs {
  868. implicit val reader: XmlReader[CAttrbs] = {
  869. for {
  870. level <- attribute[String]("level")
  871. } yield CAttrbs(level)
  872. }
  873. }
  874. case class C(attributes: CAttrbs,
  875. did: Did,
  876. c: Option[Seq[C]] = None)
  877. case class C01(attributes: CAttrbs,
  878. did: Did,
  879. c02: Option[Seq[C02]] = None)
  880. case class C02(attributes: CAttrbs,
  881. did: Did,
  882. c03: Option[Seq[C03]] = None)
  883. case class C03(attributes: CAttrbs,
  884. did: Did,
  885. c04: Option[Seq[C04]] = None)
  886. case class C04(attributes: CAttrbs,
  887. did: Did,
  888. c05: Option[Seq[C05]] = None)
  889. case class C05(attributes: CAttrbs,
  890. did: Did)