You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2010/11/22 18:08:40 UTC

svn commit: r1037775 - in /cayenne/sandbox/cayenne-mixin/trunk: ./ .settings/ src/main/java/org/apache/cayenne/mixin/ref/ src/main/java/org/apache/cayenne/mixin/relationship/ src/main/java/org/apache/cayenne/mixin/uuid/ src/test/java/org/apache/cayenne...

Author: aadamchik
Date: Mon Nov 22 17:08:38 2010
New Revision: 1037775

URL: http://svn.apache.org/viewvc?rev=1037775&view=rev
Log:
MixinRelationship implementation

Added:
    cayenne/sandbox/cayenne-mixin/trunk/.settings/org.eclipse.jdt.ui.prefs
    cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableBatchFaultMap.java
    cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/
    cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationship.java
    cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipBatchFaultingStrategy.java
    cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipFaultingStrategy.java
    cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipFilter.java
    cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/UuidBatchFault.java
    cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/UuidFault.java
    cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/uuid/
    cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/uuid/UuidCoder.java
    cayenne/sandbox/cayenne-mixin/trunk/src/test/java/org/apache/cayenne/mixin/uuid/
    cayenne/sandbox/cayenne-mixin/trunk/src/test/java/org/apache/cayenne/mixin/uuid/UuidCoderTest.java
Removed:
    cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/ref/UuidCoder.java
    cayenne/sandbox/cayenne-mixin/trunk/src/test/java/org/apache/cayenne/mixin/ref/UuidCoderTest.java
Modified:
    cayenne/sandbox/cayenne-mixin/trunk/.settings/org.eclipse.jdt.core.prefs
    cayenne/sandbox/cayenne-mixin/trunk/pom.xml
    cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableHandler.java

Modified: cayenne/sandbox/cayenne-mixin/trunk/.settings/org.eclipse.jdt.core.prefs
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/.settings/org.eclipse.jdt.core.prefs?rev=1037775&r1=1037774&r2=1037775&view=diff
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/.settings/org.eclipse.jdt.core.prefs (original)
+++ cayenne/sandbox/cayenne-mixin/trunk/.settings/org.eclipse.jdt.core.prefs Mon Nov 22 17:08:38 2010
@@ -1,4 +1,4 @@
-#Tue Nov 09 16:45:36 EST 2010
+#Mon Nov 22 10:40:25 EET 2010
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
@@ -7,7 +7,324 @@ org.eclipse.jdt.core.compiler.compliance
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
 org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=48
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=48
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=48
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=48
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=48
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=48
+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_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=48
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=48
+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.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=1
+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_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=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_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=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=90
+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.format_guardian_clause_on_one_line=false
+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=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=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=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=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_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_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_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_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_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_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_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.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=90
+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=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true

Added: cayenne/sandbox/cayenne-mixin/trunk/.settings/org.eclipse.jdt.ui.prefs
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/.settings/org.eclipse.jdt.ui.prefs?rev=1037775&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/.settings/org.eclipse.jdt.ui.prefs (added)
+++ cayenne/sandbox/cayenne-mixin/trunk/.settings/org.eclipse.jdt.ui.prefs Mon Nov 22 17:08:38 2010
@@ -0,0 +1,4 @@
+#Mon Nov 22 10:15:03 EET 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.ui.javadoc=false
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="filecomment_
 context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n */</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * @author ${user}\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecom
 ment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="c
 lassbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStac
 kTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.tex
 t.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="filecomment_context" deleted
 \="false" description\="Comment for created JavaScript files" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n */</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * @author ${user}\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for vars" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="ov
 erridecomment_context" deleted\="false" description\="Comment for overriding functions" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-JSDoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate functions" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.co
 detemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created function stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated function stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterb
 ody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>

Modified: cayenne/sandbox/cayenne-mixin/trunk/pom.xml
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/pom.xml?rev=1037775&r1=1037774&r2=1037775&view=diff
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/pom.xml (original)
+++ cayenne/sandbox/cayenne-mixin/trunk/pom.xml Mon Nov 22 17:08:38 2010
@@ -8,7 +8,7 @@
 		<version>3.1M1</version>
 	</parent>
 	<artifactId>cayenne-mixin</artifactId>
-	<version>3.1.0.4</version>
+	<version>3.1.0.5</version>
 	<name>Library: cayenne-mixin</name>
 	<packaging>jar</packaging>
 	<properties>

Added: cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableBatchFaultMap.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableBatchFaultMap.java?rev=1037775&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableBatchFaultMap.java (added)
+++ cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableBatchFaultMap.java Mon Nov 22 17:08:38 2010
@@ -0,0 +1,23 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.mixin.ref;
+
+class ReferenceableBatchFaultMap {
+
+}

Modified: cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableHandler.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableHandler.java?rev=1037775&r1=1037774&r2=1037775&view=diff
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableHandler.java (original)
+++ cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/ref/ReferenceableHandler.java Mon Nov 22 17:08:38 2010
@@ -29,94 +29,91 @@ import org.apache.cayenne.annotation.Pos
 import org.apache.cayenne.annotation.PostPersist;
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.mixin.uuid.UuidCoder;
 
 /**
  * A {@link MixinHandler} that injects {@link Referenceable#UUID_PROPERTY} into
- * DataObjects and provides methods to lookup objects by UUID, as well as read
- * UUID of the existing objects.
+ * DataObjects and provides methods to lookup objects by UUID, as well as read UUID of the
+ * existing objects.
  */
 public class ReferenceableHandler {
 
-	protected EntityResolver entityResolver;
-	protected Map<String, UuidCoder> coders;
+    protected EntityResolver entityResolver;
+    protected Map<String, UuidCoder> coders;
 
-	public ReferenceableHandler(EntityResolver entityResolver) {
-		this.entityResolver = entityResolver;
-		this.coders = new ConcurrentHashMap<String, UuidCoder>();
-	}
-
-	/**
-	 * Returns a Referenceable object matching provided UUID and bound in
-	 * provided {@link ObjectContext}.
-	 */
-	public Object getReferenceable(ObjectContext context, String uuid) {
-
-		int separator = uuid.indexOf(':');
-		if (separator <= 0 || separator == uuid.length() - 1) {
-			throw new IllegalArgumentException("Invalid uuid: " + uuid);
-		}
-
-		String entityName = uuid.substring(0, separator);
-		UuidCoder coder = coders.get(entityName);
-		if (coder == null) {
-			throw new IllegalArgumentException("Entity " + entityName
-					+ " is not a known referenceable");
-		}
-
-		ObjectId oid = coder.toObjectId(uuid.substring(separator + 1));
-		return Cayenne.objectForPK(context, oid);
-	}
-
-	public String getUuid(Object referenceable) {
-
-		if (referenceable == null) {
-			throw new NullPointerException("Null object");
-		}
-
-		if (referenceable instanceof DataObject) {
-
-			// even if this is not a registered Referenceable, don't see a
-			// problem if we return a UUID.
-			DataObject dataObject = (DataObject) referenceable;
-			String uuid = (String) dataObject
-					.readPropertyDirectly(Referenceable.UUID_PROPERTY);
-
-			if (uuid == null) {
-				throw new IllegalArgumentException(
-						"No UUID set. An object is either not a Referenceable "
-								+ "or is NEW or TRANSIENT.");
-			}
-
-			return uuid;
-		} else {
-			throw new IllegalArgumentException("Object is not a DataObject: "
-					+ referenceable.getClass().getName());
-		}
-	}
-
-	/**
-	 * A lifecycle listener method that initialzes DataObject UUID property.
-	 */
-	@PostLoad(entityAnnotations = Referenceable.class)
-	@PostPersist(entityAnnotations = Referenceable.class)
-	protected void initProperties(DataObject object) {
-
-		UuidCoder coder = coders.get(object.getObjectId().getEntityName());
-		if (coder == null) {
-
-			ObjEntity entity = entityResolver
-					.lookupObjEntity(object.getClass());
-			if (entity == null) {
-				throw new IllegalArgumentException("Entity "
-						+ object.getObjectId().getEntityName()
-						+ " is not a known referenceable");
-			}
-
-			coder = new UuidCoder(entity);
-			coders.put(entity.getName(), coder);
-		}
-
-		String uuid = coder.toUuid(object.getObjectId());
-		object.writePropertyDirectly(Referenceable.UUID_PROPERTY, uuid);
-	}
+    public ReferenceableHandler(EntityResolver entityResolver) {
+        this.entityResolver = entityResolver;
+        this.coders = new ConcurrentHashMap<String, UuidCoder>();
+    }
+
+    /**
+     * Returns a Referenceable object matching provided UUID and bound in provided
+     * {@link ObjectContext}.
+     */
+    public Object getReferenceable(ObjectContext context, String uuid) {
+
+        String entityName = UuidCoder.getEntityName(uuid);
+        UuidCoder coder = coders.get(entityName);
+        if (coder == null) {
+            throw new IllegalArgumentException("Entity "
+                    + entityName
+                    + " is not a known referenceable");
+        }
+
+        ObjectId oid = coder.toObjectId(uuid);
+        return Cayenne.objectForPK(context, oid);
+    }
+
+    public String getUuid(Object referenceable) {
+
+        if (referenceable == null) {
+            throw new NullPointerException("Null object");
+        }
+
+        if (referenceable instanceof DataObject) {
+
+            // even if this is not a registered Referenceable, don't see a
+            // problem if we return a UUID.
+            DataObject dataObject = (DataObject) referenceable;
+            String uuid = (String) dataObject
+                    .readPropertyDirectly(Referenceable.UUID_PROPERTY);
+
+            if (uuid == null) {
+                throw new IllegalArgumentException(
+                        "No UUID set. An object is either not a Referenceable "
+                                + "or is NEW or TRANSIENT.");
+            }
+
+            return uuid;
+        }
+        else {
+            throw new IllegalArgumentException("Object is not a DataObject: "
+                    + referenceable.getClass().getName());
+        }
+    }
+
+    /**
+     * A lifecycle listener method that initialzes DataObject UUID property.
+     */
+    @PostLoad(entityAnnotations = Referenceable.class)
+    @PostPersist(entityAnnotations = Referenceable.class)
+    protected void initProperties(DataObject object) {
+
+        UuidCoder coder = coders.get(object.getObjectId().getEntityName());
+        if (coder == null) {
+
+            ObjEntity entity = entityResolver.lookupObjEntity(object.getClass());
+            if (entity == null) {
+                throw new IllegalArgumentException("Entity "
+                        + object.getObjectId().getEntityName()
+                        + " is not a known referenceable");
+            }
+
+            coder = new UuidCoder(entity);
+            coders.put(entity.getName(), coder);
+        }
+
+        String uuid = coder.toUuid(object.getObjectId());
+        object.writePropertyDirectly(Referenceable.UUID_PROPERTY, uuid);
+    }
 }

Added: cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationship.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationship.java?rev=1037775&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationship.java (added)
+++ cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationship.java Mon Nov 22 17:08:38 2010
@@ -0,0 +1,46 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.mixin.relationship;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Allows to tag a relationship between a mixin entity and another entity that
+ * has a mixin attached. When a mixin is modeled via its own set of entities,
+ * this annotation is placed on a "mixin" entity class, telling Cayenne to
+ * inject related entity object in a mixin entity, resolved based on the object
+ * UUID "FK".
+ */
+@Target( { ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface MixinRelationship {
+
+	/**
+	 * Returns the name of the property of the mixin entity that is a UUID "FK"
+	 * to any of the entities implementing the mixin.
+	 */
+	String value() default "";
+}

Added: cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipBatchFaultingStrategy.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipBatchFaultingStrategy.java?rev=1037775&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipBatchFaultingStrategy.java (added)
+++ cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipBatchFaultingStrategy.java Mon Nov 22 17:08:38 2010
@@ -0,0 +1,82 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.mixin.relationship;
+
+import org.apache.cayenne.DataObject;
+
+public class MixinRelationshipBatchFaultingStrategy implements
+        MixinRelationshipFaultingStrategy {
+
+    private ThreadLocal<UuidBatchFault> batchFaultHolder;
+
+    public MixinRelationshipBatchFaultingStrategy() {
+        this.batchFaultHolder = new ThreadLocal<UuidBatchFault>();
+    }
+
+    @Override
+    public void afterObjectLoaded(DataObject object) {
+
+        UuidBatchFault batchFault = batchFaultHolder.get();
+
+        if (batchFault == null) {
+            batchFault = new UuidBatchFault(object.getObjectContext());
+            batchFaultHolder.set(batchFault);
+        }
+
+        String uuidProperty = uuidPropertyName(object);
+        String uuidRelationship = uuidRelationshipName(uuidProperty);
+        String uuid = (String) object.readProperty(uuidProperty);
+        if (uuid == null) {
+            object.writePropertyDirectly(uuidRelationship, null);
+        }
+        else {
+            batchFault.addUuid(uuid);
+            object.writePropertyDirectly(
+                    uuidRelationship,
+                    new UuidFault(batchFault, uuid));
+        }
+    }
+
+    @Override
+    public void afterQuery() {
+        batchFaultHolder.set(null);
+    }
+
+    String uuidRelationshipName(String uuidPropertyName) {
+        return "cay:related:" + uuidPropertyName;
+    }
+
+    String uuidPropertyName(DataObject object) {
+
+        MixinRelationship annotation = object.getClass().getAnnotation(
+                MixinRelationship.class);
+
+        // TODO: look it up in the superclasses??
+        if (annotation == null) {
+            throw new IllegalArgumentException(
+                    "Object class is not annotated with 'MixinRelationship': "
+                            + object.getClass().getName());
+        }
+
+        // TODO: I guess we'll need to cache this metadata for performance if we are to
+        // support inheritance lookups, etc.
+        
+        return annotation.value();
+    }
+}

Added: cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipFaultingStrategy.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipFaultingStrategy.java?rev=1037775&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipFaultingStrategy.java (added)
+++ cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipFaultingStrategy.java Mon Nov 22 17:08:38 2010
@@ -0,0 +1,31 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.mixin.relationship;
+
+import org.apache.cayenne.DataObject;
+
+/**
+ * An abstract strategy for resolving mixin relationships.
+ */
+public interface MixinRelationshipFaultingStrategy {
+
+	void afterObjectLoaded(DataObject object);
+
+	void afterQuery();
+}

Added: cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipFilter.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipFilter.java?rev=1037775&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipFilter.java (added)
+++ cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/MixinRelationshipFilter.java Mon Nov 22 17:08:38 2010
@@ -0,0 +1,76 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.mixin.relationship;
+
+import org.apache.cayenne.DataChannel;
+import org.apache.cayenne.DataChannelFilter;
+import org.apache.cayenne.DataChannelFilterChain;
+import org.apache.cayenne.DataObject;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.QueryResponse;
+import org.apache.cayenne.annotation.PostLoad;
+import org.apache.cayenne.annotation.PostPersist;
+import org.apache.cayenne.graph.GraphDiff;
+import org.apache.cayenne.query.Query;
+
+/**
+ * A {@link DataChannelFilter} that implements mixin relationships faulting
+ * functionality.
+ */
+public class MixinRelationshipFilter implements DataChannelFilter {
+
+	private MixinRelationshipFaultingStrategy faultingStrategy;
+
+	@Override
+	public void init(DataChannel channel) {
+		this.faultingStrategy = createFaultingStrategy();
+	}
+
+	protected MixinRelationshipFaultingStrategy createFaultingStrategy() {
+		return new MixinRelationshipBatchFaultingStrategy();
+	}
+
+	@Override
+	public GraphDiff onSync(ObjectContext context, GraphDiff diff,
+			int syncType, DataChannelFilterChain chain) {
+		// noop for now
+		return chain.onSync(context, diff, syncType);
+	}
+
+	@Override
+	public QueryResponse onQuery(ObjectContext context, Query query,
+			DataChannelFilterChain chain) {
+
+		try {
+			return chain.onQuery(context, query);
+		} finally {
+			faultingStrategy.afterQuery();
+		}
+	}
+
+	/**
+	 * A lifecycle callback method that delegates object post load event
+	 * processing to the underlying faulting strategy.
+	 */
+	@PostLoad(entityAnnotations = MixinRelationship.class)
+	@PostPersist(entityAnnotations = MixinRelationship.class)
+	void postLoadObject(DataObject object) {
+		faultingStrategy.afterObjectLoaded(object);
+	}
+}

Added: cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/UuidBatchFault.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/UuidBatchFault.java?rev=1037775&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/UuidBatchFault.java (added)
+++ cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/UuidBatchFault.java Mon Nov 22 17:08:38 2010
@@ -0,0 +1,144 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.mixin.relationship;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.Cayenne;
+import org.apache.cayenne.DataObject;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.mixin.uuid.UuidCoder;
+import org.apache.cayenne.query.ObjectIdQuery;
+import org.apache.cayenne.query.SelectQuery;
+
+/**
+ * Provides lazy faulting functionality for a map of objects identified by UUID.
+ */
+class UuidBatchFault {
+
+    private ObjectContext context;
+    private Collection<String> uuids;
+    private volatile Map<String, Object> resolved;
+
+    UuidBatchFault(ObjectContext context) {
+        this.context = context;
+    }
+
+    void addUuid(String uuid) {
+        if (uuids == null) {
+            uuids = new ArrayList<String>();
+        }
+
+        uuids.add(uuid);
+    }
+
+    Map<String, Object> getObjects() {
+
+        if (resolved == null) {
+
+            synchronized (this) {
+
+                if (resolved == null) {
+                    resolved = fetchObjects();
+                }
+            }
+        }
+
+        return resolved;
+    }
+
+    private Map<String, Object> fetchObjects() {
+
+        if (uuids == null) {
+            return Collections.EMPTY_MAP;
+        }
+
+        EntityResolver resolver = context.getEntityResolver();
+
+        // simple case of one query, handle it separately for performance reasons
+        if (uuids.size() == 1) {
+
+            String uuid = uuids.iterator().next();
+            String entityName = UuidCoder.getEntityName(uuid);
+
+            ObjEntity entity = resolver.getObjEntity(entityName);
+            ObjectId id = new UuidCoder(entity).toObjectId(uuid);
+
+            Object object = Cayenne.objectForQuery(context, new ObjectIdQuery(id));
+            if (object == null) {
+                return Collections.EMPTY_MAP;
+            }
+            else {
+                return Collections.singletonMap(uuid, object);
+            }
+        }
+
+        Map<String, SelectQuery> queriesByEntity = new HashMap<String, SelectQuery>();
+        Map<String, UuidCoder> codersByEntity = new HashMap<String, UuidCoder>();
+
+        for (String uuid : uuids) {
+
+            String entityName = UuidCoder.getEntityName(uuid);
+            UuidCoder coder = codersByEntity.get(entityName);
+            SelectQuery query;
+
+            if (coder == null) {
+                coder = new UuidCoder(resolver.getObjEntity(entityName));
+                codersByEntity.put(entityName, coder);
+
+                query = new SelectQuery(entityName);
+                queriesByEntity.put(entityName, query);
+            }
+            else {
+                query = queriesByEntity.get(entityName);
+            }
+
+            ObjectId id = coder.toObjectId(uuid);
+            Expression idExp = ExpressionFactory.matchAllDbExp(
+                    id.getIdSnapshot(),
+                    Expression.EQUAL_TO);
+            query.orQualifier(idExp);
+        }
+
+        int capacity = (int) Math.ceil(uuids.size() / 0.75d);
+        Map<String, Object> results = new HashMap<String, Object>(capacity);
+
+        for (SelectQuery query : queriesByEntity.values()) {
+
+            UuidCoder coder = codersByEntity.get(query.getRoot());
+            List<DataObject> objects = context.performQuery(query);
+            for (DataObject object : objects) {
+                String uuid = coder.toUuid(object.getObjectId());
+                results.put(uuid, object);
+            }
+        }
+
+        return results;
+    }
+}

Added: cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/UuidFault.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/UuidFault.java?rev=1037775&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/UuidFault.java (added)
+++ cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/relationship/UuidFault.java Mon Nov 22 17:08:38 2010
@@ -0,0 +1,38 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.mixin.relationship;
+
+import org.apache.cayenne.Fault;
+import org.apache.cayenne.Persistent;
+
+class UuidFault extends Fault {
+
+    private String uuid;
+    private UuidBatchFault batchFault;
+
+    UuidFault(UuidBatchFault batchFault, String uuid) {
+        this.batchFault = batchFault;
+        this.uuid = uuid;
+    }
+
+    @Override
+    public Object resolveFault(Persistent sourceObject, String relationshipName) {
+        return uuid != null ? batchFault.getObjects().get(uuid) : null;
+    }
+}

Added: cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/uuid/UuidCoder.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/uuid/UuidCoder.java?rev=1037775&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/uuid/UuidCoder.java (added)
+++ cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/uuid/UuidCoder.java Mon Nov 22 17:08:38 2010
@@ -0,0 +1,211 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.mixin.uuid;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.util.Util;
+
+/**
+ * An object to encode/decode persistent objects UUIDs.
+ */
+public class UuidCoder {
+
+    static final String UUID_SEPARATOR = ":";
+
+    private String entityName;
+    private SortedMap<String, Converter> converters;
+    private int idSize;
+
+    public static String getEntityName(String uuid) {
+        int separator = uuid.indexOf(UUID_SEPARATOR);
+        if (separator <= 0 || separator == uuid.length() - 1) {
+            throw new IllegalArgumentException("Invalid uuid: " + uuid);
+        }
+
+        return uuid.substring(0, separator);
+    }
+
+    public UuidCoder(ObjEntity entity) {
+
+        this.entityName = entity.getName();
+        this.converters = new TreeMap<String, Converter>();
+
+        for (ObjAttribute attribute : entity.getAttributes()) {
+            if (attribute.isPrimaryKey()) {
+                converters.put(attribute.getDbAttributeName(), create(attribute
+                        .getJavaClass()));
+            }
+        }
+
+        for (DbAttribute attribute : entity.getDbEntity().getPrimaryKeys()) {
+            if (!converters.containsKey(attribute.getName())) {
+                String type = TypesMapping.getJavaBySqlType(attribute.getType());
+                try {
+                    converters.put(attribute.getName(), create(Util.getJavaClass(type)));
+                }
+                catch (ClassNotFoundException e) {
+                    throw new CayenneRuntimeException(
+                            "Can't instantiate class " + type,
+                            e);
+                }
+            }
+        }
+
+        if (converters.isEmpty()) {
+            throw new IllegalArgumentException("Entity has no PK definied: "
+                    + entity.getName());
+        }
+
+        this.idSize = (int) Math.ceil(converters.size() / 0.75d);
+    }
+
+    public String toUuid(ObjectId id) {
+
+        if (id.isTemporary()) {
+            throw new IllegalArgumentException(
+                    "Can't create UUID for a temporary ObjectId");
+        }
+
+        Map<String, Object> idValues = id.getIdSnapshot();
+
+        StringBuilder buffer = new StringBuilder();
+        buffer.append(id.getEntityName());
+
+        for (Entry<String, Converter> entry : converters.entrySet()) {
+            Object value = idValues.get(entry.getKey());
+            buffer.append(UUID_SEPARATOR).append(entry.getValue().toUuid(value));
+        }
+
+        return buffer.toString();
+    }
+
+    public ObjectId toObjectId(String uuid) {
+
+        String uuidValues = uuid.substring(entityName.length() + 1);
+
+        if (converters.size() == 1) {
+            Entry<String, Converter> entry = converters.entrySet().iterator().next();
+
+            String decoded;
+            try {
+                decoded = URLDecoder.decode(uuidValues, "UTF-8");
+            }
+            catch (UnsupportedEncodingException e) {
+                // unexpected
+                throw new CayenneRuntimeException("Unsupported encoding", e);
+            }
+            return new ObjectId(entityName, entry.getKey(), entry.getValue().fromUuid(
+                    decoded));
+        }
+
+        Map<String, Object> idMap = new HashMap<String, Object>(idSize);
+        StringTokenizer toks = new StringTokenizer(uuidValues, UUID_SEPARATOR);
+
+        if (toks.countTokens() != converters.size()) {
+            throw new IllegalArgumentException("Invalid UUID for entity "
+                    + entityName
+                    + ": "
+                    + uuidValues);
+        }
+
+        for (Entry<String, Converter> entry : converters.entrySet()) {
+            String value = toks.nextToken();
+
+            String decoded;
+            try {
+                decoded = URLDecoder.decode(value, "UTF-8");
+            }
+            catch (UnsupportedEncodingException e) {
+                // unexpected
+                throw new CayenneRuntimeException("Unsupported encoding", e);
+            }
+
+            idMap.put(entry.getKey(), entry.getValue().fromUuid(decoded));
+        }
+
+        return new ObjectId(entityName, idMap);
+    }
+
+    private Converter create(Class<?> type) {
+
+        if (type == null) {
+            throw new NullPointerException("Null type");
+        }
+
+        if (Long.class.isAssignableFrom(type)) {
+            return new Converter() {
+
+                @Override
+                Object fromUuid(String uuid) {
+                    return Long.valueOf(uuid);
+                }
+            };
+        }
+        else if (Integer.class.isAssignableFrom(type)) {
+            return new Converter() {
+
+                @Override
+                Object fromUuid(String uuid) {
+                    return Integer.valueOf(uuid);
+                }
+            };
+        }
+        else if (String.class.isAssignableFrom(type)) {
+            return new Converter() {
+
+                @Override
+                Object fromUuid(String uuid) {
+                    return uuid;
+                }
+            };
+        }
+
+        throw new IllegalArgumentException("Unsupported UUID type: " + type.getName());
+    }
+
+    abstract class Converter {
+
+        String toUuid(Object value) {
+            try {
+                return URLEncoder.encode(String.valueOf(value), "UTF-8");
+            }
+            catch (UnsupportedEncodingException e) {
+                // unexpected
+                throw new CayenneRuntimeException("Unsupported encoding", e);
+            }
+        }
+
+        abstract Object fromUuid(String uuid);
+    }
+}

Added: cayenne/sandbox/cayenne-mixin/trunk/src/test/java/org/apache/cayenne/mixin/uuid/UuidCoderTest.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/test/java/org/apache/cayenne/mixin/uuid/UuidCoderTest.java?rev=1037775&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/src/test/java/org/apache/cayenne/mixin/uuid/UuidCoderTest.java (added)
+++ cayenne/sandbox/cayenne-mixin/trunk/src/test/java/org/apache/cayenne/mixin/uuid/UuidCoderTest.java Mon Nov 22 17:08:38 2010
@@ -0,0 +1,155 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.mixin.uuid;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.sql.Types;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjEntity;
+
+public class UuidCoderTest extends TestCase {
+
+    public void testSingleIntPk() {
+        DbEntity dbEntity = new DbEntity("X");
+        DbAttribute pk = new DbAttribute("ID");
+        pk.setType(Types.INTEGER);
+        pk.setPrimaryKey(true);
+        dbEntity.addAttribute(pk);
+
+        ObjEntity entity = mock(ObjEntity.class);
+        when(entity.getName()).thenReturn("x");
+        when(entity.getDbEntityName()).thenReturn(dbEntity.getName());
+        when(entity.getDbEntity()).thenReturn(dbEntity);
+
+        ObjectId id = new ObjectId("x", "ID", 3);
+
+        UuidCoder coder = new UuidCoder(entity);
+        assertEquals("x:3", coder.toUuid(id));
+
+        ObjectId parsedId = coder.toObjectId("x:3");
+        assertEquals(id, parsedId);
+    }
+
+    public void testSingleLongPk() {
+        DbEntity dbEntity = new DbEntity("X");
+        DbAttribute pk = new DbAttribute("ID");
+        pk.setType(Types.BIGINT);
+        pk.setPrimaryKey(true);
+        dbEntity.addAttribute(pk);
+
+        ObjEntity entity = mock(ObjEntity.class);
+        when(entity.getName()).thenReturn("x");
+        when(entity.getDbEntityName()).thenReturn(dbEntity.getName());
+        when(entity.getDbEntity()).thenReturn(dbEntity);
+
+        ObjectId id = new ObjectId("x", "ID", 3l);
+
+        UuidCoder coder = new UuidCoder(entity);
+        assertEquals("x:3", coder.toUuid(id));
+
+        ObjectId parsedId = coder.toObjectId("x:3");
+        assertEquals(id, parsedId);
+    }
+
+    public void testSingleStringPk() {
+        DbEntity dbEntity = new DbEntity("X");
+        DbAttribute pk = new DbAttribute("ID");
+        pk.setType(Types.VARCHAR);
+        pk.setPrimaryKey(true);
+        dbEntity.addAttribute(pk);
+
+        ObjEntity entity = mock(ObjEntity.class);
+        when(entity.getName()).thenReturn("x");
+        when(entity.getDbEntityName()).thenReturn(dbEntity.getName());
+        when(entity.getDbEntity()).thenReturn(dbEntity);
+
+        UuidCoder coder = new UuidCoder(entity);
+
+        ObjectId id = new ObjectId("x", "ID", "AbC");
+        assertEquals("x:AbC", coder.toUuid(id));
+
+        ObjectId parsedId = coder.toObjectId("x:AbC");
+        assertEquals(id, parsedId);
+    }
+
+    public void testIdEncoding() {
+        DbEntity dbEntity = new DbEntity("X");
+        DbAttribute pk = new DbAttribute("ID");
+        pk.setType(Types.VARCHAR);
+        pk.setPrimaryKey(true);
+        dbEntity.addAttribute(pk);
+
+        ObjEntity entity = mock(ObjEntity.class);
+        when(entity.getName()).thenReturn("x");
+        when(entity.getDbEntityName()).thenReturn(dbEntity.getName());
+        when(entity.getDbEntity()).thenReturn(dbEntity);
+
+        UuidCoder coder = new UuidCoder(entity);
+
+        ObjectId id = new ObjectId("x", "ID", "Ab:C");
+        assertEquals("x:Ab%3AC", coder.toUuid(id));
+
+        ObjectId parsedId = coder.toObjectId("x:Ab%3AC");
+        assertEquals(id, parsedId);
+    }
+
+    public void testMixedCompoundPk() {
+        DbEntity dbEntity = new DbEntity("X");
+        DbAttribute pk1 = new DbAttribute("ID");
+        pk1.setType(Types.VARCHAR);
+        pk1.setPrimaryKey(true);
+        dbEntity.addAttribute(pk1);
+
+        DbAttribute pk2 = new DbAttribute("ABC");
+        pk2.setType(Types.BIGINT);
+        pk2.setPrimaryKey(true);
+        dbEntity.addAttribute(pk2);
+
+        DbAttribute pk3 = new DbAttribute("ZZZ");
+        pk3.setType(Types.VARCHAR);
+        pk3.setPrimaryKey(true);
+        dbEntity.addAttribute(pk3);
+
+        ObjEntity entity = mock(ObjEntity.class);
+        when(entity.getName()).thenReturn("x");
+        when(entity.getDbEntityName()).thenReturn(dbEntity.getName());
+        when(entity.getDbEntity()).thenReturn(dbEntity);
+
+        UuidCoder coder = new UuidCoder(entity);
+
+        Map<String, Object> idMap = new HashMap<String, Object>();
+        idMap.put("ID", "X;Y");
+        idMap.put("ABC", 6783463l);
+        idMap.put("ZZZ", "'_'");
+        ObjectId id = new ObjectId("x", idMap);
+        assertEquals("x:6783463:X%3BY:%27_%27", coder.toUuid(id));
+
+        ObjectId parsedId = coder.toObjectId("x:6783463:X%3BY:%27_%27");
+        assertEquals(id, parsedId);
+    }
+}