Package org.mongodb.morphia.ext

Source Code of org.mongodb.morphia.ext.CustomConvertersTest$ValueObject

/**
* Copyright (C) 2010 Olafur Gauti Gudmundsson
*
* Licensed 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.mongodb.morphia.ext;


import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.DefaultDBDecoder;
import com.mongodb.DefaultDBEncoder;
import org.bson.types.ObjectId;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mongodb.morphia.TestBase;
import org.mongodb.morphia.annotations.Converters;
import org.mongodb.morphia.annotations.Embedded;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import org.mongodb.morphia.converters.IntegerConverter;
import org.mongodb.morphia.converters.SimpleValueConverter;
import org.mongodb.morphia.converters.TypeConverter;
import org.mongodb.morphia.mapping.MappedField;

import javax.activation.MimeType;
import javax.activation.MimeTypeParseException;
import java.net.UnknownHostException;

import static org.junit.Assert.assertEquals;


/**
* @author Scott Hernandez
*/
public class CustomConvertersTest extends TestBase {

    static class CharacterToByteConverter extends TypeConverter implements SimpleValueConverter {
        public CharacterToByteConverter() {
            super(Character.class, char.class);
        }

        @Override
        public Object decode(final Class targetClass, final Object fromDBObject, final MappedField optionalExtraInfo) {
            if (fromDBObject == null) {
                return null;
            }
            final IntegerConverter intConverter = new IntegerConverter();
            final Integer i = (Integer) intConverter.decode(targetClass, fromDBObject, optionalExtraInfo);
            return (char) i.intValue();
        }

        @Override
        public Object encode(final Object value, final MappedField optionalExtraInfo) {
            final Character c = (Character) value;
            return (int) c.charValue();
        }
    }

    @Converters(CharacterToByteConverter.class)
    static class CharEntity {
        @Id
        private ObjectId id = new ObjectId();
        private final Character c = 'a';
    }

    @Test
    public void testIt() {
        getMorphia().map(CharEntity.class);

        getDs().save(new CharEntity());
        final CharEntity ce = getDs().find(CharEntity.class).get();
        Assert.assertNotNull(ce.c);
        assertEquals('a', ce.c.charValue());

        final BasicDBObject dbObj = (BasicDBObject) getDs().getCollection(CharEntity.class).findOne();
        Assert.assertTrue(dbObj.getInt("c") == (int) 'a');
    }

    /**
     * This test shows an issue with an {@code @Embedded} class A inheriting from an {@code @Embedded} class B that both have a Converter
     * assigned (A has AConverter, B has BConverter). <p> When an object (here MyEntity) has a property/field of type A and is deserialized,
     * the deserialization fails with a "org.mongodb.morphia.mapping.MappingException: No usable constructor for A" . </p>
     */
    @Entity(noClassnameStored = true)
    private static class MyEntity {

        @Id
        private Long id;
        @Embedded
        private ValueObject valueObject;

        public MyEntity() {
        }

        public MyEntity(final Long id, final ValueObject valueObject) {
            this.id = id;
            this.valueObject = valueObject;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((id == null) ? 0 : id.hashCode());
            result = prime * result + ((valueObject == null) ? 0 : valueObject.hashCode());
            return result;
        }

        @Override
        public boolean equals(final Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final MyEntity other = (MyEntity) obj;
            if (id == null) {
                if (other.id != null) {
                    return false;
                }
            } else if (!id.equals(other.id)) {
                return false;
            }
            if (valueObject == null) {
                if (other.valueObject != null) {
                    return false;
                }
            } else if (!valueObject.equals(other.valueObject)) {
                return false;
            }
            return true;
        }

    }

    @Embedded
    @Converters(ValueObject.BConverter.class)
    private static class ValueObject {

        static class BConverter extends TypeConverter implements SimpleValueConverter {

            public BConverter() {
                this(ValueObject.class);
            }

            public BConverter(final Class<? extends ValueObject> clazz) {
                super(clazz);
            }

            @Override
            public ValueObject decode(final Class targetClass, final Object fromDBObject, final MappedField optionalExtraInfo) {
                if (fromDBObject == null) {
                    return null;
                }
                return create((Long) fromDBObject);
            }

            protected ValueObject create(final Long source) {
                return new ValueObject(source);
            }

            @Override
            public Long encode(final Object value, final MappedField optionalExtraInfo) {
                if (value == null) {
                    return null;
                }
                final ValueObject source = (ValueObject) value;
                return source.value;
            }

            @Override
            protected boolean isSupported(final Class<?> c, final MappedField optionalExtraInfo) {
                return c.isAssignableFrom(ValueObject.class);
            }
        }

        private long value;

        public ValueObject() {
        }

        public ValueObject(final long value) {
            this.value = value;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + (int) (value ^ (value >>> 32));
            return result;
        }

        @Override
        public boolean equals(final Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final ValueObject other = (ValueObject) obj;
            return value == other.value;
        }

        @Override
        public String toString() {
            return getClass().getSimpleName() + " [value=" + value + "]";
        }

    }

    @Before
    public void setup() {
        getMorphia().map(MyEntity.class, ValueObject.class);
    }

    /**
     * This test is green when {@link MyEntity#valueObject} is annotated with {@code @Property}, as in this case the field is not serialized
     * at all. However, the bson encoder would fail to encode the object of type ValueObject (as shown by {@link
     * #testFullBSONSerialization()}).
     */
    @Test
    public void testDBObjectSerialization() {
        final MyEntity entity = new MyEntity(1L, new ValueObject(2L));
        final DBObject dbObject = getMorphia().toDBObject(entity);

        assertEquals(new BasicDBObject("_id", 1L).append("valueObject", 2L), dbObject);
        assertEquals(entity, getMorphia().fromDBObject(MyEntity.class, dbObject));
    }

    /**
     * This test shows the full serialization, including bson encoding/decoding.
     */
    @Test
    public void testFullBSONSerialization() {
        final MyEntity entity = new MyEntity(1L, new ValueObject(2L));
        final DBObject dbObject = getMorphia().toDBObject(entity);

        final byte[] data = new DefaultDBEncoder().encode(dbObject);

        final DBObject decoded = new DefaultDBDecoder().decode(data, (DBCollection) null);
        final MyEntity actual = getMorphia().fromDBObject(MyEntity.class, decoded);
        assertEquals(entity, actual);
    }

    @Entity
    @Converters(MimeTypeConverter.class)
    public static class MimeTyped {
        @Id
        private ObjectId id;
        private String name;
        private javax.activation.MimeType mimeType;
    }

    public static class MimeTypeConverter extends TypeConverter {
        public MimeTypeConverter() {
            super(MimeType.class);
        }

        @Override
        public Object decode(final Class targetClass, final Object fromDBObject, final MappedField optionalExtraInfo) {
            try {
                return new MimeType(((BasicDBObject) fromDBObject).getString("mimeType"));
            } catch (MimeTypeParseException ex) {
                return new MimeType();
            }
        }

        @Override
        public Object encode(final Object value, final MappedField optionalExtraInfo) {
            return ((MimeType) value).getBaseType();
        }
    }

    @Test
    public void mimeType() throws UnknownHostException, MimeTypeParseException {
        getMorphia().map(MimeTyped.class);
        getDs().ensureIndexes();
        MimeTyped entity = new MimeTyped();
        entity.name = "test name";
        entity.mimeType = new MimeType("text/plain"); //MimeTypeParseException
        final DBObject dbObject = getMorphia().toDBObject(entity);
        assertEquals("text/plain", dbObject.get("mimeType"));

        getDs().save(entity); // FAILS WITH ERROR HERE
    }
}
TOP

Related Classes of org.mongodb.morphia.ext.CustomConvertersTest$ValueObject

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.