packages feed

symantic-xml-2.0.0.20200523: test/RelaxNG/Commoning.hs

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
module RelaxNG.Commoning where

import Data.Eq (Eq)
import Data.Either (Either(..))
import Data.Foldable (toList)
import Data.Functor ((<$>))
import Data.Function (($), (.))
import Data.Hashable (Hashable)
import Data.Maybe (Maybe(..))
import Data.Ord (Ord)
import Data.Sequence (Seq)
import Data.Tuple (fst)
import Text.Show (Show)
import GHC.Generics (Generic)
import qualified Data.Sequence as Seq
import qualified Data.Text.Lazy as TL
import qualified Data.TreeSeq.Strict as TS
import qualified Text.Megaparsec as P

import Symantic.XML as XML
import Symantic.XML.RelaxNG as RelaxNG

schema =
  namespace Nothing xmlns_commoning <.>
  namespace (Just "xsd") "http://www/w3/org/2001/XMLSchema-datatypes" <.>
  commoning

-- * Class 'Commonable'
xmlns_commoning :: Namespace
xmlns_commoning = "2018/commoning.rnc"
elem = element . QName xmlns_commoning
attr n = attribute (QName "" n) text
many0Seq = dimap Seq.fromList toList . many0

-- * Type 'Ident'
newtype Ident = Ident TL.Text
 deriving (Eq,Ord,Show,Hashable)

instance RNCText Ident where
  rncText_qname = QName xmlns_xsd "id"
instance EncodeText Ident where
  encodeText (Ident t) = t
instance DecodeText Ident where
  decodeText = Ident . fst <$> P.match (P.many P.anySingle)

-- * Type 'Name'
newtype Name = Name TL.Text
 deriving (Eq,Ord,Show,Hashable)
instance RNCText Name where
  rncText_qname  = rncText_qname  @TL.Text
  rncText_params = rncText_params @TL.Text

instance EncodeText Name where
  encodeText (Name t) = t
instance DecodeText Name where
  decodeText = Name . fst <$> P.match (P.many P.anySingle)

-- * Type 'Commoning'
data Commoning
 =   Commoning
 {   commoning_persons    :: Persons
 ,   commoning_opinions   :: Opinions
 ,   commoning_groups     :: Groups
 ,   commoning_operations :: Operations
 ,   commoning_resources  :: Resources
 } deriving (Show, Generic)

commoning =
  define "commoning" $
  elem "commoning" $
  adt @Commoning $
    permutable $
    persons <&>
    opinions <&>
    groups <&>
    operations <&>
    perm resources

-- ** Type 'Person'
data Person
 =   Person
 {   person_id     :: Ident
 ,   person_fields :: Seq Fields
 } deriving (Show, Generic)

person =
  define "person" $
  adt @Person $
  elem "person" $
    attr "id" <:>
    many0Seq fields

-- *** Type 'Persons'
type Persons = [Person]

persons =
  define "persons" $
  elem "persons" $
    many0 person

-- * Type 'Opinions'
type Opinions = [Grades]

opinions =
  define "opinions" $
  elem "opinions" $
    many0 grades

-- ** Type 'Grade'
data Grade
 =   Grade
 {   grade_name   :: Name
 ,   grade_abbrev :: Maybe Name
 ,   grade_color  :: Maybe Color
 } deriving (Show, Generic)

grade =
  define "grade" $
  elem "grade" $
  adt @Grade $
    attr "name" <:>
    optional (attr "abbrev") <:>
    optional (attr "color")

-- *** Type 'Color'
type Color = TL.Text

-- *** Type 'Grades'
data Grades
 =   Grades
 {   grades_id   :: Ident
 ,   grades_name :: Maybe Name
 ,   grades_list :: [Grade]
 } deriving (Show, Generic)

grades =
  define "grades" $
  elem "grades" $
  adt @Grades $
    attr "id" <:>
    optional (attr "name") <:>
    many0 grade

-- ** Type 'Field'
data Field
 =   Field
 {   field_name  :: Name
 ,   field_value :: TL.Text
 } deriving (Show, Generic)

-- *** Type 'Fields'
type Fields = TS.Tree NodeField

-- **** Type 'NodeField'
data NodeField
 =   NodeField Field
 |   NodeFields { fields_name :: Name }
 deriving (Show, Generic)

fields =
  define "fields" $
  elem "fields" $
  adt @(TS.Tree NodeField) $
    (dimap NodeFields fields_name $
      attr "name")
    <:>
    many0Seq (
      dimap
      (\case
       Left f -> TS.tree0 $ NodeField f
       Right fs -> fs)
      (\case
       TS.Tree (NodeField f) _ -> Left f
       fs -> Right fs) $
      field
      <+>
      fields
    )

field =
  define "field" $
  elem "field" $
  adt @Field $
    attr "name" <:>
    text

-- ** Type 'Group'
type Group = TS.Tree NodeGroup

-- *** Type 'NodeGroup'
data NodeGroup
 =   NodeGroup
 {   group_id      :: Ident
 ,   group_name    :: Maybe Name
 ,   group_fields  :: Seq Fields
 ,   group_members :: Members
 } deriving (Show, Generic)

-- *** Type 'Groups'
type Groups = Seq Group

groups =
  define "groups" $
  elem "groups" $
    many0Seq group

group =
  define "group" $
  elem "group" $
  adt @(TS.Tree NodeGroup) $
    (adt @NodeGroup $
      attr "id" <:>
      optional (attr "name") <:>
      many0Seq fields <:>
      members
    ) <:>
    many0Seq group

-- ** Type 'Member'
newtype Member
 =      Member
 {      member_person :: Ident
 } deriving (Show, Generic)

-- *** Type 'Members'
type Members = [Member]

members = define "members" $ many0 member
member =
  define "member" $
  elem "member" $
  adt @Member $
   attr "person"

-- ** Type 'Operation'
type Operation = TS.Tree NodeOperation
-- *** Type 'NodeOperation'
newtype NodeOperation
 =      NodeOperation
 {      operation_id :: Ident
 } deriving (Show, Generic)
-- *** Type 'Operations'
type Operations = Seq Operation

operations =
  define "operations" $
  elem "operations" $
  many0Seq operation

operation =
  define "operation" $
  elem "operation" $
  adt @(TS.Tree NodeOperation) $
    (adt $ attr "id") <:>
    many0Seq operation

-- ** Type 'Resource'
type Resource = TS.Tree NodeResource
-- *** Type 'NodeResource'
data NodeResource
 =   NodeResource
 {   resource_name     :: Name
 ,   resource_policies :: Policies
 } deriving (Show, Generic)

-- *** Type 'Resources'
type Resources = Seq Resource

resources =
  define "resources" $
  elem "resources" $
    many0Seq resource

resource =
  define "resource" $
  elem "resource" $
  adt @(TS.Tree NodeResource) $
    (adt $ attr "name" <:> many0 policy) <:>
    many0Seq resource

-- ** Type 'Policy'
data Policy
 =   Policy
 {   policy_operation :: Name
 ,   policy_by        :: Ident
 ,   policy_toward    :: Maybe Ident
 ,   policy_rules     :: Rules
 } deriving (Show, Generic)

policy =
  define "policy" $
  adt @Policy $
  elem "policy" $
    attr "operation" <:>
    attr "by" <:>
    optional (attr "toward") <:>
    many0 rule

-- *** Type 'Policies'
type Policies = [Policy]

-- ** Type 'Rule'
data Rule
 =   Rule
 {   rule_grades     :: Ident
 ,   rule_gradeRange :: GradeRange
 } deriving (Show, Generic)

rule =
  define "rule" $
  adt @Rule $
  elem "rule" $
    attr "grades" <:>
    gradeRange

-- *** Type 'Rules'
type Rules = [Rule]

-- *** Type 'GradeRange'
data GradeRange
 =   GradeRange_Single Name
 |   GradeRange_Min    Name
 |   GradeRange_Max    Name
 |   GradeRange        Name Name
 deriving (Show, Generic)

gradeRange =
  define "gradeRange" $
  adt @GradeRange $
    attr "grade" <+>
    attr "gradeMin" <+>
    attr "gradeMax" <+> (
      attr "gradeMin" <:>
      attr "gradeMax"
    )

{-
rule = define "rule" $
  element "rule" attrs
  where
  attrs
   =   attrsGrade
   <+> attrsGradeMin
   <+> attrsGradeMax
  attrsGrade =
    permutable $
    Rule
     <$> attribute "grades" ident
     <*> (GradeRange_Single <$> attribute "grade" name)
  attrsGradeMin =
    permutable $
    (\gs gMin mgMax -> Rule gs $ case mgMax of
       Nothing   -> GradeRange_Min gMin
       Just gMax -> GradeRange gMin gMax)
     <$> attribute "grades" ident
     <*> attribute "gradeMin" name
     <*> optionalPerm (attribute "gradeMax" name)
  attrsGradeMax =
    permutable $
    (\gs mgMin gMax -> Rule gs $ case mgMin of
       Nothing   -> GradeRange_Max gMax
       Just gMin -> GradeRange gMin gMax)
     <$> attribute "grades" ident
     <*> optionalPerm (attribute "gradeMin" name)
     <*> attribute "gradeMax" name
-}