{-# 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} = 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 forall a b. (a -> b) -> a -> b
$ [SSDSub] -> SSDSec
DL.SSDProg forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map SSDSub -> SSDSub
ssdSec [SSDSub]
s
  sec (ReqrmntSec (ReqsProg [ReqsSub]
r)) = ReqrmntSec -> DocSection
DL.ReqrmntSec forall a b. (a -> b) -> a -> b
$ [ReqsSub] -> ReqrmntSec
DL.ReqsProg forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map ReqsSub -> ReqsSub
reqSec [ReqsSub]
r
  sec DocSection
LCsSec = LCsSec -> DocSection
DL.LCsSec forall a b. (a -> b) -> a -> b
$ [ConceptInstance] -> LCsSec
DL.LCsProg forall a b. (a -> b) -> a -> b
$ forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB ConceptChunk
likeChgDom
  sec DocSection
UCsSec = UCsSec -> DocSection
DL.UCsSec forall a b. (a -> b) -> a -> b
$ [ConceptInstance] -> UCsSec
DL.UCsProg forall a b. (a -> b) -> a -> b
$ 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 (forall i.
(Quantity i, MayHaveUnit i) =>
[i] -> Sentence -> [ConceptInstance] -> [ConceptInstance]
fullReqs [h]
is Sentence
d forall a b. (a -> b) -> a -> b
$ forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB ConceptChunk
funcReqDom) (forall i.
(Quantity i, MayHaveUnit i) =>
[i] -> [LabelledContent] -> [LabelledContent]
fullTables [h]
is [LabelledContent]
t)
  reqSec (FReqsSub' [LabelledContent]
t) = [ConceptInstance] -> [LabelledContent] -> ReqsSub
DL.FReqsSub' (forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB ConceptChunk
funcReqDom) [LabelledContent]
t
  reqSec ReqsSub
NonFReqsSub = [ConceptInstance] -> ReqsSub
DL.NonFReqsSub forall a b. (a -> b) -> a -> b
$ 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 forall a b. (a -> b) -> a -> b
$ Sentence -> [Section] -> [PDSub] -> ProblemDescription
DL.PDProg Sentence
s [Section]
ls forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map PDSub -> PDSub
pdSub [PDSub]
p
  ssdSec (SSDSolChSpec (SCSProg [SCSSub]
scs)) = SolChSpec -> SSDSub
DL.SSDSolChSpec forall a b. (a -> b) -> a -> b
$ [SCSSub] -> SolChSpec
DL.SCSProg forall a b. (a -> b) -> a -> b
$ 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) = 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) = forall c.
Idea c =>
c -> [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 forall a b. (a -> b) -> a -> b
$ forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB ConceptChunk
goalStmtDom
  scsSub :: SCSSub -> DL.SCSSub
  scsSub :: SCSSub -> SCSSub
scsSub SCSSub
Assumptions = [ConceptInstance] -> SCSSub
DL.Assumptions forall a b. (a -> b) -> a -> b
$ 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 forall a b. (a -> b) -> a -> b
$ forall a. Getting (UMap a) ChunkDB (UMap a) -> [a]
allInDB Lens' ChunkDB (UMap TheoryModel)
theoryModelTable
  scsSub (GDs [Sentence]
s Fields
f DerivationDisplay
dd) = [Sentence] -> Fields -> [GenDefn] -> DerivationDisplay -> SCSSub
DL.GDs [Sentence]
s Fields
f (forall a. Getting (UMap a) ChunkDB (UMap a) -> [a]
allInDB 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 (forall a. Getting (UMap a) ChunkDB (UMap a) -> [a]
allInDB 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 (forall a. Getting (UMap a) ChunkDB (UMap a) -> [a]
allInDB Lens' ChunkDB (UMap InstanceModel)
insmodelTable) DerivationDisplay
dd
  scsSub (Constraints Sentence
s [c]
c) = 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) = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. UMap a -> [a]
asOrderedList forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ChunkDB
db 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 = forall a. ([a] -> [a]) -> Getting (UMap a) ChunkDB (UMap a) -> [a]
expandFromDB forall a. a -> a
id
  fromConcInsDB :: Concept c => c -> [ConceptInstance]
  fromConcInsDB :: forall c. Concept c => c -> [ConceptInstance]
fromConcInsDB c
c = forall a. ([a] -> [a]) -> Getting (UMap a) ChunkDB (UMap a) -> [a]
expandFromDB (forall a. (a -> Bool) -> [a] -> [a]
filter (\ConceptInstance
x -> [UID] -> UID
sDom (forall c. ConceptDomain c => c -> [UID]
cdom ConceptInstance
x) forall a. Eq a => a -> a -> Bool
== c
c forall s a. s -> Getting a s a -> a
^. forall c. HasUID c => Lens' c UID
uid)) Lens' ChunkDB (UMap ConceptInstance)
conceptinsTable