Uploaded image for project: 'Hibernate Search'
  1. HSEARCH-3438

Make references to value bridges and container value extractors in the mapping cleaner and simpler

    Details

    • Type: Task
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 6.0.0.Alpha2
    • Component/s: mapper-pojo
    • Labels:
      None

      Description

      It's most obvious for extractors:

      				@GenericField(extractors = {
      						@ContainerValueExtractorBeanReference(type = MapValueExtractor.class),
      						@ContainerValueExtractorBeanReference(type = IterableElementExtractor.class)
      				})
      

      It's awfully verbose.

      We could remove the intermediary @ annotation:

      				@GenericField(extractors = {MapValueExtractorImpl.class, IterableElementExtractorImpl.class})
      

      ... but then we wouldn't be able to (later) add a way for users to refer to a container value extractor by its name.

      Maybe we could expect the references to container value extractors to be strings only?
      Something like this:

      				@GenericField(extractors = {BuiltinExtractors.MAP_VALUE, BuiltinExtractors.ITERABLE})
      

      That would, however, require us to provide some way for users to register their custom container value extractors.

      Ideally we should use a dedicated reference type, but we can't use enums because we expect users to write their own extractors, and we can't use a dedicated interface because that's not allowed in annotations.

      Solution

      Maybe we could shorten the name of the "container value extractor reference" annotation (we'd have to do the same for other "reference" annotations), and allow to use either enums for built-in types, or class/string for custom types.

      Something like this:

      enum BuiltinExtractors {
      	AUTOMATIC, // special value for automatic selection based on the value type
      	ITERABLE,
      	COLLECTION,
      	MAP_VALUES,
      	MAP_KEYS,
      	...
      }
      
      @GenericField(extractors = {
      	@ContainerExtractor(BuiltinExtractors.MAP_VALUES), // Use "ContainerExtractor#value" to make references to built-in extractor types shorter
      	@ContainerExtractor(BuiltinExtractors.ITERABLE),
      	@ContainerExtractor(type = MyCustomExtractorType.class),
      	@ContainerExtractor(name = "myOtherCustomExtractorType"),
      })
      

      And for value bridges:

      enum BuiltinValueBridges {
      	AUTOMATIC, // special value for automatic selection based on the value type
      	INTEGER,
      	LONG,
      	STRING_KEYWORD,
      	DATE,
      	LOCAL_DATE,
      	LOCAL_DATE_TIME,
      	...
      }
      
      @GenericField(bridge = @ValueBridge(BuiltinValueBridges.DATE)) // Shouldn't be necessary in most cases. Maybe with badly written generics, where the user knows that "T" will always be "Date" for example?
      @GenericField(bridge = @ValueBridge(type = MyCustomValueBridge.class)) 
      @GenericField(bridge = @ValueBridge(name = "myOtherCustomValueBridge")) 
      

      If we go down that route, here is the to-do list:

      1. Rename the *BeanReference annotations: remove the BeanReference suffix
      2. Merge the *Bridge and *BridgeBuilder annotations: wherever we have a bridge and bridgeBuilder attributes in an annotation, just keep bridge, but make sure that the type of that annotation has four attributes: name, type, builderName, builderType. Keep the same constraints as today, i.e. you can refer to a bridge directly (through name and/or type) or to a builder (through builderName/builderType), but never both in the same annotation.
      3. Rename the ContainerValueExtractorBeanReference annotation to ContainerExtractor
      4. Rename the ContainerValueExtractor class to ContainerExtractor (and also rename related classes such as ContainerValueExtractorPath)
      5. Introduce a BuiltinContainerExtractor enum, with one value per available built-in container extractor + AUTOMATIC.
      6. Change ContainerExtractorPath so that it uses enums as well as classes to refer to extractors. We will probably have to change it to a linked list. The “default” container extractor path will simply be a container extractor path with one element whose value is BuiltinContainerExtractor.AUTOMATIC
      7. Change ContainerExtractorBinder so that it recognizes these enums.
      8. Add a “value” attribute to the ContainerExtractor annotation, of type BuiltinContainerExtractor, and make sure to propagate when creating the corresponding ContainerExtractorPath.
      9. Replace uses of ContainerExtractor.type in tests with ContainerExtractor.value wherever we refer to built-in container extractor types
      10. Move built-in container extractor types to an impl package.
      11. Once it’s done, let’s talk again about what could be done for value bridges, especially built-in value bridges. Maybe just create another ticket.

        Attachments

          Issue links

            Activity

              People

              • Assignee:
                fercoli Fabio Massimo Ercoli
                Reporter:
                yrodiere Yoann Rodière
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: