use std::collections::BTreeMap;
use std::cmp::Ordering;
use std::sync::Arc;
use condition::Condition;
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum StateRelation {
Extends,
Overrides,
}
pub type StateRelations<C> = BTreeMap<Arc<IssueState<C>>, StateRelation>;
pub struct IssueState<C>
where C: Condition + Sized
{
name: String,
pub conditions: Vec<C>,
pub relations: StateRelations<C>,
}
impl<C> IssueState<C>
where C: Condition + Sized
{
pub fn new(name: String) -> Self {
Self {
name: name,
conditions: Vec::new(),
relations: StateRelations::new(),
}
}
pub fn name(&self) -> &String {
&self.name
}
pub fn add_extended<I>(&mut self, dependencies: I)
where I: IntoIterator<Item = Arc<IssueState<C>>>
{
let entries = dependencies
.into_iter()
.map(|state| (state, StateRelation::Extends));
self.relations.extend(entries)
}
pub fn add_overridden<I>(&mut self, overridden_by: I)
where I: IntoIterator<Item = Arc<IssueState<C>>>
{
let entries = overridden_by
.into_iter()
.map(|state| (state, StateRelation::Overrides));
self.relations.extend(entries)
}
pub fn conditions_satisfied(&self, issue: &C::Issue) -> bool {
self.conditions.iter().all(|c| c.satisfied_by(issue))
}
}
impl<C> PartialEq for IssueState<C>
where C: Condition
{
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl<C> Eq for IssueState<C>
where C: Condition
{}
impl<C> PartialOrd for IssueState<C>
where C: Condition
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(&other))
}
}
impl<C> Ord for IssueState<C>
where C: Condition
{
fn cmp(&self, other: &Self) -> Ordering {
self.name.cmp(&other.name)
}
}
pub type IssueStateVec<C> = Vec<Arc<IssueState<C>>>;
#[cfg(test)]
mod tests {
use super::*;
use test::TestState;
#[test]
fn smoke() {
let mut issue = BTreeMap::new();
issue.insert("foo", true);
issue.insert("bar", true);
issue.insert("baz", false);
let mut state : TestState = IssueState::new("state".to_string());
state.conditions = vec!["foo".into(), "bar".into()];
assert!(state.conditions_satisfied(&issue));
state.conditions = vec!["foo".into(), "baz".into()];
assert!(!state.conditions_satisfied(&issue));
}
}