@startuml

skinparam monochrome true
skinparam shadowing false
skinparam genericDisplay old
skinparam classAttributeIconSize 0
hide circle


package Repository {
    package ModelSchnittstelle {
      class ProjectHelper <<singleton>> {
        +getProject(Integer): Project
        +getProjects(): Collection<Project>
        +createProject(): Project
      }

      interface Table <<interface>> {
        +getRow(Integer): Row
        +getColumn(Integer): Collection<Any>
        +getCell(Integer, Integer): Any
        +insertRow(Row) throws IllegalTypeException
        +getLayout(): Collection<Class<Any>>
        +addColumn(Class<Any>)
        +deleteColumn(Integer)
        'This is something I am not sure about. How do our InputElements look like?
        +getUIElement(Integer): Function(Any)
        +setUIElement(Integer, Function(Any))
      }

      interface Row <<Interface>> {
        +getCell(Integer): Any
        +getMetaData(Integer): RowMetaInformation
      }

      interface Project <<interface>> {
        +getProjectSkeleton(): ProjectSkeleton
        +getTable(): Table
        +getAdmin(): User
        +getUsers(): Collection<Users>
        +setName(String)
        +setDescription(String)
        +setWallpaper(path: String)
        +setThumbnail(path: String)
      }

      interface ProjectSkeleton <<interface>> {
        +getID(): Integer
        +getName(): String
        +getDescription(): String
        +getWallpaper(): Drawable
        +getThumbnail(): Drawable
        +getGraphs(): Collection<Graph>
        +getProjectSettings(): Settings
        +getNotifications(): Collection<Notification>
      }

      interface Graph <<interface>> {
        'Does this always recompute the DataSets? If not how does it decide when to recompute?
        +getDataSets(): Collection<Collection<Any>>
        +getCustomizing(): Settings
        +getImage(): Drawable?
        +setCalculationFunction(DataTransformation)
      }

      interface Settings <<interface>> {
        +getSetting(String): Any throws SettingNotFoundException
        +setSetting(String, Any) throws SettingNotFoundException
      }

      interface Notification <<interface>> {
        +getMessage(): String
        +sendNow(vararg Any): Boolean throws IllegalContextException
      }

      'This is kind of the same as a project without Data. However, a project really isn't
      'a subtype of ProjectTemplate. How do we want to do this? Do we know any Patterns that
      'fit this problem?
      interface ProjectTemplate <<interface>> {
        +getProjectSkeleton(): ProjectSkeleton
        +getTableLayout(): Collection<Class<Any>>
      }

      interface GraphTemplate <<interface>> {
        +getName(): String
        +getDescription(): String
        +getThumbnail(): Drawable
        +getCustomizing(): Settings

      }

      interface Post <<interface>> {
        +getContent(): Content
        +getName(): String
        +getDescription(): String
      }

      interface Content <<interface>> {

      }
      '-von Anton definiert------------------------------------------------------------------------------'
      class TemplateHelper <<singleton>> {
                  +getProjectTemplates(): Collection<ProjectTemplate>
                  +getGraphTemplates(): Collection<GraphTemplate>
                }
    }
'=================================================================================================='
  package SanityCheck {

  }
'=================================================================================================='
  package UpToDater {
        'Wenn ich einmal länger als 72h am Stück offline war merke ich mir diese Intervalle
        'dann Frage ich jemanden auf dem Server an, der in diesen 72h keine Blindspots hat
  }
'=================================================================================================='
package ServerSchnittstelle {

      }
'=================================================================================================='
  package Commands {

    enum UserRole <<enumeration>> {
        ADMIN
        CASUAL
    }

    class IllegalOperationException {
    }

    abstract class Command <<abstract>> {
    -OnlineProjectID: String?
    -WentOnline: UnixTime?
    -WentOffline: UnixTime?

    +setOnlineProjectID(String)
    +setWentOnline(UnixTime)
    +setWentOffline(UnixTime)
    }

    abstract class TableCommand <<abstract>> {
                -table: Table
                -userRole: UserRole
                -requiredRole: UserRole
                -index: Integer

                +run(): void throws IllegalOperationException
                {abstract} -execute(): void
        }
    class DeleteRow {
        -execute(): void
    }
    class DeleteColumn {
        -execute(): void
    }
    class AddRow {
        -execute(): void
    }
    class AddColumn {
        -execute(): void
    }
    class SetCellInRow {
        -positionInRow: Integer
        -execute(): void
    }
    note right of TableCommand::run
    if userRole >= requiredRole
        execute();
    else
        throw IllegalOperationException;
    end note
    Command<|-- TableCommand
    TableCommand <|-- DeleteRow
    TableCommand <|-- DeleteColumn
    TableCommand <|-- AddRow
    TableCommand <|-- AddColumn
    TableCommand <|-- SetCellInRow
  }
}

@enduml