diff --git a/bundles/cnf/localrepo/index.xml b/bundles/cnf/localrepo/index.xml index 9dbd43de2..7d17fbaa9 100644 --- a/bundles/cnf/localrepo/index.xml +++ b/bundles/cnf/localrepo/index.xml @@ -1,4880 +1,4854 @@ - - + + - + - + + + + + + + - - + + - - + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - + + - - - - - + + + + + - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + - - + + + - + + + + + + + + + - + - + + + + + + + - - + + - - + + - - + + + + - - + + + + + - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - + + + + + + - - - + + + + + - - - + + + + + - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - + + + + + - - - + + + + + - - - - + + + + + + - - - + + + + + + - - - - - + + + + + + - - - - - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + + + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + + + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - - + + - - + + + + + - - - - - - - - + + + + + - - + + - - - + + - - - + + - - - + + - - + - + + + + + + + - - - + + - - + + - - + + + + + - - + + + + + - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - + + + + + + - - - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + - - - + + + + - - - - - + + + + + + + + + + + - - - - - - - - + - + - + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - + + - - - + + + + + - - - + + + + - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - + - + + + + + + + - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - + - + - + - - + + - + - + + + + + + + - - + + - - + + + + + + + + + - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - + + - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - + + + + - - - - - - - - - - - - - - - - + + - - + + + + + - - + - + + + + + + + - - - + + - - + + - - + + + + - - + + + + - - - + + + + - - + + + + - - + + + + - - + + + + - - - - - - - - + + + + - - - - - - - - - - - - - - - + + + + + - - - + + + + + - - - + + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - + + + + + + - - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + + - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - + - + + + + + + + - - - + + - - + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - + + + + - - - - - - - - + + + + - - - - - - - + + - - + + + + - - + - + + + + + + + - - - + + - - + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - + + - - - - - + + + + + - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - + + + + - - - + + + + - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + + + + - - + + - - + + - - - + + + + - - - + + + + - - - - - + + + + + + + + + + + + + + + + + - - - - - - - + - + - + - + - - + - + + + + + + + - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + - - - + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + - + + - + + - + - + - + - + - - + + - - + - + + + + + + + - - - + + - - + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - + + + + + + - - - + + + + + + + + + + + + + - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - - + + + + + + + - - + + - - + + - - - + + + + - - - + + + + - - + + + + - - - + + + + - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + - - + + + + - - - - - + + + + + - - - - - - - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - + + + + + - - - - - - - - - + + + + + - - - + + + + + - - - + + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + - - - - - - + + + + + - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + - - - - - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + - - - - - + + + + + - - + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - + + - - - - - - - - - - - - + - + + + + + + + - - - + + - - + + - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - + - + - + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - + + - - + + + + + + - - + + + + + - - - - - - - - + + + + + + - - - - - - - - + + - - + + + - - - + + + - - - + + - - + + - - - + + - - - - + + + - - - + + + + + + + + + + + + + + + + + + + + - - + + + - - - - - - - - - + + + + + + + + + + + - - + + - - + + - - + + - - + - + + + + + + + - - - + + - - + + - - - + + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - + + - + + - + + + - + + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - + - + - + - + - + + + + + + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - - + + - - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - - - + + - - + + - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - + + + + + + - - - + + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - + + + + - - + + + + + - - + + + + + - - - - - + + + + + + - - + + - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - - + + - - + + - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - + + + + + - - - - + + - - - + + + + + - + - + - + - + - + - + - + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - - - - - - - - - + + - - + + + + - - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - - - - + + + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - + - + + + + + + + - - - + + - - + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - + + + + + - - + + + + + - - + + + + + - - - + + + + + - - + + + + + - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - + + + + + + - - - + + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - + + + + + - - - + + + + + - - - + + + + + + - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - - - + + - + - - - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - + + - - + + - - + + - + - + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - + + - - - - - + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - - - - - + + + + + + - - - + + + + + + - - - + + + + + + - - - - - + + + + + + - - - - - - + + + + + + - - - + + + + + + - - - + + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + + + + + - - + + - - + + - - - + + + + + - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - - + + - - + - + + + + + + + - - - + + - - + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - + + + + + - - + + + + + - - - - - + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - + + - - - + + - - - + + - - - + + - - - + + - - + + - - - + + - - - + + - - - + + + + + - - + - - + + + + + + + - - + + - - + + - - - - - - - - - + + + + + - + + + + - + - + - + - + - + - + @@ -4882,619 +4856,899 @@ - - + - + + + + + + + - - - + + - - + + - - - - - + + + + + - - - - - - - - - - - - - + + + + + + - - - - + + + + + + - - - + + + + + + - - - + + + + + - - + + + + + - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - + + + + + + - - - + + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - + + + - - + + + - - - - + + + + + + + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + - - - - - - - + + + + + + - - - - + + + + + + - - - + + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + + + + + - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - + - + + + + + + + + - - + + - - + + - - - + + + + + + + + - - + + + + - - + + + + - - - - - - + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + + + + + - - - - - - - + + + + + - - - - - - - - - - - - - + - + - + - + - + - - + + - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - - + + - - - - - - - - - - - - + + + + + + - - - - - + + + + + - - - - - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - + + - - + + - - + + + + + - - - - - + + + + + - - - - - - - + + @@ -5502,7647 +5756,8636 @@ - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + - - - - - - - + + + + + - - - - + + + + + + + - - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - + + + + - - + + + + - - + + + + + - - - + + - - - - - + + + + - + - + - + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + - - + - - + + + + + + + + - - + + - - + + - - - + + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + - - - - + + + - - + + + - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + - - - + + + + + + + + + + + + + + + + - - - + + + + + - - - - + + + - - - - + + + + + + + - - - - - - - - - - - - - - - + + + + + - - - + + + + - - - + + + + + - - - + + + + - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + - - + + - - - - - - - - + + - - - - - - - - - - - + + + - - + + + - + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + + - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + - + - + - + - - + + - - + + + - - + + + - - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - - + + - - + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - - - - + + + + - + - + - + - - + - - + - + + + + - - + - + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + - - + + - - - + + + + - - - + + + + + - - + + + + + - - - - - - - - + + + + + - + + - - - - - - - - - - - - - - - - - - - - + + - - + + + - - - - - + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + - + + - + + - - + + - - + + - - - - + + + - - + + + - - - - - - - - - - - - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - + + - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - + + + + + + - - - + + + + + + + + + + - - - - - + + + + + - - - + + + + + + + + + - - + + + + - - - - - + + + + + - - - + + + + + - - - + + + + + - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - - + + + - - + + + - - + + + - - + + - - + - + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + - - + + - - + + + + - - - - - - - - - + + + + + - - - - - - - + - - - + - - - + - + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - - - - - - + + + + + - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + - - + + + - - - - + + + + + + + + - + - + + + + + + + + - - + + - - - - - - - - - - - + + - - - + + + + - - - - - - - - - + + + + + - - - + + - - - + + + - - - + + + - - - + + + - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - - + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + - - + + + + - - - - - - - - + + + + - - - - - - - - + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + - - + + - - + + - - - + + - - - + + - - + - + + + + + + + + - - - + + - - + + - - + + + + - - + + + + - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - - - - - - - + + + + - + - + + - + - - + - + - + - + - - - - - - - - - - - - - - - - - - - - - + - - - + + - - - + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - + + - - - + + + + + + + - - + + + - + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + - - + + - - + - - + + + + + + + - - + + - - - - - - - - - - - - + + - - - - + + + + + + - - + + + - - - - - - - - - - - - - - - - + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + - - + + + + - - - - - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + + + + + + + + + + + + + - + - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - - - - + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - + + + + - - - + + + + - - - - - + + + + + + + + + + + - - - - + - + - - + + - - + - + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + - - + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + + + + + + + - - + + - - - - - - - - - - - - + + - - + + + + + + + - - + + + - - - - - - - - - - - - + + + + + + + + + - - + + - - + + - - - - + + - - - + + - - - + + - + - - + - - + + + + + + + - - + + - - + + - - - - + + + + + + + - - - - + + + + + - - - + + + + - - - + + + + - - - + + + + - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + + + + - - - + + + + + - - - - + + + - - - - + + + - - - + + + + - - - + + + + - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + + + + + + + + + + + - - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - + + + + - - - - - + + + + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + - - + + - - + + + + + + + + + + + + + + + + + + + - + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - - + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + - - - + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + + - - + + + - + + + + + + - - + + + + - + - + - + + + + + + + - - + - - + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + + + + + - - - - + + + + + - - - + + + + - - - - + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + - - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + + + + + + + + - - + - + - + + + - + + + - - - - - - - + + + - + - + - + + + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - + + - - - + + + + + + + - - + + + - - - - - - - - - - - - - + + + + + + + + - - + - + + + + + + + - - - + + - - + + - - - - - - - + + + + + + + - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + - - + - - + - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + + + + + + + - + - + - + - + - + - + - + - + - + + - + - + + - + - + + + + + + + - - + - - + + + + + + + - - + + - - - - - - + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + - - + + + - - - - + + + + + + + + - - + - + + + + + + + - - - + + - - + + - - - - + + + + + + - - - - + + + + + - - - - + + + + + + + - - - + + + + + + + + + - - - - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - - - - + + + + + + + + + - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + + + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + - - + + + + - - + + + + - - + + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - + + - - + + - - + + - - + + - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - - + + - - + + - - + + + + - - + + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - - + + - - + + - - + + + + - - + + + + - - - - - - - - - - - - - - - - - + + + + - + + - - - - - + + - - + + + - - + + + - - + + - - - + + + - - + + + - - - - + + + + + + + + - - + - - + + + + + + + + - - + + - - + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - - + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + - - + + + + - - + + + + - - + + + + - - + + + - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + + + + - - + + + - + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + - - - + + + + - - + + + + - - - - - + + + + + + - + - - + - - + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + - + - - - - - + + + + - - + - + + + + + + + - - - + + - - + + - - - - + + + + + + + - - - - + + + + + - - - - + + + + + + + - - - + + + + - - - + + + + - - + + + + - - + + + + - - - + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + - - - + + + - - - + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + - - - + - - + - - + + + + + + + + + + + + + + + + + + + - + + + + - + - + + + + + + + - - + + - - + + - - - - + + + + + + - - + + + - - - + + - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - + + + + - + - + - + - + - + - + - + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - - - - - - - + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + - - + + + - - - - + + + + + + + + + + + - - - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + - - - + + + + + + - - + + + - - - - - - - + + + + + + + + - - + - + + + + + + + + - - - + + - - + + + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + - + - + - - + + + + + + + + - + - + - + - + - + - + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - + + + + - - + + + + - - + + + + - - + + + + + - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + - - + - - + - - + - + - - + - - + - - + - - + + + + - - + - + + + + + + + - - - + + - - + + - - - - + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + - - - + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + + + + + + + + + - - + + + - + + + + + + + + + + + + + + + - + + - + + - - + + + - - + + + - - + + + + + + + + + + - - + - - + + + + + + + - - + + - - + + - - - - + + + + + + + + + + + + + + + + + + + + + - - - + + + + - - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + - - + - + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + - - + + - - - + + + + + - - - + + + + + - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - + + - - + + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - + + + + + - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - + + - - + - - + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - + - + + + + + + + + - - - + + - - + + + + + + - - - - - - - - - + - - - - - - - - - - - - - - - - - - - + - - + + - - + + - - + + + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - - - - - - - - - - - - - + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - - + + + + + + + + - - + + - - + + - - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + - - + + - - + + - - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - - - + + - - - + + - + - - + - - + + + + + + + - - + + - - - - - - - - - - - - + + - - - - + + + + + + + - - - - + + + + + - - - + + + - - - - + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - + + + - - - - + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + + + + - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - + + + + + - - - + + + + + + + + + - - - - - + + + + + - - - + + + + + - - - - - + + + + + + + + + + + + - + - + - - + - - - - - + - - + + - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + - - + - - - - - - - - - - - - - - - - - - - + - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - + + - - + - - + + + + + + + + - - + + - - + + - - + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + - - + + + - - + + + - - + + + + + + + + + + + + + + + + + + + + - - + - - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - - + + - - + + - - + + + + - - + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - - - - + + + + + + - - - - - - - + - + - + - - + + - - - - + + + - - + + + - - - - + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - + + + + - - + + + + + - - - - - - - - + + + + + - - - - - - - - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - + + - - + + - + + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - + + - - - - - - - - - - - - - - + - + + + + + + + + - - - + + - - + + - - - + + + + + - - + + + + + - - - - - + + + + + - - + + - + - + - + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + + + + + + + + - - + + - - - - - - - - - - - - + + - - - + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - - - - - - - + + + + + - + - + - + - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - + + + + + - - + + + + + - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + - - + + + + + + + + - - + + - - - - - - - + + - - + + + + + - - - + + + + + - - - - - - - - - + + + + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - - - - - - + + - - - - + + + + + + + - - - + + + + + - - - - + + + - - - + + + - - + + + + + - - + + + + + - - - - - - - - + + + + - - - - + + - + + - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + + + + + + + + - - + + - - + + - - + + + + + - - + + + + + - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - - - + - - - - - - - - - - - - - + + + - + + + + + + + + - + - + - + - + - - + + + + - - + - - + + + + + + + - - + + - - - - - - - + + - - - - + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + + - - - + + + + + - - - + + + + - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - + + + - - - - + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + + - - - + + + + + - - + + + + + - - - + + + + + - - - + + + + + - - + + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - - + + + + + + + + + + + + + - - - - + + + + + - - - + + + - - - - + + + - - - - + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + + - - - + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - + + + - - - - + + + + + + + - - - - + + + + + - - - - + + + - - - + + + - - - + + + + + - - - + + + + + - - + + + + + - - + + + + + - - - + + + + + - - - + + + + + - - - - - - - - - + + + + + - - + - - + - - + - - + - - + - - + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + - - + + + + + + + + + + + @@ -13150,2305 +14393,2444 @@ - - + - + + + + + + + - - - + + - - + + - - - - + + + + + + - - - - + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + - - + + + - + + + + + + + + - - + - - + + + + + + + + - - + + - - + + - - + + + + + - - + + + + - - + + + + - - - - - + + + + + - + - + - + - + - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - + + - - - + + + + + + + - - - - + + + + + - - - - + + + + + + + - - - + + + + - - - - - + + + + + + + + + - + - - + + - - + + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - - + + + + - - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + - - + + + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + - - - - - - - - + + - - + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + - - - - - - - - - - - - + + - - - - - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - + - + - + - - - + + - - + - + + + + + + + - - - + + - - + + - - - + + + + + + + - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + - + - + - - + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + - - + + + + + + + + - - + + - - + + - - + + + + - - - - - - - - - - - - - - - - - + + + + - - - - + + + + + - - - + + + + + - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + + + + + + + - - - - - - - - - - - - - + - + + - + + - - + + - - + - - + + + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + + + + + + + - + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - - + + + + + + + + - - + + - - - - - - - - + + - - - + + + + + - - - - - - - - - - + + + + + - - + + + - - + + - - + + - - + + - - - + + - - + + + + + + + + + + + + + + - - + - - + + + + + + + - - + + - - + + - - - - + + + + + + + - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - + + + - - - - - - - - - + + + + - - - + + - - - + + - - - + + + + + - - + - + + + + + + + + - - - + + - - + + - - + + + + - - + + + + - - - - + + + + - - + + + + - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + + + + + + + + - + + - + + - + + - + + - + + - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - - + + + - - - + + + - - - + + - - - + + - - + + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + + + + + + + + - - + + + - + + + + + + + + - - + - + + + + + + + + - - - + + - - - - - - - + + + + + + - - - - - - - - - - - - - - + + + + + - - + - - + - + - - - - + + - - + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + + - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + - - + + + + - - - - - + + + + + - - - - - - - + - - + + + - - + + + - - + + - - + + - - - - - - - - + + + - - + + + - - - - - + + + + + + + + - + - + + + + + + + + - - + + - - + + - - + + + + + - - + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + - - + + + + + - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + - - - + + + - - - + + + - - - + + - - - + + - - - + + - - + - - + + + + + + + - - + + - - - - - - - - - - - - - - - - - + + - - - - + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + - - - + + + + + - - - - - - - - - + + + + + - + - + - + - + - - + + - - - + + + - - - + + + - - - + + - - - + + + + + + + + + + + + - - + - + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + - - + + - - + + + + - - - + + + + - - - - - + + + + + - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + - - + + + + + + + - - + + - - + + - - - + + + + + + + - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -15456,7264 +16838,7732 @@ - + - + + + + + + + - - + + - - + + - - - + + + + + + - - + + + - + + + + + + + + - - + - + + + + + + + + - - - + + - - - - - - + + - - + + + + + - - - - - - - - + + + + + - - - + - + - - + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - + + + + + + - - + + + + + - - + + + + + - - + + + + - - - - - + + + + + - + + + - - + + - + - + + + + + + + + + - + - + - + - + + + + - + - + - + + - + - + + - + + - + + + + + - - + - + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + - - + + - - + + + + + - - - + + + + + - - - - - + + + + + + + + + + + - - + + - + + + + + - - + + - - + + - - + + - - + + - - + - + + + + + + + + - - - + + - - + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + - - - - - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - + + + + - - + + + + - - - - - + + + + + + + + + + + - + - - + - - + - + - + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + - - - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + - - - + + + + - - - - - + + + + + - - - - - - - - + + - - + + - - + + - - + + - - + + + - - + + + - - + + - - + + - + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + + - + - + - + - - + + + + + + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - - + + + + - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + - - - - - - - - + + + - - + + - - + + - - - - - + + + - - + + + - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - - + + - - + + - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + - - - + + + + + + + + - - + + + - - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - + + - - + + - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + - + - + + + + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + - - - - - - - - + + + + + - + - + - + - - + - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - + + - + + - + + - + + - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - - + + - - - - - - - - - - - - + + - - - - - - - - - + + + + + + + - + + + - + + + + + + + + + + + + - - - - - + + + - - - - - - - - - - - - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + - - - + + + + - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + + - - + + + + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - + + + + - - - + + + + - - + + + + - - - - - - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + - + - + - + - + + + + + + + + + + + + + + + + + + + + - - + - - + + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + - - + + + + - - + + + - - + + + + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + - - - + + + + - - + + + + - - + + + + - - - - - - - - + + + + - - + - + + + + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - + + + + - - - + + + + - - - - - - - - - + + + + - - + - - + - - + + - - + + + - - + + + - - + + + + + + - - + - - - + - - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + - - - + + + + - - + + + + - - - - - - - - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - + + - - + + + - - + + + - - + + + - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - - + + - - + + - - - + + + + - - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - + + - - + + - - + + + - - + + + - - + + + - - + + + + + - - - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - + - - - - - - - - + + + - + + + + + + + + - + - + + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - - - - - + + - - + + + + - - - - - - - - + + + + - + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + - - - + + + + - - - - - + + + + + + + + + + + + + + - + + + - + + - + + - + + - + + + + + + + + + - + - - - - - - - - - - - - - + + - - + + + - - - - - - - - - - - - - - - - - - - - - + + - - + + - - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + - - + + - - + + + - - + + + - - + + + - - - - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + - - + - - - + - - - - - - - - + + + - - - - - - - - - - - - + + - - + + - - - + + + + - - - + + + + - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + - - - - - + + + + + - - - - - - - - + + - - + + + - - + + + - - + + + - - + + + - - + + - - + + - + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - - + + - - + + - - + + + + - - - + + + + - - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + - + + + - + - + - + + - - + + - + - + + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - - + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + - - + + + + + - - - - - - - - + + + + - - - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + - - + + + - - - + + - - - + + - - + - - + - - - + + - - + - - + + + + + + + - - + + - - - - - - - + + - - - - + + + + + + + - - - - + + + + + - - - + + + - - - - + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + + - - - - - - - - - + + + + + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - - + - - + - - + - - + - - + - - + - - + - - + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - - - - - - - - - + + - - + + + + - - - - - - - - - - - - - - - - - - - - + + + - - - + + - - - + + + + + - - - - - - - - - - - + + + - - + + + - + + + + + + - - + - - + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - + + + - - + + + - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - + + - - - - - - - + - - - - - - - - - - - - - - - - - + - - + + + - - - - - - - - - - - - + + - - + + - - + + + + + - - - + + + + + + + + - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - + + + - - + + + - - + + + - + + - + + - + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + + - + - + - + - + + - + + + + - - + - + + + + + + + - - - + + - - - - - - - - - - + + - - + + + + - - + + + + - - - - - - - - + + + + - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + - - + + - - - + + + - - + + - - + + - - + + + + + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - + + + + + + + - - + + - - + + - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - + + - - + + - + + - + - + - + + + + - - + - - - - - - - - - - - - - - + - - + + + - - - - - - - - - - - - - - - - - - + + - - - - - - - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - + + + + + + - - - - - - - - - + - + - + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - - - - + + + + + + - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - - + + - - + + + + + - - + + + + + - - - + + + - - - - - + + + + - - - - + + - + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - - - - + + - - + + - - + + + + + - - - - - - - - - - - - - - + + + + + - - - - - + + + + + + + - + - + - + - + - + + - + + - + - + - + - + - + - + - - + + - - + + - - + + + - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - - + - - + - - + - - + - - + - - + - - + - - + - + - + - - + - - + - - + - + - + - + - - + - + + + + + + + - - - + + - - + + - - - + + + + + + + - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + - - + - + + + + + + + - - + + - - + + - - - - + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + - - - - + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + + + + + - - - + + + + + - - - + + + - - - - + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - + + + + + + + + - - + - + + + + + + + - - - + + - - - - - - - + + - - - + + + + - - - + + + + + + + + - - - - - - - - - - + + + + + - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - + - - - - - - - - - + - + - + - + - + - + - + - - + + - - + - + + + + + + + - - - + + - - + + - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - - - - + + + + - - - - - - - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + - - - - - - - - - - + - - + + + - - - - - - - - - - - - - + + - - - - - - - - - - + + - - - - - - - - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + - - + - - + - - + - - - + + + + + + + + - - + - - + + + + + + + - - + + - - - - - - - - - - - - + + - - - - + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - - - - - - + + + + - + - + + - + + - + - - + - + - + - + - + - + + + + - - - - - - - - - - - + + + + - - + + + - + + + + + + - - - - - - - + + + + + - - - + + + + + + + + + - - - - + + + + + - - - - - - - - - - - - - - + + + + + + + + + - - - - + + + + + - - - - + + + + + + + + + - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - + + + - + + + - - + - - - - - - + + - - + + + - - + - - - + + + + - - - + + + + + - - - + + + + + + + + + + - - + + + - + + + - + - - - - - - + + - - + + + - - - - - - - - - - - + - - - + + + + - - - + + + + + - - - + + + + + + + + + + - - + + + - + + + - - - + + + + - - - + + + + + - - - + + + + + + + + + + - - + + + - + + + - - + - + + + + + + + - - - + + - - - - - - + + - - - - + + + + + + + - - + + + - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - + + + + + - - + + + + + - - - - - - - - + + + + + - - - - - - - - - - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - + + - - + + + + - - + + + + + - - - - - + + + + - - - - - - - - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - + - + + + + + + + - - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - + + - - + + + + - - + + + + + - - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - + + + + + - - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + - - + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - - - + - - - - - - - - + + + - - - - - - - - - - + + - - - - - - + + - - - - - - - - - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + + + + + + + - - + - - + + + + + + + - - + + - - + + - - - + + + + + + + - - - + + + + + + + + + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - + + + + - - - - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + - - - - + + + - - + + + - - - - + + + + + + + + + + + - - - - - - - - - - - - - - + + + - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - + + + + + - - + - - + - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + - - + - - + - - + - - + - - + + + + + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - + + - - - + + + + + + + - - + + + - - - + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + + + + + + + - + + + + + + + - - + - + + + + + + + - - - + + - - - - - - - - + + - - - - - - - + - + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + + - - - - - - - - - + + + + + - - + + - - + + - - + + - - + + + + + + + + - - + - - + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - + - + + + + + + + + - - - + + - - + + - - + + + + + - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + - - + - - - + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - + - + + + + + + + + - - - + + - - + + - - + + + + + - - + + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + - - - + + + + - - - - + + + + - - - - - + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + - - + + + + + + + + - - + - + + + + + + + - - - + + - - - - - - + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + + + + - - - - - - - - - + + + - - - - - - - - - - - - - - - + + - - + + - - - - - + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - - + + + - - + + + + + + + - - + + + + + - - + + + - - + + - - - + + + + + + + + + - - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + + - - - - + + + + + - - - + + + - - - - + + + - - - + + + + + + + + + - - - - - - - + + + + - - - - - + + + + + - - - - + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + + - - - + + + + + - - + + + + - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - + + + + - - + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - - - + - - - - - - - - - + + + + + - - - + + + - - - + + + - - + + + + + - - - - - - - - + + + + - - - + + - - - + + - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + - - + + + + + + + + - + - + + + + + + + + + + - - - - + + + - - + + + - - - - - - - - - - - - - + + - - - - - - - - + + - - + - - - + - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + + + - - - + + + + + - - - + + + + + - - + + + + + - - - + + + + + - - - - - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + - - + + + - - - + + + + + + + + + + + + + + + + - - + - - - + + - - + - + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + - + - - + + + + - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -22730,12549 +24580,15941 @@ + + + + + + + + + + + + - - - + + + - - + + + - - - - + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - - + + + + + + + + + - - - - - + + + + + - - - + + + + + - - - + + + + - - - - - - - - - + + + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - - + + + + + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + + - - - + + + + + - - + + + + + - - + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + - - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - - - - - + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - - - - - - + + + + + + - - + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + + + + - - - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + + - - - - + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - + + + + + - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - + + - - + + - - + + + + + - - + + + + + - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - - - - - - - + + - - + - - - + - - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + + - - - + + + + + - - - - - + + + - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + - - - + - - - - - + + + + + - - - - + + + - - - - + + + + + + + - - - - - - - - - - - + + + + + - - + - - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - - - - - + + - - + + + + + - - + + + + + - - - + + + - - - - - + + + - - - + + + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + - - + - - + + + + + + - - - - + + + - - + + + - - - - + + + + + + + + - + - + + - - - + + + + + + + + + - - + + - - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - + + + - - - - + + + + + + + - - - - - + + + + + - - - - - + + + + - - - + + - - - + + - - - + + - - - + + - - - + + - - + + - - + + + + + + + + - - + + + + + + + + - - + - + + + + + + + - - - + + - - - - - - - - + + - - + - - - + - - - - - + + + + + - - - + + + - - - + + + - - + + + + + - - + + + + + - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + - - - + + + + + - - + + + - - + + - - - + + + + + - - - - - + + + + + + - - + + + + + + + + + + + + + + + - + + + - + - + - + - - + - + - + - + - + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + + + - - + + + - - - - - - - + + + + + + + + - - - + + - - + - + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + + - - + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - + + - - - - + + - + - + + + + + + + - - + + - - + + + + + + + + + - - + + + - - - - - - - - - - - - - - + + + + + + + + - - + - - + + + + + + + + - - + + - - + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - + + + + + - - - + + + + + - - - - - - - - + + + + + - - + - + - + - + - + - + - + - + - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + - - + - + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + + + + + + + - - + + + - + + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - + + - - - - + + + + + + + - - - - + + + + + + + + + - - - - - - - - - - - - - - - + + - - - + + - - + - + + + + + + + + - - - + + - - - - - - + + + + + + - - - - - - - - - - - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - - - - + + + + - - + + - - + + - - + + - - - + + - - + + - - + + - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + - + - + - + - + - + - + + + + + + + + + + + + + - - + - - + + + + + + + - - + + - - - - - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + - - - - + + + - - + + + - - - - - - - - - - - - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - + + + + + - - - + + + + - - - - - + + + + + - - + + - - - + + - - - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - + + - - - + + + + - - - - - + + + + + - - - - - - - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + - - - - - + + + + + - - - - + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + + + + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - - - - - - - - - - + + + - - + + + - + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - - - - - + + - - + - - + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + - + - + - + - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - - - + + - - + + - - - + + + + + - - - - - + + + + + + + + - + - + - + - + + - + - + - + - + + + + + - + - + - + + + + + + + - - + + - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - + - + + + + + + + - - + + - - + + - - - - - + + + + + + - - - - - - - + + + + + + - - - - + + + + + + - - - + + + + + + - - - + + + + + + + + + - - - - - + + + + + - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - + - + - + - + + - + - + - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - + - + - + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - - + + - - - - - - - - + + + + + - - - - - + + + - - + + - - - + + - - - + + - - - + + - - - + + - - - - - - - - - + + + - - + + + - - - - + + + + + + + + - - - - - - - - - + + + - - - + + + + + - - - + + + + - - - + + + + + - - - + + + + + - - - + + + + + + + + + + + + - - + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + + + + + + + - + - + + + + - + - + + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - + + - - - - - + + + + + + - - + + - - + + + - - + + + + + + - - + - + + + + + + + - - - + + - - + + - - - + + + + + - - + + + + + - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + + - + - + - + - + - + - + - + - + - + + + + + + + - + - + + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - - - - - - - - - - + + - - + + + + + - - + + + + + - - - - - - - - + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + - - + + + + + + + + + + - + - + + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - + + - - + + + + + - - + + + + + - - - - - - - - + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + - - + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + + + + + + + - - + + - - + + - - - - - + + + + + - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + + + + - - + - - + + + + + + + + - - + + - - + + - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - - - + + - - + + - - - + + + + - - - + + + + - - - - - + + + + + - - - + + + + + + + + + + + + + + - - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + - + - + - + - - + - + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + + - - + + - - - - - - - - + + - - - + + + - - + + + - - - - - - - - - - - - - + + - - + + - - + + + + + - - - - - + + + + + + - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - + - - + + + - - - - - - - - - - - - + + - - + + - - + + + + + - - - - - - - - - + + + + + - - + + - - - + + - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - + + - - - + + + + + - - - + + + + + - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + - - - + + + + + + - - - + + + + + + - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + - + - - + - - + + + + - + - + - + - + - + - + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + - + + - + + - + + - + + - + + - + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - + - - + + + - - - - - - - - - - - - + + - - + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - - - - - - - + + + + + - - - + + - - - + + - - - + + - - - + + + + + + + + + + + + + + + + + + + + + - - - + + - - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + + + + + + + - + - - - - - - - - - + + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - + + - - - + + + + + - - - + + + + + - - - - - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - - - - - - - - + + - - - + + + + + + - - - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - - - + + - - - + + - - + + - - + + + + + + + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - + + - - + + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - - - + + + - - - + + + - - + + + + + - - - - - - - - + + + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - - - + + - - + + - - - - - - - - + + + + + - - + + - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - - - - - - + + + + + - - + + - - - + + - - - + + - - - + + - - - + + - - + - - + + + + + + + - + - + + + + + + + - - + + - - - - - - + + - - - + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + - - + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + - - - + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + - - - - + + + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + - - - + + + + + + + - - + + + + - - + + + + + - - + + + + + - - + + + + + - - - - - + + + + + + + + + - + + + + + + + - - + - + + + + + + + - - - + + - - + + - - - - + + + + + + + - - - - + + + + + - - - - + + + + + + + + + + + - - + + + + - - + + + + - - + + + + - - - - - - - + + + + + - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - + - + + + + + + + - - + + - - + + + + + + + + + - - + + + - + + + + + + + + - - + - - + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + - - - + + + + - - - + + + + + - - + + + + - - + + + + + - - - + + + + - - - + + + + - - - - - - - - - + + + + - - - - - - - - + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + - - + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + - - + + + + + - - - - - + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - - + + + + - - - + + + + - - + + + + - - - - - + + + + + + + + + + + - + - + + - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + - - - - - + + + + + + - - + + + - - - - - - + + + + - - + + + + - + + + - + + + - + + + - + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + - - - + + + + + + + - - - + + + + + - - - - + + + + + + + - - - + + + + + + + + - - - - - - - - - - - - - - - - - - + + + - + + + - - + + - - + + + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + + - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + + + - + - - + + + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - - - + - - - - - + + + + + - - - - + + + - - - + + + - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - + + + + - - + + + + - - + + - + + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - - + + - - + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + - + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - - - - - - - - - - - - - - - - - - - + + - - - - - - + - + + + + + + + - - - + + - - - - - - - - - - + + - - + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + - + + - + + + - + + - + + - + + + + + - - + + + + + + + + - - + - + - + + + - + + + - + + + - + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - + + + - - - - - - - + + + - + - + - + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + - - - + - - - - - - - - + + + - - - - - - - - - - + + - - + + + + + + - - + + + + - - + + + + - - + + + + - - - - - - + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + + + + + + + + + - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + - + + - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - + + - + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - - + + - - + - - - - - - + - - - + + + + + - - - + + + - - - + + + - - - - + + + + + + + - - + + + - + + + + + + + + - + - - + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + + + + + + + + - - + - + - + + + - + + + - + + + - + + + - - - - - - - + + + - + - + - + - + + + + - + - + + + + + + + - - + + - - + + + + + + + + + - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + + + + + + + + + - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + + + + + + + + - - + + + - + + + + + + + + - - + - + + + + + + + + - - + + - - + + - - - + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + - - + + - - + + - - + + + + - - + + + + + - - - - - + + + + + + + + + + + + + - + - + + - - + + - + - + + + + + + + - - + + - - - - - - + + - - - + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + - - - + + + + + + + + + - - + + + - - - - + + + + + + + + - - + - - + + + + + + + - - + + - - + + - - - + + + + + - - - + + + + + - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + - - - + + + - - - + + + - - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - - - - - - - + + - - + - + + + + + + + - - - + + - - + + - - - + + + + + + + + + - - + + + + - - - - - + + + + + - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + - - - + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + - - + + + - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + - + + + + + + + - - - + + - - + + - - + + + + - - + + + + + - - + + + + + - - - + + + + - - - - - + + + + + - - - + + + + + + + + - - + - + - - - + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - - - + - - - - - - - - + + + - - - - - - - - - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - - - - - - - + + - - + - - + + + + + + + - - + + - - - - - - - - - - - - + + - - - - - + - - - - - - - - - - - - - - - - - - - - + - - - - + + + + + - - - + + + - - - + + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - - - - - - - + + + + + + + + - + - + + + + - - + - + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + - - + + - - + + + + - - + + + + - - + + + + - - + + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - + - + + - - + + - - + + - - + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - - + + + + - - + + + - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + + - - + + + + - - + + + + - - - + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + + - - + + + + + - - - + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + - - + + + + - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + - - - + + + + + - - - + + + - - - + + + - - - + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - + + + - - - + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + - + + - + + - - + + + - - + + + - - + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + + - - - - - - + + + + + + - - - + + + + + + - - - + + + + + - - - - - + + + + + - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + - - - - - - + + + + + - - - + + + + + - - - + + + + + - - + + + + - - - - - + + + + + - - - - - - - - - + + + + + + + + - - - - - + + + - - + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + + - - - + + - - + + - - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + - - + - - + + + + + + + + - - + + - - + + - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - + + + + + - - + + + + + - - - + + + + + - - + + + + - - - + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + - + - + - + - - + + - - + + - + - - - - - - - - - + - - + + + - - - - - - - - - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + - - - - - + - + - + - + - + + - + + - + - + - + - + + - + + - + + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - - - - - + + - + - + + + + + + + - - + + - - + + + + + + + + + - - + + + - + + + + + + + + - - + - + + + + + + + - - - + + - - - - - - - + + - - - + + + + - - - + + + + - - - - - - - - + + + + - - - + + - - - + + - - + + + + + + + + + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + + - - - - - - - + + + + + + - - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + - - + + + + - - - - - + + + + + + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - + + + + - - + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - + + + + + - - + + + + + - - - + + + + + - - - + + + + + - - + + + + + - - - + + + + - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - + + + + - - + + + + - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + - - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - - - - - - - + + + + + + + + + + + - - + - + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + + + + - - + + + - - - - - - - - - - - - - - - - + + + + + + + + - - + - - + + + + + + + + - - + + - - + + - - - + + + + - - - - - + + + + + - - - - - + + - - + + - - + + - - + + + - - + + + - - + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - + + + + + + + + - - + + - - + + - - + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - - - - - - - + + - - + - - - + - - - - - - - - - - - - - + + + + + - - - + + + - - - + + + - - - - - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - + - + + + + + + + + - - + + - - + + + + + + + + + + + + + + + + - - + + + - + + + + + + + + - + - + + + + + + + + - - + + - - + + + + + + + + + - + + - + + + + + + + + - - + - - + + + + + + + + - - + + - - + + - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + + + + + + + + + + + + + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - - - - - - - + + + + - - + - - + - - + + + + - + - - + + + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - + + - - + + + + - - + + + + + - - - + + + + + + - - - - + + + + + - - - + + + - - - + + + - - + + + + - - - + + + + + + - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - - - - - + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - + + + - - + + + - - + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - - - + + - - + + - - + + + + + - - - - - + + + + + + - - + + + + + + + + + + + + + + + + - - - + + - - - + + + - - - + + - - + + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - + - - + + + - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - + + - - + + + + + - - - - - - - - - + + + + + - - + + - - - + + - - - + + - - - + + - - + + - - + + - - - + + - - - + + - - - - - - - - - - - - - - - + + + + + + + + - + + + + - - + - + + + + + + + - - - + + - - + + - - - + + + + + - - + + + + + - - - - - + + + + + + - - - + + + + + + + + + - - - + - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - + - + - + + + + + + + + + + + + + + + + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + - - - - - - + + + + + + - - - + + + + + + - - - + + + + + + - - - - - + + + + + + - - - - - - - + + + + + + - - - - + + + + + + - - - + + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - - - - + + - - - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - - - - + + - - - + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + - - - - - - + + + + + + - - - + + + + + + - - - + + + + + + - - - - - + + + + + + - - - - - - + + + + + + - - - + + + + + + - - - + + + + + + - - - - - + + + + + + - - - - - - - + + + + + + - - - - + + + + + + - - - + + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + - + + + + + + + - - - + + - - - - - - - - - - - - + + - - - - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + - - + + - - + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + + + - - - + + - - + + - - + + + + - - + + + + + - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + - - + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - - - - - - - + + + + - - - - + + - - - + + - - - + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + + + + - - + - + + + + + + + - - - + + - - + + - - - + + + + - - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - + + + + - - + + + + - - - + + + + + + + + + + + + + + + + + + + + - - - - - + + + + - - - + + + + + + + + + - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + - - - + + + + + + - - - + + + + + + - - + + + + + - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - - + + + + - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - - + - - - - - - - - - - - - - - - + - - - - + + + + + - - - - + + + - - - - + + + - - - + + + + + - - - + + + + - - - + + + + + - - - + + + + + - - - + + + + - - - + + + + + - - - + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - - - - - - - + + + + + - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - + + - + + - + + - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - + + - + + + + + - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - - + + + + + - - - + + + + - - + + + + - - + + + + - - + + + + + + + + + + + + + + + + + + + + - - + + + - + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - + - - + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + - - - - - - - + + + + + - - - - + + + + + - - - + + + + + - - - + + + + - - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - + - + + + + + + + - - - + + - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - + - + + + + + + + - - - + + - - - - - - - + + - - - - - + + + + - - - - + + + + - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + + + + + + + - - + + - - - - - - - - + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + - + - + + + + + + + - - + + - - + + - - - - - + + + + + + - - - - - - + + + + + + - - - + + + + + + - - - + + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + - - + + + + + - - - - - + + + + + + - - - - - - - - - - - - - - - - - + + + + + - - - + + + + + + - - - + + + + + + - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + - - - + + + + + - - - + + + + + - - - + + + + - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + - - - + + + + + - - - + + + + + - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + - - - + + + + - - - + + + + + - - + + + + + - - - - - + + + + + + - - - - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - - + + - + - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - + - - + + + - - - - - - - - - - - - + + - - + + - - - + + + + - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - + + + + + - - - + + + + + + - - - + + + + + - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + - - - - + + + + + + - - - + + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + - - + + + + + - - + + + + - - + + + + + + + + + + + + + + + + - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + \ No newline at end of file diff --git a/bundles/cnf/localrepo/index.xml.sha b/bundles/cnf/localrepo/index.xml.sha index 5d41b9d0c..29c071bbf 100644 --- a/bundles/cnf/localrepo/index.xml.sha +++ b/bundles/cnf/localrepo/index.xml.sha @@ -1 +1 @@ -b2dbf9ecd6b0a4eebe8816f45c59ad40a98f682eeae6e5a2b2f3ded32841ff5c \ No newline at end of file +d4e95238dbdcf0608ad506462b622dbd2114f4950853eb4fb6414b724bfa6a34 \ No newline at end of file diff --git a/bundles/cnf/releaserepo/index.xml b/bundles/cnf/releaserepo/index.xml index 0ff3d3fef..c89dffca1 100644 --- a/bundles/cnf/releaserepo/index.xml +++ b/bundles/cnf/releaserepo/index.xml @@ -1,2 +1,3 @@ - - + + + \ No newline at end of file diff --git a/bundles/cnf/releaserepo/index.xml.sha b/bundles/cnf/releaserepo/index.xml.sha index 5d7e59de8..f2b26bf5d 100644 --- a/bundles/cnf/releaserepo/index.xml.sha +++ b/bundles/cnf/releaserepo/index.xml.sha @@ -1 +1 @@ -ac2a878e71e3964eac062550754c59507b3b86b848724548581b68e9493f6c0a \ No newline at end of file +262a924c4164db96f2409bfbe8d20793eb0c91a51c3dcd7c2160cde2bac8a492 \ No newline at end of file diff --git a/bundles/specmate-administration/src/com/specmate/administration/internal/services/StatusService.java b/bundles/specmate-administration/src/com/specmate/administration/internal/services/StatusService.java index fc3912861..40c7653ae 100644 --- a/bundles/specmate-administration/src/com/specmate/administration/internal/services/StatusService.java +++ b/bundles/specmate-administration/src/com/specmate/administration/internal/services/StatusService.java @@ -46,7 +46,8 @@ public boolean canGet(Object target) { @Override public boolean canPost(Object target, Object object) { - return (target instanceof Resource && object instanceof Status); + //return (target instanceof Resource && object instanceof Status); + return false; } @Override diff --git a/bundles/specmate-cdo-server/src/com/specmate/cdoserver/config/SpecmateCDOServerConfig.java b/bundles/specmate-cdo-server/src/com/specmate/cdoserver/config/SpecmateCDOServerConfig.java index a8cb70564..3a855aa9b 100644 --- a/bundles/specmate-cdo-server/src/com/specmate/cdoserver/config/SpecmateCDOServerConfig.java +++ b/bundles/specmate-cdo-server/src/com/specmate/cdoserver/config/SpecmateCDOServerConfig.java @@ -19,7 +19,7 @@ public class SpecmateCDOServerConfig { public static final String PID = "com.specmate.cdoserver"; - public static final String KEY_SERVER_PORT = "cdo.serverPort"; + public static final String KEY_SERVER_HOST_PORT = "cdo.serverHostAndPort"; public static final String KEY_REPOSITORY_NAME = "cdo.repositoryName"; public static final String KEY_CDO_USER = "cdo.user"; public static final String KEY_CDO_PASSWORD = "cdo.password"; @@ -40,7 +40,7 @@ public class SpecmateCDOServerConfig { @Activate private void activate() throws SpecmateException { - this.serverPort = configService.getConfigurationProperty(KEY_SERVER_PORT); + this.serverPort = configService.getConfigurationProperty(KEY_SERVER_HOST_PORT); this.repositoryName = configService.getConfigurationProperty(KEY_REPOSITORY_NAME); this.cdoUser = configService.getConfigurationProperty(KEY_CDO_USER); this.cdoPassword = configService.getConfigurationProperty(KEY_CDO_PASSWORD); @@ -48,7 +48,7 @@ private void activate() throws SpecmateException { Dictionary properties = new Hashtable<>(); if (!StringUtil.isEmpty(serverPort) && !StringUtil.isEmpty(repositoryName) && !StringUtil.isEmpty(cdoUser) && !StringUtil.isEmpty(cdoPassword)) { - properties.put(KEY_SERVER_PORT, serverPort); + properties.put(KEY_SERVER_HOST_PORT, serverPort); properties.put(KEY_REPOSITORY_NAME, repositoryName); properties.put(KEY_CDO_USER, cdoUser); properties.put(KEY_CDO_PASSWORD, cdoPassword); diff --git a/bundles/specmate-cdo-server/src/com/specmate/cdoserver/internal/SpecmateCDOServer.java b/bundles/specmate-cdo-server/src/com/specmate/cdoserver/internal/SpecmateCDOServer.java index 7e03598c9..a3af7fb51 100644 --- a/bundles/specmate-cdo-server/src/com/specmate/cdoserver/internal/SpecmateCDOServer.java +++ b/bundles/specmate-cdo-server/src/com/specmate/cdoserver/internal/SpecmateCDOServer.java @@ -20,6 +20,7 @@ import org.osgi.service.component.annotations.ConfigurationPolicy; import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Reference; +import org.osgi.service.log.LogService; import com.specmate.cdoserver.ICDOServer; import com.specmate.cdoserver.config.SpecmateCDOServerConfig; @@ -33,7 +34,7 @@ public class SpecmateCDOServer implements DBConfigChangedCallback, ICDOServer { /** The configured tcp port */ - private int port; + private String hostAndPort; /** The tcp acceptor */ private IAcceptor acceptorTCP; @@ -56,6 +57,10 @@ public class SpecmateCDOServer implements DBConfigChangedCallback, ICDOServer { private String cdoPassword; + private LogService logService; + + private boolean active = false; + @Activate public void activate(Map properties) throws SpecmateValidationException, SpecmateException { readConfig(properties); @@ -75,11 +80,9 @@ public void deactivate() { * if the configuration is invalid */ private void readConfig(Map properties) throws SpecmateValidationException { - String portString = (String) properties.get(SpecmateCDOServerConfig.KEY_SERVER_PORT); - try { - this.port = Integer.parseInt(portString); - } catch (Exception e) { - throw new SpecmateValidationException("Invalid port format: " + portString); + this.hostAndPort = (String) properties.get(SpecmateCDOServerConfig.KEY_SERVER_HOST_PORT); + if (StringUtil.isEmpty(this.hostAndPort)) { + throw new SpecmateValidationException("No server host and port given"); } this.repositoryName = (String) properties.get(SpecmateCDOServerConfig.KEY_REPOSITORY_NAME); @@ -103,17 +106,25 @@ private void readConfig(Map properties) throws SpecmateValidatio */ @Override public void start() throws SpecmateException { + if(active) { + return; + } if (migrationService.needsMigration()) { migrationService.doMigration(); } createServer(); + active=true; } /** Shuts the server down */ @Override public void shutdown() { + if(!active) { + return; + } LifecycleUtil.deactivate(acceptorTCP); LifecycleUtil.deactivate(repository); + active=false; } /** Creates the server instance */ @@ -136,7 +147,7 @@ private void createRepository() throws SpecmateException { Map props = new HashMap<>(); props.put(IRepository.Props.OVERRIDE_UUID, "specmate"); props.put(IRepository.Props.SUPPORTING_AUDITS, "true"); - props.put(IRepository.Props.SUPPORTING_BRANCHES, "true"); + props.put(IRepository.Props.SUPPORTING_BRANCHES, "false"); this.repository = (InternalRepository) CDOServerUtil.createRepository(this.repositoryName, dbProviderService.createStore(), props); @@ -156,8 +167,10 @@ public void authenticate(String userID, char[] password) throws SecurityExceptio /** Creates the TCP acceptor */ private void createAcceptors() { + logService.log(LogService.LOG_INFO,"Starting server on " + this.hostAndPort); this.acceptorTCP = (IAcceptor) IPluginContainer.INSTANCE.getElement("org.eclipse.net4j.acceptors", "tcp", - "0.0.0.0:" + port); + hostAndPort); + logService.log(LogService.LOG_INFO, "Server started"); } /** @@ -184,4 +197,9 @@ public void unsetDBProviderService(IDBProvider dbProviderService) { public void setMigrationService(IMigratorService migrationService) { this.migrationService = migrationService; } + + @Reference + public void setLogService(LogService logService) { + this.logService = logService; + } } diff --git a/bundles/specmate-config/config/specmate-config.properties b/bundles/specmate-config/config/specmate-config.properties index 4e95307b5..b402d1ffc 100644 --- a/bundles/specmate-config/config/specmate-config.properties +++ b/bundles/specmate-config/config/specmate-config.properties @@ -11,7 +11,7 @@ cdo.password = cdoPass ## CDO Server ### TCP port where the CDO server should listen -cdo.serverPort = 2036 +cdo.serverHostAndPort = localhost:2036 ## CDO Client ### Name of the CDO resource to use @@ -32,8 +32,13 @@ h2.jdbcConnection = jdbc:h2:./database/specmate #oracle.password = # Connectors General Settings -## Time in seconds between polling the connectors, set to -1 to disable polling, default: 20 -connectorPollTime = 20 +## cron string to schedule, when connectors are triggered. +## Set to "disabled" (without quotes) to disable polling. +## default: disabled +## generic value (will trigger every minute): * * * * * +## See: http://www.sauronsoftware.it/projects/cron4j/manual.php +# connectorPollSchedule = disabled +connectorPollSchedule = * * * * * # Sarch Service search.allowedFields = extId, type, name, description diff --git a/bundles/specmate-connectors/.gitignore b/bundles/specmate-connectors/.gitignore index af64e9f3f..42392e8f9 100644 --- a/bundles/specmate-connectors/.gitignore +++ b/bundles/specmate-connectors/.gitignore @@ -2,3 +2,4 @@ /generated/ /test_bin/ /bin_test/ +!jar/*.jar \ No newline at end of file diff --git a/bundles/specmate-connectors/bnd.bnd b/bundles/specmate-connectors/bnd.bnd index 348df4a41..45ce621f8 100644 --- a/bundles/specmate-connectors/bnd.bnd +++ b/bundles/specmate-connectors/bnd.bnd @@ -2,6 +2,7 @@ Export-Package: \ com.specmate.connectors.api,\ com.specmate.connectors.config -buildpath: \ + jar/cron4j-2.2.5.jar;version=file,\ specmate-common;version=latest,\ specmate-model-gen;version=latest,\ org.eclipse.osgi.services,\ @@ -26,4 +27,5 @@ Export-Package: \ net.bytebuddy.byte-buddy-agent Private-Package: \ com.specmate.connectors.internal,\ - com.specmate.connectors.internal.config \ No newline at end of file + com.specmate.connectors.internal.config,\ + it.sauronsoftware.cron4j \ No newline at end of file diff --git a/bundles/specmate-connectors/jar/cron4j-2.2.5.jar b/bundles/specmate-connectors/jar/cron4j-2.2.5.jar new file mode 100644 index 000000000..90fc173e9 Binary files /dev/null and b/bundles/specmate-connectors/jar/cron4j-2.2.5.jar differ diff --git a/bundles/specmate-connectors/src/com/specmate/connectors/internal/ConnectorJobRunnable.java b/bundles/specmate-connectors/src/com/specmate/connectors/internal/ConnectorJobRunnable.java new file mode 100644 index 000000000..05d9db32b --- /dev/null +++ b/bundles/specmate-connectors/src/com/specmate/connectors/internal/ConnectorJobRunnable.java @@ -0,0 +1,145 @@ +package com.specmate.connectors.internal; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.emf.common.util.TreeIterator; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.osgi.service.log.LogService; +import com.specmate.common.SpecmateException; +import com.specmate.connectors.api.IRequirementsSource; +import com.specmate.model.base.BaseFactory; +import com.specmate.model.base.Folder; +import com.specmate.model.base.IContainer; +import com.specmate.model.requirements.Requirement; +import com.specmate.model.support.util.SpecmateEcoreUtil; +import com.specmate.persistency.ITransaction; + +public class ConnectorJobRunnable implements Runnable { + + private LogService logService; + private ITransaction transaction; + private List requirementsSources; + + + public ConnectorJobRunnable(List requirementsSources, ITransaction transaction, + LogService logService) { + super(); + this.requirementsSources = requirementsSources; + this.transaction = transaction; + this.logService = logService; + } + + @Override + public void run() { + syncRequirementsFromSources(); + } + + private void syncRequirementsFromSources() { + logService.log(LogService.LOG_INFO, "Synchronizing requirements"); + Resource resource = transaction.getResource(); + for (IRequirementsSource source : requirementsSources) { + logService.log(LogService.LOG_INFO, "Retrieving requirements from " + source.getId()); + try { + Collection requirements = source.getRequirements(); + if (requirements == null) { + continue; + } + IContainer localContainer = getOrCreateLocalContainer(resource, source.getId()); + Requirement[] reqArray = requirements.toArray(new Requirement[0]); + int greatestUnhandledIndex = 0; + int maxIndex = requirements.size() - 1; + while (greatestUnhandledIndex <= maxIndex) { + int upperIndexExclusive = Math.min(greatestUnhandledIndex + 100, maxIndex + 1); + Requirement[] current = Arrays.copyOfRange(reqArray, greatestUnhandledIndex, upperIndexExclusive); + greatestUnhandledIndex = upperIndexExclusive; + List tosync = Arrays.asList(current); + syncContainers(localContainer, tosync, source); + transaction.commit(); + } + } catch (SpecmateException e) { + logService.log(LogService.LOG_ERROR, e.getMessage()); + transaction.rollback(); + } + + } + } + + private void syncContainers(IContainer localContainer, Collection requirements, + IRequirementsSource source) { + // Build hashset (extid -> requirement) for local requirements + TreeIterator localIterator = localContainer.eAllContents(); + HashMap localRequirementsMap = new HashMap<>(); + buildExtIdMap(localIterator, localRequirementsMap); + + // Build hashset (extid -> requirement) for remote requirements + HashMap remoteRequirementsMap = new HashMap<>(); + buildExtIdMap(requirements.iterator(), remoteRequirementsMap); + logService.log(LogService.LOG_INFO, "Retrieved " + remoteRequirementsMap.entrySet().size() + " requirements."); + + // find new requirements + remoteRequirementsMap.keySet().removeAll(localRequirementsMap.keySet()); + + logService.log(LogService.LOG_INFO, "Adding " + remoteRequirementsMap.size() + " new requirements."); + + // add new requirements to local container and all folders on the way + for (Entry entry : remoteRequirementsMap.entrySet()) { + Requirement requirementToAdd = (Requirement) entry.getValue(); + IContainer reqContainer; + try { + reqContainer = source.getContainerForRequirement((Requirement) entry.getValue()); + } catch (SpecmateException e) { + logService.log(LogService.LOG_ERROR, e.getMessage()); + continue; + } + IContainer foundContainer = (IContainer) SpecmateEcoreUtil.getEObjectWithId(reqContainer.getId(), + localContainer.eContents()); + if (foundContainer == null) { + logService.log(LogService.LOG_DEBUG, "Creating new folder " + reqContainer.getName()); + foundContainer = BaseFactory.eINSTANCE.createFolder(); + SpecmateEcoreUtil.copyAttributeValues(reqContainer, foundContainer); + localContainer.getContents().add(foundContainer); + } + + logService.log(LogService.LOG_DEBUG, "Adding requirement " + requirementToAdd.getId()); + foundContainer.getContents().add(requirementToAdd); + } + } + + private IContainer getOrCreateLocalContainer(Resource resource, String name) { + EObject object = SpecmateEcoreUtil.getEObjectWithId(name, resource.getContents()); + if (object != null) { + if (object instanceof IContainer) { + return (IContainer) object; + } + } + + Folder folder = BaseFactory.eINSTANCE.createFolder(); + folder.setName(name); + // TODO: sanitize id + folder.setId(name); + resource.getContents().add(folder); + return folder; + } + + private void buildExtIdMap(Iterator iterator, HashMap requirementsMap) { + while (iterator.hasNext()) { + EObject content = iterator.next(); + if (content == null) { + continue; + } + if (content.eClass().getName().equals("Requirement")) { + Requirement requirement = (Requirement) content; + if (!StringUtils.isEmpty(requirement.getExtId())) { + requirementsMap.put(requirement.getExtId(), requirement); + } + } + } + } +} diff --git a/bundles/specmate-connectors/src/com/specmate/connectors/internal/ConnectorService.java b/bundles/specmate-connectors/src/com/specmate/connectors/internal/ConnectorService.java index 5a66b58e9..ca112fd2b 100644 --- a/bundles/specmate-connectors/src/com/specmate/connectors/internal/ConnectorService.java +++ b/bundles/specmate-connectors/src/com/specmate/connectors/internal/ConnectorService.java @@ -1,24 +1,13 @@ package com.specmate.connectors.internal; -import static com.specmate.connectors.internal.config.ConnectorServiceConfig.KEY_POLL_TIME; +import static com.specmate.connectors.internal.config.ConnectorServiceConfig.KEY_POLL_SCHEDULE; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import org.apache.commons.lang3.StringUtils; import org.eclipse.emf.cdo.common.id.CDOWithID; -import org.eclipse.emf.common.util.TreeIterator; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.resource.Resource; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.ConfigurationPolicy; @@ -32,14 +21,12 @@ import com.specmate.common.SpecmateValidationException; import com.specmate.connectors.api.IRequirementsSource; import com.specmate.connectors.internal.config.ConnectorServiceConfig; -import com.specmate.model.base.BaseFactory; -import com.specmate.model.base.Folder; -import com.specmate.model.base.IContainer; -import com.specmate.model.requirements.Requirement; -import com.specmate.model.support.util.SpecmateEcoreUtil; import com.specmate.persistency.IPersistencyService; import com.specmate.persistency.ITransaction; +import it.sauronsoftware.cron4j.Scheduler; +import it.sauronsoftware.cron4j.SchedulingPattern; + @Component(immediate = true, configurationPid = ConnectorServiceConfig.PID, configurationPolicy = ConfigurationPolicy.REQUIRE) public class ConnectorService { CDOWithID id; @@ -52,26 +39,29 @@ public class ConnectorService { @Activate public void activate(Map properties) throws SpecmateValidationException, SpecmateException { validateConfig(properties); - int pollTime = (Integer) properties.get(KEY_POLL_TIME); - int initialWaitTime = 0; + + String cronStr = (String) properties.get(KEY_POLL_SCHEDULE); + if(cronStr == null) { + return; + } + this.transaction = this.persistencyService.openTransaction(); - this.scheduler = Executors.newScheduledThreadPool(1); - this.scheduler.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - syncRequirementsFromSources(); - } - }, initialWaitTime, pollTime, TimeUnit.SECONDS); + Runnable connectorRunnable = new ConnectorJobRunnable(requirementsSources, transaction, logService); + + Scheduler scheduler = new Scheduler(); + scheduler.schedule(cronStr, connectorRunnable); + scheduler.start(); } private void validateConfig(Map properties) throws SpecmateValidationException { - String errMsg = "Missing config for %s"; - if (!properties.containsKey(KEY_POLL_TIME)) { - throw new SpecmateValidationException(String.format(errMsg, KEY_POLL_TIME)); - } - if (!(properties.get(KEY_POLL_TIME) instanceof Integer)) { - throw new SpecmateValidationException(String.format("Config %s is not of type integer.", KEY_POLL_TIME)); + String cronStr = (String) properties.get(KEY_POLL_SCHEDULE); + if(!SchedulingPattern.validate(cronStr)) { + String message = "Cron " + cronStr + " invalid!"; + logService.log(LogService.LOG_ERROR, message); + throw new SpecmateValidationException(message); + } + logService.log(LogService.LOG_DEBUG, "Connector service config validated."); } @Deactivate @@ -80,108 +70,6 @@ public void deactivate() { transaction.close(); } - private void syncRequirementsFromSources() { - logService.log(LogService.LOG_INFO, "Synchronizing requirements"); - Resource resource = transaction.getResource(); - for (IRequirementsSource source : requirementsSources) { - logService.log(LogService.LOG_INFO, "Retrieving requirements from " + source.getId()); - try { - Collection requirements = source.getRequirements(); - if (requirements == null) { - continue; - } - IContainer localContainer = getOrCreateLocalContainer(resource, source.getId()); - Requirement[] reqArray = requirements.toArray(new Requirement[0]); - int greatestUnhandledIndex = 0; - int maxIndex = requirements.size() - 1; - while (greatestUnhandledIndex <= maxIndex) { - int upperIndexExclusive = Math.min(greatestUnhandledIndex + 100, maxIndex + 1); - Requirement[] current = Arrays.copyOfRange(reqArray, greatestUnhandledIndex, upperIndexExclusive); - greatestUnhandledIndex = upperIndexExclusive; - List tosync = Arrays.asList(current); - syncContainers(localContainer, tosync, source); - transaction.commit(); - } - } catch (SpecmateException e) { - logService.log(LogService.LOG_ERROR, e.getMessage()); - transaction.rollback(); - } - - } - } - - private void syncContainers(IContainer localContainer, Collection requirements, - IRequirementsSource source) { - // Build hashset (extid -> requirement) for local requirements - TreeIterator localIterator = localContainer.eAllContents(); - HashMap localRequirementsMap = new HashMap<>(); - buildExtIdMap(localIterator, localRequirementsMap); - - // Build hashset (extid -> requirement) for remote requirements - HashMap remoteRequirementsMap = new HashMap<>(); - buildExtIdMap(requirements.iterator(), remoteRequirementsMap); - logService.log(LogService.LOG_INFO, "Retrieved " + remoteRequirementsMap.entrySet().size() + " requirements."); - - // find new requirements - remoteRequirementsMap.keySet().removeAll(localRequirementsMap.keySet()); - - logService.log(LogService.LOG_INFO, "Adding " + remoteRequirementsMap.size() + " new requirements."); - - // add new requirements to local container and all folders on the way - for (Entry entry : remoteRequirementsMap.entrySet()) { - Requirement requirementToAdd = (Requirement) entry.getValue(); - IContainer reqContainer; - try { - reqContainer = source.getContainerForRequirement((Requirement) entry.getValue()); - } catch (SpecmateException e) { - logService.log(LogService.LOG_ERROR, e.getMessage()); - continue; - } - IContainer foundContainer = (IContainer) SpecmateEcoreUtil.getEObjectWithId(reqContainer.getId(), - localContainer.eContents()); - if (foundContainer == null) { - logService.log(LogService.LOG_DEBUG, "Creating new folder " + reqContainer.getName()); - foundContainer = BaseFactory.eINSTANCE.createFolder(); - SpecmateEcoreUtil.copyAttributeValues(reqContainer, foundContainer); - localContainer.getContents().add(foundContainer); - } - - logService.log(LogService.LOG_DEBUG, "Adding requirement " + requirementToAdd.getId()); - foundContainer.getContents().add(requirementToAdd); - } - } - - private void buildExtIdMap(Iterator iterator, HashMap requirementsMap) { - while (iterator.hasNext()) { - EObject content = iterator.next(); - if (content == null) { - continue; - } - if (content.eClass().getName().equals("Requirement")) { - Requirement requirement = (Requirement) content; - if (!StringUtils.isEmpty(requirement.getExtId())) { - requirementsMap.put(requirement.getExtId(), requirement); - } - } - } - } - - private IContainer getOrCreateLocalContainer(Resource resource, String name) { - EObject object = SpecmateEcoreUtil.getEObjectWithId(name, resource.getContents()); - if (object != null) { - if (object instanceof IContainer) { - return (IContainer) object; - } - } - - Folder folder = BaseFactory.eINSTANCE.createFolder(); - folder.setName(name); - // TODO: sanitize id - folder.setId(name); - resource.getContents().add(folder); - return folder; - } - @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC) public void addRequirementsConnector(IRequirementsSource source) { this.requirementsSources.add(source); diff --git a/bundles/specmate-connectors/src/com/specmate/connectors/internal/config/ConnectorServiceConfig.java b/bundles/specmate-connectors/src/com/specmate/connectors/internal/config/ConnectorServiceConfig.java index 4c32277af..b519aab54 100644 --- a/bundles/specmate-connectors/src/com/specmate/connectors/internal/config/ConnectorServiceConfig.java +++ b/bundles/specmate-connectors/src/com/specmate/connectors/internal/config/ConnectorServiceConfig.java @@ -16,8 +16,9 @@ @Component(immediate = true) public class ConnectorServiceConfig { + public static final String DISABLED_STRING = "disabled"; public static final String PID = "com.specmate.connectors.ConnectorService"; - public static final String KEY_POLL_TIME = "connectorPollTime"; + public static final String KEY_POLL_SCHEDULE = "connectorPollSchedule"; private ConfigurationAdmin configurationAdmin; private IConfigService configService; @@ -27,18 +28,14 @@ public class ConnectorServiceConfig { @Activate public void configureConnectorService() throws SpecmateException { Dictionary properties = new Hashtable<>(); - Integer connectorsPollTime = Integer.parseInt(configService.getConfigurationProperty(KEY_POLL_TIME, "20")); + String connectorScheduleStr = configService.getConfigurationProperty(KEY_POLL_SCHEDULE, DISABLED_STRING); - // Values < 0 to disable the connectors - if (connectorsPollTime < 0) { + if (connectorScheduleStr.equalsIgnoreCase(DISABLED_STRING)) { logService.log(LogService.LOG_INFO, "Connectors service disabled."); return; } - // Minimum wait time beween polls: 1 second - connectorsPollTime = Math.max(connectorsPollTime, 1); - - properties.put(KEY_POLL_TIME, connectorsPollTime); + properties.put(KEY_POLL_SCHEDULE, connectorScheduleStr); logService.log(LogService.LOG_DEBUG, "Configuring Connectors with:\n" + OSGiUtil.configDictionaryToString(properties)); diff --git a/bundles/specmate-connectors/test/com/specmate/connectors/test/ConnectorServiceTest.java b/bundles/specmate-connectors/test/com/specmate/connectors/test/ConnectorServiceTest.java index c949e5e0c..1372fe00e 100644 --- a/bundles/specmate-connectors/test/com/specmate/connectors/test/ConnectorServiceTest.java +++ b/bundles/specmate-connectors/test/com/specmate/connectors/test/ConnectorServiceTest.java @@ -28,7 +28,7 @@ public void testConnectorServiceDisabling() connectorConfig.setLogService(mock(LogService.class)); IConfigService configServiceMock = mock(IConfigService.class); - when(configServiceMock.getConfigurationProperty(ConnectorServiceConfig.KEY_POLL_TIME, "20")).thenReturn("-1"); + when(configServiceMock.getConfigurationProperty(ConnectorServiceConfig.KEY_POLL_SCHEDULE, ConnectorServiceConfig.DISABLED_STRING)).thenReturn(ConnectorServiceConfig.DISABLED_STRING); connectorConfig.setConfigurationService(configServiceMock); ConfigurationAdmin configAdminMock = mock(ConfigurationAdmin.class); @@ -39,6 +39,7 @@ public void testConnectorServiceDisabling() verifyZeroInteractions(configAdminMock); } + @SuppressWarnings("unchecked") @Test public void testConnectorServiceEnabling() throws SpecmateException, SpecmateValidationException, InterruptedException, IOException { @@ -46,7 +47,7 @@ public void testConnectorServiceEnabling() connectorConfig.setLogService(mock(LogService.class)); IConfigService configServiceMock = mock(IConfigService.class); - when(configServiceMock.getConfigurationProperty(ConnectorServiceConfig.KEY_POLL_TIME, "20")).thenReturn("20"); + when(configServiceMock.getConfigurationProperty(ConnectorServiceConfig.KEY_POLL_SCHEDULE, ConnectorServiceConfig.DISABLED_STRING)).thenReturn("* * * * *"); connectorConfig.setConfigurationService(configServiceMock); ConfigurationAdmin configAdminMock = mock(ConfigurationAdmin.class); diff --git a/bundles/specmate-dbprovider-h2/src/specmate/dbprovider/h2/H2Provider.java b/bundles/specmate-dbprovider-h2/src/specmate/dbprovider/h2/H2Provider.java index 2af2c439a..f95a157bb 100644 --- a/bundles/specmate-dbprovider-h2/src/specmate/dbprovider/h2/H2Provider.java +++ b/bundles/specmate-dbprovider-h2/src/specmate/dbprovider/h2/H2Provider.java @@ -113,7 +113,7 @@ public boolean isVirginDB() throws SpecmateException { public IStore createStore() { JdbcDataSource jdataSource = new JdbcDataSource(); jdataSource.setURL(this.jdbcConnection); - IMappingStrategy jmappingStrategy = CDODBUtil.createHorizontalMappingStrategy(true); + IMappingStrategy jmappingStrategy = CDODBUtil.createHorizontalMappingStrategy(true,false); IDBAdapter h2dbAdapter = new H2Adapter(); IDBConnectionProvider jdbConnectionProvider = DBUtil.createConnectionProvider(jdataSource); return CDODBUtil.createStore(jmappingStrategy, h2dbAdapter, jdbConnectionProvider); diff --git a/bundles/specmate-dbprovider-oracle/src/specmate/dbprovider/oracle/config/OracleProviderConfig.java b/bundles/specmate-dbprovider-oracle/src/specmate/dbprovider/oracle/config/OracleProviderConfig.java index bcb88a4d3..ac56b8b66 100644 --- a/bundles/specmate-dbprovider-oracle/src/specmate/dbprovider/oracle/config/OracleProviderConfig.java +++ b/bundles/specmate-dbprovider-oracle/src/specmate/dbprovider/oracle/config/OracleProviderConfig.java @@ -16,10 +16,10 @@ @Component public class OracleProviderConfig { public static final String PID = "com.specmate.dbprovider.oracle.OracleProviderConfig"; - public static final String KEY_JDBC_CONNECTION = "jdbcConnection"; - public static final String KEY_USERNAME = "username"; - public static final String KEY_PASSWORD = "password"; private static final String DB_PREFIX = "oracle."; + public static final String KEY_JDBC_CONNECTION = DB_PREFIX+ "jdbcConnection"; + public static final String KEY_USERNAME = DB_PREFIX + "username"; + public static final String KEY_PASSWORD = DB_PREFIX + "password"; private ConfigurationAdmin configurationAdmin; private IConfigService configService; private LogService logService; @@ -28,9 +28,9 @@ public class OracleProviderConfig { private void configure() throws SpecmateException { Dictionary properties = new Hashtable<>(); - String specmateJDBCConnection = configService.getConfigurationProperty(DB_PREFIX + KEY_JDBC_CONNECTION); - String specmateUsername = configService.getConfigurationProperty(DB_PREFIX + KEY_USERNAME); - String specmatePassword = configService.getConfigurationProperty(DB_PREFIX + KEY_PASSWORD); + String specmateJDBCConnection = configService.getConfigurationProperty(KEY_JDBC_CONNECTION); + String specmateUsername = configService.getConfigurationProperty(KEY_USERNAME); + String specmatePassword = configService.getConfigurationProperty(KEY_PASSWORD); if (specmateJDBCConnection != null) { properties.put(KEY_JDBC_CONNECTION, specmateJDBCConnection); diff --git a/bundles/specmate-emfrest/bnd.bnd b/bundles/specmate-emfrest/bnd.bnd index 6486719fa..04e2f9ac9 100644 --- a/bundles/specmate-emfrest/bnd.bnd +++ b/bundles/specmate-emfrest/bnd.bnd @@ -35,7 +35,8 @@ Bundle-Version: 0.0.0.${tstamp} specmate-administration;version=latest,\ specmate-emfrest-api;version=latest,\ specmate-connectors;version=latest,\ - specmate-auth-api;version=latest + specmate-auth-api;version=latest,\ + specmate-metrics;version=latest -dsannotations: \ * @@ -45,7 +46,8 @@ Private-Package: \ com.specmate.emfrest.internal.rest,\ com.specmate.emfrest.history,\ com.specmate.emfrest.internal.auth,\ - com.specmate.emfrest.internal.batch + com.specmate.emfrest.internal.batch,\ + com.specmate.emfrest.internal.metrics Export-Package: \ com.specmate.emfrest.crud,\ com.specmate.emfrest.search,\ diff --git a/bundles/specmate-emfrest/src/com/specmate/emfrest/crud/CopyService.java b/bundles/specmate-emfrest/src/com/specmate/emfrest/crud/CopyService.java new file mode 100644 index 000000000..269b0ad77 --- /dev/null +++ b/bundles/specmate-emfrest/src/com/specmate/emfrest/crud/CopyService.java @@ -0,0 +1,31 @@ +package com.specmate.emfrest.crud; + +import org.osgi.service.component.annotations.Component; + +import com.specmate.common.RestResult; +import com.specmate.common.SpecmateException; +import com.specmate.common.SpecmateValidationException; +import com.specmate.emfrest.api.IRestService; +import com.specmate.emfrest.api.RestServiceBase; +import com.specmate.model.processes.Process; +import com.specmate.model.requirements.CEGModel; +import com.specmate.model.testspecification.TestSpecification; + +@Component(immediate = true, service = IRestService.class) +public class CopyService extends RestServiceBase { + @Override + public String getServiceName() { + return "duplicate"; + } + + @Override + public boolean canPost(Object target, Object object) { + return target instanceof CEGModel || target instanceof Process || target instanceof TestSpecification; + } + + @Override + public RestResult post(Object target, Object child, String token) + throws SpecmateException, SpecmateValidationException { + return CrudUtil.duplicate(target); + } +} diff --git a/bundles/specmate-emfrest/src/com/specmate/emfrest/crud/CrudUtil.java b/bundles/specmate-emfrest/src/com/specmate/emfrest/crud/CrudUtil.java index ed81744b0..649bce391 100644 --- a/bundles/specmate-emfrest/src/com/specmate/emfrest/crud/CrudUtil.java +++ b/bundles/specmate-emfrest/src/com/specmate/emfrest/crud/CrudUtil.java @@ -3,7 +3,9 @@ import static com.specmate.model.support.util.SpecmateEcoreUtil.getProjectId; import java.util.List; +import java.util.Set; import java.util.regex.Pattern; +import java.util.stream.Collectors; import javax.ws.rs.core.Response; @@ -12,10 +14,13 @@ import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EcoreUtil; import com.specmate.common.RestResult; import com.specmate.common.SpecmateException; import com.specmate.common.SpecmateValidationException; +import com.specmate.model.base.IContainer; +import com.specmate.model.base.IContentElement; import com.specmate.model.support.util.SpecmateEcoreUtil; public class CrudUtil { @@ -64,6 +69,35 @@ public static RestResult update(Object target, EObject update, String userNam return new RestResult<>(Response.Status.OK, target, userName); } + public static RestResult duplicate(Object target) throws SpecmateException { + EObject original = (EObject) target; + IContentElement copy = (IContentElement) EcoreUtil.copy(original); + IContainer parent = (IContainer) original.eContainer(); + EList contents = parent.getContents(); + + // Change ID + String newID = SpecmateEcoreUtil.getIdForChild(parent, copy.eClass()); + copy.setId(newID); + + String name = copy.getName().replaceFirst("^Copy [0-9]+ of ", ""); + + String prefix = "Copy "; + String suffix = " of " + name; + int copyNumber = 1; + + Set names = contents.stream().map(e -> e.getName()).filter(e -> e.startsWith(prefix) && e.endsWith(suffix)).collect(Collectors.toSet()); + String newName = ""; + do { + newName = prefix + copyNumber + suffix; + copyNumber++; + } while(names.contains(newName)); + + copy.setName(newName); + contents.add(copy); + + return new RestResult<>(Response.Status.OK, target); + } + public static RestResult delete(Object target, String userName) throws SpecmateException { if (target instanceof EObject && !(target instanceof Resource)) { SpecmateEcoreUtil.detach((EObject) target); diff --git a/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/EmfRestJerseyApplication.java b/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/EmfRestJerseyApplication.java index cc6e19e90..da4151cb7 100644 --- a/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/EmfRestJerseyApplication.java +++ b/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/EmfRestJerseyApplication.java @@ -3,6 +3,7 @@ import org.glassfish.jersey.server.ResourceConfig; import com.specmate.emfrest.internal.auth.AuthenticationFilter; +import com.specmate.emfrest.internal.metrics.MetricsDynamicFeature; import com.specmate.emfrest.internal.rest.JsonEObjectWriter; import com.specmate.emfrest.internal.rest.JsonListWriter; import com.specmate.emfrest.internal.rest.JsonReader; @@ -12,7 +13,7 @@ class EmfRestJerseyApplication extends ResourceConfig { public EmfRestJerseyApplication() { registerClasses(RootResource.class, JsonEObjectWriter.class, JsonListWriter.class, JsonReader.class, - AuthenticationFilter.class); + AuthenticationFilter.class, MetricsDynamicFeature.class); } } diff --git a/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/EmfRestServletDeployer.java b/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/EmfRestServletDeployer.java index a8c9b8da1..786312c6c 100644 --- a/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/EmfRestServletDeployer.java +++ b/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/EmfRestServletDeployer.java @@ -14,6 +14,7 @@ import com.specmate.administration.api.IStatusService; import com.specmate.auth.api.IAuthenticationService; import com.specmate.common.ISerializationConfiguration; +import com.specmate.metrics.IMetricsService; import com.specmate.persistency.IPersistencyService; import com.specmate.persistency.ITransaction; import com.specmate.urihandler.IObjectResolver; @@ -32,6 +33,7 @@ public class EmfRestServletDeployer { private IAuthenticationService authenticationService; private ISerializationConfiguration serializationConfiguration; private IStatusService statusService; + private IMetricsService metricsService; @Activate public void activate(BundleContext context) { @@ -49,6 +51,7 @@ protected void configure() { bind(restServiceProvider).to(RestServiceProvider.class); bind(authenticationService).to(IAuthenticationService.class); bind(statusService).to(IStatusService.class); + bind(metricsService).to(IMetricsService.class); bindFactory(new TransactionFactory(persistencyService, logService)).to(ITransaction.class) .in(PerThread.class).proxy(true); @@ -112,4 +115,9 @@ public void setAuthenticationService(IAuthenticationService authenticationServic public void setStatusService(IStatusService statusService) { this.statusService = statusService; } + + @Reference + public void setMetricsService(IMetricsService metricsService) { + this.metricsService = metricsService; + } } diff --git a/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/metrics/AMetric.java b/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/metrics/AMetric.java new file mode 100644 index 000000000..438e28c2f --- /dev/null +++ b/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/metrics/AMetric.java @@ -0,0 +1,16 @@ +package com.specmate.emfrest.internal.metrics; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface AMetric { + String name() default ""; + + String help() default ""; +} \ No newline at end of file diff --git a/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/metrics/MetricsDynamicFeature.java b/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/metrics/MetricsDynamicFeature.java new file mode 100644 index 000000000..77805d380 --- /dev/null +++ b/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/metrics/MetricsDynamicFeature.java @@ -0,0 +1,33 @@ +package com.specmate.emfrest.internal.metrics; + +import javax.inject.Inject; +import javax.ws.rs.container.DynamicFeature; +import javax.ws.rs.container.ResourceInfo; +import javax.ws.rs.core.FeatureContext; +import javax.ws.rs.ext.Provider; + +import org.osgi.service.log.LogService; + +import com.specmate.common.SpecmateException; +import com.specmate.metrics.IMetricsService; + +@Provider +public class MetricsDynamicFeature implements DynamicFeature { + + @Inject + IMetricsService metricsService; + @Inject + LogService logService; + + @Override + public void configure(ResourceInfo resourceInfo, FeatureContext context) { + AMetric annotation = resourceInfo.getResourceClass().getAnnotation(AMetric.class); + + try { + context.register(new MetricsFilter(metricsService, logService, resourceInfo, annotation)); + } catch (SpecmateException e) { + logService.log(LogService.LOG_ERROR, "Could not register metrics filter", e); + } + + } +} \ No newline at end of file diff --git a/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/metrics/MetricsFilter.java b/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/metrics/MetricsFilter.java new file mode 100644 index 000000000..4108a07bd --- /dev/null +++ b/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/metrics/MetricsFilter.java @@ -0,0 +1,173 @@ +package com.specmate.emfrest.internal.metrics; + +import java.io.IOException; +import java.net.URI; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.container.ResourceInfo; +import javax.ws.rs.core.MultivaluedMap; + +import org.osgi.service.log.LogService; + +import com.specmate.common.SpecmateException; +import com.specmate.metrics.ICounter; +import com.specmate.metrics.IHistogram; +import com.specmate.metrics.IMetricsService; +import com.specmate.metrics.ITimer; + +public class MetricsFilter implements ContainerRequestFilter, ContainerResponseFilter { + + private static final String TRACKER_TIMER = "prometheus.timer"; + + protected final ResourceInfo resourceInfo; + private IHistogram tracker; + + private AMetric annotation; + + private IMetricsService metricsService; + + private LogService logService; + + private ICounter response_5xx; + + private ICounter response_4xx; + + private ICounter response_3xx; + + private ICounter response_2xx; + + private ICounter requests; + + /** + * Registers a filter specifically for the defined method. + * + * @param resourceInfo + * - the resource (uri ==> class + method) we are registering + * this filter for + * @param prefix + * - the prefix we should apply to all metrics (if any) + * @param annotation + * @throws SpecmateException + */ + public MetricsFilter(IMetricsService metricsService, LogService logService, ResourceInfo resourceInfo, + AMetric annotation) throws SpecmateException { + this.resourceInfo = resourceInfo; + this.annotation = annotation; + this.metricsService = metricsService; + this.logService = logService; + + getGeneralMetics(); + + buildTimerFromAnnotation(annotation); + } + + private void getGeneralMetics() throws SpecmateException { + + this.requests = metricsService.createCounter("requests", "Total number of requests"); + this.response_5xx = metricsService.createCounter("response_5xx", "Responses with code 5xx"); + this.response_4xx = metricsService.createCounter("response_4xx", "Responses with code 4xx"); + this.response_3xx = metricsService.createCounter("response_3xx", "Responses with code 3xx"); + this.response_2xx = metricsService.createCounter("response_2xx", "Responses with code 2xx"); + } + + /** + * if the annotation is fully specified, use it. + * + * @param annotation + * - provides us a name and help + */ + private void buildTimerFromAnnotation(AMetric annotation) { + if (annotation != null && annotation.help().length() > 0 && annotation.name().length() > 0) { + try { + tracker = metricsService.createHistogram(annotation.name(), annotation.help()); + } catch (SpecmateException e) { + logService.log(LogService.LOG_ERROR, "Could not register jersey metric " + annotation.name(), e); + } + } + } + + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + requests.inc(); + if (tracker == null) { // we only need to do this once + try { + buildTracker(requestContext); + } catch (SpecmateException e) { + logService.log(LogService.LOG_ERROR, "Could not create metrics tracker", e); + } + } + + ITimer timer = tracker.startTimer(); + requestContext.setProperty(TRACKER_TIMER, timer); + } + + private void buildTracker(ContainerRequestContext requestContext) throws SpecmateException { + String path = annotation == null ? "" : annotation.help(); + + if (path.length() == 0) { + // this won't change from request to request + MultivaluedMap pathParameters = requestContext.getUriInfo().getPathParameters(); + + path = path(requestContext.getUriInfo().getRequestUri()); + + for (Map.Entry> entry : pathParameters.entrySet()) { + final String originalPathFragment = String.format("{%s}", entry.getKey()); + + for (String currentPathFragment : entry.getValue()) { + path = path.replace(currentPathFragment, originalPathFragment); + } + } + } + + String name = annotation == null ? "" : annotation.name(); + + if (name.length() == 0) { + // we cannot use the class name as it is always a proxy + name = resourceInfo.getResourceMethod().getName(); + } + + tracker = metricsService.createHistogram(name, path); + } + + /** + * Returns path of given URI. If the first character of path is '/' then it + * is removed. + * + * @author Pavol Loffay + * @param uri + * @return path or null + */ + public static String path(URI uri) { + String path = uri.getPath(); + if (path != null && path.startsWith("/")) { + path = path.substring(1); + } + + return path; + } + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + ITimer timer = ITimer.class.cast(requestContext.getProperty(TRACKER_TIMER)); + + if (timer != null) { + timer.observeDuration(); + } + + if (responseContext.getStatus() >= 500) { + response_5xx.inc(); + } else if (responseContext.getStatus() >= 400) { + response_4xx.inc(); + } else if (responseContext.getStatus() >= 300) { + response_3xx.inc(); + } else if (responseContext.getStatus() >= 200) { + response_2xx.inc(); + } + } +} diff --git a/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/rest/SpecmateResource.java b/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/rest/SpecmateResource.java index ea7d7f72b..1d4b9092b 100644 --- a/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/rest/SpecmateResource.java +++ b/bundles/specmate-emfrest/src/com/specmate/emfrest/internal/rest/SpecmateResource.java @@ -32,6 +32,9 @@ import com.specmate.emfrest.internal.RestServiceProvider; import com.specmate.emfrest.internal.auth.AuthorizationHeader; import com.specmate.emfrest.internal.auth.Secured; +import com.specmate.metrics.IHistogram; +import com.specmate.metrics.IMetricsService; +import com.specmate.metrics.ITimer; import com.specmate.model.support.util.SpecmateEcoreUtil; import com.specmate.persistency.ITransaction; @@ -56,6 +59,9 @@ public abstract class SpecmateResource { @Inject IStatusService statusService; + @Inject + IMetricsService metricsService; + /** OSGi logging service */ @Inject LogService logService; @@ -139,25 +145,28 @@ private Object handleRequest(String serviceName, RestServiceChecker checkRestSer logService.log(LogService.LOG_ERROR, "Attempt to access writing resource when in read-only mode"); return Response.status(Status.FORBIDDEN).build(); } - RestResult result; - if (!commitTransaction) { - try { - result = executeRestService.executeRestService(service); - return result.getResponse(); - } catch (SpecmateException e) { - transaction.rollback(); - logService.log(LogService.LOG_ERROR, e.getLocalizedMessage()); - return Response.status(Status.INTERNAL_SERVER_ERROR).build(); - } catch (SpecmateValidationException e) { - transaction.rollback(); - logService.log(LogService.LOG_ERROR, e.getLocalizedMessage()); - return Response.status(Status.BAD_REQUEST).build(); - } - } else { + + IHistogram histogram; + ITimer timer = null; + try { + histogram = metricsService.createHistogram(service.getServiceName(), + "Service time for service " + service.getServiceName()); + timer = histogram.startTimer(); + } catch (SpecmateException e) { + logService.log(LogService.LOG_ERROR, "Could not obtain metric.", e); + } + + try { + + RestResult result; + try { if (commitTransaction) { result = transaction.doAndCommit(() -> executeRestService.executeRestService(service)); return result.getResponse(); + } else { + result = executeRestService.executeRestService(service); + return result.getResponse(); } } catch (SpecmateValidationException e) { transaction.rollback(); @@ -168,6 +177,11 @@ private Object handleRequest(String serviceName, RestServiceChecker checkRestSer logService.log(LogService.LOG_ERROR, e.getLocalizedMessage()); return Response.status(Status.INTERNAL_SERVER_ERROR).build(); } + + } finally { + if (timer != null) { + timer.observeDuration(); + } } } } diff --git a/bundles/specmate-integration-test/bnd.bnd b/bundles/specmate-integration-test/bnd.bnd index 0586403ad..4fd0ab283 100644 --- a/bundles/specmate-integration-test/bnd.bnd +++ b/bundles/specmate-integration-test/bnd.bnd @@ -2,7 +2,6 @@ Test-Cases: \ com.specmate.test.integration.CrudTest,\ com.specmate.test.integration.SearchTest,\ com.specmate.test.integration.HistoryTest,\ - com.specmate.test.integration.AdministrationTest,\ com.specmate.test.integration.AuthenticationTest,\ com.specmate.test.integration.CDOPersistencyShutdownTest -buildpath: \ @@ -237,15 +236,15 @@ Bundle-Version: 0.0.0.${tstamp} org.apache.commons.lang3;version='[3.3.2,3.3.3)',\ org.eclipse.emf.cdo.server.db;version='[4.4.0,4.4.1)' --runproperties: \ +-runproperties: \ jetty.http.port=8088,\ - jetty.etc.config.urls='etc/jetty.xml,etc/jetty-http.xml,etc/jetty-deployer.xml,etc/jetty-rewrite.xml',\ osgi.console=,\ jetty.home.bundle=specmate-jettystarter,\ - osgi.compatibility.bootdelegation=true,\ + jetty.etc.config.urls='etc/jetty.xml,etc/jetty-http.xml,etc/jetty-deployer.xml,etc/jetty-rewrite.xml',\ + tester.dir=testdir,\ tester.trace=true,\ tester.continuous=true,\ - tester.dir=testdir + osgi.compatibility.bootdelegation=true -runrepos: \ Workspace,\ diff --git a/bundles/specmate-integration-test/src/com/specmate/test/integration/AdministrationTest.java b/bundles/specmate-integration-test/src/com/specmate/test/integration/AdministrationTest.java index 40697158e..f99dc540d 100644 --- a/bundles/specmate-integration-test/src/com/specmate/test/integration/AdministrationTest.java +++ b/bundles/specmate-integration-test/src/com/specmate/test/integration/AdministrationTest.java @@ -53,37 +53,37 @@ private void checkIsInNormalMode() { checkIsInMode(ESpecmateStatus.NORMAL_NAME); } - @Test - public void testMaintenanceMode() { - JSONObject folder = postFolderToRoot(); - String folderId = getId(folder); - enterMaintenanceMode(); - checkIsInMaintenanceMode(); - - // check if read is still possible - JSONObject retrievedFolder1 = getObject(folderId); - - // check if write access (post) leads to an exception - JSONObject folder2 = createTestFolder(); - postObject(Status.FORBIDDEN.getStatusCode(), folder2); - - // check if write access (put) leads to an an exception - updateObject(Status.FORBIDDEN.getStatusCode(), retrievedFolder1, folderId); - - enterNormalMode(); - checkIsInNormalMode(); - - // check if read is still possible - retrievedFolder1 = getObject(folderId); - - // check if write access (post) is possible again - postObject(Status.OK.getStatusCode(), folder2); - - // check if write access (put) is possible again - updateObject(Status.OK.getStatusCode(), retrievedFolder1, folderId); - - postFolderToRoot(); - - } + //@Test +// public void testMaintenanceMode() { +// JSONObject folder = postFolderToRoot(); +// String folderId = getId(folder); +// enterMaintenanceMode(); +// checkIsInMaintenanceMode(); +// +// // check if read is still possible +// JSONObject retrievedFolder1 = getObject(folderId); +// +// // check if write access (post) leads to an exception +// JSONObject folder2 = createTestFolder(); +// postObject(Status.FORBIDDEN.getStatusCode(), folder2); +// +// // check if write access (put) leads to an an exception +// updateObject(Status.FORBIDDEN.getStatusCode(), retrievedFolder1, folderId); +// +// enterNormalMode(); +// checkIsInNormalMode(); +// +// // check if read is still possible +// retrievedFolder1 = getObject(folderId); +// +// // check if write access (post) is possible again +// postObject(Status.OK.getStatusCode(), folder2); +// +// // check if write access (put) is possible again +// updateObject(Status.OK.getStatusCode(), retrievedFolder1, folderId); +// +// postFolderToRoot(); +// +// } } diff --git a/bundles/specmate-integration-test/src/com/specmate/test/integration/IntegrationTestBase.java b/bundles/specmate-integration-test/src/com/specmate/test/integration/IntegrationTestBase.java index 7342d5e4a..462df5f0c 100644 --- a/bundles/specmate-integration-test/src/com/specmate/test/integration/IntegrationTestBase.java +++ b/bundles/specmate-integration-test/src/com/specmate/test/integration/IntegrationTestBase.java @@ -56,7 +56,7 @@ private void configureCDOServer(Dictionary cdoServerProperties) private Dictionary getCDOServerProperties() { Dictionary properties = new Hashtable<>(); - properties.put(SpecmateCDOServerConfig.KEY_SERVER_PORT, "2036"); + properties.put(SpecmateCDOServerConfig.KEY_SERVER_HOST_PORT, "localhost:2036"); properties.put(SpecmateCDOServerConfig.KEY_REPOSITORY_NAME, SPECMATE_REPOSITORY); properties.put(SpecmateCDOServerConfig.KEY_CDO_USER, CDO_USER); properties.put(SpecmateCDOServerConfig.KEY_CDO_PASSWORD, CDO_PASSWORD); diff --git a/bundles/specmate-metrics/src/com/specmate/metrics/ICounter.java b/bundles/specmate-metrics/src/com/specmate/metrics/ICounter.java new file mode 100644 index 000000000..1109a3079 --- /dev/null +++ b/bundles/specmate-metrics/src/com/specmate/metrics/ICounter.java @@ -0,0 +1,7 @@ +package com.specmate.metrics; + +public interface ICounter { + + void inc(); + +} diff --git a/bundles/specmate-metrics/src/com/specmate/metrics/IHistogram.java b/bundles/specmate-metrics/src/com/specmate/metrics/IHistogram.java new file mode 100644 index 000000000..9efe51093 --- /dev/null +++ b/bundles/specmate-metrics/src/com/specmate/metrics/IHistogram.java @@ -0,0 +1,7 @@ +package com.specmate.metrics; + +public interface IHistogram { + + ITimer startTimer(); + +} diff --git a/bundles/specmate-metrics/src/com/specmate/metrics/IMetricsService.java b/bundles/specmate-metrics/src/com/specmate/metrics/IMetricsService.java index 63e8f0182..73565fa4a 100644 --- a/bundles/specmate-metrics/src/com/specmate/metrics/IMetricsService.java +++ b/bundles/specmate-metrics/src/com/specmate/metrics/IMetricsService.java @@ -12,10 +12,14 @@ public interface IMetricsService { /** * Creates a metric of type Gauge - * + * * @throws SpecmateException * */ IGauge createGauge(String name, String description) throws SpecmateException; + IHistogram createHistogram(String name, String description) throws SpecmateException; + + ICounter createCounter(String name, String description) throws SpecmateException; + } diff --git a/bundles/specmate-metrics/src/com/specmate/metrics/ITimer.java b/bundles/specmate-metrics/src/com/specmate/metrics/ITimer.java new file mode 100644 index 000000000..6aebc5d8e --- /dev/null +++ b/bundles/specmate-metrics/src/com/specmate/metrics/ITimer.java @@ -0,0 +1,7 @@ +package com.specmate.metrics; + +public interface ITimer { + + void observeDuration(); + +} diff --git a/bundles/specmate-metrics/src/com/specmate/metrics/internal/MetricsServiceImpl.java b/bundles/specmate-metrics/src/com/specmate/metrics/internal/MetricsServiceImpl.java index e590f339a..fac4243b9 100644 --- a/bundles/specmate-metrics/src/com/specmate/metrics/internal/MetricsServiceImpl.java +++ b/bundles/specmate-metrics/src/com/specmate/metrics/internal/MetricsServiceImpl.java @@ -11,10 +11,14 @@ import org.osgi.service.log.LogService; import com.specmate.common.SpecmateException; +import com.specmate.metrics.ICounter; import com.specmate.metrics.IGauge; +import com.specmate.metrics.IHistogram; import com.specmate.metrics.IMetricsService; +import io.prometheus.client.Counter; import io.prometheus.client.Gauge; +import io.prometheus.client.Histogram; import io.prometheus.client.exporter.MetricsServlet; import io.prometheus.client.hotspot.DefaultExports; @@ -54,22 +58,55 @@ private void configureMetricsServlet() throws SpecmateException { } } - @Override - public IGauge createGauge(String name, String description) throws SpecmateException { - String theName = "specmate_" + name.toLowerCase(); - if (collectors.containsKey(theName)) { - Object collector = collectors.get(theName); - if (collector instanceof IGauge) { - return (IGauge) collector; + public T checkIfCreated(Class clazz, String name, String description) throws SpecmateException { + if (collectors.containsKey(name)) { + Object collector = collectors.get(name); + if (clazz.isAssignableFrom(collector.getClass())) { + return clazz.cast(collector); } else { throw new SpecmateException( "A metric with name " + name + " is already registered, but has a different type."); } - } else { - PrometheusGaugeImpl gauge = new PrometheusGaugeImpl(Gauge.build(theName, description).register()); + } + return null; + } + + private String getMetricName(String name) { + String theName = "specmate_" + name.toLowerCase(); + return theName; + } + + @Override + public IGauge createGauge(String name, String description) throws SpecmateException { + String theName = getMetricName(name); + IGauge gauge = checkIfCreated(IGauge.class, theName, description); + if (gauge == null) { + gauge = new PrometheusGaugeImpl(Gauge.build(theName, description).register()); collectors.put(theName, gauge); - return gauge; } + return gauge; + } + + @Override + public IHistogram createHistogram(String name, String description) throws SpecmateException { + String theName = getMetricName(name); + IHistogram histogram = checkIfCreated(IHistogram.class, theName, description); + if (histogram == null) { + histogram = new PrometheusHistogramImpl(Histogram.build(theName, description).register()); + collectors.put(theName, histogram); + } + return histogram; + } + + @Override + public ICounter createCounter(String name, String description) throws SpecmateException { + String theName = getMetricName(name); + ICounter counter = checkIfCreated(ICounter.class, theName, description); + if (counter == null) { + counter = new PrometheusCounterImpl(Counter.build(theName, description).register()); + collectors.put(theName, counter); + } + return counter; } @Reference(cardinality = ReferenceCardinality.OPTIONAL) diff --git a/bundles/specmate-metrics/src/com/specmate/metrics/internal/PrometheusCounterImpl.java b/bundles/specmate-metrics/src/com/specmate/metrics/internal/PrometheusCounterImpl.java new file mode 100644 index 000000000..75ba25531 --- /dev/null +++ b/bundles/specmate-metrics/src/com/specmate/metrics/internal/PrometheusCounterImpl.java @@ -0,0 +1,20 @@ +package com.specmate.metrics.internal; + +import com.specmate.metrics.ICounter; + +import io.prometheus.client.Counter; + +public class PrometheusCounterImpl implements ICounter { + + private Counter counter; + + public PrometheusCounterImpl(Counter counter) { + this.counter = counter; + } + + @Override + public void inc() { + this.counter.inc(); + } + +} diff --git a/bundles/specmate-metrics/src/com/specmate/metrics/internal/PrometheusHistogramImpl.java b/bundles/specmate-metrics/src/com/specmate/metrics/internal/PrometheusHistogramImpl.java new file mode 100644 index 000000000..993ec92f8 --- /dev/null +++ b/bundles/specmate-metrics/src/com/specmate/metrics/internal/PrometheusHistogramImpl.java @@ -0,0 +1,21 @@ +package com.specmate.metrics.internal; + +import com.specmate.metrics.IHistogram; +import com.specmate.metrics.ITimer; + +import io.prometheus.client.Histogram; + +public class PrometheusHistogramImpl implements IHistogram { + + private Histogram histogram; + + public PrometheusHistogramImpl(Histogram histogram) { + this.histogram = histogram; + } + + @Override + public ITimer startTimer() { + return new PrometheusTimerImpl(histogram.startTimer()); + } + +} diff --git a/bundles/specmate-metrics/src/com/specmate/metrics/internal/PrometheusTimerImpl.java b/bundles/specmate-metrics/src/com/specmate/metrics/internal/PrometheusTimerImpl.java new file mode 100644 index 000000000..80c1abb80 --- /dev/null +++ b/bundles/specmate-metrics/src/com/specmate/metrics/internal/PrometheusTimerImpl.java @@ -0,0 +1,20 @@ +package com.specmate.metrics.internal; + +import com.specmate.metrics.ITimer; + +import io.prometheus.client.Histogram.Timer; + +public class PrometheusTimerImpl implements ITimer { + + private Timer timer; + + public PrometheusTimerImpl(Timer timer) { + this.timer = timer; + } + + @Override + public void observeDuration() { + this.timer.observeDuration(); + } + +} diff --git a/bundles/specmate-migration-test/bnd.bnd b/bundles/specmate-migration-test/bnd.bnd index 38a4c5b79..8522fac66 100644 --- a/bundles/specmate-migration-test/bnd.bnd +++ b/bundles/specmate-migration-test/bnd.bnd @@ -157,12 +157,12 @@ Test-Cases: \ specmate-cdo-server;version=snapshot,\ org.eclipse.emf.cdo.server.db;version='[4.4.0,4.4.1)' -runvm: -ea --runproperties:\ +-runproperties: \ jetty.http.port=8088,\ - jetty.etc.config.urls='etc/jetty.xml,etc/jetty-http.xml,etc/jetty-deployer.xml,etc/jetty-rewrite.xml',\ osgi.console=,\ jetty.home.bundle=specmate-jettystarter,\ - osgi.compatibility.bootdelegation=true,\ + jetty.etc.config.urls='etc/jetty.xml,etc/jetty-http.xml,etc/jetty-deployer.xml,etc/jetty-rewrite.xml',\ + tester.dir=testdir,\ tester.trace=true,\ tester.continuous=true,\ - tester.dir=testdir + osgi.compatibility.bootdelegation=true diff --git a/bundles/specmate-migration-test/src/com/specmate/migration/test/MigrationTestBase.java b/bundles/specmate-migration-test/src/com/specmate/migration/test/MigrationTestBase.java index cfcac5569..87a36d595 100644 --- a/bundles/specmate-migration-test/src/com/specmate/migration/test/MigrationTestBase.java +++ b/bundles/specmate-migration-test/src/com/specmate/migration/test/MigrationTestBase.java @@ -60,6 +60,7 @@ public MigrationTestBase(String dbname, String testModelName) throws Exception { configureDBProvider(getDBProviderProperites()); configurePersistency(getPersistencyProperties()); configureMigrator(); + this.server = getCDOServer(); addBaselinedata(); @@ -76,7 +77,7 @@ private void configureCDOServer(Dictionary cdoServerProperties) private Dictionary getCDOServerProperties() { Dictionary properties = new Hashtable<>(); - properties.put(SpecmateCDOServerConfig.KEY_SERVER_PORT, "2036"); + properties.put(SpecmateCDOServerConfig.KEY_SERVER_HOST_PORT, "localhost:2036"); properties.put(SpecmateCDOServerConfig.KEY_REPOSITORY_NAME, SPECMATE_REPOSITORY); properties.put(SpecmateCDOServerConfig.KEY_CDO_USER, CDO_USER); properties.put(SpecmateCDOServerConfig.KEY_CDO_PASSWORD, CDO_PASSWORD); @@ -109,15 +110,17 @@ public void doMigration() throws Exception { assertTrue(migratorService.needsMigration()); - // Initiate the migration - server.shutdown(); - server.start(); persistency.shutdown(); + server.shutdown(); + + server.start(); persistency.start(); + checkMigrationPostconditions(); + // Resetting the model to the base model such that all tests start with // the same // model diff --git a/bundles/specmate-std-env/specmate.bndrun b/bundles/specmate-std-env/dev-specmate-all.bndrun similarity index 100% rename from bundles/specmate-std-env/specmate.bndrun rename to bundles/specmate-std-env/dev-specmate-all.bndrun diff --git a/bundles/specmate-std-env/prod-specmate-all.bndrun b/bundles/specmate-std-env/prod-specmate-all.bndrun new file mode 100644 index 000000000..d62dd2793 --- /dev/null +++ b/bundles/specmate-std-env/prod-specmate-all.bndrun @@ -0,0 +1,184 @@ +-runfw: org.eclipse.osgi;version='[3.10.2.v20150203-1939,3.10.2.v20150203-1939]' +-runee: JavaSE-1.8 +-runrequires: \ + osgi.identity;filter:='(osgi.identity=specmate-cdo-server)',\ + osgi.identity;filter:='(osgi.identity=org.glassfish.hk2.locator)',\ + osgi.identity;filter:='(osgi.identity=org.eclipse.equinox.log)',\ + osgi.identity;filter:='(osgi.identity=jul.to.slf4j)',\ + osgi.identity;filter:='(osgi.identity=log4j.over.slf4j)',\ + osgi.identity;filter:='(osgi.identity=specmate-common)',\ + osgi.identity;filter:='(osgi.identity=specmate-emfjson)',\ + osgi.identity;filter:='(osgi.identity=specmate-logging)',\ + osgi.identity;filter:='(osgi.identity=specmate-logging-slf4j)',\ + osgi.identity;filter:='(osgi.identity=specmate-logging-slf4j-julbridge)',\ + osgi.identity;filter:='(osgi.identity=specmate-persistency-api)',\ + osgi.identity;filter:='(osgi.identity=org.glassfish.jersey.containers.jersey-container-servlet)',\ + osgi.identity;filter:='(osgi.identity=org.eclipse.equinox.event)',\ + osgi.identity;filter:='(osgi.identity=specmate-emfrest)',\ + osgi.identity;filter:='(osgi.identity=specmate-model-gen)',\ + osgi.identity;filter:='(osgi.identity=org.eclipse.equinox.cm)',\ + osgi.identity;filter:='(osgi.identity=org.eclipse.equinox.metatype)',\ + osgi.identity;filter:='(osgi.identity=specmate-model-support)',\ + osgi.identity;filter:='(osgi.identity=specmate-ui-core)',\ + osgi.identity;filter:='(osgi.identity=specmate-config)',\ + osgi.identity;filter:='(osgi.identity=specmate-connectors)',\ + osgi.identity;filter:='(osgi.identity=specmate-testspecification)',\ + osgi.identity;filter:='(osgi.identity=specmate-hp-connector)',\ + osgi.identity;filter:='(osgi.identity=org.apache.felix.scr)',\ + osgi.identity;filter:='(&(osgi.identity=org.eclipse.jetty.osgi.boot)(version>=9.4.6))',\ + osgi.identity;filter:='(osgi.identity=org.eclipse.jetty.osgi.httpservice)',\ + osgi.identity;filter:='(osgi.identity=org.eclipse.jetty.rewrite)',\ + osgi.identity;filter:='(osgi.identity=specmate-jettystarter)',\ + osgi.identity;filter:='(osgi.identity=org.eclipse.emf.cdo.server.ocl)',\ + osgi.identity;filter:='(osgi.identity=org.json)',\ + osgi.identity;filter:='(osgi.identity=specmate-file-connector)',\ + osgi.identity;filter:='(osgi.identity=specmate-search)',\ + osgi.identity;filter:='(osgi.identity=specmate-migration)',\ + osgi.identity;filter:='(osgi.identity=specmate-persistency-cdo)',\ + osgi.identity;filter:='(osgi.identity=specmate-administration)',\ + osgi.identity;filter:='(osgi.identity=org.apache.commons.fileupload)',\ + osgi.identity;filter:='(osgi.identity=specmate-trello-connector)',\ + osgi.identity;filter:='(osgi.identity=specmate-auth-api)',\ + osgi.identity;filter:='(osgi.identity=specmate-auth)',\ + osgi.identity;filter:='(osgi.identity=specmate-dbprovider-api)',\ + osgi.identity;filter:='(osgi.identity=specmate-dbprovider-h2)' +-runbundles: \ + javassist;version='[3.18.1,3.18.2)',\ + javax.annotation-api;version='[1.2.0,1.2.1)',\ + javax.validation.api;version='[1.1.0,1.1.1)',\ + javax.ws.rs-api;version='[2.0.1,2.0.2)',\ + jul.to.slf4j;version='[1.7.12,1.7.13)',\ + log4j.over.slf4j;version='[1.7.12,1.7.13)',\ + org.eclipse.core.contenttype;version='[3.4.200,3.4.201)',\ + org.eclipse.core.jobs;version='[3.6.1,3.6.2)',\ + org.eclipse.core.runtime;version='[3.10.0,3.10.1)',\ + org.eclipse.emf.ecore.change;version='[2.11.0,2.11.1)',\ + org.eclipse.equinox.app;version='[1.3.200,1.3.201)',\ + org.eclipse.equinox.cm;version='[1.1.0,1.1.1)',\ + org.eclipse.equinox.common;version='[3.6.200,3.6.201)',\ + org.eclipse.equinox.event;version='[1.3.100,1.3.101)',\ + org.eclipse.equinox.log;version='[1.2.300,1.2.301)',\ + org.eclipse.equinox.metatype;version='[1.4.0,1.4.1)',\ + org.eclipse.equinox.preferences;version='[3.5.200,3.5.201)',\ + org.eclipse.equinox.registry;version='[3.5.400,3.5.401)',\ + org.eclipse.osgi.services;version='[3.4.0,3.4.1)',\ + org.glassfish.hk2.api;version='[2.4.0,2.4.1)',\ + org.glassfish.hk2.external.aopalliance-repackaged;version='[2.4.0,2.4.1)',\ + org.glassfish.hk2.external.javax.inject;version='[2.4.0,2.4.1)',\ + org.glassfish.hk2.locator;version='[2.4.0,2.4.1)',\ + org.glassfish.hk2.osgi-resource-locator;version='[1.0.1,1.0.2)',\ + org.glassfish.hk2.utils;version='[2.4.0,2.4.1)',\ + org.glassfish.jersey.bundles.repackaged.jersey-guava;version='[2.17.0,2.17.1)',\ + org.glassfish.jersey.containers.jersey-container-servlet;version='[2.17.0,2.17.1)',\ + org.glassfish.jersey.containers.jersey-container-servlet-core;version='[2.17.0,2.17.1)',\ + org.glassfish.jersey.core.jersey-client;version='[2.17.0,2.17.1)',\ + org.glassfish.jersey.core.jersey-common;version='[2.17.0,2.17.1)',\ + org.glassfish.jersey.core.jersey-server;version='[2.17.0,2.17.1)',\ + org.glassfish.jersey.media.jersey-media-sse;version='[2.17.0,2.17.1)',\ + org.json;version=snapshot,\ + org.slf4j.api;version='[1.7.2,1.7.3)',\ + slf4j.api;version='[1.7.12,1.7.13)',\ + specmate-common;version=snapshot,\ + specmate-emfjson;version=snapshot,\ + specmate-emfrest;version=snapshot,\ + specmate-logging;version=snapshot,\ + specmate-logging-slf4j;version=snapshot,\ + specmate-logging-slf4j-julbridge;version=snapshot,\ + specmate-model-gen;version=snapshot,\ + specmate-persistency-api;version=snapshot,\ + specmate-persistency-cdo;version=snapshot,\ + specmate-model-support;version=snapshot,\ + specmate-ui-core;version=snapshot,\ + specmate-config;version=snapshot,\ + specmate-connectors;version=snapshot,\ + org.eclipse.emf.cdo;version='[4.5.0,4.5.1)',\ + org.eclipse.emf.cdo.common;version='[4.5.0,4.5.1)',\ + org.eclipse.emf.cdo.ecore.retrofit;version='[4.2.300,4.2.301)',\ + org.eclipse.emf.cdo.net4j;version='[4.1.400,4.1.401)',\ + org.eclipse.emf.cdo.server;version='[4.5.0,4.5.1)',\ + org.eclipse.emf.cdo.server.net4j;version='[4.1.300,4.1.301)',\ + org.eclipse.emf.common;version='[2.12.0,2.12.1)',\ + org.eclipse.emf.ecore;version='[2.12.0,2.12.1)',\ + org.eclipse.emf.ecore.xmi;version='[2.12.0,2.12.1)',\ + org.eclipse.net4j;version='[4.5.0,4.5.1)',\ + org.eclipse.net4j.tcp;version='[4.1.400,4.1.401)',\ + org.eclipse.net4j.util;version='[3.6.0,3.6.1)',\ + com.google.guava;version='[21.0.0,21.0.1)',\ + specmate-hp-connector;version=snapshot,\ + specmate-testspecification;version=snapshot,\ + org.apache.felix.scr;version='[2.0.8,2.0.9)',\ + org.apache.commons.fileupload;version='[1.3.1,1.3.2)',\ + org.apache.commons.io;version='[2.4.0,2.4.1)',\ + org.eclipse.equinox.http.servlet;version='[1.1.500,1.1.501)',\ + org.eclipse.jetty.deploy;version='[9.4.6,9.4.7)',\ + org.eclipse.jetty.http;version='[9.4.6,9.4.7)',\ + org.eclipse.jetty.io;version='[9.4.6,9.4.7)',\ + org.eclipse.jetty.osgi-servlet-api;version='[3.1.0,3.1.1)',\ + org.eclipse.jetty.osgi.boot;version='[9.4.6,9.4.7)',\ + org.eclipse.jetty.osgi.httpservice;version='[9.4.6,9.4.7)',\ + org.eclipse.jetty.rewrite;version='[9.4.6,9.4.7)',\ + org.eclipse.jetty.security;version='[9.4.6,9.4.7)',\ + org.eclipse.jetty.server;version='[9.4.6,9.4.7)',\ + org.eclipse.jetty.servlet;version='[9.4.6,9.4.7)',\ + org.eclipse.jetty.util;version='[9.4.6,9.4.7)',\ + org.eclipse.jetty.webapp;version='[9.4.6,9.4.7)',\ + org.eclipse.jetty.xml;version='[9.4.6,9.4.7)',\ + org.eclipse.equinox.http.jetty;version='[3.0.200,3.0.201)',\ + org.eclipse.jetty.continuation;version='[8.1.16,8.1.17)',\ + org.eclipse.jetty.http;version='[8.1.16,8.1.17)',\ + org.eclipse.jetty.io;version='[8.1.16,8.1.17)',\ + org.eclipse.jetty.security;version='[8.1.16,8.1.17)',\ + org.eclipse.jetty.server;version='[8.1.16,8.1.17)',\ + org.eclipse.jetty.servlet;version='[8.1.16,8.1.17)',\ + org.eclipse.jetty.util;version='[8.1.16,8.1.17)',\ + specmate-jettystarter;version=snapshot,\ + lpg.runtime.java;version='[2.0.17,2.0.18)',\ + org.eclipse.emf.cdo.server.ocl;version='[4.2.100,4.2.101)',\ + org.eclipse.ocl;version='[3.6.200,3.6.201)',\ + org.eclipse.ocl.common;version='[1.4.200,1.4.201)',\ + org.eclipse.ocl.ecore;version='[3.6.200,3.6.201)',\ + org.sat4j.core;version='[2.3.5,2.3.6)',\ + org.jgrapht.core;version='[1.0.1,1.0.2)',\ + org.apache.commons.cli;version='[1.4.0,1.4.1)',\ + org.sat4j.maxsat;version='[2.3.5,2.3.6)',\ + org.sat4j.pb;version='[2.3.5,2.3.6)',\ + specmate-file-connector;version=snapshot,\ + org.apache.servicemix.bundles.jakarta-regexp;version='[1.4.0,1.4.1)',\ + org.apache.servicemix.bundles.lucene;version='[7.2.0,7.2.1)',\ + org.apache.servicemix.bundles.lucene-queries;version='[7.2.0,7.2.1)',\ + org.apache.servicemix.bundles.lucene-queryparser;version='[7.2.0,7.2.1)',\ + org.apache.servicemix.bundles.lucene-sandbox;version='[7.2.0,7.2.1)',\ + specmate-search;version=snapshot,\ + specmate-migration;version=snapshot,\ + specmate-administration;version=snapshot,\ + specmate-emfrest-api;version=snapshot,\ + specmate-trello-connector;version=snapshot,\ + specmate-auth-api;version=snapshot,\ + specmate-auth;version=snapshot,\ + specmate-dbprovider-api;version=snapshot,\ + org.eclipse.net4j.db;version='[4.5.0,4.5.1)',\ + org.eclipse.net4j.db.jdbc;version='[4.3.100,4.3.101)',\ + org.eclipse.net4j.db.h2;version='[4.2.300,4.2.301)',\ + specmate-dbprovider-h2;version=snapshot,\ + specmate-config-api;version=snapshot,\ + com.diffplug.osgi.extension.sun.misc;version='[0.0.0,0.0.1)',\ + io.prometheus.simpleclient;version='[0.4.0,0.4.1)',\ + io.prometheus.simpleclient_common;version='[0.4.0,0.4.1)',\ + io.prometheus.simpleclient_servlet;version='[0.4.0,0.4.1)',\ + specmate-metrics;version=snapshot,\ + io.prometheus.simpleclient_hotspot;version='[0.4.0,0.4.1)',\ + org.h2;version='[1.3.168,1.3.169)',\ + specmate-cdo-server;version=snapshot,\ + org.apache.commons.lang3;version='[3.3.2,3.3.3)',\ + org.eclipse.emf.cdo.server.db;version='[4.4.0,4.4.1)' + +-runproperties: \ + jetty.http.port=8080,\ + osgi.console=,\ + jetty.home.bundle=specmate-jettystarter,\ + jetty.etc.config.urls='etc/jetty.xml,etc/jetty-http.xml,etc/jetty-deployer.xml,etc/jetty-rewrite.xml',\ + osgi.compatibility.bootdelegation=true +-runrepos: \ + Workspace,\ + Local +-runvm: -Xmx6000m \ No newline at end of file diff --git a/bundles/specmate-std-env/specmate-cdo-server-oracle.bndrun b/bundles/specmate-std-env/prod-specmate-cdo-server-oracle.bndrun similarity index 93% rename from bundles/specmate-std-env/specmate-cdo-server-oracle.bndrun rename to bundles/specmate-std-env/prod-specmate-cdo-server-oracle.bndrun index 0bab7f091..366072f3b 100644 --- a/bundles/specmate-std-env/specmate-cdo-server-oracle.bndrun +++ b/bundles/specmate-std-env/prod-specmate-cdo-server-oracle.bndrun @@ -11,7 +11,6 @@ osgi.identity;filter:='(osgi.identity=org.eclipse.equinox.cm)',\ osgi.identity;filter:='(osgi.identity=org.eclipse.equinox.metatype)',\ osgi.identity;filter:='(osgi.identity=org.apache.felix.scr)',\ - osgi.identity;filter:='(&(osgi.identity=org.apache.felix.webconsole)(version>=4.3.0))',\ osgi.identity;filter:='(osgi.identity=specmate-cdo-server)',\ osgi.identity;filter:='(osgi.identity=org.eclipse.emf.cdo.server.ocl)',\ osgi.identity;filter:='(osgi.identity=specmate-migration)',\ @@ -36,10 +35,7 @@ jul.to.slf4j;version='[1.7.12,1.7.13)',\ log4j.over.slf4j;version='[1.7.12,1.7.13)',\ lpg.runtime.java;version='[2.0.17,2.0.18)',\ - org.apache.commons.fileupload;version='[1.3.1,1.3.2)',\ - org.apache.commons.io;version='[2.4.0,2.4.1)',\ org.apache.felix.scr;version='[2.0.8,2.0.9)',\ - org.apache.felix.webconsole;version='[4.3.0,4.3.1)',\ org.eclipse.core.contenttype;version='[3.4.200,3.4.201)',\ org.eclipse.core.jobs;version='[3.6.1,3.6.2)',\ org.eclipse.core.runtime;version='[3.10.0,3.10.1)',\ @@ -60,7 +56,6 @@ org.eclipse.equinox.metatype;version='[1.4.0,1.4.1)',\ org.eclipse.equinox.preferences;version='[3.5.200,3.5.201)',\ org.eclipse.equinox.registry;version='[3.5.400,3.5.401)',\ - org.eclipse.jetty.osgi-servlet-api;version='[3.1.0,3.1.1)',\ org.eclipse.net4j;version='[4.5.0,4.5.1)',\ org.eclipse.net4j.db;version='[4.5.0,4.5.1)',\ org.eclipse.net4j.db.jdbc;version='[4.3.100,4.3.101)',\ diff --git a/bundles/specmate-std-env/specmate-cdo-server.bndrun b/bundles/specmate-std-env/prod-specmate-cdo-server.bndrun similarity index 98% rename from bundles/specmate-std-env/specmate-cdo-server.bndrun rename to bundles/specmate-std-env/prod-specmate-cdo-server.bndrun index 4f6947c44..219834008 100644 --- a/bundles/specmate-std-env/specmate-cdo-server.bndrun +++ b/bundles/specmate-std-env/prod-specmate-cdo-server.bndrun @@ -12,7 +12,6 @@ osgi.identity;filter:='(osgi.identity=org.eclipse.equinox.metatype)',\ osgi.identity;filter:='(osgi.identity=specmate-config)',\ osgi.identity;filter:='(osgi.identity=org.apache.felix.scr)',\ - osgi.identity;filter:='(&(osgi.identity=org.apache.felix.webconsole)(version>=4.3.0))',\ osgi.identity;filter:='(osgi.identity=specmate-cdo-server)',\ osgi.identity;filter:='(osgi.identity=org.eclipse.emf.cdo.server.ocl)',\ osgi.identity;filter:='(&(osgi.identity=org.h2)(version>=1.3.168))',\ diff --git a/bundles/specmate-std-env/specmate-no-cdo-server.bndrun b/bundles/specmate-std-env/prod-specmate-no-cdo-server.bndrun similarity index 94% rename from bundles/specmate-std-env/specmate-no-cdo-server.bndrun rename to bundles/specmate-std-env/prod-specmate-no-cdo-server.bndrun index b72ad184e..fb6b0af32 100644 --- a/bundles/specmate-std-env/specmate-no-cdo-server.bndrun +++ b/bundles/specmate-std-env/prod-specmate-no-cdo-server.bndrun @@ -1,8 +1,6 @@ -runfw: org.eclipse.osgi;version='[3.10.2.v20150203-1939,3.10.2.v20150203-1939]' -runee: JavaSE-1.8 -runrequires: \ - osgi.identity;filter:='(osgi.identity=org.apache.felix.gogo.command)',\ - osgi.identity;filter:='(osgi.identity=org.apache.felix.gogo.shell)',\ osgi.identity;filter:='(osgi.identity=org.glassfish.hk2.locator)',\ osgi.identity;filter:='(osgi.identity=org.eclipse.equinox.log)',\ osgi.identity;filter:='(osgi.identity=jul.to.slf4j)',\ @@ -21,13 +19,11 @@ osgi.identity;filter:='(osgi.identity=org.eclipse.equinox.metatype)',\ osgi.identity;filter:='(osgi.identity=specmate-model-support)',\ osgi.identity;filter:='(osgi.identity=specmate-ui-core)',\ - osgi.identity;filter:='(osgi.identity=specmate-dummy-data)',\ osgi.identity;filter:='(osgi.identity=specmate-config)',\ osgi.identity;filter:='(osgi.identity=specmate-connectors)',\ osgi.identity;filter:='(osgi.identity=specmate-testspecification)',\ osgi.identity;filter:='(osgi.identity=specmate-hp-connector)',\ osgi.identity;filter:='(osgi.identity=org.apache.felix.scr)',\ - osgi.identity;filter:='(&(osgi.identity=org.apache.felix.webconsole)(version>=4.3.0))',\ osgi.identity;filter:='(&(osgi.identity=org.eclipse.jetty.osgi.boot)(version>=9.4.6))',\ osgi.identity;filter:='(osgi.identity=org.eclipse.jetty.osgi.httpservice)',\ osgi.identity;filter:='(osgi.identity=org.eclipse.jetty.rewrite)',\ @@ -50,9 +46,6 @@ javax.ws.rs-api;version='[2.0.1,2.0.2)',\ jul.to.slf4j;version='[1.7.12,1.7.13)',\ log4j.over.slf4j;version='[1.7.12,1.7.13)',\ - org.apache.felix.gogo.command;version='[0.10.0,0.10.1)',\ - org.apache.felix.gogo.runtime;version='[0.10.0,0.10.1)',\ - org.apache.felix.gogo.shell;version='[0.10.0,0.10.1)',\ org.eclipse.core.contenttype;version='[3.4.200,3.4.201)',\ org.eclipse.core.jobs;version='[3.6.1,3.6.2)',\ org.eclipse.core.runtime;version='[3.10.0,3.10.1)',\ @@ -93,7 +86,6 @@ specmate-persistency-cdo;version=snapshot,\ specmate-model-support;version=snapshot,\ specmate-ui-core;version=snapshot,\ - specmate-dummy-data;version=snapshot,\ specmate-config;version=snapshot,\ specmate-connectors;version=snapshot,\ org.eclipse.emf.cdo;version='[4.5.0,4.5.1)',\ @@ -113,7 +105,6 @@ org.apache.felix.scr;version='[2.0.8,2.0.9)',\ org.apache.commons.fileupload;version='[1.3.1,1.3.2)',\ org.apache.commons.io;version='[2.4.0,2.4.1)',\ - org.apache.felix.webconsole;version='[4.3.0,4.3.1)',\ org.eclipse.equinox.http.servlet;version='[1.1.500,1.1.501)',\ org.eclipse.jetty.deploy;version='[9.4.6,9.4.7)',\ org.eclipse.jetty.http;version='[9.4.6,9.4.7)',\ diff --git a/web/src/app/config/config.ts b/web/src/app/config/config.ts index a3a9011cf..395e9b992 100644 --- a/web/src/app/config/config.ts +++ b/web/src/app/config/config.ts @@ -25,6 +25,9 @@ export class Config { public static USE_BROWSER_LANGUAGE = false; public static CONNECTIVITY_CHECK_DELAY = 10000; + public static NUM_HTTP_RETRIES = 10; + public static HTTP_RETRY_DELAY = 500; + public static HTTP_RETRY_ERRORS = [503, 404, 403, 401]; public static LOG_START_MESSAGE = 'Specmate Started'; public static LOG_LENGTH = 100; diff --git a/web/src/app/modules/actions/modules/common-controls/components/common-controls.component.html b/web/src/app/modules/actions/modules/common-controls/components/common-controls.component.html index 678ab8956..92799853b 100644 --- a/web/src/app/modules/actions/modules/common-controls/components/common-controls.component.html +++ b/web/src/app/modules/actions/modules/common-controls/components/common-controls.component.html @@ -1,7 +1,7 @@
-   -   -   -   +   +   +   +  
 {{'connection.lost' | translate}}
\ No newline at end of file diff --git a/web/src/app/modules/actions/modules/test-specification-generator-button/components/test-specification-generator-button.component.html b/web/src/app/modules/actions/modules/test-specification-generator-button/components/test-specification-generator-button.component.html index a9ddb0dd2..9441f1f61 100644 --- a/web/src/app/modules/actions/modules/test-specification-generator-button/components/test-specification-generator-button.component.html +++ b/web/src/app/modules/actions/modules/test-specification-generator-button/components/test-specification-generator-button.component.html @@ -1,2 +1,2 @@ {{error}} - \ No newline at end of file + \ No newline at end of file diff --git a/web/src/app/modules/actions/modules/test-specification-generator-button/components/test-specification-generator-button.component.ts b/web/src/app/modules/actions/modules/test-specification-generator-button/components/test-specification-generator-button.component.ts index b17feb428..20343d87c 100644 --- a/web/src/app/modules/actions/modules/test-specification-generator-button/components/test-specification-generator-button.component.ts +++ b/web/src/app/modules/actions/modules/test-specification-generator-button/components/test-specification-generator-button.component.ts @@ -72,7 +72,25 @@ export class TestSpecificationGeneratorButton { .then(() => this.dataService.createElement(testSpec, true, Id.uuid)) .then(() => this.dataService.commit(this.translate.instant('save'))) .then(() => this.dataService.performOperations(testSpec.url, 'generateTests')) - .then(() => this.dataService.readContents(testSpec.url)) + .then(async () => { + let contents: IContainer[] = []; + + let numRetries = 0; + while ((contents === undefined || contents === null || contents.length === 0) && numRetries < 10) { + try { + contents = await this.dataService.readContents(testSpec.url); + } catch (e) { + this.logger.warn('Error while loading contents for test specification'); + } + await new Promise(res => setTimeout(res, 500)); + this.logger.warn('Retry loading of test spec contents'); + numRetries++; + } + if (contents === undefined || contents === null || contents.length === 0) { + throw new Error('Could not load contents of generated test specification'); + } + return contents; + }) .then((contents: IContainer[]) => this.finalizeTestGeneration(contents, testSpec)) .catch(() => { }); } diff --git a/web/src/app/modules/common/modules/i18n/components/language-chooser.component.html b/web/src/app/modules/common/modules/i18n/components/language-chooser.component.html index 01fa0eee3..738a7aaaa 100644 --- a/web/src/app/modules/common/modules/i18n/components/language-chooser.component.html +++ b/web/src/app/modules/common/modules/i18n/components/language-chooser.component.html @@ -1,9 +1,9 @@
-
-
diff --git a/web/src/app/modules/data/modules/data-service/services/service-interface.ts b/web/src/app/modules/data/modules/data-service/services/service-interface.ts index d830a4d0a..027d71434 100644 --- a/web/src/app/modules/data/modules/data-service/services/service-interface.ts +++ b/web/src/app/modules/data/modules/data-service/services/service-interface.ts @@ -5,10 +5,15 @@ import { Objects } from '../../../../../util/objects'; import { CEGConnection } from '../../../../../model/CEGConnection'; import { Type } from '../../../../../util/type'; import 'rxjs/add/operator/toPromise'; +import { retryWhen, mergeMap, finalize, catchError } from 'rxjs/operators'; +import { _throw } from 'rxjs/observable/throw'; import { UserToken } from '../../../../views/main/authentication/base/user-token'; import { UserSession } from '../../../../../model/UserSession'; import { User } from '../../../../../model/User'; import { BatchOperation } from '../../../../../model/BatchOperation'; +import { Observable } from 'rxjs/Observable'; +import { Config } from '../../../../../config/config'; +import { timer } from 'rxjs/observable/timer'; export class ServiceInterface { @@ -21,78 +26,64 @@ export class ServiceInterface { } let params = new HttpParams(); params = params.append('heartbeat', 'true'); - return this.http.get(Url.urlCheckConnectivity(token.project), { headers: this.getAuthHeader(token), params: params }) - .toPromise() + return this.toRetryPromise(this.http + .get(Url.urlCheckConnectivity(token.project), { headers: this.getAuthHeader(token), params: params })) .then(() => Promise.resolve()); } public async authenticate(user: User): Promise { - return this.http.post(Url.urlAuthenticate(), user) - .toPromise() + return this.toRetryPromise(this.http.post(Url.urlAuthenticate(), user)) .then((session: UserSession) => new UserToken(session, user.projectName)); } public deauthenticate(token: UserToken): Promise { - return this.http.get(Url.urlDeauthenticate(), { headers: this.getAuthHeader(token), responseType: 'text' }) - .toPromise() + return this.toRetryPromise(this.http + .get(Url.urlDeauthenticate(), { headers: this.getAuthHeader(token), responseType: 'text' })) .then(() => Promise.resolve()); } public async projectnames(): Promise { - return this.http.get(Url.urlProjectNames()).toPromise(); + return this.toRetryPromise(this.http.get(Url.urlProjectNames())); } public async performBatchOperation(batchOperation: BatchOperation, token: UserToken): Promise { - return this.http - .post(Url.batchOperationUrl(token), batchOperation, { headers: this.getAuthHeader(token) }) - .toPromise(); + return this.toRetryPromise(this.http + .post(Url.batchOperationUrl(token), batchOperation, { headers: this.getAuthHeader(token) })); } public createElement(element: IContainer, token: UserToken): Promise { let payload: any = this.prepareElementPayload(element); - return this.http - .post(Url.urlCreate(element.url), payload, { headers: this.getAuthHeader(token) }) - .toPromise() - .catch(e => this.handleError(e, element.url)) + return this.toRetryPromise(this.http + .post(Url.urlCreate(element.url), payload, { headers: this.getAuthHeader(token) }), element.url) .then(() => { }); } public readElement(url: string, token: UserToken): Promise { - return this.http - .get(Url.urlElement(url), { headers: this.getAuthHeader(token) }) - .toPromise() - .catch(e => this.handleError(e, url)) + return this.toRetryPromise(this.http + .get(Url.urlElement(url), { headers: this.getAuthHeader(token) }), url) .then((element: IContainer) => element); } public readContents(url: string, token: UserToken): Promise { - return this.http - .get(Url.urlContents(url), { headers: this.getAuthHeader(token) }) - .toPromise() - .catch(e => this.handleError(e, url)) + return this.toRetryPromise(this.http + .get(Url.urlContents(url), { headers: this.getAuthHeader(token) }), url) .then((contents: IContainer[]) => contents); } public updateElement(element: IContainer, token: UserToken): Promise { let payload: any = this.prepareElementPayload(element); - return this.http - .put(Url.urlUpdate(element.url), payload, { headers: this.getAuthHeader(token) }) - .toPromise() - .catch(e => this.handleError(e, element.url)); + return this.toRetryPromise(this.http + .put(Url.urlUpdate(element.url), payload, { headers: this.getAuthHeader(token) }), element.url); } public deleteElement(url: string, token: UserToken): Promise { - return this.http - .delete(Url.urlDelete(url), { headers: this.getAuthHeader(token) }) - .toPromise() - .catch(e => this.handleError(e, url)); + return this.toRetryPromise(this.http + .delete(Url.urlDelete(url), { headers: this.getAuthHeader(token) }), url); } public performOperation(url: string, serviceSuffix: string, payload: any, token: UserToken): Promise { - return this.http - .post(Url.urlCustomService(url, serviceSuffix), payload, { headers: this.getAuthHeader(token) }) - .toPromise() - .catch(this.handleError); + return this.toRetryPromise(this.http + .post(Url.urlCustomService(url, serviceSuffix), payload, { headers: this.getAuthHeader(token) }), url); } public performQuery(url: string, serviceSuffix: string, parameters: { [key: string]: string }, token: UserToken): Promise { @@ -102,10 +93,8 @@ export class ServiceInterface { urlParams = urlParams.append(key, parameters[key]); } } - return this.http - .get(Url.urlCustomService(url, serviceSuffix), { params: urlParams, headers: this.getAuthHeader(token) }) - .toPromise() - .catch(this.handleError) + return this.toRetryPromise(this.http + .get(Url.urlCustomService(url, serviceSuffix), { params: urlParams, headers: this.getAuthHeader(token) }), url) .then((data: any) => data); } @@ -187,4 +176,32 @@ export class ServiceInterface { } return headers; } + + private toRetryPromise(req: Observable, url?: string): Promise { + return req.pipe( + retryWhen(genericRetryStrategy()), + catchError(error => Observable.of(error))) + .toPromise().catch(e => this.handleError(e, url)); + } } + +export const genericRetryStrategy = ({ + maxRetryAttempts = Config.NUM_HTTP_RETRIES, + delay = Config.HTTP_RETRY_DELAY, + includedStatusCodes = Config.HTTP_RETRY_ERRORS}: { + maxRetryAttempts?: number, + delay?: number, + includedStatusCodes?: number[] + } = {}) => (attempts: Observable) => { + return attempts.pipe( + mergeMap((error, i) => { + const retryAttempt = i + 1; + if (retryAttempt > maxRetryAttempts || includedStatusCodes.indexOf(error.status) < 0) { + return _throw(error); + } + console.log(`Attempt ${retryAttempt}: retrying in ${delay}ms`); + return timer(delay); + }), + finalize(() => {}) + ); + }; diff --git a/web/src/app/modules/data/modules/data-service/services/specmate-data.service.ts b/web/src/app/modules/data/modules/data-service/services/specmate-data.service.ts index 161bc1053..ad679f9c5 100644 --- a/web/src/app/modules/data/modules/data-service/services/specmate-data.service.ts +++ b/web/src/app/modules/data/modules/data-service/services/specmate-data.service.ts @@ -80,7 +80,14 @@ export class SpecmateDataService { public readContents(url: string, virtual?: boolean): Promise { this.busy = true; - if (virtual || this.scheduler.isVirtualElement(url) || this.cache.isCachedContents(url)) { + let getFromCache = this.cache.isCachedContents(url); + if (this.scheduler.isVirtualElement(url)) { + getFromCache = true; + } else if (virtual === false) { + getFromCache = false; + } + + if (getFromCache) { let contents: IContainer[] = this.readContentsVirtual(url); if (contents) { return Promise.resolve(contents).then((loadedContents: IContainer[]) => this.readContentsComplete(loadedContents)); diff --git a/web/src/app/modules/navigation/modules/navigation-bar/components/navigation-bar.component.html b/web/src/app/modules/navigation/modules/navigation-bar/components/navigation-bar.component.html index adf8dfd6c..a6af03088 100644 --- a/web/src/app/modules/navigation/modules/navigation-bar/components/navigation-bar.component.html +++ b/web/src/app/modules/navigation/modules/navigation-bar/components/navigation-bar.component.html @@ -1,5 +1,5 @@
- +
@@ -29,7 +29,7 @@

{{'login' | translate}}

- +
@@ -40,17 +40,17 @@

{{'login' | translate}}

-
- +
- - +
diff --git a/web/src/app/modules/views/main/authentication/modules/logout/components/logout.component.html b/web/src/app/modules/views/main/authentication/modules/logout/components/logout.component.html index eff4e22d5..582826ca9 100644 --- a/web/src/app/modules/views/main/authentication/modules/logout/components/logout.component.html +++ b/web/src/app/modules/views/main/authentication/modules/logout/components/logout.component.html @@ -1,3 +1,3 @@ - \ No newline at end of file diff --git a/web/src/app/modules/views/main/editors/modules/graphical-editor/components/graphical-editor.component.html b/web/src/app/modules/views/main/editors/modules/graphical-editor/components/graphical-editor.component.html index 1bfcaae2e..55df81849 100644 --- a/web/src/app/modules/views/main/editors/modules/graphical-editor/components/graphical-editor.component.html +++ b/web/src/app/modules/views/main/editors/modules/graphical-editor/components/graphical-editor.component.html @@ -5,9 +5,9 @@
{{name}} - + - +
@@ -29,7 +29,7 @@
{{name}} - + diff --git a/web/src/app/modules/views/main/editors/modules/requirements-details/components/requirement-details.component.html b/web/src/app/modules/views/main/editors/modules/requirements-details/components/requirement-details.component.html index 03d5f662e..5a4e566ed 100644 --- a/web/src/app/modules/views/main/editors/modules/requirements-details/components/requirement-details.component.html +++ b/web/src/app/modules/views/main/editors/modules/requirements-details/components/requirement-details.component.html @@ -96,14 +96,16 @@
{{'Cause-EffectModels' | translate}}
- + + +
-
@@ -132,14 +134,15 @@
{{'ProcessModels' | translate}}
- + +
-
@@ -150,7 +153,7 @@
{{'ProcessModels' | translate}}
{{'TestSpecifications' | translate}}
-
+
{{'noTestSpecifications' | translate}} @@ -167,7 +170,8 @@
{{'TestSpecifications' | translate}}
{{testSpec.description | truncate: 60}} - + + diff --git a/web/src/app/modules/views/main/editors/modules/requirements-details/components/requirement-details.component.ts b/web/src/app/modules/views/main/editors/modules/requirements-details/components/requirement-details.component.ts index 91ad6e8ba..708f10c86 100644 --- a/web/src/app/modules/views/main/editors/modules/requirements-details/components/requirement-details.component.ts +++ b/web/src/app/modules/views/main/editors/modules/requirements-details/components/requirement-details.component.ts @@ -87,6 +87,15 @@ export class RequirementsDetails extends SpecmateViewBase { .catch(() => {})); } + public duplicate(element: IContentElement): void { + this.dataService.performOperations(element.url, 'duplicate') + .then(() => this.dataService.commit(this.translate.instant('duplicate'))) + .then(() => this.dataService.readContents(this.requirement.url, false)) + .then((contents: IContainer[]) => this.contents = contents) + .then(() => this.readTestSpecifications()) + .catch(() => {}); + } + public createModel(): void { let factory: ModelFactoryBase = new CEGModelFactory(this.dataService); factory.create(this.requirement, true).then((element: IContainer) => this.navigator.navigate(element)); diff --git a/web/src/app/modules/views/main/editors/modules/tool-pallette/components/tool-pallette.component.html b/web/src/app/modules/views/main/editors/modules/tool-pallette/components/tool-pallette.component.html index f9438db82..d37624867 100644 --- a/web/src/app/modules/views/main/editors/modules/tool-pallette/components/tool-pallette.component.html +++ b/web/src/app/modules/views/main/editors/modules/tool-pallette/components/tool-pallette.component.html @@ -1,11 +1,11 @@
-   -
\ No newline at end of file diff --git a/web/src/app/modules/views/main/editors/modules/tool-pallette/components/tool-pallette.component.ts b/web/src/app/modules/views/main/editors/modules/tool-pallette/components/tool-pallette.component.ts index 6f48310e5..727d14f7e 100644 --- a/web/src/app/modules/views/main/editors/modules/tool-pallette/components/tool-pallette.component.ts +++ b/web/src/app/modules/views/main/editors/modules/tool-pallette/components/tool-pallette.component.ts @@ -51,7 +51,8 @@ export class ToolPallette { event.preventDefault(); event.stopPropagation(); let message = this.translate.instant('doYouReallyWantToDeleteAll', {name: this.model.name}); - this.modal.open(message) + let title = this.translate.instant('ConfirmationRequired'); + this.modal.confirmDelete(title, message) .then(() => this.dataService.readContents(this.model.url, true)) .then((contents: IContainer[]) => this.removeAllElements(contents)) .catch(() => {}); diff --git a/web/src/app/modules/views/side/modules/history-view/components/extended-history-view.component.html b/web/src/app/modules/views/side/modules/history-view/components/extended-history-view.component.html index 538a48f97..3da5b570a 100644 --- a/web/src/app/modules/views/side/modules/history-view/components/extended-history-view.component.html +++ b/web/src/app/modules/views/side/modules/history-view/components/extended-history-view.component.html @@ -1,7 +1,7 @@
{{'Changes' | translate}} - +
  • diff --git a/web/src/app/modules/views/side/modules/history-view/components/simple-history-view.component.html b/web/src/app/modules/views/side/modules/history-view/components/simple-history-view.component.html index 77c45822f..9031b4488 100644 --- a/web/src/app/modules/views/side/modules/history-view/components/simple-history-view.component.html +++ b/web/src/app/modules/views/side/modules/history-view/components/simple-history-view.component.html @@ -1,7 +1,7 @@
    {{'Changes' | translate}} - +
    • diff --git a/web/src/app/modules/views/side/modules/links-actions/components/links-actions.component.html b/web/src/app/modules/views/side/modules/links-actions/components/links-actions.component.html index bce0ce9b2..d07ef66ed 100644 --- a/web/src/app/modules/views/side/modules/links-actions/components/links-actions.component.html +++ b/web/src/app/modules/views/side/modules/links-actions/components/links-actions.component.html @@ -1,11 +1,11 @@
      {{'LinksandActions' | translate}} - +
      • {{'Requirement' | translate}}: {{requirement.extId}}: {{requirement.name}}
      • -
      • {{'RequirementDescription' | translate}}: {{requirementDescription}} 
      • +
      • {{'RequirementDescription' | translate}}: {{requirementDescription}} 
      • {{'Model' | translate}}: {{model.name}}
      • {{'TestSpecification' | translate}}: {{testSpecification.name}}
      • diff --git a/web/src/app/modules/views/side/modules/properties-editor/components/properties-editor.component.html b/web/src/app/modules/views/side/modules/properties-editor/components/properties-editor.component.html index 582a3d46d..41bd301c6 100644 --- a/web/src/app/modules/views/side/modules/properties-editor/components/properties-editor.component.html +++ b/web/src/app/modules/views/side/modules/properties-editor/components/properties-editor.component.html @@ -1,7 +1,7 @@
        {{'Properties' | translate}} - +
        diff --git a/web/src/app/modules/views/side/modules/tracing-links/components/tracing-links.component.html b/web/src/app/modules/views/side/modules/tracing-links/components/tracing-links.component.html index ef9bf67ea..44cdf71cb 100644 --- a/web/src/app/modules/views/side/modules/tracing-links/components/tracing-links.component.html +++ b/web/src/app/modules/views/side/modules/tracing-links/components/tracing-links.component.html @@ -1,7 +1,7 @@
        {{'Traces' | translate}} - +
        @@ -11,7 +11,7 @@
        - {{'searching' | translate}}... diff --git a/web/src/assets/i18n/de.json b/web/src/assets/i18n/de.json index 23ab896d0..ae1397e26 100644 --- a/web/src/assets/i18n/de.json +++ b/web/src/assets/i18n/de.json @@ -75,6 +75,7 @@ "discardUnsavedChangesConfirmation": "Es gibt ungespeicherte Änderungen. Verwerfen?", "doYouReallyWantToDelete": "Möchten Sie \"{{name}}\" wirklich löschen?", "doYouReallyWantToDeleteAll": "Möchten Sie wirklich alle Inhalte aus \"{{name}}\" entfernen?", + "duplicate": "Duplizieren", "elementCouldNotBeDeleted": "Element konnte nicht gelöscht werden", "elementCouldNotBeRead": "Element konnte nicht geladen werden", "elementCouldNotBeSaved": "Element konnte nicht gespeichert werden", diff --git a/web/src/assets/i18n/gb.json b/web/src/assets/i18n/gb.json index 25f47c2f2..7b090c55a 100644 --- a/web/src/assets/i18n/gb.json +++ b/web/src/assets/i18n/gb.json @@ -75,6 +75,7 @@ "discardUnsavedChangesConfirmation": "You have unsaved changes. Do you really want to discard them?", "doYouReallyWantToDelete": "Do you really want to delete \"{{name}}\"?", "doYouReallyWantToDeleteAll": "Do you really want to delete all elements in \"{{name}}\"?", + "duplicate": "Duplicate", "elementCouldNotBeDeleted": "Could not delete element", "elementCouldNotBeRead": "Could not read element", "elementCouldNotBeSaved": "Could not save element", diff --git a/web/webpack/webpack.common.js b/web/webpack/webpack.common.js index 92e2be594..785a5ae12 100644 --- a/web/webpack/webpack.common.js +++ b/web/webpack/webpack.common.js @@ -1,4 +1,4 @@ -const SPECMATE_VERSION = '0.2.1' +const SPECMATE_VERSION = '0.2.2' const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin');