diff --git a/Dream2/.classpath b/Dream2/.classpath
index d085f01..03be8b6 100644
--- a/Dream2/.classpath
+++ b/Dream2/.classpath
@@ -12,6 +12,7 @@
+
diff --git a/Dream2/.project b/Dream2/.project
index efc6b2e..0722981 100644
--- a/Dream2/.project
+++ b/Dream2/.project
@@ -15,10 +15,16 @@
+
+ com.stateofflow.eclipse.metrics.MetricsBuilder
+
+
+
org.eclipse.ajdt.ui.ajnature
org.eclipse.jdt.core.javanature
org.eclipse.m2e.core.maven2Nature
+ com.stateofflow.eclipse.metrics.MetricsNature
diff --git a/Dream2/.settings/org.eclipse.jdt.core.prefs b/Dream2/.settings/org.eclipse.jdt.core.prefs
index 714351a..0d59eef 100644
--- a/Dream2/.settings/org.eclipse.jdt.core.prefs
+++ b/Dream2/.settings/org.eclipse.jdt.core.prefs
@@ -3,3 +3,288 @@ org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/Dream2/.settings/org.eclipse.jdt.ui.prefs b/Dream2/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..07ccfe5
--- /dev/null
+++ b/Dream2/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,62 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_Dream
+formatter_settings_version=12
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=false
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_trailing_whitespaces=false
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_type_arguments=false
diff --git a/Dream2/.settings/org.eclipse.ltk.core.refactoring.prefs b/Dream2/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..b196c64
--- /dev/null
+++ b/Dream2/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/Dream2/src/examples/java/dream/examples/LineCount.txt b/Dream2/src/examples/java/dream/examples/LineCount.txt
new file mode 100644
index 0000000..dc926e5
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/LineCount.txt
@@ -0,0 +1,20 @@
+Distributed Form
+ Single-source glitch freedom with DREAM: 297
+ Single-source glitch freedom without DREAM: 343
+ Complete glitch freedom with DREAM: 314
+ Complete glitch freedom without DREAM: 607
+
+
+Management application
+ causal consistency with DREAM: XXX
+ causal consistency without DREAM: YYY
+
+
+Scrum board
+ atomic consistency with Dream: 155
+ atomic consistency without Dream: 213
+
+
+Chat application
+ fifo consistency with Dream: 516
+ fifo consistency without Dream: 798
\ No newline at end of file
diff --git a/Dream2/src/examples/java/dream/examples/StartLockManager.java b/Dream2/src/examples/java/dream/examples/StartLockManager.java
index 0396296..62dc661 100755
--- a/Dream2/src/examples/java/dream/examples/StartLockManager.java
+++ b/Dream2/src/examples/java/dream/examples/StartLockManager.java
@@ -3,8 +3,8 @@
import dream.locking.LockManagerLauncher;
public class StartLockManager {
- public static void main(String[] args) {
- LockManagerLauncher.start();
- }
+ public static void main(String[] args) {
+ LockManagerLauncher.start();
+ }
}
diff --git a/Dream2/src/examples/java/dream/examples/StartServer.java b/Dream2/src/examples/java/dream/examples/StartServer.java
index ed7cbad..056fbf9 100755
--- a/Dream2/src/examples/java/dream/examples/StartServer.java
+++ b/Dream2/src/examples/java/dream/examples/StartServer.java
@@ -4,8 +4,8 @@
public class StartServer {
- public static void main(String[] args) {
- ServerLauncher.start();
- }
+ public static void main(String[] args) {
+ ServerLauncher.start();
+ }
}
diff --git a/Dream2/src/examples/java/dream/examples/biginer/AppEntryPoint.java b/Dream2/src/examples/java/dream/examples/biginer/AppEntryPoint.java
new file mode 100644
index 0000000..e3265ab
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/biginer/AppEntryPoint.java
@@ -0,0 +1,49 @@
+/**
+ *
+ */
+package dream.examples.biginer;
+
+import dream.examples.util.NewJvmHelper;
+
+/**
+ * @author Ram
+ *
+ */
+public class AppEntryPoint {
+ public static void main(String args[]) {
+ Process infra = null;
+ Process producer = null;
+ Process consumer = null;
+ try {
+ // Init the infra
+ infra = new NewJvmHelper().startNewJVM(StartInfra.class);
+
+ // Start Producer
+ producer = new NewJvmHelper().startNewJVM(ProducerApp.class);
+
+ // Start Consumer
+ consumer = new NewJvmHelper().startNewJVM(ConsumerApp.class);
+
+ Thread.sleep(5000);
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ /**
+ * All of the JVMs should be closed before exit
+ */
+ finally {
+ if (infra != null) {
+ infra.destroyForcibly();
+ }
+ if (producer != null) {
+ producer.destroyForcibly();
+ }
+ if (consumer != null) {
+ consumer.destroyForcibly();
+ }
+ }
+
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/biginer/ConsumerApp.java b/Dream2/src/examples/java/dream/examples/biginer/ConsumerApp.java
new file mode 100644
index 0000000..e490ae4
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/biginer/ConsumerApp.java
@@ -0,0 +1,40 @@
+package dream.examples.biginer;
+
+import dream.client.RemoteVar;
+import dream.client.Signal;
+import dream.common.Consts;
+
+/**
+ * An application which consumes the variables
+ */
+public class ConsumerApp {
+
+ public ConsumerApp() throws Exception {
+ // App will be running on host different from the producer
+ Consts.hostName = "Host2";
+
+ // Register a Subscription
+ RemoteVar rv = new RemoteVar("Host1", "exVar");
+ System.out.println("Consumer has started\n Please wait..initial communication may take upto 10 seconds");
+ // On every change in remote variable rv create a signal which could
+ // trigger appropriate action
+ Signal s = new Signal("s", () -> {
+ return rv.get() + "ABC";
+ } , rv);
+
+ // Register a handler which will be executed upon receiving the signal
+ s.change().addHandler((oldVal, val) -> System.out.println("Signal1: " + val));
+ }
+
+ public static void main(String args[]) {
+ try {
+ // Start Consumer
+ new ConsumerApp();
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/biginer/ProducerApp.java b/Dream2/src/examples/java/dream/examples/biginer/ProducerApp.java
new file mode 100644
index 0000000..16f743d
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/biginer/ProducerApp.java
@@ -0,0 +1,43 @@
+package dream.examples.biginer;
+
+import dream.client.Var;
+import dream.common.Consts;
+
+/**
+ * An app which produces the variables
+ */
+public class ProducerApp {
+
+ public ProducerApp() throws Exception {
+ // Mention the host(node) which is producing the value
+ Consts.hostName = "Host1";
+
+ // myVar is created and registered as exVar for remote consumption.
+ // exVar is initialized to AAA
+ Var myVar = new Var("exVar", "AAA");
+ System.out.println("Producer has started\n Please wait..initial communication may take upto 10 seconds");
+ int iteration = 10;
+ Thread.sleep(3000);
+ while (iteration > 0) {
+ Thread.sleep(100);
+ // change value of exVar
+ myVar.set("Value-" + (10 - iteration) + "");
+ System.out.println("Changed myvar " + myVar.get());
+ iteration--;
+ }
+ }
+
+ public static void main(String args[]) {
+ try {
+
+ // Start Producer
+ new ProducerApp();
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+}
diff --git a/Dream2/src/examples/java/dream/examples/biginer/StartInfra.java b/Dream2/src/examples/java/dream/examples/biginer/StartInfra.java
new file mode 100644
index 0000000..d5fc712
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/biginer/StartInfra.java
@@ -0,0 +1,19 @@
+package dream.examples.biginer;
+
+import dream.locking.LockManagerLauncher;
+import dream.server.ServerLauncher;
+
+public class StartInfra {
+
+ public static void main(String args[]) {
+ try {
+ // Start the Server
+ ServerLauncher.start();
+ // Start the LockManager
+ LockManagerLauncher.start();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+
+ }
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/chat/DependencyGraph.dot b/Dream2/src/examples/java/dream/examples/chat/DependencyGraph.dot
new file mode 100644
index 0000000..6e68b34
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/chat/DependencyGraph.dot
@@ -0,0 +1,14 @@
+digraph G {
+"incoming_messages@Bob" -> "display@Bob"
+"chat_message@Bob" -> "incomingBob@Bob"
+"chat_message@Alice" -> "incomingAlice@Bob"
+"incomingAlice@Bob" -> "incoming_messages@Bob"
+"incomingBob@Bob" -> "incoming_messages@Bob"
+"incoming_messages@Alice" -> "display@Alice"
+"chat_message@Bob" -> "incomingBob@Alice"
+"chat_message@Alice" -> "incomingAlice@Alice"
+"incomingAlice@Alice" -> "incoming_messages@Alice"
+"incomingBob@Alice" -> "incoming_messages@Alice"
+"server_RegisteredClients@ChatServer" -> "setup@Bob"
+"server_RegisteredClients@ChatServer" -> "setup@Alice"
+}
\ No newline at end of file
diff --git a/Dream2/src/examples/java/dream/examples/chat/DependencyGraph.png b/Dream2/src/examples/java/dream/examples/chat/DependencyGraph.png
new file mode 100644
index 0000000..1ba7ada
Binary files /dev/null and b/Dream2/src/examples/java/dream/examples/chat/DependencyGraph.png differ
diff --git a/Dream2/src/examples/java/dream/examples/chat/Starter.java b/Dream2/src/examples/java/dream/examples/chat/Starter.java
new file mode 100644
index 0000000..3360b41
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/chat/Starter.java
@@ -0,0 +1,46 @@
+package dream.examples.chat;
+
+import dream.examples.chat.core.Chat;
+import dream.examples.chat.core.ChatServer;
+import dream.examples.util.MultipleStarter;
+
+/**
+ * Convenience class to start ChatServer and x Chats (x = CHAT_COUNT), each in
+ * its own VM.
+ *
+ * To exit all processes just close one chat window.
+ */
+public class Starter {
+
+ public static final int CHAT_COUNT = 4;
+
+ public static void main(String[] args) {
+ new Starter().start();
+ }
+
+ private static final String[] names = { "Alice", "Bob", "Chris", "David", "Eve", "Fred", "Georg", "Hans", "Igor" };
+ int xStep = 450;
+ int yStep = 175;
+
+ private void start() {
+ MultipleStarter.addStartQueue(ChatServer.class);
+ int x = 0;
+ int y = 0;
+ for (int i = 0; i < CHAT_COUNT; i++) {
+ MultipleStarter.addStartQueue(Chat.class, getName(i), Integer.toString(x), Integer.toString(y));
+ x += xStep;
+ if (x >= 3 * xStep) {
+ x = 0;
+ y += yStep;
+ }
+ }
+ MultipleStarter.start();
+ }
+
+ private String getName(int i) {
+ if (i < names.length)
+ return names[i];
+ else
+ return names[i % names.length] + "" + i;
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/chat/core/Chat.java b/Dream2/src/examples/java/dream/examples/chat/core/Chat.java
new file mode 100644
index 0000000..c80227e
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/chat/core/Chat.java
@@ -0,0 +1,230 @@
+package dream.examples.chat.core;
+
+import java.awt.EventQueue;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+import dream.client.DreamClient;
+import dream.client.RemoteVar;
+import dream.client.Signal;
+import dream.client.Var;
+import dream.examples.util.Client;
+import dream.examples.util.DependencyVisualization;
+
+public class Chat extends Client {
+
+ private ChatGUI gui;
+
+ private final Signal> onlineList;
+ private List lastOnline;
+
+ private Var toServer;
+
+ private Map> rooms = new HashMap<>();
+ private Map roomNames = new HashMap<>();
+
+ private int posX;
+ private int posY;
+
+ public Chat(String username, int window_x, int window_y) {
+ super(username);
+ this.posX = window_x;
+ this.posY = window_y;
+
+ // Establish new session with server
+ RemoteVar> registeredClients = new RemoteVar>(ChatServer.NAME,
+ ChatServer.SERVER_REGISTERED_CLIENTS);
+ onlineList = new Signal>("onlineList", () -> {
+ if (registeredClients.get() == null)
+ return new ArrayList();
+ else
+ return registeredClients.get();
+ }, registeredClients);
+ onlineList.change().addHandler((o, n) -> {
+ if (n.contains("toServerVar@" + username) && gui == null)
+ setup();
+
+ List names = n.stream().map(x -> x.split("@")[1]).collect(Collectors.toList());
+ setOnline(names);
+ });
+
+ toServer = new Var("toServerVar", "");
+ logger.fine("Setup: Waiting for Registration to Server ...");
+ }
+
+ private void setOnline(List online) {
+ if (lastOnline != null) {
+ for (String s : lastOnline) {
+ if (!online.contains(s)) {
+ String msg = s + " has left the Chat.";
+ // gui.displayMessage(0, msg);
+ }
+ }
+ for (String s : online) {
+ if (!lastOnline.contains(s)) {
+ String msg = s + " has joined.";
+ // gui.displayMessage(0, msg);
+ }
+ }
+ }
+ lastOnline = online;
+ gui.setOnline(online);
+ }
+
+ private void setup() {
+ logger.fine("Setup: Var successfully registered to Server");
+ // Var for messages from server
+ String serverVar = ChatServer.getRandom();
+ sendServerMessage(serverVar);
+ // while (!DreamClient.instance.listVariables().contains(serverVar + "@"
+ // + ChatServer.NAME)) {
+ logger.fine(DreamClient.instance.listVariables().toString());
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ // }
+ RemoteVar remote = new RemoteVar(ChatServer.NAME, serverVar);
+ Signal fromServer = new Signal<>("fromServer", () -> {
+ if (remote.get() != null)
+ return remote.get();
+ else
+ return "";
+ }, remote);
+ fromServer.change().addHandler((oldValue, newValue) -> receivedServerMessage(newValue));
+
+ logger.fine("Setup: Starting GUI");
+ gui = new ChatGUI(getHostName(), posX, posY);
+ gui.setListener(this);
+
+ // main room:
+ // newRoom("Main", "*");
+ }
+
+ protected void receivedChatMessage(int roomNumber, String sender, String message) {
+ gui.displayMessage(roomNumber, sender + ": " + message);
+ }
+
+ protected void receivedServerMessage(String message) {
+ logger.fine("Received message from server: " + message);
+ String[] temp = message.split(" ", 2);
+ String command = temp[0];
+ String rest = temp.length > 1 ? temp[1] : "";
+ if (command.equalsIgnoreCase("room")) {
+ // room ...
+ String[] t = rest.split(" ", 2);
+ String roomName = t[0];
+ String otherClients = t[1];
+ logger.finer("Server requested a Var for room " + roomName + " with " + otherClients);
+
+ String roomVar = newRoom(roomName);
+ sendServerMessage("roomVar " + roomName + " " + roomVar);
+ } else if (command.equalsIgnoreCase("roomVar")) {
+ // roomVar = =
+ String[] t = rest.split(" ", 2);
+ String roomName = t[0];
+ String[] pairs = t[1].split(" ");
+ for (String p : pairs) {
+ String[] t2 = p.split("=", 2);
+ String clientName = t2[0];
+ String clientVar = t2[1];
+ int roomNumber = roomNames.get(roomName);
+ createConnection(roomNumber, roomName, clientName, clientVar);
+ }
+ }
+ }
+
+ protected void sendChatMessage(int roomNumber, String message) {
+ rooms.get(roomNumber).set(message);
+ }
+
+ protected void sendServerMessage(String message) {
+ toServer.set(message);
+ }
+
+ private String newRoom(String roomName) {
+ int roomNumber = gui.newChat(roomName);
+ return newRoom(roomName, roomNumber);
+ }
+
+ protected String newRoom(String roomName, int roomNumber) {
+ String roomVar = "room" + roomNumber;
+ Var room = new Var(roomVar, "");
+ rooms.put(roomNumber, room);
+ roomNames.put(roomName, roomNumber);
+ logger.fine("Room: Creating new Room(" + roomNumber + ")");
+ return roomVar;
+ }
+
+ private void createConnection(int roomNumber, String roomName, String clientName, String clientVar) {
+ if (clientName.equals(getHostName()))
+ return;
+ RemoteVar r = new RemoteVar<>(clientName, clientVar);
+ Signal s = new Signal<>(roomName + "_" + clientName, () -> {
+ if (r.get() != null)
+ return r.get();
+ else
+ return "";
+ }, r);
+ s.change().addHandler((oldValue, newValue) -> receivedChatMessage(roomNumber, clientName, newValue));
+ }
+
+ protected void typedMessage(String text) {
+ if (!text.startsWith("/")) {
+ // normal message
+ int room = gui.getSelectedChat();
+ gui.displayMessage(room, "You: " + text);
+ sendChatMessage(room, text);
+ logger.fine("Send Message to Room" + room + ": " + text);
+ } else {
+ // message to server
+ processCommand(text.substring(1, text.length()));
+ }
+ }
+
+ private void processCommand(String text) {
+ String[] temp = text.split(" ", 2);
+ String command = temp[0];
+ String rest = temp.length > 1 ? temp[1] : "";
+ if (command.equalsIgnoreCase("room")) {
+ String[] temp1 = rest.split(" ", 2);
+ String name = temp1[0];
+ initiateNewRoom(name, temp1[1]);
+ } else if (command.equalsIgnoreCase("graph")) {
+ DependencyVisualization.show();
+ } else if (command.equalsIgnoreCase("sgraph")) {
+ sendServerMessage("graph");
+ }
+ logger.fine("Processed Command: " + text);
+ }
+
+ private void initiateNewRoom(String name, String recipients) {
+ String roomVar = newRoom(name);
+ // room command: room ...
+ logger.finer("Room: Sending to Server: " + "room " + name + " " + roomVar + " " + recipients);
+ sendServerMessage("room " + name + " " + roomVar + " " + recipients);
+ }
+
+ public static void main(String[] args) {
+ if (args.length < 1) {
+ Logger.getGlobal().severe("username missing");
+ return;
+ }
+ int x, y;
+ if (args.length < 3)
+ y = -1;
+ else
+ y = Integer.parseInt(args[2]);
+
+ if (args.length < 2)
+ x = -1;
+ else
+ x = Integer.parseInt(args[1]);
+ EventQueue.invokeLater(() -> new Chat(args[0], x, y));
+ }
+}
\ No newline at end of file
diff --git a/Dream2/src/examples/java/dream/examples/chat/core/ChatGUI.java b/Dream2/src/examples/java/dream/examples/chat/core/ChatGUI.java
new file mode 100644
index 0000000..94e5d63
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/chat/core/ChatGUI.java
@@ -0,0 +1,264 @@
+package dream.examples.chat.core;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.io.File;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.DefaultListModel;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+import javax.swing.SpringLayout;
+import javax.swing.SwingUtilities;
+
+public class ChatGUI extends JFrame implements WindowListener {
+
+ private static final long serialVersionUID = 4659984914364067514L;
+ private JTabbedPane jtp;
+ private List msgs;
+ private JTextField sendText;
+ private JList statusList;
+ private DefaultListModel listModel;
+
+ private Chat listener;
+
+ public ChatGUI(String userName, int posX, int posY) {
+ this.addWindowListener(this);
+ initUI(userName);
+ if (posX >= 0 && posY >= 0)
+ this.setLocation(posX, posY);
+ }
+
+ public void setListener(Chat c) {
+ listener = c;
+ }
+
+ public String getTypedText() {
+ return sendText.getText();
+ }
+
+ public void resetTypedText() {
+ sendText.setText("");
+ }
+
+ public int getSelectedChat() {
+ return jtp.getSelectedIndex();
+ }
+
+ public int newChat(String name) {
+ msgs.add(new JTextArea(5, 27));
+ int r = msgs.size() - 1;
+ msgs.get(r).setEditable(false);
+ JScrollPane sp = new JScrollPane(msgs.get(r));
+ sp.setAutoscrolls(true);
+ jtp.add(name, sp);
+ pack();
+ return r;
+ }
+
+ public void closeChat(int index) {
+ Component t = jtp.getComponentAt(index);
+ jtp.remove(t);
+ }
+
+ public void displayMessage(int room, String text) {
+ if (msgs.get(room).getText().isEmpty())
+ msgs.get(room).append(text);
+ else
+ msgs.get(room).append(System.lineSeparator() + text);
+ }
+
+ public void setOnline(List online) {
+ List offlineList = new ArrayList();
+ for (int i = 0; i < listModel.size(); i++) {
+ if (!online.contains(listModel.get(i)))
+ offlineList.add(listModel.get(i));
+ }
+ SwingUtilities.invokeLater(() -> {
+ listModel.clear();
+ for (String e : online) {
+ listModel.addElement(e);
+ }
+ for (String e : offlineList)
+ listModel.addElement(e);
+ statusList.setSelectionInterval(0, online.size() - 1);
+ });
+
+ }
+
+ public void removeOnline(String name) {
+ listModel.removeElement(name);
+ }
+
+ private void sendText() {
+ listener.typedMessage(getTypedText());
+ this.resetTypedText();
+ }
+
+ private void initUI(String userName) {
+ sendText = new JTextField(20);
+ sendText.addKeyListener(new KeyListener() {
+
+ @Override
+ public void keyTyped(KeyEvent e) {
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_ENTER)
+ sendText();
+ }
+ });
+ JButton sendButton = new JButton("Send");
+ sendButton.addActionListener((e) -> sendText());
+ jtp = new JTabbedPane(JTabbedPane.TOP);
+ jtp.setPreferredSize(new Dimension(400, 100));
+ msgs = new ArrayList<>();
+ // newChat("Main");
+
+ listModel = new DefaultListModel();
+ statusList = new JList(listModel);
+ statusList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ statusList.setEnabled(false);
+ statusList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
+ statusList.setVisibleRowCount(-1);
+ // statusList.setSelectionBackground(Color.GREEN);
+ // statusList.setSelectionForeground(Color.BLACK);
+ // statusList.setForeground(Color.BLACK);
+ // statusList.setBackground(Color.WHITE);
+ // statusList.setCellRenderer(new DefaultListCellRenderer());
+
+ statusList.setCellRenderer(new DefaultListCellRenderer() {
+
+ private static final long serialVersionUID = 9019815674349211344L;
+ private JLabel label = new JLabel();
+ private Color textSelectionColor = Color.BLACK;
+ private Color backgroundSelectionColor = Color.CYAN;
+ private Color textNonSelectionColor = Color.BLACK;
+ private Color backgroundNonSelectionColor = Color.WHITE;
+
+ @Override
+ public java.awt.Component getListCellRendererComponent(javax.swing.JList> list, Object value, int index,
+ boolean isSelected, boolean cellHasFocus) {
+
+ String name = (String) value;
+ label.setText(name);
+
+ if (isSelected) {
+ label.setBackground(backgroundSelectionColor);
+ label.setForeground(textSelectionColor);
+ label.setIcon(createImageIcon("status-online.png", "Online"));
+ } else {
+ label.setBackground(backgroundNonSelectionColor);
+ label.setForeground(textNonSelectionColor);
+ label.setIcon(createImageIcon("status-offline.png", "Offline"));
+ }
+
+ return label;
+ };
+
+ });
+
+ SpringLayout layout = new SpringLayout();
+
+ // put messages on (5,5)
+ layout.putConstraint(SpringLayout.WEST, jtp, 5, SpringLayout.WEST, getContentPane());
+ layout.putConstraint(SpringLayout.NORTH, jtp, 5, SpringLayout.NORTH, getContentPane());
+
+ // put textfield below messages
+ layout.putConstraint(SpringLayout.NORTH, sendText, 5, SpringLayout.SOUTH, jtp);
+ layout.putConstraint(SpringLayout.WEST, sendText, 5, SpringLayout.WEST, getContentPane());
+
+ // put button next to the textfield
+ layout.putConstraint(SpringLayout.NORTH, sendButton, 5, SpringLayout.SOUTH, jtp);
+ layout.putConstraint(SpringLayout.WEST, sendButton, 5, SpringLayout.EAST, sendText);
+
+ // make the frame big enough to fit all in
+ layout.putConstraint(SpringLayout.EAST, getContentPane(), 10, SpringLayout.EAST, statusList);
+ layout.putConstraint(SpringLayout.SOUTH, getContentPane(), 10, SpringLayout.SOUTH, sendText);
+
+ layout.putConstraint(SpringLayout.NORTH, statusList, 5, SpringLayout.NORTH, getContentPane());
+ layout.putConstraint(SpringLayout.WEST, statusList, 15, SpringLayout.EAST, jtp);
+
+ getContentPane().setLayout(layout);
+
+ getContentPane().add(jtp);
+ getContentPane().add(sendText);
+ getContentPane().add(sendButton);
+ getContentPane().add(statusList);
+
+ setTitle("Chat - " + userName);
+ // setSize(300, 200);
+ setLocationRelativeTo(null);
+ setDefaultCloseOperation(EXIT_ON_CLOSE);
+
+ pack();
+ setVisible(true);
+ }
+
+ /** Returns an ImageIcon, or null if the path was invalid. */
+ protected ImageIcon createImageIcon(String path, String description) {
+ File img = new File("./src/resources/dream/examples/chat/" + path);
+ try {
+ java.net.URL imgURL = img.toURI().toURL();
+ if (imgURL != null) {
+ return new ImageIcon(imgURL, description);
+ } else {
+ System.err.println("Couldn't find file: " + path);
+ return null;
+ }
+ } catch (MalformedURLException e) {
+ System.err.println("Couldn't find file: " + path);
+ return null;
+ }
+ }
+
+ @Override
+ public void windowOpened(WindowEvent e) {
+ }
+
+ @Override
+ public void windowIconified(WindowEvent e) {
+ }
+
+ @Override
+ public void windowDeiconified(WindowEvent e) {
+ }
+
+ @Override
+ public void windowDeactivated(WindowEvent e) {
+ }
+
+ @Override
+ public void windowClosing(WindowEvent e) {
+ listener.typedMessage("/quit");
+ }
+
+ @Override
+ public void windowClosed(WindowEvent e) {
+ }
+
+ @Override
+ public void windowActivated(WindowEvent e) {
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/chat/core/ChatServer.java b/Dream2/src/examples/java/dream/examples/chat/core/ChatServer.java
new file mode 100644
index 0000000..18a61f4
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/chat/core/ChatServer.java
@@ -0,0 +1,172 @@
+package dream.examples.chat.core;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import dream.client.DreamClient;
+import dream.client.RemoteVar;
+import dream.client.Signal;
+import dream.client.Var;
+import dream.examples.util.Client;
+import dream.examples.util.DependencyVisualization;
+import dream.examples.util.Pair;
+
+public class ChatServer extends Client {
+ public static final String NAME = "ChatServer";
+
+ private final static SecureRandom r = new SecureRandom();
+
+ private final Var> clients;
+ private final HashMap> clientVars;
+ private final HashMap> rooms;
+ private final Logger logger = Logger.getLogger("ChatServer");
+
+ public static final String SERVER_PREFIX = "server_";
+ public static final String SERVER_REGISTERED_CLIENTS = SERVER_PREFIX + "RegisteredClients";
+
+ public static void main(String[] args) {
+ new ChatServer();
+ }
+
+ public ChatServer() {
+ super(NAME);
+ logger.setLevel(Level.ALL);
+ logger.addHandler(Logger.getGlobal().getHandlers()[0]);
+ clientVars = new HashMap<>();
+ rooms = new HashMap<>();
+ clients = new Var>(SERVER_REGISTERED_CLIENTS, new ArrayList());
+ detectNewSession();
+ }
+
+ /**
+ * Look for new clients every 5 seconds
+ */
+ private void detectNewSession() {
+ Set vars = DreamClient.instance.listVariables();
+ vars.stream().map(x -> new Pair(x.split("@")[1], x.split("@")[0])).// Pair(Host,Var)
+ filter(x -> !clients.get().contains(x.getSecond() + "@" + x.getFirst())
+ && x.getSecond().equalsIgnoreCase("toServerVar"))
+ .//
+ forEach(x -> createNewSessionFor(x.getFirst(), x.getSecond()));
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ logger.log(Level.SEVERE, "Failed to sleep for 0.5 seconds", e);
+ }
+
+ detectNewSession();
+ }
+
+ /**
+ * Registers a new chat client with its name and the name of the variable it
+ * is sending messages on
+ *
+ * @param clientName
+ * the name of the client
+ * @param clientVar
+ * the name of the variable, must be of type String
+ */
+ private void createNewSessionFor(String clientName, String clientVar) {
+ logger.fine("Creating new Session for " + clientName + " with Var " + clientVar);
+
+ // add listener to messages from this client
+ RemoteVar var = new RemoteVar(clientName, clientVar);
+ Signal sig = new Signal<>(SERVER_PREFIX + "receive_" + clientName, () -> {
+ if (var.get() != null)
+ return var.get();
+ else
+ return "";
+ }, var);
+ sig.change().addHandler((oldValue, newValue) -> receivedMessage(clientName, newValue));
+
+ // add client as registered
+ clients.modify((old) -> old.add(clientVar + "@" + clientName));
+
+ // now wait for first message from client
+ logger.fine("Setup: Waiting for first message from " + clientName);
+ }
+
+ protected void sendMessage(String clientName, String message) {
+ clientVars.get(clientName).set(message);
+ }
+
+ protected void receivedMessage(String clientName, String message) {
+ logger.fine("Received client message from " + clientName + ": " + message);
+ if (!clientVars.containsKey(clientName)) {
+ // first message from client
+ // setup Var for messages to this client
+ clientVars.put(clientName, new Var(message, ""));
+ logger.fine("Setup: new Var for messages to " + clientName);
+ } else {
+ String[] temp = message.split(" ", 2);
+ String command = temp[0];
+ String rest = temp.length > 1 ? temp[1] : "";
+
+ if (command.equalsIgnoreCase("room")) {
+ // room ...
+ logger.fine("Room: Received command to create new room (" + message + ")");
+ String[] t = rest.split(" ", 3);
+ String roomName = t[0];
+ String otherClients = t[2];
+ // Map: clientName -> clientRoomVar
+ HashMap roomVars = new HashMap<>();
+ roomVars.put(clientName, t[1]);
+ // send message to every recipient to send a Var for that room
+ if (otherClients.equals("*")) {
+ for (String client : clients.get()) {
+ // set Var for c as "not sent"
+ roomVars.put(client, null);
+ // and ask c for his Var
+ logger.finer("Room: Sending Var-Request for " + roomName + " to " + client);
+ sendMessage(client, "room " + roomName + " " + otherClients.replace(client, clientName));
+ }
+ } else {
+ for (String client : otherClients.split(" ")) {
+ // set Var for c as "not sent"
+ roomVars.put(client, null);
+ // and ask c for his Var
+ logger.finer("Room: Sending Var-Request for " + roomName + " to " + client);
+ sendMessage(client, "room " + roomName + " " + otherClients.replace(client, clientName));
+ }
+ }
+ rooms.put(roomName, roomVars);
+ } else if (command.equalsIgnoreCase("roomVar")) {
+ // roomVar
+ String[] t = rest.split(" ", 2);
+ String roomName = t[0];
+ String varName = t[1];
+ logger.fine("Room: Received a Var (" + varName + ") from " + clientName + " for room " + roomName);
+ Map roomVars = rooms.get(roomName);
+ roomVars.put(clientName, varName);
+
+ // check if every room member has sent a Var
+ if (!roomVars.values().contains(null)) {
+ String varString = "";
+ for (Entry e : roomVars.entrySet()) {
+ varString += e.getKey() + "=" + e.getValue() + " ";
+ }
+ for (String client : roomVars.keySet()) {
+ sendMessage(client, "roomVar " + roomName + " " + varString);
+ }
+ logger.fine("Room: Finished setting up room " + roomName);
+ }
+ } else if (command.equalsIgnoreCase("graph")) {
+ DependencyVisualization.show();
+ }
+ }
+ }
+
+ /**
+ * @return random String hashed with SHA-256
+ */
+ public static String getRandom() {
+ return new BigInteger(130, r).toString(32);
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/chat/fifo/Chat.java b/Dream2/src/examples/java/dream/examples/chat/fifo/Chat.java
new file mode 100644
index 0000000..a529577
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/chat/fifo/Chat.java
@@ -0,0 +1,110 @@
+package dream.examples.chat.fifo;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+public class Chat extends dream.examples.chat.core.Chat {
+
+ private HashMap roomClocks = new HashMap<>();
+ private HashMap> messageCache = new HashMap<>();
+
+ public Chat(String username, int window_x, int window_y) {
+ super(username, window_x, window_y);
+ }
+
+ @Override
+ protected void sendChatMessage(int roomNumber, String message) {
+ // increment VectorClock by 1
+ VectorClock roomClock = roomClocks.get(roomNumber);
+ roomClock.incrementClock(getHostName());
+ // attach VectorClock to message
+ String newMessage = roomClock.toString() + "|" + message;
+ logger.fine("Sending message with VectorClock " + roomClock + ": " + message);
+ super.sendChatMessage(roomNumber, newMessage);
+ }
+
+ @Override
+ protected void receivedChatMessage(int roomNumber, String sender, String message) {
+ String[] temp = message.split("\\|", 2);
+ VectorClock messageClock = new VectorClock(temp[0]);
+ String newMessage = temp[1];
+ cacheMessage(messageClock, roomNumber, sender, newMessage);
+ processCachedMessages(roomNumber);
+ }
+
+ private void cacheMessage(VectorClock messageClock, int roomNumber, String sender, String message) {
+ messageCache.get(roomNumber).add(new CachedMessage(messageClock, roomNumber, sender, message));
+ }
+
+ private void processCachedMessages(int roomNumber) {
+ List messages = messageCache.get(roomNumber);
+ VectorClock roomClock = roomClocks.get(roomNumber);
+ boolean removed = false;
+ for (CachedMessage cm : messages) {
+ if (cm.canSend(roomClock)) {
+ // increase received messages from the sender
+ roomClock.incrementClock(cm.getSender());
+ // deliver the message
+ super.receivedChatMessage(cm.getRoom(), cm.getSender(), cm.getMessage());
+ // remove message from cache
+ messages.remove(cm);
+ }
+ }
+ if (removed)
+ processCachedMessages(roomNumber);
+ }
+
+ @Override
+ protected String newRoom(String roomName, int roomNumber) {
+ roomClocks.put(roomNumber, new VectorClock());
+ messageCache.put(roomNumber, new ArrayList<>());
+ return super.newRoom(roomName, roomNumber);
+ }
+}
+
+class CachedMessage {
+ private VectorClock clock;
+ private int room;
+ private String sender;
+ private String message;
+
+ public CachedMessage(VectorClock messageClock, int roomNumber, String sender, String message) {
+ this.clock = messageClock;
+ this.room = roomNumber;
+ this.sender = sender;
+ this.message = message;
+ }
+
+ public boolean canSend(VectorClock roomClock) {
+ // delivered every message that the sender has sent before this message
+ boolean senderSent = clock.get(sender) == roomClock.get(sender) + 1;
+ // delivered every message that the sender has delivered before this
+ // message
+ boolean senderDelivered = true;
+ for (Entry e : clock.entrySet()) {
+ if (!e.getKey().equals(sender)) {
+ if (clock.get(e.getKey()) > roomClock.get(e.getKey()))
+ senderDelivered = false;
+ }
+ }
+ return senderSent && senderDelivered;
+ }
+
+ public VectorClock getClock() {
+ return clock;
+ }
+
+ public int getRoom() {
+ return room;
+ }
+
+ public String getSender() {
+ return sender;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/chat/fifo/VectorClock.java b/Dream2/src/examples/java/dream/examples/chat/fifo/VectorClock.java
new file mode 100644
index 0000000..4e5b3e5
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/chat/fifo/VectorClock.java
@@ -0,0 +1,252 @@
+package dream.examples.chat.fifo;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+
+/**
+ * Implements a VectorClock that records the time stamps of all send and receive
+ * events. It contains functions to compare and merge two VectorClocks.
+ *
+ * @author Frits de Nijs
+ * @author Peter Dijkshoorn
+ */
+public class VectorClock extends HashMap implements Serializable, Comparator {
+ // Unique Serial.
+ private static final long serialVersionUID = 6668164199894268488L;
+
+ public VectorClock() {
+
+ }
+
+ public VectorClock(String initString) {
+ fromString(this, initString);
+ }
+
+ /**
+ * Increases the component of pUnit by 1.
+ *
+ * @param pUnit
+ * - The ID of the vector element being increased.
+ */
+ public void incrementClock(String pUnit) {
+ // If we have it in the vector, increment.
+ if (this.containsKey(pUnit)) {
+ this.put(pUnit, this.get(pUnit).intValue() + 1);
+ }
+ // Else, store with value 1 (starts at 0, +1).
+ else {
+ this.put(pUnit, 1);
+ }
+ }
+
+ /**
+ * GUI operation, returns the IDs in some neat order.
+ *
+ * @return The IDs of the elements in the Clock.
+ */
+ public String[] getOrderedIDs() {
+ String[] lResult = new String[this.size()];
+
+ lResult = this.keySet().toArray(lResult);
+
+ Arrays.sort(lResult);
+
+ return lResult;
+ }
+
+ /**
+ * GUI operation, returns the values in some neat order.
+ *
+ * @return The Values of the elements in the Clock.
+ */
+ public Integer[] getOrderedValues() {
+ Integer[] lResult = new Integer[this.size()];
+ String[] lKeySet = this.getOrderedIDs();
+
+ int i = 0;
+ for (String lKey : lKeySet) {
+ lResult[i] = this.get(lKey);
+ i++;
+ }
+
+ return lResult;
+ }
+
+ @Override
+ public Integer get(Object key) {
+ Integer lResult = super.get(key);
+
+ if (lResult == null)
+ lResult = 0;
+
+ return lResult;
+ }
+
+ @Override
+ public VectorClock clone() {
+ return (VectorClock) super.clone();
+ }
+
+ @Override
+ public String toString() {
+ return toString(this);
+ }
+
+ /**
+ * VectorClock merging operation. Creates a new VectorClock with the maximum
+ * for each element in either clock. Used in Buffer and Process to
+ * manipulate clocks.
+ *
+ * @param pOne
+ * - First Clock being merged.
+ * @param pTwo
+ * - Second Clock being merged.
+ *
+ * @return A new VectorClock with the maximum for each element in either
+ * clock.
+ */
+ public static VectorClock max(VectorClock pOne, VectorClock pTwo) {
+ // Create new Clock.
+ VectorClock lResult = new VectorClock();
+
+ // Go over all elements in clock One, put them in the new clock.
+ for (String lEntry : pOne.keySet()) {
+ lResult.put(lEntry, pOne.get(lEntry));
+ }
+
+ // Go over all elements in clock Two,
+ for (String lEntry : pTwo.keySet()) {
+ // Insert the Clock Two value if it is not present in One, or if it
+ // is higher.
+ if (!lResult.containsKey(lEntry) || lResult.get(lEntry) < pTwo.get(lEntry)) {
+ lResult.put(lEntry, pTwo.get(lEntry));
+ }
+ }
+
+ // Return the merged clock.
+ return lResult;
+ }
+
+ public int compare(VectorClock v1, VectorClock v2) {
+ switch (order(v1, v2)) {
+ case GREATER:
+ return 1;
+ case SMALLER:
+ return -1;
+ default:
+ return 0;
+ }
+ }
+
+ /**
+ * VectorClock compare operation. Returns one of four possible values
+ * indicating how clock one relates to clock two:
+ *
+ * VectorComparison.GREATER If One > Two. VectorComparison.EQUAL If One =
+ * Two. VectorComparison.SMALLER If One < Two. VectorComparison.SIMULTANEOUS
+ * If One <> Two.
+ *
+ * @param pOne
+ * - First Clock being compared.
+ * @param pTwo
+ * - Second Clock being compared.
+ *
+ * @return VectorComparison value indicating how One relates to Two.
+ */
+ public static VectorComparison order(VectorClock pOne, VectorClock pTwo) {
+ // Initially we assume it is all possible things.
+ boolean lEqual = true;
+ boolean lGreater = true;
+ boolean lSmaller = true;
+
+ // Go over all elements in Clock one.
+ for (String lEntry : pOne.keySet()) {
+ // Compare if also present in clock two.
+ if (pTwo.containsKey(lEntry)) {
+ // If there is a difference, it can never be equal.
+ // Greater / smaller depends on the difference.
+ if (pOne.get(lEntry) < pTwo.get(lEntry)) {
+ lEqual = false;
+ lGreater = false;
+ }
+ if (pOne.get(lEntry) > pTwo.get(lEntry)) {
+ lEqual = false;
+ lSmaller = false;
+ }
+ }
+ // Else assume zero (default value is 0).
+ else if (pOne.get(lEntry) != 0) {
+ lEqual = false;
+ lSmaller = false;
+ }
+ }
+
+ // Go over all elements in Clock two.
+ for (String lEntry : pTwo.keySet()) {
+ // Only elements we have not found in One still need to be checked.
+ if (!pOne.containsKey(lEntry) && (pTwo.get(lEntry) != 0)) {
+ lEqual = false;
+ lGreater = false;
+ }
+ }
+
+ // Return based on determined information.
+ if (lEqual) {
+ return VectorComparison.EQUAL;
+ } else if (lGreater && !lSmaller) {
+ return VectorComparison.GREATER;
+ } else if (lSmaller && !lGreater) {
+ return VectorComparison.SMALLER;
+ } else {
+ return VectorComparison.SIMULTANEOUS;
+ }
+ }
+
+ public static String toString(VectorClock clock) {
+ StringBuilder sb = new StringBuilder();
+ String[] lIDs = clock.getOrderedIDs();
+ Integer[] lRequests = clock.getOrderedValues();
+ sb.append("[");
+ for (int i = 0; i < lRequests.length; i++) {
+ sb.append(lIDs[i]).append("=").append(lRequests[i].toString());
+ if (i + 1 < lRequests.length) {
+ sb.append(",");
+ }
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+ public static VectorClock fromString(String clockString) {
+ return fromString(new VectorClock(), clockString);
+ }
+
+ private static VectorClock fromString(VectorClock vc, String clockString) {
+ if (clockString.startsWith("[") && clockString.endsWith("]")) {
+ clockString = clockString.substring(1, clockString.length() - 1);
+ String[] pairs = clockString.split(",");
+ for (int i = 0; i < pairs.length; i++) {
+ if (pairs[i].length() > 0) {
+ String[] temp = pairs[i].split("=");
+ String key = temp[0];
+ int value = Integer.valueOf(temp[1]);
+ vc.put(key, value);
+ }
+ }
+ return vc;
+ } else
+ throw new IllegalArgumentException("String is not a VectorClock: " + clockString);
+ }
+}
+
+/**
+ * Enumerates the four different outcomes of comparing two VectorClocks.
+ *
+ * @author Frits de Nijs
+ * @author Peter Dijkshoorn
+ */
+enum VectorComparison {
+ GREATER, EQUAL, SMALLER, SIMULTANEOUS;
+}
\ No newline at end of file
diff --git a/Dream2/src/examples/java/dream/examples/chat/line-count.core.txt b/Dream2/src/examples/java/dream/examples/chat/line-count.core.txt
new file mode 100644
index 0000000..064384d
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/chat/line-count.core.txt
@@ -0,0 +1,8 @@
+http://cloc.sourceforge.net v 1.64 T=0.02 s (145.4 files/s, 32269.1 lines/s)
+-------------------------------------------------------------------------------
+Language files blank comment code
+-------------------------------------------------------------------------------
+Java 3 95 55 516
+-------------------------------------------------------------------------------
+SUM: 3 95 55 516
+-------------------------------------------------------------------------------
diff --git a/Dream2/src/examples/java/dream/examples/chat/line-count.diff.core.fifo.txt b/Dream2/src/examples/java/dream/examples/chat/line-count.diff.core.fifo.txt
new file mode 100644
index 0000000..ca3fd13
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/chat/line-count.diff.core.fifo.txt
@@ -0,0 +1,16 @@
+http://cloc.sourceforge.net v 1.64 T=0.08 s (13.1 files/s, 13.1 lines/s)
+-------------------------------------------------------------------------------
+Language files blank comment code
+-------------------------------------------------------------------------------
+Java
+ same 0 0 0 20
+ modified 1 0 8 59
+ added 1 31 75 153
+ removed 2 79 47 437
+-------------------------------------------------------------------------------
+SUM:
+ same 0 0 0 20
+ modified 1 0 8 59
+ added 1 31 75 153
+ removed 2 79 47 437
+-------------------------------------------------------------------------------
diff --git a/Dream2/src/examples/java/dream/examples/chat/line-count.fifo.txt b/Dream2/src/examples/java/dream/examples/chat/line-count.fifo.txt
new file mode 100644
index 0000000..c974ab7
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/chat/line-count.fifo.txt
@@ -0,0 +1,8 @@
+http://cloc.sourceforge.net v 1.64 T=0.03 s (57.9 files/s, 10488.8 lines/s)
+-------------------------------------------------------------------------------
+Language files blank comment code
+-------------------------------------------------------------------------------
+Java 2 47 83 232
+-------------------------------------------------------------------------------
+SUM: 2 47 83 232
+-------------------------------------------------------------------------------
diff --git a/Dream2/src/examples/java/dream/examples/chat/package-info.java b/Dream2/src/examples/java/dream/examples/chat/package-info.java
new file mode 100644
index 0000000..cba4f26
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/chat/package-info.java
@@ -0,0 +1,10 @@
+/**
+ * A small example for a Chat Application
+ *
+ * Usage: Start {@link javareact.chat.ChatServer ChatServer} first. Then start
+ * as many instances of {@link dream.examples.chat.core.Chat Chat} as you need
+ * and supply a user name as the first parameter.
+ *
+ * @author Tobias Becker
+ */
+package dream.examples.chat;
diff --git a/Dream2/src/examples/java/dream/examples/financial/FinancialApp.java b/Dream2/src/examples/java/dream/examples/financial/FinancialApp.java
index 450dc9c..77823f6 100644
--- a/Dream2/src/examples/java/dream/examples/financial/FinancialApp.java
+++ b/Dream2/src/examples/java/dream/examples/financial/FinancialApp.java
@@ -1,67 +1,68 @@
package dream.examples.financial;
+import java.util.Arrays;
+import java.util.List;
+
+import dream.client.ChangeEventHandler;
import dream.client.RemoteVar;
import dream.client.Signal;
-import dream.client.ValueChangeListener;
-import dream.common.Consts;
-
-public class FinancialApp implements ValueChangeListener {
- private Signal f1Signal;
- private Signal f2Signal;
- private Signal f3Signal;
+import dream.examples.util.Client;
- private RemoteVar f1;
- private RemoteVar f2;
- private RemoteVar f3;
+public class FinancialApp extends Client implements ChangeEventHandler {
- public static void main(String[] args) {
- new FinancialApp().start();
- }
+ public FinancialApp() {
+ super("Local");
+ }
- public void start() {
- Consts.hostName = "Local";
+ private Signal f1Signal;
+ private Signal f2Signal;
+ private Signal f3Signal;
- try {
- Thread.sleep(2000);
- } catch (final InterruptedException e) {
- e.printStackTrace();
- }
+ private RemoteVar f1;
+ private RemoteVar f2;
+ private RemoteVar f3;
- f1 = new RemoteVar<>("f1@Model1");
- f2 = new RemoteVar<>("f2@Model2");
- f3 = new RemoteVar<>("f3@Model3");
+ public static void main(String[] args) {
+ new FinancialApp().start();
+ }
- final RemoteVar model1 = new RemoteVar<>("Model1", "model1");
+ @Override
+ protected List waitForVars() {
+ return Arrays.asList("f1@Model1", "f2@Model2", "f3@Model3");
+ }
- f1Signal = new Signal<>("f1Signal", () -> f1.get(), f1);
- f2Signal = new Signal<>("f2Signal", () -> f2.get(), f2);
- f3Signal = new Signal<>("f3Signal", () -> f3.get(), f3);
+ public void start() {
+ f1 = new RemoteVar<>("Model1", "f1");
+ f2 = new RemoteVar<>("Model2", "f2");
+ f3 = new RemoteVar<>("Model3", "f3");
- f1Signal.addValueChangeListener(this);
- f2Signal.addValueChangeListener(this);
- f3Signal.addValueChangeListener(this);
+ f1Signal = new Signal<>("f1Signal", () -> f1.get(), f1);
+ f2Signal = new Signal<>("f2Signal", () -> f2.get(), f2);
+ f3Signal = new Signal<>("f3Signal", () -> f3.get(), f3);
- try {
- Thread.sleep(2000);
- } catch (final InterruptedException e) {
- e.printStackTrace();
- }
+ f1Signal.change().addHandler(this);
+ f2Signal.change().addHandler(this);
+ f3Signal.change().addHandler(this);
- System.out.println(f1.get());
- System.out.println(f2.get());
- System.out.println(f3.get());
+ try {
+ Thread.sleep(2000);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
- System.out.println(model1.get());
- }
+ System.out.println(f1.get());
+ System.out.println(f2.get());
+ System.out.println(f3.get());
+ }
- @Override
- public void notifyValueChanged(Integer newValue) {
- System.out.println("Value changed");
+ @Override
+ public void handle(Integer oldVal, Integer newVal) {
+ System.out.println("Value changed");
- if (f1.get() != null && f2.get() != null && f3.get() != null) {
- if ((f1.get() + f2.get() + f3.get()) / 3.0 > 150) {
- System.out.println("Financial Alert!");
- }
- }
- }
+ if (f1.get() != null && f2.get() != null && f3.get() != null) {
+ if ((f1.get() + f2.get() + f3.get()) / 3.0 > 150) {
+ System.out.println("Financial Alert!");
+ }
+ }
+ }
}
diff --git a/Dream2/src/examples/java/dream/examples/financial/InputModel.java b/Dream2/src/examples/java/dream/examples/financial/InputModel.java
index b8b4a67..42f6b90 100644
--- a/Dream2/src/examples/java/dream/examples/financial/InputModel.java
+++ b/Dream2/src/examples/java/dream/examples/financial/InputModel.java
@@ -3,66 +3,37 @@
import java.util.Random;
import dream.client.Var;
-import dream.common.Consts;
-import dream.locking.LockManagerLauncher;
-import dream.server.ServerLauncher;
+import dream.examples.util.Client;
-public class InputModel {
- private boolean serverStarted = false;
- private boolean lockManagerStarted = false;
+public class InputModel extends Client {
- public static void main(String[] args) {
- new InputModel().start();
- }
+ public InputModel() {
+ super("InputModel");
+ }
- public void start() {
- startServerIfNeeded();
- startLockManagerIfNeeded();
+ public static void main(String[] args) {
+ new InputModel().start();
+ }
- Consts.hostName = "InputModel";
+ public void start() {
+ final Var marketIndex = new Var<>("marketIndex", 1);
+ final Var stockOpts = new Var<>("stockOpts", 1);
+ final Var news = new Var<>("news", 1);
- final Var marketIndex = new Var<>("marketIndex", 1);
- final Var stockOpts = new Var<>("stockOpts", 1);
- final Var news = new Var<>("news", 1);
+ final Random random = new Random();
- final Random random = new Random();
+ while (true) {
+ marketIndex.set(random.nextInt(100));
+ stockOpts.set(random.nextInt(100));
+ news.set(random.nextInt(100));
- while (true) {
- marketIndex.set(random.nextInt(100));
- stockOpts.set(random.nextInt(100));
- news.set(random.nextInt(100));
+ System.out.println("New values: " + marketIndex.get() + ", " + stockOpts.get() + ", " + news.get());
- System.out.println("New values: " + marketIndex.get() + ", " + stockOpts.get() + ", " + news.get());
-
- try {
- Thread.sleep(1000);
- } catch (final InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
-
- private final void startServerIfNeeded() {
- if (!serverStarted) {
- ServerLauncher.start();
- serverStarted = true;
- }
- try {
- Thread.sleep(500);
- } catch (final InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- private final void startLockManagerIfNeeded() {
- if (!lockManagerStarted) {
- LockManagerLauncher.start();
- lockManagerStarted = true;
- }
- try {
- Thread.sleep(500);
- } catch (final InterruptedException e) {
- e.printStackTrace();
- }
- }
+ try {
+ Thread.sleep(1000);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
}
diff --git a/Dream2/src/examples/java/dream/examples/financial/Model1.java b/Dream2/src/examples/java/dream/examples/financial/Model1.java
index 705b564..3d7e9c9 100644
--- a/Dream2/src/examples/java/dream/examples/financial/Model1.java
+++ b/Dream2/src/examples/java/dream/examples/financial/Model1.java
@@ -1,34 +1,38 @@
package dream.examples.financial;
+import java.util.Arrays;
+import java.util.List;
+
import dream.client.RemoteVar;
import dream.client.Signal;
-import dream.client.ValueChangeListener;
-import dream.common.Consts;
-
-public class Model1 implements ValueChangeListener {
- public void start() {
- Consts.hostName = "Model1";
-
- final RemoteVar marketIndex = new RemoteVar<>("InputModel", "marketIndex");
- final RemoteVar stockOpts = new RemoteVar<>("InputModel", "stockOpts");
-
- final Signal f1 = new Signal<>("f1", () -> {
- if (marketIndex.get() == null || stockOpts.get() == null) {
- return null;
- } else {
- return marketIndex.get() * 2 + stockOpts.get();
- }
- } , marketIndex, stockOpts);
-
- f1.addValueChangeListener(this);
- }
-
- @Override
- public void notifyValueChanged(Integer newValue) {
- System.out.println("New value for f1: " + newValue);
- }
-
- public static void main(String[] args) {
- new Model1().start();
- }
+import dream.examples.util.Client;
+
+public class Model1 extends Client {
+ public Model1() {
+ super("Model1");
+ }
+
+ @Override
+ protected List waitForVars() {
+ return Arrays.asList("marketIndex@InputModel", "stockOpts@InputModel");
+ }
+
+ public void start() {
+ final RemoteVar marketIndex = new RemoteVar<>("InputModel", "marketIndex");
+ final RemoteVar stockOpts = new RemoteVar<>("InputModel", "stockOpts");
+
+ final Signal f1 = new Signal<>("f1", () -> {
+ if (marketIndex.get() == null || stockOpts.get() == null) {
+ return null;
+ } else {
+ return marketIndex.get() * 2 + stockOpts.get();
+ }
+ } , marketIndex, stockOpts);
+
+ f1.change().addHandler((oldVal, newVal) -> System.out.println("New value for f1: " + newVal));
+ }
+
+ public static void main(String[] args) {
+ new Model1().start();
+ }
}
diff --git a/Dream2/src/examples/java/dream/examples/financial/Model2.java b/Dream2/src/examples/java/dream/examples/financial/Model2.java
index 7676696..a63825b 100644
--- a/Dream2/src/examples/java/dream/examples/financial/Model2.java
+++ b/Dream2/src/examples/java/dream/examples/financial/Model2.java
@@ -1,30 +1,37 @@
package dream.examples.financial;
+import java.util.Arrays;
+import java.util.List;
+
import dream.client.RemoteVar;
import dream.client.Signal;
-import dream.client.ValueChangeListener;
-import dream.common.Consts;
+import dream.examples.util.Client;
+
+public class Model2 extends Client {
+ public Model2() {
+ super("Model2");
+ }
+
+ @Override
+ protected List waitForVars() {
+ return Arrays.asList("marketIndex@InputModel", "stockOpts@InputModel");
+ }
-public class Model2 implements ValueChangeListener {
public void start() {
- Consts.hostName = "Model2";
+ final RemoteVar marketIndex = new RemoteVar<>("InputModel", "marketIndex");
+ final RemoteVar stockOpts = new RemoteVar<>("InputModel", "stockOpts");
- RemoteVar marketIndex = new RemoteVar<>("InputModel", "marketIndex");
- RemoteVar stockOpts = new RemoteVar<>("InputModel", "stockOpts");
+ final Signal f2 = new Signal<>("f2", () -> {
+ if (marketIndex.get() == null || stockOpts.get() == null) {
+ return null;
+ } else {
+ return marketIndex.get() + stockOpts.get() * 2;
+ }
+ } , marketIndex, stockOpts);
- Signal f2 = new Signal<>("f2", () -> {
- if (marketIndex.get() == null || stockOpts.get() == null) { return null; }
- else { return marketIndex.get() + stockOpts.get() * 2; }
- }, marketIndex, stockOpts);
-
- f2.addValueChangeListener(this);
+ f2.change().addHandler((oldVal, newVal) -> System.out.println("New value for f2: " + newVal));
}
- @Override
- public void notifyValueChanged(Integer newValue) {
- System.out.println("New value for f2: " + newValue);
- }
-
public static void main(String[] args) {
new Model2().start();
}
diff --git a/Dream2/src/examples/java/dream/examples/financial/Model3.java b/Dream2/src/examples/java/dream/examples/financial/Model3.java
index 0151fdf..f85bdce 100644
--- a/Dream2/src/examples/java/dream/examples/financial/Model3.java
+++ b/Dream2/src/examples/java/dream/examples/financial/Model3.java
@@ -1,30 +1,38 @@
package dream.examples.financial;
+import java.util.Arrays;
+import java.util.List;
+
import dream.client.RemoteVar;
import dream.client.Signal;
-import dream.client.ValueChangeListener;
-import dream.common.Consts;
+import dream.examples.util.Client;
-public class Model3 implements ValueChangeListener {
- public void start() {
- Consts.hostName = "Model3";
-
- RemoteVar marketIndex = new RemoteVar<>("InputModel", "marketIndex");
- RemoteVar news = new RemoteVar<>("InputModel", "news");
-
- Signal f3 = new Signal<>("f3", () -> {
- if (marketIndex.get() == null || news.get() == null) { return null; }
- else { return marketIndex.get() + news.get(); }
- }, marketIndex, news);
-
- f3.addValueChangeListener(this);
+public class Model3 extends Client {
+
+ public Model3() {
+ super("Model3");
}
@Override
- public void notifyValueChanged(Integer newValue) {
- System.out.println("New value for f3: " + newValue);
+ protected List waitForVars() {
+ return Arrays.asList("marketIndex@InputModel", "news@InputModel");
}
-
+
+ public void start() {
+ final RemoteVar marketIndex = new RemoteVar<>("InputModel", "marketIndex");
+ final RemoteVar news = new RemoteVar<>("InputModel", "news");
+
+ final Signal f3 = new Signal<>("f3", () -> {
+ if (marketIndex.get() == null || news.get() == null) {
+ return null;
+ } else {
+ return marketIndex.get() + news.get();
+ }
+ } , marketIndex, news);
+
+ f3.change().addHandler((oldVal, newVal) -> System.out.println("New value for f3: " + newVal));
+ }
+
public static void main(String[] args) {
new Model3().start();
}
diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/Boss.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/Boss.java
new file mode 100644
index 0000000..d278e17
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/Boss.java
@@ -0,0 +1,60 @@
+package dream.examples.form.complete_glitchfree;
+
+import dream.client.Var;
+import dream.examples.util.Pair;
+
+public class Boss extends FormClient {
+
+ public static final String NAME = "Boss";
+ public static final String EuroPerHour = "euro_per_hour";
+ public static final String RequiredHours = "required_hours";
+
+ private Var eph;
+ private Var> rh;
+
+ public Boss() {
+ super(NAME, "Euro/Hour", "Minimum Hours", "Maximum Hours");
+ setInitValues(Double.toString(8.5), Integer.toString(10), Integer.toString(60));
+ }
+
+ @Override
+ protected void init() {
+ eph = new Var<>(EuroPerHour, 8.5);
+ rh = new Var<>(RequiredHours, new Pair<>(10, 60));
+ }
+
+ @Override
+ public void typedText(int i, String typedText) {
+ switch (i) {
+ case 0:
+ Double value = Double.valueOf(typedText);
+ lock(Variable.get(eph));
+ eph.set(value);
+ unlock();
+ logger.fine("Set Euro_Per_Hour to " + value);
+ break;
+ case 1:
+ Integer value2 = Integer.valueOf(typedText);
+ lock(Variable.get(rh));
+ rh.set(new Pair<>(value2, rh.get().getSecond()));
+ unlock();
+ logger.fine("Set minimum @ Required_Hours to " + value2);
+ break;
+ case 2:
+ Integer value3 = Integer.valueOf(typedText);
+ lock(Variable.get(rh));
+ rh.set(new Pair<>(rh.get().getFirst(), value3));
+ unlock();
+ logger.fine("Set maximum @ Required_Hours to " + value3);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ public static void main(String[] args) {
+ new Boss();
+ }
+
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/CompleteGlitchFreeFormServer.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/CompleteGlitchFreeFormServer.java
new file mode 100644
index 0000000..df02d5b
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/CompleteGlitchFreeFormServer.java
@@ -0,0 +1,52 @@
+package dream.examples.form.complete_glitchfree;
+
+import dream.client.Signal;
+
+public class CompleteGlitchFreeFormServer extends FormServer {
+
+ @Override
+ protected void createDependencies() {
+ logger.fine("Building Dependencies");
+ // TODO implement glitch freedom
+ final Signal minimumHours = new Signal<>(MinimumHours, () -> {
+ if (working_hours.get() != null && required_hours.get() != null)
+ return working_hours.get() > required_hours.get().getFirst();
+ else
+ return false;
+ }, working_hours, required_hours);
+
+ final Signal maximumHours = new Signal<>(MaximumHours, () -> {
+ if (working_hours.get() != null && required_hours.get() != null)
+ return working_hours.get() < required_hours.get().getSecond();
+ else
+ return false;
+ }, working_hours, required_hours);
+
+ final Signal minimumEuroPerHour = new Signal<>(MinimumEuroPerHour, () -> {
+ if (euro_per_hour.get() != null)
+ return euro_per_hour.get() > 10;
+ else
+ return false;
+ }, euro_per_hour);
+
+ new Signal<>(SettingsOkay, () -> {
+ if (minimumHours.get() != null && maximumHours.get() != null && minimumEuroPerHour.get() != null)
+ return minimumHours.get() && maximumHours.get() && minimumEuroPerHour.get();
+ else
+ return false;
+ }, minimumHours, maximumHours, minimumEuroPerHour);
+
+ new Signal<>(Salary, () -> {
+ if (working_hours.get() != null && euro_per_hour.get() != null)
+ return working_hours.get() * euro_per_hour.get();
+ else
+ return 0.0;
+ }, working_hours, euro_per_hour);
+
+ logger.fine("Finished building Dependencies");
+ }
+
+ public static void main(String[] args) {
+ new CompleteGlitchFreeFormServer();
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormClient.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormClient.java
new file mode 100644
index 0000000..efe026a
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormClient.java
@@ -0,0 +1,71 @@
+package dream.examples.form.complete_glitchfree;
+
+import java.awt.Color;
+import java.util.Arrays;
+import java.util.List;
+
+import dream.client.RemoteVar;
+import dream.client.Signal;
+
+public abstract class FormClient extends LockClient {
+
+ private RemoteVar salary;
+ private RemoteVar settings;
+ private Signal remoteSalary;
+ private Signal remoteSettings;
+
+ private FormGUI gui;
+ private String[] labelText;
+ private String[] values;
+
+ public FormClient(String name, String... labelText) {
+ super(name);
+ this.labelText = labelText;
+ }
+
+ @Override
+ protected List waitForVars() {
+ return Arrays.asList(toVar(FormServer.NAME, FormServer.Salary),
+ toVar(FormServer.NAME, FormServer.SettingsOkay));
+ }
+
+ protected void start() {
+ gui = new FormGUI(getHostName(), labelText);
+ gui.setListener(this);
+ if (values != null)
+ gui.setInitValues(values);
+
+ salary = new RemoteVar<>(FormServer.NAME, FormServer.Salary);
+ settings = new RemoteVar<>(FormServer.NAME, FormServer.SettingsOkay);
+
+ remoteSalary = new Signal<>("remoteSalary", () -> {
+ if (salary.get() != null)
+ return salary.get();
+ else
+ return 0.0;
+ }, salary);
+
+ remoteSettings = new Signal<>("remoteSettings", () -> {
+ if (settings.get() != null)
+ return settings.get();
+ else
+ return false;
+ }, settings);
+
+ gui.setText("Salary: ");
+ gui.setColor(Color.red);
+ remoteSalary.change().addHandler((o, n) -> gui.setText("Salary: " + n.toString()));
+ remoteSettings.change().addHandler((o, n) -> gui.setColor((n ? Color.green : Color.red)));
+ }
+
+ public abstract void typedText(int i, String typedText);
+
+ public void setInitValues(String... values) {
+ this.values = values;
+ }
+
+ @Override
+ protected void setup() {
+ start();
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormGUI.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormGUI.java
new file mode 100644
index 0000000..93f96dd
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormGUI.java
@@ -0,0 +1,124 @@
+package dream.examples.form.complete_glitchfree;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+public class FormGUI extends JFrame {
+
+ private static final long serialVersionUID = 9205614575242281482L;
+ private JTextField[] sendText;
+ private FormClient listener;
+ private JLabel display;
+ private String[] labelText;
+
+ public FormGUI(String name, String... labelText) {
+ setTitle(name);
+ this.labelText = labelText;
+ initUI();
+ }
+
+ private void initUI() {
+ getContentPane().setLayout(new BorderLayout());
+ JPanel all = new JPanel();
+ all.setLayout(new GridLayout(0, 2));
+ getContentPane().add(all, BorderLayout.CENTER);
+
+ sendText = new JTextField[labelText.length];
+
+ for (int i = 0; i < labelText.length; i++) {
+ sendText[i] = new JTextField(20);
+ sendText[i].addKeyListener(new MultiListener(i));
+ JButton sendButton = new JButton("Set");
+ sendButton.addActionListener(new MultiListener(i));
+
+ JLabel label = new JLabel(labelText[i] + ": ");
+
+ JPanel p = new JPanel();
+ p.add(label);
+ p.add(sendText[i]);
+
+ all.add(p);
+ all.add(sendButton);
+ }
+
+ display = new JLabel("");
+ display.setPreferredSize(new Dimension(100, 30));
+ display.setMinimumSize(new Dimension(100, 30));
+ display.setOpaque(true);
+ getContentPane().add(display, BorderLayout.NORTH);
+
+ // setSize(300, 200);
+ setLocationRelativeTo(null);
+ setDefaultCloseOperation(EXIT_ON_CLOSE);
+
+ pack();
+ setVisible(true);
+ }
+
+ public void setInitValues(String... values) {
+ for (int i = 0; i < values.length; i++) {
+ if (sendText[i].getText() == null || sendText[i].getText().isEmpty()) {
+ sendText[i].setText(values[i]);
+ }
+ }
+ }
+
+ private void sendText(int i) {
+ listener.typedText(i, getTypedText(i));
+ }
+
+ public void setListener(FormClient c) {
+ listener = c;
+ }
+
+ public String getTypedText(int i) {
+ return sendText[i].getText();
+ }
+
+ public void setText(String text) {
+ display.setText(text);
+ }
+
+ public void setColor(Color bg) {
+ display.setBackground(bg);
+ }
+
+ class MultiListener implements KeyListener, ActionListener {
+ private int i;
+
+ public MultiListener(int i) {
+ this.i = i;
+ }
+
+ @Override
+ public void keyTyped(KeyEvent e) {
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_ENTER)
+ sendText(i);
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ sendText(i);
+ }
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormServer.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormServer.java
new file mode 100644
index 0000000..3789a9a
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormServer.java
@@ -0,0 +1,105 @@
+package dream.examples.form.complete_glitchfree;
+
+import java.util.logging.Level;
+
+import dream.client.DreamClient;
+import dream.client.RemoteVar;
+import dream.client.Signal;
+import dream.examples.util.Pair;
+
+public class FormServer extends LockClient {
+
+ protected RemoteVar working_hours;
+ protected RemoteVar euro_per_hour;
+ protected RemoteVar> required_hours;
+
+ public static final String NAME = "FormServer";
+ public static final String MinimumHours = "minimumHours";
+ public static final String MaximumHours = "maximumHours";
+ public static final String MinimumEuroPerHour = "minimumEuroPerHour";
+ public static final String SettingsOkay = "settingsOkay";
+ public static final String Salary = "salary";
+
+ public FormServer() {
+ super(NAME);
+ detectNewSession();
+ }
+
+ /**
+ * Look for new clients every 5 seconds
+ */
+ private void detectNewSession() {
+ while (euro_per_hour == null || working_hours == null || required_hours == null) {
+ for (String str : DreamClient.instance.listVariables()) {
+ String host = str.split("@")[1];
+ String var = str.split("@")[0];
+ if (working_hours == null && var.equalsIgnoreCase(Secretary.WorkingHours)) {
+ working_hours = new RemoteVar<>(host, var);
+ logger.fine("Found Secretary");
+ } else if (euro_per_hour == null && var.equalsIgnoreCase(Boss.EuroPerHour)) {
+ euro_per_hour = new RemoteVar<>(host, var);
+ logger.fine("Found Boss");
+ } else if (required_hours == null && var.equalsIgnoreCase(Boss.RequiredHours)) {
+ required_hours = new RemoteVar<>(host, var);
+ logger.fine("Found Boss");
+ }
+ }
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ logger.log(Level.SEVERE, "Failed to sleep for 0.5 seconds", e);
+ }
+ }
+ createDependencies();
+ }
+
+ protected void createDependencies() {
+ logger.fine("Building Dependencies");
+
+ final Signal minimumHours = new Signal<>(MinimumHours, () -> {
+ if (working_hours.get() != null && required_hours.get() != null)
+ return working_hours.get() > required_hours.get().getFirst();
+ else
+ return false;
+ }, working_hours, required_hours);
+
+ final Signal maximumHours = new Signal<>(MaximumHours, () -> {
+ if (working_hours.get() != null && required_hours.get() != null)
+ return working_hours.get() < required_hours.get().getSecond();
+ else
+ return false;
+ }, working_hours, required_hours);
+
+ final Signal minimumEuroPerHour = new Signal<>(MinimumEuroPerHour, () -> {
+ if (euro_per_hour.get() != null)
+ return euro_per_hour.get() > 10;
+ else
+ return false;
+ }, euro_per_hour);
+
+ new Signal<>(SettingsOkay, () -> {
+ if (minimumHours.get() != null && maximumHours.get() != null && minimumEuroPerHour.get() != null)
+ return minimumHours.get() && maximumHours.get() && minimumEuroPerHour.get();
+ else
+ return false;
+ }, minimumHours, maximumHours, minimumEuroPerHour);
+
+ new Signal<>(Salary, () -> {
+ if (working_hours.get() != null && euro_per_hour.get() != null)
+ return working_hours.get() * euro_per_hour.get();
+ else
+ return 0.0;
+ }, working_hours, euro_per_hour);
+
+ logger.fine("Finished building Dependencies");
+ }
+
+ public static void main(String[] args) {
+ new FormServer();
+ }
+
+ @Override
+ protected void setup() {
+ }
+
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/LockClient.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/LockClient.java
new file mode 100644
index 0000000..7b88796
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/LockClient.java
@@ -0,0 +1,80 @@
+package dream.examples.form.complete_glitchfree;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import dream.client.RemoteVar;
+import dream.client.Signal;
+import dream.client.Var;
+import dream.examples.util.Client;
+import dream.examples.util.Pair;
+
+public abstract class LockClient extends Client {
+ private boolean setup = false;
+ private Var lockRequest;
+ private List hasLock;
+
+ public LockClient(String name) {
+ super(name);
+
+ // Establish new session with LockManager
+ RemoteVar>> registeredClients = new RemoteVar<>(LockManager.NAME,
+ LockManager.VAR_clients);
+ Signal>> s = new Signal<>("s", () -> {
+ if (registeredClients.get() == null)
+ return new ArrayList>();
+ else
+ return registeredClients.get();
+ }, registeredClients);
+ s.change().addHandler((o, n) -> {
+ if (n.contains(new Pair<>(this.getHostName(), LockManager.VAR_requestLock)) && setup == false)
+ lockSetup();
+ });
+
+ hasLock = new ArrayList<>();
+ lockRequest = new Var<>(LockManager.VAR_requestLock, null);
+ logger.fine("Setup: Waiting for Registration to LockManager ...");
+ }
+
+ private void lockSetup() {
+ setup = true;
+ RemoteVar lock = new RemoteVar<>(LockManager.NAME, LockManager.VAR_lock);
+ Signal sLock = new Signal<>("lock", () -> {
+ return lock.get();
+ }, lock);
+ sLock.change().addHandler((oldValue, newValue) -> {
+ newValue.forEach((var, client) -> {
+ if (client.equals(getHostName()))
+ hasLock.add(var);
+ else
+ hasLock.remove(var);
+ });
+ synchronized (this) {
+ this.notify();
+ }
+ });
+
+ setup();
+ }
+
+ protected abstract void setup();
+
+ public void lock(Variable... vars) {
+ lockRequest.set(new LockRequest(getHostName(), vars));
+ synchronized (this) {
+ while (!hasLock.containsAll(Arrays.asList(vars))) {
+ try {
+ this.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public void unlock() {
+ lockRequest.set(new LockRequest(getHostName()));
+ }
+
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/LockManager.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/LockManager.java
new file mode 100644
index 0000000..d925fd0
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/LockManager.java
@@ -0,0 +1,224 @@
+package dream.examples.form.complete_glitchfree;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.logging.Level;
+
+import dream.client.DreamClient;
+import dream.client.RemoteVar;
+import dream.client.Signal;
+import dream.client.Var;
+import dream.common.utils.DependencyGraph;
+import dream.examples.util.Client;
+import dream.examples.util.Pair;
+
+public class LockManager extends Client {
+
+ public static final String VAR_lock = "lock";
+ public static final String VAR_requestLock = "requestLock";
+ public static final String VAR_clients = "clients";
+ public static final String NAME = "LockManager";
+
+ private Var lock;
+ private final Var> clients;
+ private LinkedList lockRequests;
+
+ public LockManager() {
+ super(NAME);
+ clients = new Var<>(VAR_clients, new ArrayList<>());
+ lock = new Var<>(VAR_lock, new Lock());
+ lockRequests = new LinkedList<>();
+ detectNewSession();
+ }
+
+ private void detectNewSession() {
+ Set vars = DreamClient.instance.listVariables();
+ vars.stream().map(x -> new Variable(x.split("@")[1], x.split("@")[0])).// Pair(Host,Var)
+ filter(x -> !clients.get().contains(x) && x.getVar().equalsIgnoreCase(VAR_requestLock)).//
+ forEach(x -> createNewSessionFor(x));
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ logger.log(Level.SEVERE, "Failed to sleep for 0.5 seconds", e);
+ }
+
+ detectNewSession();
+ }
+
+ private void createNewSessionFor(Variable x) {
+ RemoteVar rv = new RemoteVar<>(x.getHost(), x.getVar());
+ Signal s = new Signal<>(x.getHost() + "request", () -> {
+ if (rv.get() != null)
+ return rv.get();
+ else
+ return null;
+ }, rv);
+ s.change().addHandler((oldValue, newValue) -> {
+ if (newValue.isLockRequest()) {
+ // client requesting a lock
+ if (!lock.get().isLocked(newValue.getVars())) {
+ lock.set(new Lock(lock.get(), newValue));
+ } else {
+ // already locked, adding to queue
+ lockRequests.add(newValue);
+ }
+ } else {
+ // client trying to release a lock
+ lock.set(new Lock(lock.get(), newValue));
+ removeLockRequestsFor(x.getHost());
+ processNextRequest();
+ }
+ });
+ clients.modify(old -> old.add(x));
+ }
+
+ private void processNextRequest() {
+ for (LockRequest req : lockRequests) {
+ if (!lock.get().isLocked(req.getVars())) {
+ lock.set(new Lock(lock.get(), req));
+ lockRequests.remove(req);
+ break;
+ }
+ }
+ }
+
+ private void removeLockRequestsFor(String host) {
+ for (LockRequest req : lockRequests) {
+ if (req.getClient().equals(host)) {
+ lockRequests.remove(req);
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ new LockManager();
+ }
+}
+
+class Variable extends Pair {
+ private static final long serialVersionUID = 4689891891604406371L;
+
+ public Variable(String host, String var) {
+ super(host, var);
+ }
+
+ public String getHost() {
+ return getFirst();
+ }
+
+ public String getVar() {
+ return getSecond();
+ }
+
+ public static Variable get(Var> v) {
+ return new Variable(v.getHost(), v.getObject());
+ }
+
+ public static Variable fromDreamString(String s) {
+ String[] temp = s.split("@", 2);
+ return new Variable(temp[1], temp[0]);
+ }
+
+ public String toDreamString() {
+ return getVar() + "@" + getHost();
+ }
+
+ @Override
+ public String toString() {
+ return "Var" + super.toString();
+ }
+}
+
+class LockRequest implements Serializable {
+ private static final long serialVersionUID = -7166632148414861582L;
+ private CopyOnWriteArrayList vars;
+ private String client;
+
+ public LockRequest(String client, Variable... vars) {
+ this.vars = new CopyOnWriteArrayList<>();
+ this.vars.addAll(Arrays.asList(vars));
+ this.client = client;
+
+ computeDependencies();
+ }
+
+ private void computeDependencies() {
+ Map> nodes = new HashMap<>();
+ DependencyGraph.instance.getGraph().forEach((v1, v2) -> {
+ Collection t = new LinkedList<>();
+ v2.forEach(x -> t.add(Variable.fromDreamString(x)));
+ nodes.put(Variable.fromDreamString(v1), t);
+ });
+ for (Variable v : vars) {
+ computeDependencies(nodes, v);
+ }
+ }
+
+ private void computeDependencies(Map> nodes, Variable v) {
+ nodes.forEach((v1, v2) -> {
+ if (v2.contains(v) && !vars.contains(v1)) {
+ // v1 depends on v
+ this.vars.add(v1);
+ computeDependencies(nodes, v1);
+ }
+ });
+ }
+
+ public Variable[] getVars() {
+ return vars.toArray(new Variable[] {});
+ }
+
+ public String getClient() {
+ return client;
+ }
+
+ public boolean isLockRequest() {
+ return vars.size() > 0;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ if (isLockRequest())
+ sb.append("LockRequest(").append(client).append("->").append(vars).append(")");
+ else
+ sb.append("LockRelease()");
+ return sb.toString();
+ }
+}
+
+class Lock extends HashMap {
+ private static final long serialVersionUID = -4195570287637533298L;
+
+ public Lock() {
+
+ }
+
+ public Lock(Lock lock, LockRequest req) {
+ this.putAll(lock);
+ if (!req.isLockRequest()) {
+ // lock release
+ for (Iterator k = keySet().iterator(); k.hasNext();) {
+ if (get(k.next()).equals(req.getClient()))
+ k.remove();
+ }
+ } else {
+ for (int i = 0; i < req.getVars().length; i++) {
+ put(req.getVars()[i], req.getClient());
+ }
+ }
+ }
+
+ public boolean isLocked(Variable[] vars) {
+ return Arrays.asList(vars).stream().anyMatch(x -> containsKey(x));
+ }
+
+}
\ No newline at end of file
diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/Secretary.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/Secretary.java
new file mode 100644
index 0000000..638968e
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/Secretary.java
@@ -0,0 +1,34 @@
+package dream.examples.form.complete_glitchfree;
+
+import dream.client.Var;
+
+public class Secretary extends FormClient {
+
+ public static final String NAME = "Secretary";
+ public static final String WorkingHours = "working_hours";
+
+ private Var wh;
+
+ public Secretary() {
+ super(NAME, "Working Hours");
+ setInitValues(Integer.toString(5));
+ }
+
+ @Override
+ protected void init() {
+ wh = new Var<>(WorkingHours, 5);
+ }
+
+ @Override
+ public void typedText(int i, String typedText) {
+ Integer value = Integer.valueOf(typedText);
+ lock(Variable.get(wh));
+ wh.set(value);
+ unlock();
+ logger.fine("Set Working_Hours to " + value);
+ }
+
+ public static void main(String[] args) {
+ new Secretary();
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/complete_glitchfree_graph.png b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/complete_glitchfree_graph.png
new file mode 100644
index 0000000..2381fa5
Binary files /dev/null and b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/complete_glitchfree_graph.png differ
diff --git a/Dream2/src/examples/java/dream/examples/form/core/FormClient.java b/Dream2/src/examples/java/dream/examples/form/core/FormClient.java
new file mode 100644
index 0000000..dd77f4d
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/core/FormClient.java
@@ -0,0 +1,67 @@
+package dream.examples.form.core;
+
+import java.awt.Color;
+import java.util.Arrays;
+import java.util.List;
+
+import dream.client.RemoteVar;
+import dream.client.Signal;
+import dream.examples.util.Client;
+
+public abstract class FormClient extends Client {
+
+ private RemoteVar salary;
+ private RemoteVar settings;
+ private Signal remoteSalary;
+ private Signal remoteSettings;
+
+ private FormGUI gui;
+ private String[] labelText;
+ private String[] values;
+
+ public FormClient(String name, String... labelText) {
+ super(name);
+ this.labelText = labelText;
+ }
+
+ @Override
+ protected List waitForVars() {
+ return Arrays.asList(toVar(FormServer.NAME, FormServer.Salary),
+ toVar(FormServer.NAME, FormServer.SettingsOkay));
+ }
+
+ protected void start() {
+ gui = new FormGUI(getHostName(), labelText);
+ gui.setListener(this);
+ if (values != null)
+ gui.setInitValues(values);
+
+ salary = new RemoteVar<>(FormServer.NAME, FormServer.Salary);
+ settings = new RemoteVar<>(FormServer.NAME, FormServer.SettingsOkay);
+
+ remoteSalary = new Signal<>("remoteSalary", () -> {
+ if (salary.get() != null)
+ return salary.get();
+ else
+ return 0.0;
+ }, salary);
+
+ remoteSettings = new Signal<>("remoteSettings", () -> {
+ if (settings.get() != null)
+ return settings.get();
+ else
+ return false;
+ }, settings);
+
+ gui.setText("Salary: ");
+ gui.setColor(Color.red);
+ remoteSalary.change().addHandler((o, n) -> gui.setText("Salary: " + n.toString()));
+ remoteSettings.change().addHandler((o, n) -> gui.setColor((n ? Color.green : Color.red)));
+ }
+
+ public abstract void typedText(int i, String typedText);
+
+ public void setInitValues(String... values) {
+ this.values = values;
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/core/FormGUI.java b/Dream2/src/examples/java/dream/examples/form/core/FormGUI.java
new file mode 100644
index 0000000..3e91cc7
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/core/FormGUI.java
@@ -0,0 +1,124 @@
+package dream.examples.form.core;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+public class FormGUI extends JFrame {
+
+ private static final long serialVersionUID = 9205614575242281482L;
+ private JTextField[] sendText;
+ private FormClient listener;
+ private JLabel display;
+ private String[] labelText;
+
+ public FormGUI(String name, String... labelText) {
+ setTitle(name);
+ this.labelText = labelText;
+ initUI();
+ }
+
+ private void initUI() {
+ getContentPane().setLayout(new BorderLayout());
+ JPanel all = new JPanel();
+ all.setLayout(new GridLayout(0, 2));
+ getContentPane().add(all, BorderLayout.CENTER);
+
+ sendText = new JTextField[labelText.length];
+
+ for (int i = 0; i < labelText.length; i++) {
+ sendText[i] = new JTextField(20);
+ sendText[i].addKeyListener(new MultiListener(i));
+ JButton sendButton = new JButton("Set");
+ sendButton.addActionListener(new MultiListener(i));
+
+ JLabel label = new JLabel(labelText[i] + ": ");
+
+ JPanel p = new JPanel();
+ p.add(label);
+ p.add(sendText[i]);
+
+ all.add(p);
+ all.add(sendButton);
+ }
+
+ display = new JLabel("");
+ display.setPreferredSize(new Dimension(100, 30));
+ display.setMinimumSize(new Dimension(100, 30));
+ display.setOpaque(true);
+ getContentPane().add(display, BorderLayout.NORTH);
+
+ // setSize(300, 200);
+ setLocationRelativeTo(null);
+ setDefaultCloseOperation(EXIT_ON_CLOSE);
+
+ pack();
+ setVisible(true);
+ }
+
+ public void setInitValues(String... values) {
+ for (int i = 0; i < values.length; i++) {
+ if (sendText[i].getText() == null || sendText[i].getText().isEmpty()) {
+ sendText[i].setText(values[i]);
+ }
+ }
+ }
+
+ private void sendText(int i) {
+ listener.typedText(i, getTypedText(i));
+ }
+
+ public void setListener(FormClient c) {
+ listener = c;
+ }
+
+ public String getTypedText(int i) {
+ return sendText[i].getText();
+ }
+
+ public void setText(String text) {
+ display.setText(text);
+ }
+
+ public void setColor(Color bg) {
+ display.setBackground(bg);
+ }
+
+ class MultiListener implements KeyListener, ActionListener {
+ private int i;
+
+ public MultiListener(int i) {
+ this.i = i;
+ }
+
+ @Override
+ public void keyTyped(KeyEvent e) {
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_ENTER)
+ sendText(i);
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ sendText(i);
+ }
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/core/FormServer.java b/Dream2/src/examples/java/dream/examples/form/core/FormServer.java
new file mode 100644
index 0000000..ea9795f
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/core/FormServer.java
@@ -0,0 +1,25 @@
+package dream.examples.form.core;
+
+import dream.client.RemoteVar;
+import dream.examples.util.Client;
+
+public class FormServer extends Client {
+
+ public static final String NAME = "FormServer";
+ public static final String MinimumHours = "minimumHours";
+ public static final String MaximumHours = "maximumHours";
+ public static final String MinimumEuroPerHour = "minimumEuroPerHour";
+ public static final String SettingsOkay = "settingsOkay";
+ public static final String Salary = "salary";
+
+ protected RemoteVar working_hours;
+ protected RemoteVar euro_per_hour;
+
+ public FormServer() {
+ super(NAME);
+ }
+
+ public static void main(String[] args) {
+ new FormServer();
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/graph2.png b/Dream2/src/examples/java/dream/examples/form/graph2.png
new file mode 100644
index 0000000..195cccc
Binary files /dev/null and b/Dream2/src/examples/java/dream/examples/form/graph2.png differ
diff --git a/Dream2/src/examples/java/dream/examples/form/line-count-advanced-complete-glitch-freedom.txt b/Dream2/src/examples/java/dream/examples/form/line-count-advanced-complete-glitch-freedom.txt
new file mode 100644
index 0000000..14deb29
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/line-count-advanced-complete-glitch-freedom.txt
@@ -0,0 +1,17 @@
+complete_glitchfree/Boss.java
+complete_glitchfree/Secretary.java
+complete_glitchfree/FormClient.java
+complete_glitchfree/FormGUI.java
+complete_glitchfree/FormServer.java
+complete_glitchfree/LockClient.java
+complete_glitchfree/CompleteGlitchFreeFormServer.java
+complete_glitchfree/LockManager.java
+
+http://cloc.sourceforge.net v 1.64 T=0.03 s (314.6 files/s, 29496.1 lines/s)
+-------------------------------------------------------------------------------
+Language files blank comment code
+-------------------------------------------------------------------------------
+Java 8 132 11 607
+-------------------------------------------------------------------------------
+SUM: 8 132 11 607
+-------------------------------------------------------------------------------
diff --git a/Dream2/src/examples/java/dream/examples/form/line-count-advanced-dream.txt b/Dream2/src/examples/java/dream/examples/form/line-count-advanced-dream.txt
new file mode 100644
index 0000000..9ba9b2d
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/line-count-advanced-dream.txt
@@ -0,0 +1,14 @@
+complete_glitchfree/Boss.java
+complete_glitchfree/Secretary.java
+complete_glitchfree/FormClient.java
+complete_glitchfree/FormGUI.java
+complete_glitchfree/FormServer.java
+
+http://cloc.sourceforge.net v 1.64 T=0.02 s (263.4 files/s, 20755.3 lines/s)
+-------------------------------------------------------------------------------
+Language files blank comment code
+-------------------------------------------------------------------------------
+Java 5 76 4 314
+-------------------------------------------------------------------------------
+SUM: 5 76 4 314
+-------------------------------------------------------------------------------
diff --git a/Dream2/src/examples/java/dream/examples/form/line-count-simple-dream.txt b/Dream2/src/examples/java/dream/examples/form/line-count-simple-dream.txt
new file mode 100644
index 0000000..35c620c
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/line-count-simple-dream.txt
@@ -0,0 +1,14 @@
+Counted files:
+core
+simple/Boss.java
+simple/Secretary.java
+simple/FormServer.java
+
+http://cloc.sourceforge.net v 1.64 T=0.02 s (295.7 files/s, 18678.1 lines/s)
+-------------------------------------------------------------------------------
+Language files blank comment code
+-------------------------------------------------------------------------------
+Java 6 78 4 297
+-------------------------------------------------------------------------------
+SUM: 6 78 4 297
+-------------------------------------------------------------------------------
diff --git a/Dream2/src/examples/java/dream/examples/form/line-count-simple-single-glitch-freedom.txt b/Dream2/src/examples/java/dream/examples/form/line-count-simple-single-glitch-freedom.txt
new file mode 100644
index 0000000..47cfd91
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/line-count-simple-single-glitch-freedom.txt
@@ -0,0 +1,15 @@
+Counted Files:
+core
+simple/Boss.java
+simple/Secretary.java
+simple/FormServer.java
+simple/GlitchFreeFormServer.java
+
+http://cloc.sourceforge.net v 1.64 T=0.03 s (279.9 files/s, 17590.9 lines/s)
+-------------------------------------------------------------------------------
+Language files blank comment code
+-------------------------------------------------------------------------------
+Java 7 93 4 343
+-------------------------------------------------------------------------------
+SUM: 7 93 4 343
+-------------------------------------------------------------------------------
diff --git a/Dream2/src/examples/java/dream/examples/form/package-info.java b/Dream2/src/examples/java/dream/examples/form/package-info.java
new file mode 100644
index 0000000..14f2b0c
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/package-info.java
@@ -0,0 +1,21 @@
+/**
+ * This packages contains two examples:
+ * a) {@link dream.examples.form.simple simple}: uses a simple graph with a
+ * probable glitch. There are two different solutions to this glitch:
+ * {@link dream.examples.form.simple.FormServer FormServer} depending on Dream's
+ * single_glitch_free consistency to solve the glitch and
+ * {@link dream.examples.form.simple.GlitchFreeFormServer GlitchFreeFormServer},
+ * which ensures itself that no glitch can occur.
+ *
+ * b) {@link dream.examples.form.complete_glitchfree complete} uses a different
+ * graph, which requires a locking mechanism.
+ * {@link dream.examples.form.complete_glitchfree.CompleteGlitchFreeFormServer
+ * CompleteGlitchFreeFormServer}, which ensures complete_glitch_freedom itself
+ * with a own locking mechanism.
+ *
+ *
+ * Both examples contain an image of their used dependency graph
+ *
+ * @author Tobias Becker
+ */
+package dream.examples.form;
\ No newline at end of file
diff --git a/Dream2/src/examples/java/dream/examples/form/simple/Boss.java b/Dream2/src/examples/java/dream/examples/form/simple/Boss.java
new file mode 100644
index 0000000..c21fd78
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/simple/Boss.java
@@ -0,0 +1,41 @@
+package dream.examples.form.simple;
+
+import dream.client.Var;
+import dream.examples.form.core.FormClient;
+
+public class Boss extends FormClient {
+
+ public static final String NAME = "Boss";
+ public static final String EuroPerHour = "euro_per_hour";
+
+ protected Var eph;
+
+ public Boss() {
+ super(NAME, "Euro/Hour");
+ setInitValues(Double.toString(8.5));
+ }
+
+ @Override
+ protected void init() {
+ eph = new Var<>(EuroPerHour, 8.5);
+ }
+
+ @Override
+ public void typedText(int i, String typedText) {
+ switch (i) {
+ case 0:
+ Double value = Double.valueOf(typedText);
+ eph.set(value);
+ logger.fine("Set Euro_Per_Hour to " + value);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ public static void main(String[] args) {
+ Boss b = new Boss();
+ b.start();
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/simple/FormServer.java b/Dream2/src/examples/java/dream/examples/form/simple/FormServer.java
new file mode 100644
index 0000000..3a56c02
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/simple/FormServer.java
@@ -0,0 +1,87 @@
+package dream.examples.form.simple;
+
+import java.util.logging.Level;
+
+import dream.client.DreamClient;
+import dream.client.RemoteVar;
+import dream.client.Signal;
+
+public class FormServer extends dream.examples.form.core.FormServer {
+
+ protected RemoteVar working_hours;
+ protected RemoteVar euro_per_hour;
+
+ public FormServer() {
+ detectNewSession();
+ }
+
+ /**
+ * Look for new clients every 5 seconds
+ */
+ private void detectNewSession() {
+ while (euro_per_hour == null || working_hours == null) {
+ for (String str : DreamClient.instance.listVariables()) {
+ String host = str.split("@")[1];
+ String var = str.split("@")[0];
+ if (working_hours == null && var.equalsIgnoreCase(Secretary.WorkingHours)) {
+ working_hours = new RemoteVar<>(host, var);
+ logger.fine("Found Secretary");
+ } else if (euro_per_hour == null && var.equalsIgnoreCase(Boss.EuroPerHour)) {
+ euro_per_hour = new RemoteVar<>(host, var);
+ logger.fine("Found Boss");
+ }
+ }
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ logger.log(Level.SEVERE, "Failed to sleep for 0.5 seconds", e);
+ }
+ }
+ createDependencies();
+ }
+
+ protected void createDependencies() {
+ logger.fine("Building Dependencies");
+
+ final Signal minimumHours = new Signal<>(MinimumHours, () -> {
+ if (working_hours.get() != null)
+ return working_hours.get() > 10;
+ else
+ return false;
+ }, working_hours);
+
+ final Signal maximumHours = new Signal<>(MaximumHours, () -> {
+ if (working_hours.get() != null)
+ return working_hours.get() < 60;
+ else
+ return false;
+ }, working_hours);
+
+ final Signal minimumEuroPerHour = new Signal<>(MinimumEuroPerHour, () -> {
+ if (euro_per_hour.get() != null)
+ return euro_per_hour.get() > 10;
+ else
+ return false;
+ }, euro_per_hour);
+
+ new Signal<>(SettingsOkay, () -> {
+ if (minimumHours.get() != null && maximumHours.get() != null && minimumEuroPerHour.get() != null)
+ return minimumHours.get() && maximumHours.get() && minimumEuroPerHour.get();
+ else
+ return false;
+ }, minimumHours, maximumHours, minimumEuroPerHour);
+
+ new Signal<>(Salary, () -> {
+ if (working_hours.get() != null && euro_per_hour.get() != null)
+ return working_hours.get() * euro_per_hour.get();
+ else
+ return 0.0;
+ }, working_hours, euro_per_hour);
+
+ logger.fine("Finished building Dependencies");
+ }
+
+ public static void main(String[] args) {
+ new FormServer();
+ }
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/simple/GlitchFreeFormServer.java b/Dream2/src/examples/java/dream/examples/form/simple/GlitchFreeFormServer.java
new file mode 100644
index 0000000..d98caab
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/simple/GlitchFreeFormServer.java
@@ -0,0 +1,61 @@
+package dream.examples.form.simple;
+
+import java.util.LinkedList;
+
+import dream.client.Signal;
+import dream.client.Var;
+
+public class GlitchFreeFormServer extends FormServer {
+
+ final LinkedList minimumQueue = new LinkedList<>();
+ final LinkedList maximumQueue = new LinkedList<>();
+ final Var settingsOkay = new Var<>(SettingsOkay, false);
+ Signal minimumEuroPerHour;
+
+ private void updateSettingsOkay() {
+ if (minimumQueue.size() > 0 && maximumQueue.size() > 0 && minimumEuroPerHour.get() != null)
+ settingsOkay.set(minimumQueue.pop() && maximumQueue.pop() && minimumEuroPerHour.get());
+ }
+
+ @Override
+ protected void createDependencies() {
+ logger.fine("Building Dependencies");
+
+ minimumEuroPerHour = new Signal<>(MinimumEuroPerHour, () -> {
+ return euro_per_hour.get() > 10;
+ }, euro_per_hour);
+
+ final Signal minimumHours = new Signal<>(MinimumHours, () -> {
+ return working_hours.get() > 10;
+ }, working_hours);
+
+ final Signal maximumHours = new Signal<>(MaximumHours, () -> {
+ return working_hours.get() < 60;
+ }, working_hours);
+
+ minimumEuroPerHour.change().addHandler((o, n) -> updateSettingsOkay());
+
+ minimumHours.change().addHandler((o, n) -> {
+ minimumQueue.add(n);
+ updateSettingsOkay();
+ });
+
+ maximumHours.change().addHandler((o, n) -> {
+ maximumQueue.add(n);
+ updateSettingsOkay();
+ });
+
+ new Signal<>(Salary, () -> {
+ if (working_hours.get() != null && euro_per_hour.get() != null)
+ return working_hours.get() * euro_per_hour.get();
+ else
+ return 0.0;
+ }, working_hours, euro_per_hour);
+
+ logger.fine("Finished building Dependencies");
+ }
+
+ public static void main(String[] args) {
+ new GlitchFreeFormServer();
+ }
+}
\ No newline at end of file
diff --git a/Dream2/src/examples/java/dream/examples/form/simple/Secretary.java b/Dream2/src/examples/java/dream/examples/form/simple/Secretary.java
new file mode 100644
index 0000000..b10e312
--- /dev/null
+++ b/Dream2/src/examples/java/dream/examples/form/simple/Secretary.java
@@ -0,0 +1,35 @@
+package dream.examples.form.simple;
+
+import dream.client.Var;
+import dream.examples.form.core.FormClient;
+
+public class Secretary extends FormClient {
+
+ public static final String NAME = "Secretary";
+ public static final String WorkingHours = "working_hours";
+
+ private Var wh;
+
+ public Secretary() {
+ super(NAME, "Working Hours");
+ setInitValues(Integer.toString(5));
+ }
+
+ @Override
+ protected void init() {
+ wh = new Var<>(WorkingHours, 5);
+ }
+
+ @Override
+ public void typedText(int i, String typedText) {
+ Integer value = Integer.valueOf(typedText);
+ wh.set(value);
+ logger.fine("Set Working_Hours to " + value);
+ }
+
+ public static void main(String[] args) {
+ Secretary s = new Secretary();
+ s.start();
+ }
+
+}
diff --git a/Dream2/src/examples/java/dream/examples/form/simple/graph.png b/Dream2/src/examples/java/dream/examples/form/simple/graph.png
new file mode 100644
index 0000000..c2275dc
Binary files /dev/null and b/Dream2/src/examples/java/dream/examples/form/simple/graph.png differ
diff --git a/Dream2/src/examples/java/dream/examples/local/Example1.java b/Dream2/src/examples/java/dream/examples/local/Example1.java
index 77d7626..03f0632 100755
--- a/Dream2/src/examples/java/dream/examples/local/Example1.java
+++ b/Dream2/src/examples/java/dream/examples/local/Example1.java
@@ -5,34 +5,41 @@
public class Example1 {
- public static void main(String args[]) {
- final Var varInt = new Var<>("varInt", 1);
- final Var varDouble = new Var<>("varDouble", 1.0);
- final Var varBool = new Var<>("varBool", false);
- final Var varString1 = new Var<>("varString1", "");
- final Var varString2 = new Var<>("varString2", "");
-
- final Signal signalInt = new Signal("signalInt", () -> 10 - 2 + (varInt.get() * 2 + varInt.get()) / 2, varInt);
- final Signal signalDouble = new Signal("signalDouble", () -> varDouble.get() + varDouble.get() * 2, varDouble);
- final Signal signalBool = new Signal("signalBool", () -> !varBool.get(), varBool);
- final Signal signalString = new Signal("signalString", () -> varString1.get() + varString2.get(), varString1, varString2);
-
- signalInt.addValueChangeListener(val -> System.out.println("signalInt: " + val + " (correct value: 158)"));
- signalDouble.addValueChangeListener(val -> System.out.println("signalDouble: " + val + " (correct value: 4.8)"));
- signalBool.addValueChangeListener(val -> System.out.println("signalBool: " + val + " (correct value: false)"));
- signalString.addValueChangeListener(val -> System.out.println("signalString: " + val + " (correct value: Hello World!)"));
-
- try {
- Thread.sleep(500);
- } catch (final InterruptedException e) {
- e.printStackTrace();
- }
-
- varInt.set(100);
- varDouble.set(1.6);
- varBool.set(true);
- varString1.set("Hello ");
- varString2.set("World!");
-
- }
+ public static void main(String args[]) {
+ final Var varInt = new Var<>("varInt", 1);
+ final Var varDouble = new Var<>("varDouble", 1.0);
+ final Var varBool = new Var<>("varBool", false);
+ final Var varString1 = new Var<>("varString1", "");
+ final Var varString2 = new Var<>("varString2", "");
+
+ final Signal signalInt = new Signal("signalInt",
+ () -> 10 - 2 + (varInt.get() * 2 + varInt.get()) / 2, varInt);
+ final Signal signalDouble = new Signal("signalDouble",
+ () -> varDouble.get() + varDouble.get() * 2, varDouble);
+ final Signal signalBool = new Signal("signalBool", () -> !varBool.get(), varBool);
+ final Signal signalString = new Signal("signalString",
+ () -> varString1.get() + varString2.get(), varString1, varString2);
+
+ signalInt.change()
+ .addHandler((oldVal, val) -> System.out.println("signalInt: " + val + " (correct value: 158)"));
+ signalDouble.change()
+ .addHandler((oldVal, val) -> System.out.println("signalDouble: " + val + " (correct value: 4.8)"));
+ signalBool.change()
+ .addHandler((oldVal, val) -> System.out.println("signalBool: " + val + " (correct value: false)"));
+ signalString.change().addHandler(
+ (oldVal, val) -> System.out.println("signalString: " + val + " (correct value: Hello World!)"));
+
+ try {
+ Thread.sleep(500);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ varInt.set(100);
+ varDouble.set(1.6);
+ varBool.set(true);
+ varString1.set("Hello ");
+ varString2.set("World!");
+
+ }
}
diff --git a/Dream2/src/examples/java/dream/examples/local/ExampleFilter.java b/Dream2/src/examples/java/dream/examples/local/ExampleFilter.java
index e3ff1f5..22292e2 100644
--- a/Dream2/src/examples/java/dream/examples/local/ExampleFilter.java
+++ b/Dream2/src/examples/java/dream/examples/local/ExampleFilter.java
@@ -4,32 +4,34 @@
import dream.client.Var;
public class ExampleFilter {
- public static void main(String args[]) {
-
- final Var varInt = new Var<>("varInt", 1);
- final Signal signalInt = new Signal<>("signalInt", () -> varInt.get() + 1, varInt.filter(val -> val > 10));
- final Signal signalInt2 = new Signal<>("signalInt2", () -> signalInt.get() + 1, signalInt.filter(val -> val > 20));
-
- signalInt.addValueChangeListener(val -> System.out.println("SignalInt: " + val));
- signalInt2.addValueChangeListener(val -> System.out.println("SignalInt2: " + val));
-
- try {
- Thread.sleep(500);
- } catch (final InterruptedException e) {
- e.printStackTrace();
- }
-
- System.out.println("Expected results:");
- System.out.println("SignalInt: 12");
- System.out.println("SignalInt: 21");
- System.out.println("SignalInt2: 22");
- System.out.println();
-
- varInt.set(1);
- varInt.set(2);
- varInt.set(11);
- varInt.set(20);
- varInt.set(10);
-
- }
+ public static void main(String args[]) {
+
+ final Var varInt = new Var<>("varInt", 1);
+ final Signal signalInt = new Signal<>("signalInt", () -> varInt.get() + 1,
+ varInt.filter(val -> val > 10));
+ final Signal signalInt2 = new Signal<>("signalInt2", () -> signalInt.get() + 1,
+ signalInt.filter(val -> val > 20));
+
+ signalInt.change().addHandler((oldVal, val) -> System.out.println("SignalInt: " + val));
+ signalInt2.change().addHandler((oldVal, val) -> System.out.println("SignalInt2: " + val));
+
+ try {
+ Thread.sleep(500);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ System.out.println("Expected results:");
+ System.out.println("SignalInt: 12");
+ System.out.println("SignalInt: 21");
+ System.out.println("SignalInt2: 22");
+ System.out.println();
+
+ varInt.set(1);
+ varInt.set(2);
+ varInt.set(11);
+ varInt.set(20);
+ varInt.set(10);
+
+ }
}
diff --git a/Dream2/src/examples/java/dream/examples/local/ExampleGlitch.java b/Dream2/src/examples/java/dream/examples/local/ExampleGlitch.java
index c050628..70fe13b 100755
--- a/Dream2/src/examples/java/dream/examples/local/ExampleGlitch.java
+++ b/Dream2/src/examples/java/dream/examples/local/ExampleGlitch.java
@@ -5,45 +5,45 @@
public class ExampleGlitch {
- public static void main(String args[]) {
- final ExampleGlitch example = new ExampleGlitch();
- example.launch();
- }
-
- public void launch() {
- final Var var = new Var<>("var", 1.0);
-
- final Signal mid1 = new Signal<>("mid1", () -> var.get() * 2, var);
- final Signal mid2 = new Signal<>("mid2", () -> var.get() * 3, var);
-
- final Signal finalResult = new Signal<>("final", () -> mid1.get() + mid2.get(), mid1, mid2);
- finalResult.addValueChangeListener(System.out::println);
-
- try {
- Thread.sleep(500);
- } catch (final InterruptedException e) {
- e.printStackTrace();
- }
-
- final double v1 = 10;
- final double v2 = 20;
- final double v3 = 30;
-
- System.out.println("Expected values (with glitch freedom): ");
- System.out.println("1) " + (v1 * 2 + v1 * 3));
- System.out.println("2) " + (v2 * 2 + v2 * 3));
- System.out.println("3) " + (v3 * 2 + v3 * 3));
-
- try {
- Thread.sleep(500);
- } catch (final InterruptedException e) {
- e.printStackTrace();
- }
-
- var.set(v1);
- var.set(v2);
- var.set(v3);
-
- }
+ public static void main(String args[]) {
+ final ExampleGlitch example = new ExampleGlitch();
+ example.launch();
+ }
+
+ public void launch() {
+ final Var var = new Var<>("var", 1.0);
+
+ final Signal mid1 = new Signal<>("mid1", () -> var.get() * 2, var);
+ final Signal mid2 = new Signal<>("mid2", () -> var.get() * 3, var);
+
+ final Signal finalResult = new Signal<>("final", () -> mid1.get() + mid2.get(), mid1, mid2);
+ finalResult.change().addHandler((oldVal, val) -> System.out.println(val));
+
+ try {
+ Thread.sleep(500);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ final double v1 = 10;
+ final double v2 = 20;
+ final double v3 = 30;
+
+ System.out.println("Expected values (with glitch freedom): ");
+ System.out.println("1) " + (v1 * 2 + v1 * 3));
+ System.out.println("2) " + (v2 * 2 + v2 * 3));
+ System.out.println("3) " + (v3 * 2 + v3 * 3));
+
+ try {
+ Thread.sleep(500);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ var.set(v1);
+ var.set(v2);
+ var.set(v3);
+
+ }
}
diff --git a/Dream2/src/examples/java/dream/examples/local/ExampleList.java b/Dream2/src/examples/java/dream/examples/local/ExampleList.java
index cd934ed..4e8aa67 100755
--- a/Dream2/src/examples/java/dream/examples/local/ExampleList.java
+++ b/Dream2/src/examples/java/dream/examples/local/ExampleList.java
@@ -7,32 +7,32 @@
public class ExampleList {
- public static void main(String args[]) {
- final Var> varList = new Var<>("varList", new ArrayList());
- final Signal signalInt = new Signal("signalInt", () -> 1000 + varList.get().size(), varList);
-
- signalInt.addValueChangeListener(System.out::println);
-
- System.out.println("Expected results: ");
- System.out.println(1001);
- System.out.println(1002);
- System.out.println(1003);
- System.out.println(1002);
- System.out.println(1000);
- System.out.println();
-
- try {
- Thread.sleep(500);
- } catch (final InterruptedException e) {
- e.printStackTrace();
- }
-
- varList.modify(self -> self.add(10));
- varList.modify(self -> self.add(20));
- varList.modify(self -> self.add(30));
- varList.modify(self -> self.remove(1));
- varList.modify(self -> self.clear());
-
- }
+ public static void main(String args[]) {
+ final Var> varList = new Var<>("varList", new ArrayList());
+ final Signal signalInt = new Signal("signalInt", () -> 1000 + varList.get().size(), varList);
+
+ signalInt.change().addHandler((oldVal, val) -> System.out.println(val));
+
+ System.out.println("Expected results: ");
+ System.out.println(1001);
+ System.out.println(1002);
+ System.out.println(1003);
+ System.out.println(1002);
+ System.out.println(1000);
+ System.out.println();
+
+ try {
+ Thread.sleep(500);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ varList.modify(self -> self.add(10));
+ varList.modify(self -> self.add(20));
+ varList.modify(self -> self.add(30));
+ varList.modify(self -> self.remove(1));
+ varList.modify(self -> self.clear());
+
+ }
}
diff --git a/Dream2/src/examples/java/dream/examples/remote/RemoteSignalExample.java b/Dream2/src/examples/java/dream/examples/remote/RemoteSignalExample.java
index 82dbfe4..9d3eeee 100755
--- a/Dream2/src/examples/java/dream/examples/remote/RemoteSignalExample.java
+++ b/Dream2/src/examples/java/dream/examples/remote/RemoteSignalExample.java
@@ -1,7 +1,7 @@
package dream.examples.remote;
+import java.util.ArrayList;
import java.util.HashSet;
-import java.util.LinkedList;
import java.util.Set;
import dream.client.DreamClient;
@@ -11,38 +11,41 @@
public class RemoteSignalExample {
- public static void main(String args[]) {
- Consts.hostName = "Signal";
-
- final DreamClient client = DreamClient.instance;
- client.connect();
-
- final Set relevantRemoteVars = new HashSet<>();
- relevantRemoteVars.add("remoteInt@Remote");
- relevantRemoteVars.add("remoteString1@Remote");
- relevantRemoteVars.add("remoteString2@Remote");
- relevantRemoteVars.add("remoteList@Remote");
- while (!client.listVariables().containsAll(relevantRemoteVars)) {
- try {
- Thread.sleep(100);
- } catch (final InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- final RemoteVar remoteInt = new RemoteVar("Remote", "remoteInt");
- final RemoteVar remoteString1 = new RemoteVar("Remote", "remoteString1");
- final RemoteVar remoteString2 = new RemoteVar("Remote", "remoteString2");
- final RemoteVar> remoteList = new RemoteVar<>("Remote", "remoteList");
-
- final Signal signal1 = new Signal("signal1", () -> remoteInt.get() + remoteString1.get().length(), remoteInt, remoteString1);
- final Signal signal2 = new Signal("signal2", () -> remoteInt.get(), remoteInt);
- final Signal signal3 = new Signal("signal3", () -> remoteString1.get() + remoteString2.get(), remoteString1, remoteString2);
- final Signal signal4 = new Signal("signal4", () -> remoteString1.get().length() + remoteList.get().size(), remoteString1, remoteList);
-
- signal1.addValueChangeListener(val -> System.out.println("Signal1: " + val));
- signal2.addValueChangeListener(val -> System.out.println("Signal2: " + val));
- signal3.addValueChangeListener(val -> System.out.println("Signal3: " + val));
- signal4.addValueChangeListener(val -> System.out.println("Signal4: " + val));
- }
+ public static void main(String args[]) {
+ Consts.hostName = "Signal";
+
+ final DreamClient client = DreamClient.instance;
+ client.connect();
+
+ final Set relevantRemoteVars = new HashSet<>();
+ relevantRemoteVars.add("remoteInt@Remote");
+ relevantRemoteVars.add("remoteString1@Remote");
+ relevantRemoteVars.add("remoteString2@Remote");
+ relevantRemoteVars.add("remoteList@Remote");
+ while (!client.listVariables().containsAll(relevantRemoteVars)) {
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ final RemoteVar remoteInt = new RemoteVar("Remote", "remoteInt");
+ final RemoteVar remoteString1 = new RemoteVar("Remote", "remoteString1");
+ final RemoteVar remoteString2 = new RemoteVar("Remote", "remoteString2");
+ final RemoteVar> remoteList = new RemoteVar<>("Remote", "remoteList");
+
+ final Signal signal1 = new Signal("signal1",
+ () -> remoteInt.get() + remoteString1.get().length(), remoteInt, remoteString1);
+ final Signal signal2 = new Signal("signal2", () -> remoteInt.get(), remoteInt);
+ final Signal signal3 = new Signal("signal3", () -> remoteString1.get() + remoteString2.get(),
+ remoteString1, remoteString2);
+ final Signal