/*
 * Copyright (c) 2005, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2005, 2015 SAP. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     SAP - initial API and implementation

package org.eclipse.persistence.testing.tests.wdf.jpa1.simple;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Arrays;
import java.util.Date;
import java.util.GregorianCalendar;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceException;

import org.eclipse.persistence.testing.framework.wdf.Bugzilla;
import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.framework.wdf.Skip;
import org.eclipse.persistence.testing.models.wdf.jpa1.types.BasicTypesPropertyAccess;
import org.eclipse.persistence.testing.models.wdf.jpa1.types.UserDefinedEnum;
import org.eclipse.persistence.testing.models.wdf.jpa1.types.UserDefinedSerializable;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Test;

public class TestBasicPropertyTypes extends JPA1Base {

    @Test
    public void testInsert() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            BasicTypesPropertyAccess obj = new BasicTypesPropertyAccess(0);
            obj.fill();
            env.beginTransaction(em);
            em.persist(obj);
            env.commitTransactionAndClear(em);
            verify(true, "no Exception");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(0));
        } finally {
            closeEntityManager(em);
        }
    }

    private void validatePrimitive(final int id, Validator validator, String fieldName) {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            // insert the object
            env.beginTransaction(em);
            BasicTypesPropertyAccess obj = new BasicTypesPropertyAccess(id);
            validator.set(obj);
            em.persist(obj);
            env.commitTransactionAndClear(em);
            verify(true, "no Exception");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(!validator.isChanged(obj), fieldName + " not persisted");
            // update unchanged object
            env.beginTransaction(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            obj.clearPostUpdate();
            env.commitTransactionAndClear(em);
            verify(!obj.postUpdateWasCalled(), "postUpdate was called -> before image fails");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(!validator.isChanged(obj), fieldName + " is changed");
            // update changed object
            env.beginTransaction(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            obj.clearPostUpdate();
            validator.change(obj);
            env.commitTransactionAndClear(em);
            verify(obj.postUpdateWasCalled(), "postUpdate was not called -> before image fails");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(validator.isChanged(obj), fieldName + " is unchanged");
        } finally {
            closeEntityManager(em);
        }
    }

    private void validateReference(final int id, ReferenceValidator validator, String fieldName) {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            BasicTypesPropertyAccess obj = new BasicTypesPropertyAccess(id);
            // insert object with null-field
            env.beginTransaction(em);
            em.persist(obj);
            env.commitTransactionAndClear(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(validator.isNull(obj), fieldName + " is not null");
            // delete the object again
            env.beginTransaction(em);
            em.remove(em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id)));
            env.commitTransactionAndClear(em);
            // insert object with non-null field
            env.beginTransaction(em);
            validator.set(obj);
            em.persist(obj);
            env.commitTransactionAndClear(em);
            verify(true, "no Exception");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(!validator.isChanged(obj), fieldName + " not persisted");
            // update unchanged
            env.beginTransaction(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            obj.clearPostUpdate();
            env.commitTransactionAndClear(em);
            verify(!obj.postUpdateWasCalled(), "postUpdate was called");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(!validator.isChanged(obj), fieldName + " is changed");
            // update changed object
            env.beginTransaction(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            obj.clearPostUpdate();
            validator.change(obj);
            env.commitTransactionAndClear(em);
            verify(obj.postUpdateWasCalled(), "postUpdate was not called");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(validator.isChanged(obj), fieldName + " is unchanged");
            // update to null
            env.beginTransaction(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            obj.clearPostUpdate();
            validator.setNull(obj);
            env.commitTransactionAndClear(em);
            verify(obj.postUpdateWasCalled(), "postUpdate was not called");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(validator.isNull(obj), fieldName + " is not null");
        } finally {
            closeEntityManager(em);
        }
    }

    private void validateMutable(final int id, MutableValidator validator, String fieldName) {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            BasicTypesPropertyAccess obj = new BasicTypesPropertyAccess(id);
            // insert object with null-field
            env.beginTransaction(em);
            em.persist(obj);
            env.commitTransactionAndClear(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(validator.isNull(obj), fieldName + " is not null");
            // delete the object again
            env.beginTransaction(em);
            em.remove(em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id)));
            env.commitTransactionAndClear(em);
            // insert object with non-null field
            env.beginTransaction(em);
            validator.set(obj);
            em.persist(obj);
            env.commitTransactionAndClear(em);
            verify(true, "no Exception");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(!validator.isChanged(obj), fieldName + " not persisted");
            // update unchanged
            env.beginTransaction(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            obj.clearPostUpdate();
            env.commitTransactionAndClear(em);
            verify(!obj.postUpdateWasCalled(), "postUpdate was not called");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(!validator.isChanged(obj), fieldName + " is changed");
            // update changed
            env.beginTransaction(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            obj.clearPostUpdate();
            validator.setNull(obj);
            env.commitTransactionAndClear(em);
            verify(obj.postUpdateWasCalled(), "postUpdate was not called");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(validator.isNull(obj), fieldName + " is not null");
            // update original
            env.beginTransaction(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            validator.set(obj);
            env.commitTransactionAndClear(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(!validator.isChanged(obj), fieldName + " not persisted");
            // mutate
            env.beginTransaction(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            obj.clearPostUpdate();
            validator.mutate(obj);
            env.commitTransactionAndClear(em);
            verify(obj.postUpdateWasCalled(), "postUpdate was not called");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(validator.isChanged(obj), fieldName + " not mutated");
            // update to null
            env.beginTransaction(em);
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            obj.clearPostUpdate();
            validator.setNull(obj);
            env.commitTransactionAndClear(em);
            verify(obj.postUpdateWasCalled(), "postUpdate was not called");
            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(id));
            verify(validator.isNull(obj), fieldName + " is not null");
        } finally {
            closeEntityManager(em);
        }
    }

    // primitive types
    @Test
    public void testPrimitiveBoolean() {
        Validator validator = new Validator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveBoolean(true);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveBoolean(false);
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return obj.getPrimitiveBoolean() != true;
            }
        };
        validatePrimitive(1, validator, "primitiveBoolean");
    }

    @Test
    public void testPrimitiveByte() {
        Validator validator = new Validator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimititveByte((byte) 17);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimititveByte((byte) 23);
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return obj.getPrimititveByte() != 17;
            }
        };
        validatePrimitive(2, validator, "primitiveByte");
    }

    @Test
    public void testPrimitiveChar() {
        Validator validator = new Validator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveChar('A');
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveChar('B');
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return obj.getPrimitiveChar() != 'A';
            }
        };
        validatePrimitive(3, validator, "primitiveChar");
    }

    @Test
    public void testPrimitiveShort() {
        Validator validator = new Validator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveShort((short) 19);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveShort((short) 45);
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return obj.getPrimitiveShort() != 19;
            }
        };
        validatePrimitive(4, validator, "primitiveShort");
    }

    @Test
    public void testPrimitiveInt() {
        Validator validator = new Validator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveInt(88);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveInt(77);
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return obj.getPrimitiveInt() != 88;
            }
        };
        validatePrimitive(5, validator, "primitiveInt");
    }

    @Test
    public void testPrimitiveLong() {
        Validator validator = new Validator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveLong(88);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveLong(77);
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return obj.getPrimitiveLong() != 88;
            }
        };
        validatePrimitive(6, validator, "primitiveLong");
    }

    @Test
    public void testPrimitiveFloat() {
        Validator validator = new Validator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveFloat((float) 88.5);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveFloat((float) 77.5);
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return obj.getPrimitiveFloat() != 88.5;
            }
        };
        validatePrimitive(7, validator, "primitiveFloat");
    }

    @Test
    public void testPrimitiveDouble() {
        Validator validator = new Validator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveDouble(99.5);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveDouble(77.5);
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return obj.getPrimitiveDouble() != 99.5;
            }
        };
        validatePrimitive(8, validator, "primitiveDouble");
    }

    // wrappers of primitive types
    @Test
    public void testWrapperBoolean() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperBoolean(Boolean.TRUE);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperBoolean(Boolean.FALSE);
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperBoolean(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.isWrapperBoolean() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.isWrapperBoolean().equals(Boolean.TRUE);
            }
        };
        validateReference(11, validator, "wrapperBoolean");
    }

    @Test
    public void testWrapperByte() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperByte(Byte.valueOf((byte) 17));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperByte(Byte.valueOf((byte) 18));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperByte(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getWrapperByte() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getWrapperByte().equals(Byte.valueOf((byte) 17));
            }
        };
        validateReference(12, validator, "wrapperByte");
    }

    @Test
    public void testWrapperCharacter() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperCharacter(Character.valueOf('A'));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperCharacter(Character.valueOf('B'));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperCharacter(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getWrapperCharacter() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getWrapperCharacter().equals(Character.valueOf('A'));
            }
        };
        validateReference(13, validator, "wrapperCharacter");
    }

    @Test
    public void testWrapperShort() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperShort(Short.valueOf((short) 1));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperShort(Short.valueOf((short) 2));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperShort(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getWrapperShort() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getWrapperShort().equals(Short.valueOf((short) 1));
            }
        };
        validateReference(14, validator, "wrapperShort");
    }

    @Test
    public void testWrapperInteger() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperInteger(Integer.valueOf(1));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperInteger(Integer.valueOf(2));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperInteger(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getWrapperInteger() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getWrapperInteger().equals(Integer.valueOf(1));
            }
        };
        validateReference(15, validator, "wrapperInteger");
    }

    @Test
    public void testWrapperLong() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperLong(Long.valueOf(1));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperLong(Long.valueOf(2));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperLong(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getWrapperLong() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getWrapperLong().equals(Long.valueOf(1));
            }
        };
        validateReference(16, validator, "wrapperLong");
    }

    @Test
    public void testWrapperDouble() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperDouble(Double.valueOf(1));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperDouble(Double.valueOf(2));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperDouble(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getWrapperDouble() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getWrapperDouble().equals(Double.valueOf(1));
            }
        };
        validateReference(18, validator, "wrapperDouble");
    }

    @Test
    public void testWrapperFloat() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperFloat(Float.valueOf(1));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperFloat(Float.valueOf(2));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperFloat(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getWrapperFloat() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getWrapperFloat().equals(Float.valueOf(1));
            }
        };
        validateReference(17, validator, "wrapperFloat");
    }

    // immutable reference types
    @Test
    public void testString2Varchar() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setString2Varchar("VC 1");
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setString2Varchar("VC 2");
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setString2Varchar(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getString2Varchar() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getString2Varchar().equals("VC 1");
            }
        };
        validateReference(21, validator, "string2Varchar");
    }

    @Test
    public void testString2Clob() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setString2Clob("VC 1");
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setString2Clob("VC 2");
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setString2Clob(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getString2Clob() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getString2Clob().equals("VC 1");
            }
        };
        validateReference(22, validator, "string2Clob");
    }

    @Test
    public void testBigDecimal() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setBigDecimal(new BigDecimal("1.1"));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setBigDecimal(new BigDecimal("2.2"));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setBigDecimal(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getBigDecimal() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return obj.getBigDecimal().compareTo(new BigDecimal("1.1")) != 0;
            }
        };
        validateReference(23, validator, "bigDecimal");
    }

    @Test
    public void testBigInteger() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setBigInteger(new BigInteger("11"));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setBigInteger(new BigInteger("22"));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setBigInteger(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getBigInteger() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getBigInteger().equals(new BigInteger("11"));
            }
        };
        validateReference(24, validator, "bigInteger");
    }

    // mutable types
    @Test
    public void testUtilDate() {
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setUtilDate(new Date(1000));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setUtilDate(new Date(2000));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setUtilDate(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getUtilDate() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getUtilDate().equals(new Date(1000));
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getUtilDate().setTime(2000);
            }
        };
        validateMutable(31, validator, "utilDate");
    }

    @Test
    public void testUtilCalendar() {
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setUtilCalendar(new GregorianCalendar(2005, 9, 8, 10, 49));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setUtilCalendar(new GregorianCalendar(2005, 9, 9, 10, 49));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setUtilCalendar(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getUtilCalendar() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getUtilCalendar().equals(new GregorianCalendar(2005, 9, 8, 10, 49));
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getUtilCalendar().set(2005, 9, 9);
            }
        };
        validateMutable(32, validator, "utilCalendar");
    }

    @Test
    public void testSqlDate() {
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setSqlDate(java.sql.Date.valueOf("2005-09-08"));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setSqlDate(java.sql.Date.valueOf("2005-09-09"));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setSqlDate(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getSqlDate() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getSqlDate().equals(java.sql.Date.valueOf("2005-09-08"));
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getSqlDate().setTime(java.sql.Date.valueOf("2005-09-09").getTime());
            }
        };
        validateMutable(33, validator, "sqlDate");
    }

    @Test
    public void testSqlTime() {
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setSqlTime(java.sql.Time.valueOf("10:49:00"));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setSqlTime(java.sql.Time.valueOf("11:49:00"));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setSqlTime(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getSqlTime() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getSqlTime().equals(java.sql.Time.valueOf("10:49:00"));
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getSqlTime().setTime(java.sql.Time.valueOf("11:49:00").getTime());
            }
        };
        validateMutable(34, validator, "sqlTime");
    }

    @Test
    public void testSqlTimestamp() {
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setSqlTimestamp(new java.sql.Timestamp(1000));
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setSqlTimestamp(new java.sql.Timestamp(2000));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setSqlTimestamp(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getSqlTimestamp() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !obj.getSqlTimestamp().equals(new java.sql.Timestamp(1000));
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getSqlTimestamp().setTime(2000);
            }
        };
        validateMutable(35, validator, "sqlTimestamp");
    }

    // arrays
    @Test
    public void testPrimitiveByteArray2Binary() {
        final byte[] UNCHANGED = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveByteArray2Binary(UNCHANGED);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveByteArray2Binary(new byte[] { 8, 1, 2, 3, 4, 5, 6, 7 });
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveByteArray2Binary(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getPrimitiveByteArray2Binary() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !Arrays.equals(UNCHANGED, obj.getPrimitiveByteArray2Binary());
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getPrimitiveByteArray2Binary()[0] = 8;
            }
        };
        validateMutable(41, validator, "primitiveByteArray2Binary");
    }

    @Test
    @Skip(databaseNames = "org.eclipse.persistence.platform.database.MaxDBPlatform")
    public void testPrimitiveByteArray2Longvarbinary() {
        final byte[] UNCHANGED = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveByteArray2Longvarbinary(UNCHANGED);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveByteArray2Longvarbinary(new byte[] { 8, 1, 2, 3, 4, 5, 6, 7 });
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveByteArray2Longvarbinary(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getPrimitiveByteArray2Longvarbinary() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !Arrays.equals(UNCHANGED, obj.getPrimitiveByteArray2Longvarbinary());
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getPrimitiveByteArray2Longvarbinary()[0] = 8;
            }
        };
        validateMutable(42, validator, "primitiveByteArray2Longvarbinary");
    }

    @Test
    public void testPrimitiveByteArray2Blob() {
        final byte[] UNCHANGED = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveByteArray2Blob(UNCHANGED);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveByteArray2Blob(new byte[] { 8, 1, 2, 3, 4, 5, 6, 7 });
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveByteArray2Blob(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getPrimitiveByteArray2Blob() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !Arrays.equals(UNCHANGED, obj.getPrimitiveByteArray2Blob());
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getPrimitiveByteArray2Blob()[0] = 8;
            }
        };
        validateMutable(43, validator, "primitiveByteArray2Blob");
    }

    @Test
    public void testPrimitiveCharArray2Varchar() {
        final char[] UNCHANGED = new char[] { 'U', 'N', 'C', 'H', 'A', 'N', 'G', 'E', 'D' };
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveCharArray2Varchar(UNCHANGED);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveCharArray2Varchar(new char[] { 'C', 'H', 'A', 'N', 'G', 'E', 'D' });
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveCharArray2Varchar(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getPrimitiveCharArray2Varchar() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !Arrays.equals(UNCHANGED, obj.getPrimitiveCharArray2Varchar());
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getPrimitiveCharArray2Varchar()[0] = 'X';
            }
        };
        validateMutable(44, validator, "primitiveCharArray2Varchar");
    }

    @Test
    public void testPrimitiveCharArray2Clob() {
        final char[] UNCHANGED = new char[] { 'U', 'N', 'C', 'H', 'A', 'N', 'G', 'E', 'D' };
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveCharArray2Clob(UNCHANGED);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveCharArray2Clob(new char[] { 'C', 'H', 'A', 'N', 'G', 'E', 'D' });
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setPrimitiveCharArray2Clob(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getPrimitiveCharArray2Clob() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !Arrays.equals(UNCHANGED, obj.getPrimitiveCharArray2Clob());
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getPrimitiveCharArray2Clob()[0] = 'X';
            }
        };
        validateMutable(45, validator, "primitiveCharArray2Clob");
    }

    @Test
    public void testWrapperByteArray2Binary() {
        final Byte[] UNCHANGED = new Byte[] { Byte.valueOf((byte) 0), Byte.valueOf((byte) 1), Byte.valueOf((byte) 2),
                Byte.valueOf((byte) 3), Byte.valueOf((byte) 4), Byte.valueOf((byte) 5), Byte.valueOf((byte) 6),
                Byte.valueOf((byte) 7), };
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperByteArray2Binary(UNCHANGED);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperByteArray2Binary(new Byte[] { Byte.valueOf((byte) 8), Byte.valueOf((byte) 1),
                        Byte.valueOf((byte) 2), Byte.valueOf((byte) 3), Byte.valueOf((byte) 4), Byte.valueOf((byte) 5),
                        Byte.valueOf((byte) 6), Byte.valueOf((byte) 7), });
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperByteArray2Binary(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getWrapperByteArray2Binary() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !Arrays.equals(UNCHANGED, obj.getWrapperByteArray2Binary());
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getWrapperByteArray2Binary()[0] = Byte.valueOf((byte) 8);
            }
        };
        validateMutable(46, validator, "wrapperByteArray2Binary");
    }

    @Test
    public void testWrapperByteArray2Longvarbinary() {
        final Byte[] UNCHANGED = new Byte[] { Byte.valueOf((byte) 0), Byte.valueOf((byte) 1), Byte.valueOf((byte) 2),
                Byte.valueOf((byte) 3), Byte.valueOf((byte) 4), Byte.valueOf((byte) 5), Byte.valueOf((byte) 6),
                Byte.valueOf((byte) 7), };
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperByteArray2Longvarbinary(UNCHANGED);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperByteArray2Longvarbinary(new Byte[] { Byte.valueOf((byte) 8), Byte.valueOf((byte) 1),
                        Byte.valueOf((byte) 2), Byte.valueOf((byte) 3), Byte.valueOf((byte) 4), Byte.valueOf((byte) 5),
                        Byte.valueOf((byte) 6), Byte.valueOf((byte) 7), });
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperByteArray2Longvarbinary(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getWrapperByteArray2Longvarbinary() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !Arrays.equals(UNCHANGED, obj.getWrapperByteArray2Longvarbinary());
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getWrapperByteArray2Longvarbinary()[0] = Byte.valueOf((byte) 8);
            }
        };
        validateMutable(47, validator, "wrapperByteArray2Longvarbinary");
    }

    @Test
    public void testWrapperByteArray2Blob() {
        final Byte[] UNCHANGED = new Byte[] { Byte.valueOf((byte) 0), Byte.valueOf((byte) 1), Byte.valueOf((byte) 2),
                Byte.valueOf((byte) 3), Byte.valueOf((byte) 4), Byte.valueOf((byte) 5), Byte.valueOf((byte) 6),
                Byte.valueOf((byte) 7), };
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperByteArray2Blob(UNCHANGED);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperByteArray2Blob(new Byte[] { Byte.valueOf((byte) 8), Byte.valueOf((byte) 1),
                        Byte.valueOf((byte) 2), Byte.valueOf((byte) 3), Byte.valueOf((byte) 4), Byte.valueOf((byte) 5),
                        Byte.valueOf((byte) 6), Byte.valueOf((byte) 7) });
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperByteArray2Blob(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getWrapperByteArray2Blob() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !Arrays.equals(UNCHANGED, obj.getWrapperByteArray2Blob());
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getWrapperByteArray2Blob()[0] = Byte.valueOf((byte) 8);
            }
        };
        validateMutable(48, validator, "wrapperByteArray2Blob");
    }

    @SuppressWarnings("boxing")
    @Test
    public void testWrapperCharArray2Varchar() {
        final Character[] UNCHANGED = new Character[] { 'U', 'N', 'C', 'H', 'A', 'N', 'G', 'E', 'D' };
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperCharacterArray2Varchar(UNCHANGED);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperCharacterArray2Varchar(new Character[] { 'C', 'H', 'A', 'N', 'G', 'E', 'D' });
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperCharacterArray2Varchar(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getWrapperCharacterArray2Varchar() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !Arrays.equals(UNCHANGED, obj.getWrapperCharacterArray2Varchar());
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getWrapperCharacterArray2Varchar()[0] = 'X';
            }
        };
        validateMutable(49, validator, "wrapperCharArray2Varchar");
    }

    @SuppressWarnings("boxing")
    @Test
    public void testWrapperCharArray2Clob() {
        final Character[] UNCHANGED = new Character[] { 'U', 'N', 'C', 'H', 'A', 'N', 'G', 'E', 'D' };
        MutableValidator validator = new MutableValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setWrapperCharacterArray2Clob(UNCHANGED);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setWrapperCharacterArray2Clob(new Character[] { 'C', 'H', 'A', 'N', 'G', 'E', 'D' });
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setWrapperCharacterArray2Clob(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getWrapperCharacterArray2Clob() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !Arrays.equals(UNCHANGED, obj.getWrapperCharacterArray2Clob());
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                obj.getWrapperCharacterArray2Clob()[0] = 'X';
            }
        };
        validateMutable(50, validator, "wrapperCharArray2Clob");
    }

    @Test
    public void testSerializable() {
        MutableValidator validator = new MutableValidator() {
            UserDefinedSerializable UNCHANGED = new UserDefinedSerializable("Unchanged");

            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setSerializable(UNCHANGED);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setSerializable(new UserDefinedSerializable("Changed"));
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setSerializable(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getSerializable() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return !UNCHANGED.equals(obj.getSerializable());
            }

            @Override
            public void mutate(BasicTypesPropertyAccess obj) {
                ((UserDefinedSerializable) obj.getSerializable()).setTxt("Changed");
            }
        };
        validateMutable(51, validator, "serializable");
    }

    @Test
    public void testEnumString() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setEnumString(UserDefinedEnum.HUGO);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setEnumString(UserDefinedEnum.EMIL);
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setEnumString(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getEnumString() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return obj.getEnumString() != UserDefinedEnum.HUGO;
            }
        };
        validateReference(52, validator, "enumString");
    }

    @Test
    public void testEnumOrdinal() {
        ReferenceValidator validator = new ReferenceValidator() {
            @Override
            public void set(BasicTypesPropertyAccess obj) {
                obj.setEnumOrdinal(UserDefinedEnum.HUGO);
            }

            @Override
            public void change(BasicTypesPropertyAccess obj) {
                obj.setEnumOrdinal(UserDefinedEnum.EMIL);
            }

            @Override
            public void setNull(BasicTypesPropertyAccess obj) {
                obj.setEnumOrdinal(null);
            }

            @Override
            public boolean isNull(BasicTypesPropertyAccess obj) {
                return obj.getEnumOrdinal() == null;
            }

            @Override
            public boolean isChanged(BasicTypesPropertyAccess obj) {
                return obj.getEnumOrdinal() != UserDefinedEnum.HUGO;
            }
        };
        validateReference(53, validator, "enumOrdinal");
    }

    @Test
    @Bugzilla(bugid=309681)
    public void testNullsPAshort() throws SQLException {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        BasicTypesPropertyAccess obj = new BasicTypesPropertyAccess(8888);
        try {
            obj.fill();
            env.beginTransaction(em);
            em.persist(obj);
            env.commitTransactionAndClear(em);

            Connection con = env.getDataSource().getConnection();
            try {
                String stmt = "update TMP_BASIC_TYPES_PA set P_SHORT = ? where ID = 8888";
                PreparedStatement pstmt = con.prepareStatement(stmt);
                try {
                    pstmt.setNull(1, Types.SMALLINT);
                    pstmt.executeUpdate();
                } finally {
                    pstmt.close();
                }
                if (!con.getAutoCommit()) {
                    con.commit();
                }
            } finally {
                con.close();
            }

            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(8888));
            flop("missing exception");
        } catch (PersistenceException iae) {
            // $JL-EXC$ expected behavior
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @Bugzilla(bugid = 309681)
    public void testNullsPAint() throws SQLException {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        BasicTypesPropertyAccess obj = new BasicTypesPropertyAccess(8889);
        try {
            obj.fill();
            env.beginTransaction(em);
            em.persist(obj);
            env.commitTransactionAndClear(em);

            Connection con = env.getDataSource().getConnection();
            try {
                String stmt = "update TMP_BASIC_TYPES_PA set P_INT = ? where ID = 8889";
                PreparedStatement pstmt = con.prepareStatement(stmt);
                try {
                    pstmt.setNull(1, Types.INTEGER);
                    pstmt.executeUpdate();
                } finally {
                    pstmt.close();
                }
                if (!con.getAutoCommit()) {
                    con.commit();
                }
            } finally {
                con.close();
            }

            obj = em.find(BasicTypesPropertyAccess.class, Integer.valueOf(8889));
            flop("missing exception");
        } catch (PersistenceException iae) {
            // $JL-EXC$ expected behavior
        } finally {
            closeEntityManager(em);
        }
    }

    private interface Validator {
        void set(BasicTypesPropertyAccess obj);

        void change(BasicTypesPropertyAccess obj);

        boolean isChanged(BasicTypesPropertyAccess obj);
    }

    private interface ReferenceValidator extends Validator {
        boolean isNull(BasicTypesPropertyAccess obj);

        void setNull(BasicTypesPropertyAccess obj);
    }

    private interface MutableValidator extends ReferenceValidator {
        void mutate(BasicTypesPropertyAccess obj);
    }
}
