{-# LANGUAGE GADTs #-}
-- | Document declaration types and functions for generating Software Requirement Specifications.

-- Changes to DocSection and its subections should be reflected in the 'Creating Your Project 
-- in Drasil' tutorial found on the wiki:
-- https://github.com/JacquesCarette/Drasil/wiki/Creating-Your-Project-in-Drasil

module Drasil.DocDecl where

import Drasil.DocumentLanguage.Core (DocDesc)
import Drasil.DocumentLanguage.Definitions (Fields)
import qualified Drasil.DocumentLanguage.Core as DL (DocSection(..), RefSec(..),
  IntroSec(..), StkhldrSec(..), GSDSec(..), SSDSec(..), SSDSub(..),
  ProblemDescription(..), PDSub(..), SolChSpec(..), SCSSub(..), ReqrmntSec(..),
  ReqsSub(..), LCsSec(..), UCsSec(..), TraceabilitySec(..), AuxConstntSec(..),
  AppndxSec(..), OffShelfSolnsSec(..), DerivationDisplay)
import Drasil.Sections.Requirements (fullReqs, fullTables)

import Database.Drasil
import SysInfo.Drasil
import Language.Drasil hiding (sec)

import Data.Drasil.Concepts.Documentation (assumpDom, funcReqDom, goalStmtDom,
  nonFuncReqDom, likeChgDom, unlikeChgDom)

import Control.Lens((^.), Getting)

-- * Types

-- | A Software Requirements Specification Declaration is made up of all necessary sections ('DocSection's).
type SRSDecl = [DocSection]

-- | Contains all the different sections needed for a full SRS ('SRSDecl').
data DocSection = TableOfContents                       -- ^ Table of Contents
                | RefSec DL.RefSec                      -- ^ Reference.
                | IntroSec DL.IntroSec                  -- ^ Introduction.
                | StkhldrSec DL.StkhldrSec              -- ^ Stakeholders.
                | GSDSec DL.GSDSec                      -- ^ General System Description.
                | SSDSec SSDSec                         -- ^ Specific System Description.
                | ReqrmntSec ReqrmntSec                 -- ^ Requirements.
                | LCsSec                                -- ^ Likely Changes.
                | UCsSec                                -- ^ Unlikely Changes.
                | TraceabilitySec DL.TraceabilitySec    -- ^ Traceability.
                | AuxConstntSec DL.AuxConstntSec        -- ^ Auxiliary Constants.
                | Bibliography                          -- ^ Bibliography.
                | AppndxSec DL.AppndxSec                -- ^ Appendix.
                | OffShelfSolnsSec DL.OffShelfSolnsSec  -- ^ Off the Shelf Solutions.

-- | Specific System Description section (wraps 'SSDSub' subsections).
newtype SSDSec = SSDProg [SSDSub]

-- | Specific System Description subsections.
data SSDSub where
  -- | Problem description.
  SSDProblem :: ProblemDescription -> SSDSub
  -- | Solution characteristics.
  SSDSolChSpec :: SolChSpec -> SSDSub

-- | Problem Description section.
data ProblemDescription where
  PDProg :: Sentence -> [Section] -> [PDSub] -> ProblemDescription

-- | Problem Description subsections.
data PDSub where
  -- | Terms and Definitions.
  TermsAndDefs :: Concept c => Maybe Sentence -> [c] -> PDSub
  -- | Physical System Description.
  PhySysDesc :: Idea a => a -> [Sentence] -> LabelledContent -> [Contents] -> PDSub
  -- | Goals.
  Goals :: [Sentence] -> PDSub

-- | Solution Characteristics Specification section (wraps 'SCSSub' subsections).
data SolChSpec where
  SCSProg :: [SCSSub] -> SolChSpec

-- | Solution Characteristics Specification subsections.
data SCSSub where
  -- | Assumptions.
  Assumptions    :: SCSSub
  -- | Theory models.
  TMs            :: [Sentence] -> Fields  -> SCSSub
  -- | General definitions.
  GDs            :: [Sentence] -> Fields  -> DL.DerivationDisplay -> SCSSub
  -- | Data definitions.
  DDs            :: [Sentence] -> Fields  -> DL.DerivationDisplay -> SCSSub
  -- | Instance models.
  IMs            :: [Sentence] -> Fields  -> DL.DerivationDisplay -> SCSSub
  -- | Constraints.
  Constraints    :: (HasUncertainty c, Quantity c, Constrained c, HasReasVal c, MayHaveUnit c) => Sentence -> [c] -> SCSSub
  -- | Properties of a correct solution.
  CorrSolnPpties :: (Quantity c, Constrained c) => [c] -> [Contents] -> SCSSub

-- | Requirements section (wraps 'ReqsSub' subsections).
newtype ReqrmntSec = ReqsProg [ReqsSub]

-- | Requirements subsections.
data ReqsSub where
  -- | Functional requirements. 'LabelledContent' for tables (includes input values).
  FReqsSub    :: Sentence -> [LabelledContent] -> ReqsSub
  -- | Functional requirements. 'LabelledContent' for tables (no input values).
  FReqsSub'   :: [LabelledContent] -> ReqsSub
  -- | Non-Functional requirements.
  NonFReqsSub :: ReqsSub

-- * Functions

-- | Creates the document description (translates 'SRSDecl' into a more usable form for generating documents).
mkDocDesc :: SystemInformation -> SRSDecl -> DocDesc
mkDocDesc :: SystemInformation -> SRSDecl -> DocDesc
mkDocDesc SI{_inputs :: ()
_inputs = [h]
is, _sysinfodb :: SystemInformation -> ChunkDB
_sysinfodb = ChunkDB
db} = (DocSection -> DocSection) -> SRSDecl -> DocDesc
forall a b. (a -> b) -> [a] -> [b]
map DocSection -> DocSection
sec where
  sec :: DocSection -> DL.DocSection
  sec :: DocSection -> DocSection
sec DocSection
TableOfContents = DocSection
DL.TableOfContents
  sec (RefSec RefSec
r) = RefSec -> DocSection
DL.RefSec RefSec
r
  sec (IntroSec IntroSec
i) = IntroSec -> DocSection
DL.IntroSec IntroSec
i
  sec (StkhldrSec StkhldrSec
s) = StkhldrSec -> DocSection
DL.StkhldrSec StkhldrSec
s
  sec (GSDSec GSDSec
g) = GSDSec -> DocSection
DL.GSDSec GSDSec
g
  sec (SSDSec (SSDProg [SSDSub]
s)) = SSDSec -> DocSection
DL.SSDSec (SSDSec -> DocSection) -> SSDSec -> DocSection
forall a b. (a -> b) -> a -> b
$ [SSDSub] -> SSDSec
DL.SSDProg ([SSDSub] -> SSDSec) -> [SSDSub] -> SSDSec
forall a b. (a -> b) -> a -> b
$ (SSDSub -> SSDSub) -> [SSDSub] -> [SSDSub]
forall a b. (a -> b) -> [a] -> [b]
map SSDSub -> SSDSub
ssdSec [SSDSub]
s
  sec (ReqrmntSec (ReqsProg [ReqsSub]
r)) = ReqrmntSec -> DocSection
DL.ReqrmntSec (ReqrmntSec -> DocSection) -> ReqrmntSec -> DocSection
forall a b. (a -> b) -> a -> b
$ [ReqsSub] -> ReqrmntSec
DL.ReqsProg ([ReqsSub] -> ReqrmntSec) -> [ReqsSub] -> ReqrmntSec
forall a b. (a -> b) -> a -> b
$ (ReqsSub -> ReqsSub) -> [ReqsSub] -> [ReqsSub]
forall a b. (a -> b) -> [a] -> [b]
map ReqsSub -> ReqsSub
reqSec [ReqsSub]
r
  sec DocSection
LCsSec = LCsSec -> DocSection
DL.LCsSec (LCsSec -> DocSection) -> LCsSec -> DocSection
forall a b. (a -> b) -> a -> b
$ [ConceptInstance] -> LCsSec
DL.LCsProg ([ConceptInstance] -> LCsSec) -> [ConceptInstance] -> LCsSec
forall a b. (a -> b) -> a -> b
$ ConceptChunk -> [ConceptInstance]
forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB ConceptChunk
likeChgDom
  sec DocSection
UCsSec = UCsSec -> DocSection
DL.UCsSec (UCsSec -> DocSection) -> UCsSec -> DocSection
forall a b. (a -> b) -> a -> b
$ [ConceptInstance] -> UCsSec
DL.UCsProg ([ConceptInstance] -> UCsSec) -> [ConceptInstance] -> UCsSec
forall a b. (a -> b) -> a -> b
$ ConceptChunk -> [ConceptInstance]
forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB ConceptChunk
unlikeChgDom
  sec (TraceabilitySec TraceabilitySec
t) = TraceabilitySec -> DocSection
DL.TraceabilitySec TraceabilitySec
t
  sec (AuxConstntSec AuxConstntSec
a) = AuxConstntSec -> DocSection
DL.AuxConstntSec AuxConstntSec
a
  sec DocSection
Bibliography = DocSection
DL.Bibliography
  sec (AppndxSec AppndxSec
a) = AppndxSec -> DocSection
DL.AppndxSec AppndxSec
a
  sec (OffShelfSolnsSec OffShelfSolnsSec
e) = OffShelfSolnsSec -> DocSection
DL.OffShelfSolnsSec OffShelfSolnsSec
e
  reqSec :: ReqsSub -> DL.ReqsSub
  reqSec :: ReqsSub -> ReqsSub
reqSec (FReqsSub Sentence
d [LabelledContent]
t) = [ConceptInstance] -> [LabelledContent] -> ReqsSub
DL.FReqsSub ([h] -> Sentence -> [ConceptInstance] -> [ConceptInstance]
forall i.
(Quantity i, MayHaveUnit i) =>
[i] -> Sentence -> [ConceptInstance] -> [ConceptInstance]
fullReqs [h]
is Sentence
d ([ConceptInstance] -> [ConceptInstance])
-> [ConceptInstance] -> [ConceptInstance]
forall a b. (a -> b) -> a -> b
$ ConceptChunk -> [ConceptInstance]
forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB ConceptChunk
funcReqDom) ([h] -> [LabelledContent] -> [LabelledContent]
forall i.
(Quantity i, MayHaveUnit i) =>
[i] -> [LabelledContent] -> [LabelledContent]
fullTables [h]
is [LabelledContent]
t)
  reqSec (FReqsSub' [LabelledContent]
t) = [ConceptInstance] -> [LabelledContent] -> ReqsSub
DL.FReqsSub' (ConceptChunk -> [ConceptInstance]
forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB ConceptChunk
funcReqDom) [LabelledContent]
t
  reqSec ReqsSub
NonFReqsSub = [ConceptInstance] -> ReqsSub
DL.NonFReqsSub ([ConceptInstance] -> ReqsSub) -> [ConceptInstance] -> ReqsSub
forall a b. (a -> b) -> a -> b
$ ConceptChunk -> [ConceptInstance]
forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB ConceptChunk
nonFuncReqDom
  ssdSec :: SSDSub -> DL.SSDSub
  ssdSec :: SSDSub -> SSDSub
ssdSec (SSDProblem (PDProg Sentence
s [Section]
ls [PDSub]
p)) = ProblemDescription -> SSDSub
DL.SSDProblem (ProblemDescription -> SSDSub) -> ProblemDescription -> SSDSub
forall a b. (a -> b) -> a -> b
$ Sentence -> [Section] -> [PDSub] -> ProblemDescription
DL.PDProg Sentence
s [Section]
ls ([PDSub] -> ProblemDescription) -> [PDSub] -> ProblemDescription
forall a b. (a -> b) -> a -> b
$ (PDSub -> PDSub) -> [PDSub] -> [PDSub]
forall a b. (a -> b) -> [a] -> [b]
map PDSub -> PDSub
pdSub [PDSub]
p
  ssdSec (SSDSolChSpec (SCSProg [SCSSub]
scs)) = SolChSpec -> SSDSub
DL.SSDSolChSpec (SolChSpec -> SSDSub) -> SolChSpec -> SSDSub
forall a b. (a -> b) -> a -> b
$ [SCSSub] -> SolChSpec
DL.SCSProg ([SCSSub] -> SolChSpec) -> [SCSSub] -> SolChSpec
forall a b. (a -> b) -> a -> b
$ (SCSSub -> SCSSub) -> [SCSSub] -> [SCSSub]
forall a b. (a -> b) -> [a] -> [b]
map SCSSub -> SCSSub
scsSub [SCSSub]
scs
  pdSub :: PDSub -> DL.PDSub
  pdSub :: PDSub -> PDSub
pdSub (TermsAndDefs Maybe Sentence
s [c]
c) = Maybe Sentence -> [c] -> PDSub
forall c. Concept c => Maybe Sentence -> [c] -> PDSub
DL.TermsAndDefs Maybe Sentence
s [c]
c
  pdSub (PhySysDesc a
i [Sentence]
s LabelledContent
lc [Contents]
c) = a -> [Sentence] -> LabelledContent -> [Contents] -> PDSub
forall a.
Idea a =>
a -> [Sentence] -> LabelledContent -> [Contents] -> PDSub
DL.PhySysDesc a
i [Sentence]
s LabelledContent
lc [Contents]
c
  pdSub (Goals [Sentence]
s) = [Sentence] -> [ConceptInstance] -> PDSub
DL.Goals [Sentence]
s ([ConceptInstance] -> PDSub) -> [ConceptInstance] -> PDSub
forall a b. (a -> b) -> a -> b
$ ConceptChunk -> [ConceptInstance]
forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB ConceptChunk
goalStmtDom
  scsSub :: SCSSub -> DL.SCSSub
  scsSub :: SCSSub -> SCSSub
scsSub SCSSub
Assumptions = [ConceptInstance] -> SCSSub
DL.Assumptions ([ConceptInstance] -> SCSSub) -> [ConceptInstance] -> SCSSub
forall a b. (a -> b) -> a -> b
$ ConceptChunk -> [ConceptInstance]
forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB ConceptChunk
assumpDom
  scsSub (TMs [Sentence]
s Fields
f) = [Sentence] -> Fields -> [TheoryModel] -> SCSSub
DL.TMs [Sentence]
s Fields
f ([TheoryModel] -> SCSSub) -> [TheoryModel] -> SCSSub
forall a b. (a -> b) -> a -> b
$ Getting (UMap TheoryModel) ChunkDB (UMap TheoryModel)
-> [TheoryModel]
forall a. Getting (UMap a) ChunkDB (UMap a) -> [a]
allInDB Getting (UMap TheoryModel) ChunkDB (UMap TheoryModel)
Lens' ChunkDB (UMap TheoryModel)
theoryModelTable
  scsSub (GDs [Sentence]
s Fields
f DerivationDisplay
dd) = [Sentence] -> Fields -> [GenDefn] -> DerivationDisplay -> SCSSub
DL.GDs [Sentence]
s Fields
f (Getting (UMap GenDefn) ChunkDB (UMap GenDefn) -> [GenDefn]
forall a. Getting (UMap a) ChunkDB (UMap a) -> [a]
allInDB Getting (UMap GenDefn) ChunkDB (UMap GenDefn)
Lens' ChunkDB (UMap GenDefn)
gendefTable) DerivationDisplay
dd
  scsSub (DDs [Sentence]
s Fields
f DerivationDisplay
dd) = [Sentence]
-> Fields -> [DataDefinition] -> DerivationDisplay -> SCSSub
DL.DDs [Sentence]
s Fields
f (Getting (UMap DataDefinition) ChunkDB (UMap DataDefinition)
-> [DataDefinition]
forall a. Getting (UMap a) ChunkDB (UMap a) -> [a]
allInDB Getting (UMap DataDefinition) ChunkDB (UMap DataDefinition)
Lens' ChunkDB (UMap DataDefinition)
dataDefnTable) DerivationDisplay
dd
  scsSub (IMs [Sentence]
s Fields
f DerivationDisplay
dd) = [Sentence]
-> Fields -> [InstanceModel] -> DerivationDisplay -> SCSSub
DL.IMs [Sentence]
s Fields
f (Getting (UMap InstanceModel) ChunkDB (UMap InstanceModel)
-> [InstanceModel]
forall a. Getting (UMap a) ChunkDB (UMap a) -> [a]
allInDB Getting (UMap InstanceModel) ChunkDB (UMap InstanceModel)
Lens' ChunkDB (UMap InstanceModel)
insmodelTable) DerivationDisplay
dd
  scsSub (Constraints Sentence
s [c]
c) = Sentence -> [c] -> SCSSub
forall c.
(HasUncertainty c, Quantity c, Constrained c, HasReasVal c,
 MayHaveUnit c) =>
Sentence -> [c] -> SCSSub
DL.Constraints Sentence
s [c]
c
  scsSub (CorrSolnPpties [c]
c [Contents]
cs) = [c] -> [Contents] -> SCSSub
forall c.
(Quantity c, Constrained c) =>
[c] -> [Contents] -> SCSSub
DL.CorrSolnPpties [c]
c [Contents]
cs
  expandFromDB :: ([a] -> [a]) -> Getting (UMap a) ChunkDB (UMap a) -> [a]
  expandFromDB :: forall a. ([a] -> [a]) -> Getting (UMap a) ChunkDB (UMap a) -> [a]
expandFromDB [a] -> [a]
f = [a] -> [a]
f ([a] -> [a])
-> (Getting (UMap a) ChunkDB (UMap a) -> [a])
-> Getting (UMap a) ChunkDB (UMap a)
-> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UMap a -> [a]
forall a. UMap a -> [a]
asOrderedList (UMap a -> [a])
-> (Getting (UMap a) ChunkDB (UMap a) -> UMap a)
-> Getting (UMap a) ChunkDB (UMap a)
-> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ChunkDB
db ChunkDB -> Getting (UMap a) ChunkDB (UMap a) -> UMap a
forall s a. s -> Getting a s a -> a
^.)
  allInDB :: Getting (UMap a) ChunkDB (UMap a) -> [a]
  allInDB :: forall a. Getting (UMap a) ChunkDB (UMap a) -> [a]
allInDB = ([a] -> [a]) -> Getting (UMap a) ChunkDB (UMap a) -> [a]
forall a. ([a] -> [a]) -> Getting (UMap a) ChunkDB (UMap a) -> [a]
expandFromDB [a] -> [a]
forall a. a -> a
id
  fromConcInsDB :: Concept c => c -> [ConceptInstance]
  fromConcInsDB :: forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB c
c = ([ConceptInstance] -> [ConceptInstance])
-> Getting (UMap ConceptInstance) ChunkDB (UMap ConceptInstance)
-> [ConceptInstance]
forall a. ([a] -> [a]) -> Getting (UMap a) ChunkDB (UMap a) -> [a]
expandFromDB ((ConceptInstance -> Bool) -> [ConceptInstance] -> [ConceptInstance]
forall a. (a -> Bool) -> [a] -> [a]
filter (\ConceptInstance
x -> [UID] -> UID
sDom (ConceptInstance -> [UID]
forall c. ConceptDomain c => c -> [UID]
cdom ConceptInstance
x) UID -> UID -> Bool
forall a. Eq a => a -> a -> Bool
== c
c c -> Getting UID c UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID c UID
forall c. HasUID c => Getter c UID
Getter c UID
uid)) Getting (UMap ConceptInstance) ChunkDB (UMap ConceptInstance)
Lens' ChunkDB (UMap ConceptInstance)
conceptinsTable