Menu

Copy custom immutable types

Servy
2014-07-07
2014-12-11
  • Servy

    Servy - 2014-07-07

    I was wondering if there is a way to mark some properties as immutable
    value properties,
    that is, properties that holds values that can't be
    modified after creation and, thus, should not be deep copied. An example
    unit test below. Basically, there is a SomeId class, which is immutable.
    SomeEntity class have a property of SomeId type. Mapping SomeEntity to
    another SomeEntity does not copy the id property as I expected it to. It
    would be nice to be able to mark the id property of SomeEntity or the
    SomeId class as immutable (via annotation or MergingContext) and have java
    merger just copy such properties (the same way it does it for String class
    and other built in immutables).

    I tried to achieve it using PropertyConverter with no success. My current
    workaround is to @Skip the id property and to copy it manually after the
    mapping, which is kind of ugly.

    public class MergerTest {
    
        /**
         * Some immutable class that should not be deep copied
         */
        public static class SomeId {
            private long innerId;
    
            public SomeId(int innerId) {
                this.innerId = innerId;
            }
    
            /**
             * There should not be public constructor with no parameters because this is an immutable class,
             * but merger fails with ObjectCreationException otherwise
             */
            public SomeId() {
            }
    
            /**
             * Compares by inner id.
             */
            @Override
            public boolean equals(Object o) {
                if (this == o) return true;
                if (o == null || getClass() != o.getClass()) return false;
    
                SomeId someId = (SomeId) o;
    
                if (innerId != someId.innerId) return false;
    
                return true;
            }
    
            @Override
            public int hashCode() {
                return (int) (innerId ^ (innerId >>> 32));
            }
        }
    
        /**
         * Bean class with an immutable property
         */
        public static class SomeEntity {
            private SomeId id;
    
            public SomeId getId() {
                return id;
            }
    
            public void setId(SomeId id) {
                this.id = id;
            }
        }
    
        @Test
        public void testImmutableMapping() throws Exception {
            IMergingContext mergingContext = new MergingContext();
    
            SomeEntity a = new SomeEntity();
            a.setId(new SomeId(5));
    
            SomeEntity result = mergingContext.map(a, SomeEntity.class);
    
            assertEquals(result.getId(), a.getId());
        }
    }
    
     

    Last edit: Servy 2014-07-07
    • Evgeniy Voronyuk

      To make it work as you expected, you should declare SomeId.class as value type in MergingContext. Like this:

      mergingContext.setValueTypes(Arrays.asList(SomeId.class));
      See javadoc of method 'setValueTypes' for details.

      Then costructor with no arguments in SomeId could aslo be removed.

       

Anonymous
Anonymous

Add attachments
Cancel





Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.