You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2022/07/14 08:00:55 UTC

[cayenne] branch master updated (7823a8701 -> fee848de3)

This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git


    from 7823a8701 Replace deprecated JUnit method assertThat()
     new 1debe62f2 Some more warnings cleanup
     new f7a44ff1d code cleanup
     new fee848de3 Add generics for the type-safety to the Entity/Attribute/Relationship hierarchy

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../java/org/apache/cayenne/map/Attribute.java     |  12 +-
 .../main/java/org/apache/cayenne/map/DataMap.java  |  10 +-
 .../java/org/apache/cayenne/map/DbAttribute.java   |   2 +-
 .../main/java/org/apache/cayenne/map/DbEntity.java |  89 +-----
 .../org/apache/cayenne/map/DbRelationship.java     |   2 +-
 .../main/java/org/apache/cayenne/map/Entity.java   |  56 ++--
 .../java/org/apache/cayenne/map/ObjAttribute.java  |   2 +-
 .../java/org/apache/cayenne/map/ObjEntity.java     |  71 ++---
 .../org/apache/cayenne/map/ObjRelationship.java    |  18 +-
 .../apache/cayenne/map/PathComponentIterator.java  |  30 +-
 .../java/org/apache/cayenne/map/Relationship.java  |  20 +-
 .../java/org/apache/cayenne/reflect/Converter.java |   4 +-
 .../apache/cayenne/reflect/ConverterFactory.java   | 310 +++++++++------------
 .../org/apache/cayenne/reflect/EnumConverter.java  |   4 +-
 .../org/apache/cayenne/reflect/ToAnyConverter.java |  11 +-
 .../cayenne/access/types/MockExtendedType.java     |   4 +-
 .../server/JNDIDataSourceFactoryIT.java            |   1 +
 .../java/org/apache/cayenne/map/AttributeTest.java |   6 +-
 .../test/java/org/apache/cayenne/map/EntityIT.java |  36 +--
 .../java/org/apache/cayenne/map/MockAttribute.java |   2 +-
 .../java/org/apache/cayenne/map/MockEntity.java    |   8 +-
 .../org/apache/cayenne/map/MockRelationship.java   |   2 +-
 .../org/apache/cayenne/map/RelationshipTest.java   |  12 +-
 .../reflect/LifecycleCallbackEventHandlerTest.java |   2 +-
 .../apache/cayenne/reflect/PropertyUtilsTest.java  |  29 +-
 .../template/directive/BindDirectiveIT.java        |   2 +-
 .../java/org/apache/cayenne/unit/util/TstBean.java |   4 +-
 .../apache/cayenne/velocity/ResultDirective.java   |   5 +-
 .../apache/cayenne/modeler/ProjectController.java  | 201 ++++++-------
 .../apache/cayenne/modeler/ProjectTreeView.java    |   4 +-
 .../modeler/action/ImportEOModelAction.java        |   3 +-
 .../modeler/editor/ObjAttributeTableModel.java     |  55 ++--
 .../editor/wrapper/ObjAttributeWrapper.java        |  12 +-
 .../cayenne/modeler/graph/BaseGraphBuilder.java    |   2 +-
 .../modeler/graph/DbEntityCellMetadata.java        |  20 +-
 .../cayenne/modeler/graph/EntityCellMetadata.java  |  13 +-
 .../modeler/graph/ObjEntityCellMetadata.java       |  19 +-
 .../modeler/undo/RelationshipUndoableEdit.java     |  42 +--
 .../cayenne/modeler/util/EntityTreeModel.java      |  24 +-
 .../org/apache/cayenne/wocompat/EOObjEntity.java   |   3 +-
 40 files changed, 479 insertions(+), 673 deletions(-)


[cayenne] 01/03: Some more warnings cleanup

Posted by nt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit 1debe62f23a29027c9de55c4cdcce4b9b7661dec
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Wed Jul 13 18:10:08 2022 +0300

    Some more warnings cleanup
---
 .../java/org/apache/cayenne/reflect/Converter.java |   4 +-
 .../apache/cayenne/reflect/ConverterFactory.java   | 310 +++++++++------------
 .../org/apache/cayenne/reflect/EnumConverter.java  |   4 +-
 .../org/apache/cayenne/reflect/ToAnyConverter.java |  11 +-
 .../cayenne/access/types/MockExtendedType.java     |   4 +-
 .../server/JNDIDataSourceFactoryIT.java            |   1 +
 .../reflect/LifecycleCallbackEventHandlerTest.java |   2 +-
 .../apache/cayenne/reflect/PropertyUtilsTest.java  |  29 +-
 .../template/directive/BindDirectiveIT.java        |   2 +-
 .../java/org/apache/cayenne/unit/util/TstBean.java |   4 +-
 .../apache/cayenne/velocity/ResultDirective.java   |   5 +-
 .../apache/cayenne/modeler/ProjectTreeView.java    |   4 +-
 .../modeler/action/ImportEOModelAction.java        |   3 +-
 13 files changed, 166 insertions(+), 217 deletions(-)

diff --git a/cayenne-server/src/main/java/org/apache/cayenne/reflect/Converter.java b/cayenne-server/src/main/java/org/apache/cayenne/reflect/Converter.java
index 567b5d448..687c8b9e1 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/reflect/Converter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/reflect/Converter.java
@@ -24,7 +24,7 @@ package org.apache.cayenne.reflect;
  * 
  * @since 1.2
  */
-public abstract class Converter<T> {
+public interface Converter<T> {
 
 	/**
 	 * Converts object to supported class without doing any type checking.
@@ -35,5 +35,5 @@ public abstract class Converter<T> {
 	 * @return
 	 * 		an object of type @code{type}. If the conversion fails an exception will be thrown. If value is null then the result will be null.
 	 */
-    protected abstract T convert(Object value, Class<T> type);
+    T convert(Object value, Class<T> type);
 }
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/reflect/ConverterFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/reflect/ConverterFactory.java
index 248dcd765..03894217a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/reflect/ConverterFactory.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/reflect/ConverterFactory.java
@@ -36,222 +36,173 @@ public class ConverterFactory {
 
     static final ConverterFactory factory = new ConverterFactory();
 
-    private Map<Class<?>, Converter<?>> converters;
-    private EnumConverter enumConveter = new EnumConverter();
-    private Converter<Object> toAnyConverter = new ToAnyConverter<Object>();
-    
+    private final Map<Class<?>, Converter<?>> converters;
+    private final EnumConverter<?> enumConverter = new EnumConverter<>();
+    private final Converter<Object> toAnyConverter = new ToAnyConverter<>();
+
+    // TODO: this methods uses deprecated Date.parse method that has no direct replacement,
+    //       we need to determine date formats we should support and update code accordingly
+    @SuppressWarnings("deprecation")
     private ConverterFactory() {
 
-        Converter<String> toStringConverter = new Converter<String>() {
+        Converter<String> toStringConverter = (object, type) -> object != null ? object.toString() : null;
 
-            @Override
-			protected String convert(Object object, Class<String> type) {
-                return object != null ? object.toString() : null;
+        Converter<Boolean> toBooleanConverter = (object, type) -> {
+            if (object == null) {
+                return type.isPrimitive() ? Boolean.FALSE : null;
             }
-        };
-
-        Converter<Boolean> toBooleanConverter = new Converter<Boolean>() {
-
-            @Override
-            protected Boolean convert(Object object, Class<Boolean> type) {
-                if (object == null) {
-                    return type.isPrimitive() ? Boolean.FALSE : null;
-                }
 
-                if (object instanceof Boolean) {
-                    return (Boolean)object;
-                } else if (object instanceof Integer || object instanceof Long || object instanceof Short || object instanceof Byte) {
-                	if (((Number)object).longValue() == 0) {
-                        return Boolean.FALSE;
-                    } else if (((Number)object).longValue() == 1) {
-                        return Boolean.TRUE;
-                    }
+            if (object instanceof Boolean) {
+                return (Boolean) object;
+            } else if (object instanceof Integer || object instanceof Long || object instanceof Short || object instanceof Byte) {
+                if (((Number) object).longValue() == 0) {
+                    return Boolean.FALSE;
+                } else if (((Number) object).longValue() == 1) {
+                    return Boolean.TRUE;
                 }
-
-                return "true".equalsIgnoreCase(object.toString())
-                        ? Boolean.TRUE
-                        : Boolean.FALSE;
             }
-        };
-
-        Converter<Long> toLongConverter = new Converter<Long>() {
-
-            @Override
-            protected Long convert(Object object, Class<Long> type) {
-                if (object == null) {
-                    return type.isPrimitive() ? Long.valueOf(0) : null;
-                }
-
-                if (object instanceof Long) {
-                    return (Long)object;
-                }
 
-                return Long.valueOf(object.toString());
-            }
+            return "true".equalsIgnoreCase(object.toString())
+                    ? Boolean.TRUE
+                    : Boolean.FALSE;
         };
-        
-        Converter<Integer> toIntConverter = new Converter<Integer>() {
-
-            @Override
-            protected Integer convert(Object object, Class<Integer> type) {
-                if (object == null) {
-                    return type.isPrimitive() ? 0 : null;
-                }
-
-                if (object instanceof Integer) {
-                    return (Integer)object;
-                }
 
-                return Integer.valueOf(object.toString());
+        Converter<Long> toLongConverter = (object, type) -> {
+            if (object == null) {
+                return type.isPrimitive() ? 0L : null;
             }
-        };
 
-        Converter<Byte> toByteConverter = new Converter<Byte>() {
+            if (object instanceof Long) {
+                return (Long) object;
+            }
 
-            @Override
-            protected Byte convert(Object object, Class<Byte> type) {
-                if (object == null) {
-                    return type.isPrimitive() ? (byte) 0 : null;
-                }
+            return Long.valueOf(object.toString());
+        };
 
-                if (object instanceof Byte) {
-                    return (Byte)object;
-                }
+        Converter<Integer> toIntConverter = (object, type) -> {
+            if (object == null) {
+                return type.isPrimitive() ? 0 : null;
+            }
 
-                return Byte.valueOf(object.toString());
+            if (object instanceof Integer) {
+                return (Integer) object;
             }
+
+            return Integer.valueOf(object.toString());
         };
 
-        Converter<Short> toShortConverter = new Converter<Short>() {
+        Converter<Byte> toByteConverter = (object, type) -> {
+            if (object == null) {
+                return type.isPrimitive() ? (byte) 0 : null;
+            }
 
-            @Override
-            protected Short convert(Object object, Class<Short> type) {
-                if (object == null) {
-                    return type.isPrimitive() ? (short) 0 : null;
-                }
+            if (object instanceof Byte) {
+                return (Byte) object;
+            }
 
-                if (object instanceof Short) {
-                    return (Short)object;
-                }
+            return Byte.valueOf(object.toString());
+        };
 
-                return Short.valueOf(object.toString());
+        Converter<Short> toShortConverter = (object, type) -> {
+            if (object == null) {
+                return type.isPrimitive() ? (short) 0 : null;
             }
-        };
 
-        Converter<Character> toCharConverter = new Converter<Character>() {
+            if (object instanceof Short) {
+                return (Short) object;
+            }
 
-            @Override
-            protected Character convert(Object object, Class<Character> type) {
-                if (object == null) {
-                    return type.isPrimitive() ? (char) 0 : null;
-                }
+            return Short.valueOf(object.toString());
+        };
 
-                if (object instanceof Character) {
-                    return (Character)object;
-                }
+        Converter<Character> toCharConverter = (object, type) -> {
+            if (object == null) {
+                return type.isPrimitive() ? (char) 0 : null;
+            }
 
-                String string = object.toString();
-                return Character.valueOf(string.length() > 0 ? string.charAt(0) : 0);
+            if (object instanceof Character) {
+                return (Character) object;
             }
+
+            String string = object.toString();
+            return string.length() > 0 ? string.charAt(0) : 0;
         };
 
-        Converter<Double> toDoubleConverter = new Converter<Double>() {
+        Converter<Double> toDoubleConverter = (object, type) -> {
+            if (object == null) {
+                return type.isPrimitive() ? 0.0d : null;
+            }
 
-            @Override
-            protected Double convert(Object object, Class<Double> type) {
-                if (object == null) {
-                    return type.isPrimitive() ? 0.0d : null;
-                }
+            if (object instanceof Double) {
+                return (Double) object;
+            }
 
-                if (object instanceof Double) {
-                    return (Double)object;
-                }
+            return Double.valueOf(object.toString());
+        };
 
-                return Double.valueOf(object.toString());
+        Converter<Float> toFloatConverter = (object, type) -> {
+            if (object == null) {
+                return type.isPrimitive() ? 0.0f : null;
             }
-        };
 
-        Converter<Float> toFloatConverter = new Converter<Float>() {
+            if (object instanceof Float) {
+                return (Float) object;
+            }
 
-            @Override
-            protected Float convert(Object object, Class<Float> type) {
-                if (object == null) {
-                    return type.isPrimitive() ? 0.0f : null;
-                }
+            return Float.valueOf(object.toString());
+        };
 
-                if (object instanceof Float) {
-                    return (Float)object;
-                }
+        Converter<BigDecimal> toBigDecimalConverter = (object, type) -> {
+            if (object == null) {
+                return null;
+            }
 
-                return Float.valueOf(object.toString());
+            if (object instanceof BigDecimal) {
+                return (BigDecimal) object;
             }
+
+            return new BigDecimal(object.toString());
         };
 
-        Converter<BigDecimal> toBigDecimalConverter = new Converter<BigDecimal>() {
+        Converter<BigInteger> toBigIntegerConverter = (object, type) -> {
+            if (object == null) {
+                return null;
+            }
 
-            @Override
-            protected BigDecimal convert(Object object, Class<BigDecimal> type) {
-                if (object == null) {
-                    return null;
-                }
+            if (object instanceof BigInteger) {
+                return (BigInteger) object;
+            }
 
-                if (object instanceof BigDecimal) {
-                    return (BigDecimal)object;
-                }
+            return new BigInteger(object.toString());
+        };
 
-                return new BigDecimal(object.toString());
+        Converter<Date> toDateConverter = (value, type) -> {
+            if (value == null) {
+                return null;
             }
+            if (value instanceof Date) {
+                return (Date) value;
+            }
+            if (value instanceof Number) {
+                return new Date(((Number) value).longValue());
+            }
+            return new Date(value.toString());
         };
 
-        Converter<BigInteger> toBigIntegerConverter = new Converter<BigInteger>() {
-
-            @Override
-            protected BigInteger convert(Object object, Class<BigInteger> type) {
-                if (object == null) {
-                    return null;
-                }
-
-                if (object instanceof BigInteger) {
-                    return (BigInteger)object;
-                }
-
-                return new BigInteger(object.toString());
+        Converter<Timestamp> toTimestampConverter = (value, type) -> {
+            if (value == null) {
+                return null;
+            }
+            if (value instanceof Timestamp) {
+                return (Timestamp) value;
+            }
+            if (value instanceof Number) {
+                return new Timestamp(((Number) value).longValue());
             }
+            return new Timestamp(Date.parse(value.toString()));
         };
 
-		Converter<Date> toDateConverter = new Converter<Date>() {
-			@Override
-			protected Date convert(Object value, Class<Date> type) {
-				if (value == null) {
-                    return null;
-                }
-				if (value instanceof Date) {
-                    return (Date) value;
-                }
-				if (value instanceof Number){
-				    return new Date(((Number)value).longValue());
-                }
-				return new Date(value.toString());
-			}
-		};
-		
-		Converter<Timestamp> toTimestampConverter = new Converter<Timestamp>() {
-			@Override
-			protected Timestamp convert(Object value, Class<Timestamp> type) {
-				if (value == null) {
-                    return null;
-                }
-				if (value instanceof Timestamp) {
-                    return (Timestamp) value;
-                }
-				if (value instanceof Number){
-				    return new Timestamp(((Number)value).longValue());
-                }
-				return new Timestamp(Date.parse(value.toString()));
-			}
-		};
-		
-		// TODO: byte[] converter...
+        // TODO: byte[] converter...
 
         converters = new HashMap<>();
 
@@ -283,28 +234,27 @@ public class ConverterFactory {
         _addConverter(BigInteger.class, toBigIntegerConverter);
         _addConverter(Number.class, toBigDecimalConverter);
         _addConverter(String.class, toStringConverter);
-		_addConverter(Date.class, toDateConverter);
-		_addConverter(Timestamp.class, toTimestampConverter);
+        _addConverter(Date.class, toDateConverter);
+        _addConverter(Timestamp.class, toTimestampConverter);
     }
 
     /**
      * Converters are used by {@link PropertyUtils#setProperty(Object, String, Object)} to coerce
      * generic Object values into the specific type expected by the named setter.
-     * 
-     * @param type
-     * 		the Class to convert a value to; the destination type
-     * @param converter
-     * 		a converter used to convert the value from Object to T
+     *
+     * @param type      the Class to convert a value to; the destination type
+     * @param converter a converter used to convert the value from Object to T
      * @since 4.0
      */
     public static <T> void addConverter(Class<? super T> type, Converter<T> converter) {
-    	factory._addConverter(type, converter);
+        factory._addConverter(type, converter);
     }
-    
+
     private <T> void _addConverter(Class<? super T> type, Converter<T> converter) {
-    	converters.put(type, converter);
+        converters.put(type, converter);
     }
-    
+
+    @SuppressWarnings("unchecked")
     <T> Converter<T> getConverter(Class<T> type) {
         if (type == null) {
             throw new IllegalArgumentException("Null type");
@@ -312,10 +262,10 @@ public class ConverterFactory {
 
         // check for enum BEFORE super call, as it will return a noop converter
         if (type.isEnum()) {
-            return enumConveter;
+            return (Converter<T>) enumConverter;
         }
 
         Converter<T> c = (Converter<T>) converters.get(type);
-        return c != null ? c : (Converter<T>)toAnyConverter;
+        return c != null ? c : (Converter<T>) toAnyConverter;
     }
 }
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/reflect/EnumConverter.java b/cayenne-server/src/main/java/org/apache/cayenne/reflect/EnumConverter.java
index 1c7536090..ebb419451 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/reflect/EnumConverter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/reflect/EnumConverter.java
@@ -26,11 +26,11 @@ import org.apache.cayenne.util.Util;
 /**
  * @since 1.2
  */
-class EnumConverter<T extends Enum & ExtendedEnumeration> extends Converter<T> {
+class EnumConverter<T extends Enum<T> & ExtendedEnumeration> implements Converter<T> {
 
     @Override
     @SuppressWarnings("unchecked")
-    protected T convert(Object object, Class<T> type) {
+    public T convert(Object object, Class<T> type) {
 
         if (ExtendedEnumeration.class.isAssignableFrom(type)) {
             ExtendedEnumeration[] values;
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/reflect/ToAnyConverter.java b/cayenne-server/src/main/java/org/apache/cayenne/reflect/ToAnyConverter.java
index b69a765ba..257e0d9d4 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/reflect/ToAnyConverter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/reflect/ToAnyConverter.java
@@ -26,9 +26,10 @@ import org.apache.cayenne.CayenneRuntimeException;
  * Can convert to any class that has a constructor that takes a 
  * single Object or a single String parameter.
  */
-public class ToAnyConverter<T> extends Converter<T> {
-	@Override
-	protected T convert(Object value, Class<T> type) {
+public class ToAnyConverter<T> implements Converter<T> {
+	@SuppressWarnings("unchecked")
+    @Override
+	public T convert(Object value, Class<T> type) {
 		if (value == null) {
             return null;
         }
@@ -37,14 +38,14 @@ public class ToAnyConverter<T> extends Converter<T> {
         }
 		
         try {
-            Constructor<?> constructor;
+            Constructor<T> constructor;
             try {
             	constructor = type.getConstructor(Object.class);
             } catch (NoSuchMethodException e) {
                 constructor = type.getConstructor(String.class);
             	value = value.toString();
             }
-            return (T) constructor.newInstance(value);
+            return constructor.newInstance(value);
         } catch (Exception e) {
             throw new CayenneRuntimeException(e);
         }
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/types/MockExtendedType.java b/cayenne-server/src/test/java/org/apache/cayenne/access/types/MockExtendedType.java
index 4fe6f30cb..3152ac104 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/types/MockExtendedType.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/types/MockExtendedType.java
@@ -51,13 +51,13 @@ public class MockExtendedType implements ExtendedType<Object> {
 
     @Override
     public Object materializeObject(ResultSet rs, int index, int type) throws Exception {
-        return objectClass.newInstance();
+        return objectClass.getDeclaredConstructor().newInstance();
     }
 
     @Override
     public Object materializeObject(CallableStatement rs, int index, int type)
             throws Exception {
-        return objectClass.newInstance();
+        return objectClass.getDeclaredConstructor().newInstance();
     }
 
     @Override
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/JNDIDataSourceFactoryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/JNDIDataSourceFactoryIT.java
index 7642926c2..fb03f1634 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/JNDIDataSourceFactoryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/JNDIDataSourceFactoryIT.java
@@ -34,6 +34,7 @@ import javax.naming.NameNotFoundException;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.fail;
 
+@Deprecated
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
 public class JNDIDataSourceFactoryIT extends ServerCase {
     
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandlerTest.java b/cayenne-server/src/test/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandlerTest.java
index ed0f25e92..39ff19c83 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandlerTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandlerTest.java
@@ -158,7 +158,7 @@ public class LifecycleCallbackEventHandlerTest {
         protected List callbackTimes = new ArrayList();
 
         void callback(Object entity) {
-            callbackTimes.add(new Long(System.currentTimeMillis()));
+            callbackTimes.add(System.currentTimeMillis());
             try {
                 Thread.sleep(100);
             }
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/reflect/PropertyUtilsTest.java b/cayenne-server/src/test/java/org/apache/cayenne/reflect/PropertyUtilsTest.java
index 75ee53f87..51a58683a 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/reflect/PropertyUtilsTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/reflect/PropertyUtilsTest.java
@@ -281,24 +281,21 @@ public class PropertyUtilsTest {
 		Converter<Date> oldConverter = ConverterFactory.factory.getConverter(Date.class);
 
 		try {
-			ConverterFactory.addConverter(Date.class, new Converter<>() {
-				@Override
-				protected Date convert(Object value, Class<Date> type) {
-					if (value == null)
-						return null;
-					if (value instanceof Date) {
-						return (Date) value;
-					}
-					if (value instanceof String) {
-						SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
-						try {
-							return format.parse((String) value);
-						} catch (ParseException e) {
-							throw new CayenneRuntimeException("Unable to convert '" + value + "' to a Date", e);
-						}
+			ConverterFactory.addConverter(Date.class, (value, type) -> {
+				if (value == null)
+					return null;
+				if (value instanceof Date) {
+					return (Date) value;
+				}
+				if (value instanceof String) {
+					SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+					try {
+						return format.parse((String) value);
+					} catch (ParseException e) {
+						throw new CayenneRuntimeException("Unable to convert '" + value + "' to a Date", e);
 					}
-					throw new CayenneRuntimeException("Unable to convert '" + value + "' to a Date");
 				}
+				throw new CayenneRuntimeException("Unable to convert '" + value + "' to a Date");
 			});
 
 			TstJavaBean o1 = new TstJavaBean();
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/template/directive/BindDirectiveIT.java b/cayenne-server/src/test/java/org/apache/cayenne/template/directive/BindDirectiveIT.java
index 9e618a035..6d9ef6452 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/template/directive/BindDirectiveIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/template/directive/BindDirectiveIT.java
@@ -137,7 +137,7 @@ public class BindDirectiveIT extends ServerCase {
 
 		// insert 3 artists
 		for (int i = 1; i < 4; i++) {
-			tArtist.insert(new Long(i), "Artist" + i);
+			tArtist.insert((long) i, "Artist" + i);
 		}
 
 		// now select only with names: Artist1 and Artist3
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/util/TstBean.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/util/TstBean.java
index 2bb9615e0..da4d07687 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/util/TstBean.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/util/TstBean.java
@@ -56,11 +56,11 @@ public class TstBean {
 
     public TstBean(String string, int intValue) {
         this.string = string;
-        this.integer = new Integer(intValue);
+        this.integer = intValue;
     }
 
     public TstBean(int intValue) {
-        integer = new Integer(intValue);
+        integer = intValue;
     }
 
     public Integer getInteger() {
diff --git a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/ResultDirective.java b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/ResultDirective.java
index 8d80f347b..676459b29 100644
--- a/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/ResultDirective.java
+++ b/cayenne-velocity/src/main/java/org/apache/cayenne/velocity/ResultDirective.java
@@ -192,8 +192,9 @@ public class ResultDirective extends Directive {
 	 */
 	protected void bindResult(InternalContextAdapter context, ColumnDescriptor columnDescriptor) {
 
-		Collection<Object> resultColumns = (Collection<Object>) context.getInternalUserContext().get(
-				VelocitySQLTemplateProcessor.RESULT_COLUMNS_LIST_KEY);
+		@SuppressWarnings("unchecked")
+		Collection<Object> resultColumns = (Collection<Object>) context
+				.getInternalUserContext().get(VelocitySQLTemplateProcessor.RESULT_COLUMNS_LIST_KEY);
 
 		if (resultColumns != null) {
 			resultColumns.add(columnDescriptor);
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectTreeView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectTreeView.java
index 00d3fdd05..d17490a98 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectTreeView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectTreeView.java
@@ -976,7 +976,7 @@ public class ProjectTreeView extends JTree implements DomainDisplayListener,
         return list.toArray();
     }
 
-    private void positionNode(Object[] path, Comparator comparator) {
+    private void positionNode(Object[] path, Comparator<ConfigurationNode> comparator) {
         if (path == null) {
             return;
         }
@@ -992,7 +992,7 @@ public class ProjectTreeView extends JTree implements DomainDisplayListener,
     private void positionNode(
             MutableTreeNode parent,
             DefaultMutableTreeNode treeNode,
-            Comparator comparator) {
+            Comparator<ConfigurationNode> comparator) {
 
         removeTreeSelectionListener(treeSelectionListener);
         try {
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportEOModelAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportEOModelAction.java
index 67c04f110..1df3949a0 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportEOModelAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportEOModelAction.java
@@ -142,8 +142,7 @@ public class ImportEOModelAction extends CayenneAction {
         Map connection = (Map) eomodelIndex.get("connectionDictionary");
 
         if (adapter != null && connection != null) {
-            CreateNodeAction nodeBuilder = (CreateNodeAction) getApplication().getActionManager().getAction(
-                    CreateNodeAction.class);
+            CreateNodeAction nodeBuilder = getApplication().getActionManager().getAction(CreateNodeAction.class);
 
             // this should make created node current, resulting in the new map being added
             // to the node automatically once it is loaded


[cayenne] 03/03: Add generics for the type-safety to the Entity/Attribute/Relationship hierarchy

Posted by nt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit fee848de3895952a70f93ff4ec5f6ce3b27fa177
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Thu Jul 14 10:55:05 2022 +0300

    Add generics for the type-safety to the Entity/Attribute/Relationship hierarchy
---
 .../java/org/apache/cayenne/map/Attribute.java     | 12 +--
 .../main/java/org/apache/cayenne/map/DataMap.java  | 10 +--
 .../java/org/apache/cayenne/map/DbAttribute.java   |  2 +-
 .../main/java/org/apache/cayenne/map/DbEntity.java | 89 +++-------------------
 .../org/apache/cayenne/map/DbRelationship.java     |  2 +-
 .../main/java/org/apache/cayenne/map/Entity.java   | 56 +++++++-------
 .../java/org/apache/cayenne/map/ObjAttribute.java  |  2 +-
 .../java/org/apache/cayenne/map/ObjEntity.java     | 71 ++++++-----------
 .../org/apache/cayenne/map/ObjRelationship.java    | 18 ++---
 .../apache/cayenne/map/PathComponentIterator.java  | 30 ++++----
 .../java/org/apache/cayenne/map/Relationship.java  | 20 ++---
 .../java/org/apache/cayenne/map/AttributeTest.java |  6 +-
 .../test/java/org/apache/cayenne/map/EntityIT.java | 36 ++++-----
 .../java/org/apache/cayenne/map/MockAttribute.java |  2 +-
 .../java/org/apache/cayenne/map/MockEntity.java    |  8 +-
 .../org/apache/cayenne/map/MockRelationship.java   |  2 +-
 .../org/apache/cayenne/map/RelationshipTest.java   | 12 +--
 .../modeler/editor/ObjAttributeTableModel.java     | 55 ++++++-------
 .../editor/wrapper/ObjAttributeWrapper.java        | 12 +--
 .../cayenne/modeler/graph/BaseGraphBuilder.java    |  2 +-
 .../modeler/graph/DbEntityCellMetadata.java        | 20 ++---
 .../cayenne/modeler/graph/EntityCellMetadata.java  | 13 ++--
 .../modeler/graph/ObjEntityCellMetadata.java       | 19 ++---
 .../modeler/undo/RelationshipUndoableEdit.java     | 42 +++++-----
 .../cayenne/modeler/util/EntityTreeModel.java      | 24 +++---
 .../org/apache/cayenne/wocompat/EOObjEntity.java   |  3 +-
 26 files changed, 228 insertions(+), 340 deletions(-)

diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/Attribute.java b/cayenne-server/src/main/java/org/apache/cayenne/map/Attribute.java
index 48a40ab09..3dc4d318a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/Attribute.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/Attribute.java
@@ -32,10 +32,11 @@ import org.apache.cayenne.util.XMLSerializable;
  * are described by attributes are Java class properties and database table columns.
  * 
  */
-public abstract class Attribute implements CayenneMapEntry, XMLSerializable, Serializable {
+public abstract class Attribute<E extends Entity<E,T,U>, T extends Attribute<E,T,U>, U extends Relationship<E,T,U>>
+        implements CayenneMapEntry, XMLSerializable, Serializable {
 
     protected String name;
-    protected Entity entity;
+    protected Entity<E,T,U> entity;
 
     /**
      * Creates an unnamed Attribute.
@@ -61,14 +62,14 @@ public abstract class Attribute implements CayenneMapEntry, XMLSerializable, Ser
     /**
      * Returns parent entity that holds this attribute.
      */
-    public Entity getEntity() {
+    public Entity<E,T,U> getEntity() {
         return entity;
     }
 
     /**
      * Sets parent entity that holds this attribute.
      */
-    public void setEntity(Entity entity) {
+    public void setEntity(Entity<E,T,U> entity) {
         this.entity = entity;
     }
 
@@ -84,11 +85,12 @@ public abstract class Attribute implements CayenneMapEntry, XMLSerializable, Ser
         return getEntity();
     }
 
+    @SuppressWarnings("unchecked")
     public void setParent(Object parent) {
         if (parent != null && !(parent instanceof Entity)) {
             throw new IllegalArgumentException("Expected null or Entity, got: " + parent);
         }
 
-        setEntity((Entity) parent);
+        setEntity((Entity<E,T,U>) parent);
     }
 }
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java
index 94c6d5988..bda2ea70b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java
@@ -271,7 +271,7 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable
 
 	// stores relationships for the map of entities
 	private void encodeDbRelationshipsAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
-		for (Entity entity : new TreeMap<>(getDbEntityMap()).values()) {
+		for (DbEntity entity : new TreeMap<>(getDbEntityMap()).values()) {
 			entity.getRelationships().stream()
 					.filter(r -> !r.isRuntime())
 					.sorted(Comparator.comparing(Relationship::getName))
@@ -759,7 +759,7 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable
 		if (dbEntityToDelete != null && clearDependencies) {
 			for (DbEntity dbEnt : this.getDbEntities()) {
 				// take a copy since we're going to modify the entity
-				for (Relationship rel : new ArrayList<>(dbEnt.getRelationships())) {
+				for (DbRelationship rel : new ArrayList<>(dbEnt.getRelationships())) {
 					if (dbEntityName.equals(rel.getTargetEntityName())) {
 						dbEnt.removeRelationship(rel.getName());
 					}
@@ -810,7 +810,7 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable
 			// remove relationships that point to this entity
 			for (ObjEntity ent : getObjEntities()) {
 				// take a copy since we're going to modify the entity
-				for (Relationship relationship : new ArrayList<>(ent.getRelationships())) {
+				for (ObjRelationship relationship : new ArrayList<>(ent.getRelationships())) {
 					if (objEntityName.equals(relationship.getSourceEntity().getName())
 							|| objEntityName.equals(relationship.getTargetEntityName())) {
 						ent.removeRelationship(relationship.getName());
@@ -970,7 +970,7 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable
 	 * @since 1.2
 	 */
 	public void dbEntityChanged(EntityEvent e) {
-		Entity entity = e.getEntity();
+		Entity<?,?,?> entity = e.getEntity();
 		if (entity instanceof DbEntity) {
 
 			DbEntity dbEntity = (DbEntity) entity;
@@ -1013,7 +1013,7 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable
 	 * @since 1.2
 	 */
 	public void objEntityChanged(EntityEvent e) {
-		Entity entity = e.getEntity();
+		Entity<?,?,?> entity = e.getEntity();
 		if (entity instanceof ObjEntity) {
 
 			ObjEntity objEntity = (ObjEntity) entity;
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java
index a50e79098..1c1cd9f44 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java
@@ -29,7 +29,7 @@ import org.apache.cayenne.util.XMLEncoder;
 /**
  * A DbAttribute defines a descriptor for a single database table column.
  */
-public class DbAttribute extends Attribute implements ConfigurationNode {
+public class DbAttribute extends Attribute<DbEntity, DbAttribute, DbRelationship> implements ConfigurationNode {
 
     /**
      * Defines JDBC type of the column.
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java
index e68c1feaf..ef4305f15 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java
@@ -52,8 +52,8 @@ import org.apache.cayenne.util.XMLEncoder;
  * A DbEntity is a mapping descriptor that defines a structure of a database
  * table.
  */
-public class DbEntity extends Entity implements ConfigurationNode, DbEntityListener, DbAttributeListener,
-        DbRelationshipListener {
+public class DbEntity extends Entity<DbEntity, DbAttribute, DbRelationship>
+        implements ConfigurationNode, DbEntityListener, DbAttributeListener, DbRelationshipListener {
 
     protected String catalog;
     protected String schema;
@@ -76,7 +76,6 @@ public class DbEntity extends Entity implements ConfigurationNode, DbEntityListe
      */
     public DbEntity() {
         super();
-
         this.primaryKey = new ArrayList<>(2);
         this.generatedAttributes = new ArrayList<>(2);
     }
@@ -89,16 +88,6 @@ public class DbEntity extends Entity implements ConfigurationNode, DbEntityListe
         this.setName(name);
     }
 
-    @Override
-    public DbRelationship getRelationship(String relName) {
-        return (DbRelationship) super.getRelationship(relName);
-    }
-
-    @Override
-    public DbAttribute getAttribute(String attributeName) {
-        return (DbAttribute) super.getAttribute(attributeName);
-    }
-
     /**
      * @since 3.1
      */
@@ -189,16 +178,6 @@ public class DbEntity extends Entity implements ConfigurationNode, DbEntityListe
         return Collections.unmodifiableList(primaryKey);
     }
 
-    /**
-     * Returns a Collection of all attributes that either belong to this
-     * DbEntity or inherited.
-     */
-    @SuppressWarnings("unchecked")
-    @Override
-    public Collection<DbAttribute> getAttributes() {
-        return (Collection<DbAttribute>) super.getAttributes();
-    }
-
     /**
      * Returns an unmodifiable collection of DbAttributes that are generated by
      * the database.
@@ -231,7 +210,7 @@ public class DbEntity extends Entity implements ConfigurationNode, DbEntityListe
      */
     @Override
     public void removeAttribute(String attrName) {
-        Attribute attr = getAttribute(attrName);
+        DbAttribute attr = getAttribute(attrName);
         if (attr == null) {
             return;
         }
@@ -256,30 +235,6 @@ public class DbEntity extends Entity implements ConfigurationNode, DbEntityListe
         this.dbAttributeRemoved(new AttributeEvent(this, null, this, MapEvent.REMOVE));
     }
 
-    /**
-     * Returns a Collection of relationships from this entity or inherited.
-     */
-    @SuppressWarnings("unchecked")
-    @Override
-    public Collection<DbRelationship> getRelationships() {
-        return (Collection<DbRelationship>) super.getRelationships();
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Map<String, DbRelationship> getRelationshipMap() {
-        return (Map<String, DbRelationship>) super.getRelationshipMap();
-    }
-
-    /**
-     * @since 3.0
-     */
-    @Override
-    @SuppressWarnings("unchecked")
-    public PathComponent<DbAttribute, DbRelationship> lastPathComponent(Expression path, Map aliasMap) {
-        return super.lastPathComponent(path, aliasMap);
-    }
-
     /**
      * Returns an Iterable instance over expression path components based on
      * this entity.
@@ -287,17 +242,10 @@ public class DbEntity extends Entity implements ConfigurationNode, DbEntityListe
      * @since 3.0
      */
     @Override
-    @SuppressWarnings("unchecked")
-    public Iterable<PathComponent<DbAttribute, DbRelationship>> resolvePath(final Expression pathExp, final Map aliasMap) {
+    public Iterable<PathComponent<DbAttribute, DbRelationship>> resolvePath(Expression pathExp, Map<String, String> aliasMap) {
 
         if (pathExp.getType() == Expression.DB_PATH) {
-
-            return new Iterable<PathComponent<DbAttribute, DbRelationship>>() {
-
-                public Iterator iterator() {
-                    return new PathComponentIterator(DbEntity.this, (String) pathExp.getOperand(0), aliasMap);
-                }
-            };
+            return () -> new PathComponentIterator<>(DbEntity.this, (String) pathExp.getOperand(0), aliasMap);
         }
 
         throw new ExpressionException("Invalid expression type: '" + pathExp.expName() + "',  DB_PATH is expected.");
@@ -400,7 +348,7 @@ public class DbEntity extends Entity implements ConfigurationNode, DbEntityListe
         }
 
         // catch clearing (event with null ('any') DbAttribute)
-        Attribute attribute = e.getAttribute();
+        Attribute<?,?,?> attribute = e.getAttribute();
         if (attribute == null && this.attributes.isEmpty()) {
             this.primaryKey.clear();
             this.generatedAttributes.clear();
@@ -516,7 +464,7 @@ public class DbEntity extends Entity implements ConfigurationNode, DbEntityListe
             return;
         }
 
-        Relationship rel = e.getRelationship();
+        Relationship<?,?,?> rel = e.getRelationship();
         // make sure we handle a DbRelationship
         if (!(rel instanceof DbRelationship)) {
             return;
@@ -676,17 +624,17 @@ public class DbEntity extends Entity implements ConfigurationNode, DbEntityListe
             return transformed;
         }
 
-        private PathComponentIterator createPathIterator(String path) {
-            return new PathComponentIterator(DbEntity.this, path, Collections.emptyMap());
+        private PathComponentIterator<DbEntity, DbAttribute, DbRelationship> createPathIterator(String path) {
+            return new PathComponentIterator<>(DbEntity.this, path, Collections.emptyMap());
             // TODO: do we need aliases here?
         }
 
         String translatePath(String path) {
             LinkedList<String> finalPath = new LinkedList<>();
-            PathComponentIterator pathIt = createPathIterator(relationshipPath);
+            PathComponentIterator<DbEntity, DbAttribute, DbRelationship> pathIt = createPathIterator(relationshipPath);
             while (pathIt.hasNext()) {
                 // relationship path components must be DbRelationships
-                DbRelationship lastDBR = (DbRelationship) pathIt.next().getRelationship();
+                DbRelationship lastDBR = pathIt.next().getRelationship();
                 if(lastDBR != null) {
                     prependReversedPath(finalPath, lastDBR);
                 }
@@ -706,20 +654,5 @@ public class DbEntity extends Entity implements ConfigurationNode, DbEntityListe
 
             finalPath.addFirst(revNextDBR.getName());
         }
-
-        private void appendPath(LinkedList<String> finalPath, CayenneMapEntry pathComponent) {
-            finalPath.addLast(pathComponent.getName());
-        }
-
-        private void appendPath(LinkedList<String> finalPath, PathComponent<Attribute, Relationship> pathComponent) {
-            CayenneMapEntry mapEntry = pathComponent.getAttribute() != null ? pathComponent.getAttribute()
-                    : pathComponent.getRelationship();
-            String name = mapEntry.getName();
-            if (pathComponent.getJoinType() == JoinType.LEFT_OUTER) {
-                name += OUTER_JOIN_INDICATOR;
-            }
-
-            finalPath.addLast(name);
-        }
     }
 }
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
index 2b581b78a..98351a78c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
@@ -37,7 +37,7 @@ import java.util.function.Function;
  * A DbRelationship is a descriptor of a database inter-table relationship based
  * on one or more primary key/foreign key pairs.
  */
-public class DbRelationship extends Relationship implements ConfigurationNode {
+public class DbRelationship extends Relationship<DbEntity, DbAttribute, DbRelationship> implements ConfigurationNode {
 
     // The columns through which the join is implemented.
     protected List<DbJoin> joins = new ArrayList<>(2);
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/Entity.java b/cayenne-server/src/main/java/org/apache/cayenne/map/Entity.java
index f2a9a349a..1d57c60cb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/Entity.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/Entity.java
@@ -27,12 +27,10 @@ import org.apache.cayenne.util.ToStringBuilder;
 import org.apache.cayenne.util.XMLSerializable;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.StringTokenizer;
 
@@ -41,7 +39,8 @@ import java.util.StringTokenizer;
  * either a descriptor of database table or a persistent object.
  * 
  */
-public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serializable {
+public abstract class Entity<E extends Entity<E,T,U>, T extends Attribute<E,T,U>, U extends Relationship<E,T,U>>
+        implements CayenneMapEntry, XMLSerializable, Serializable {
 
     public static final String PATH_SEPARATOR = ".";
 
@@ -56,8 +55,8 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
     protected String name;
     protected DataMap dataMap;
 
-    protected final Map<String, Attribute> attributes = new LinkedHashMap<>();
-    protected final Map<String, Relationship> relationships = new LinkedHashMap<>();
+    protected final Map<String, T> attributes = new LinkedHashMap<>();
+    protected final Map<String, U> relationships = new LinkedHashMap<>();
 
     /**
      * Creates an unnamed Entity.
@@ -119,7 +118,7 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
      * Returns attribute with name <code>attributeName</code> or null if no attribute
      * with this name exists.
      */
-    public Attribute getAttribute(String attributeName) {
+    public T getAttribute(String attributeName) {
         return attributes.get(attributeName);
     }
 
@@ -127,7 +126,7 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
      * Adds new attribute to the entity, setting its parent entity to be this object. If
      * attribute has no name, IllegalArgumentException is thrown.
      */
-    public void addAttribute(Attribute attribute) {
+    public void addAttribute(T attribute) {
         if (attribute.getName() == null) {
             throw new IllegalArgumentException("Attempt to insert unnamed attribute.");
         }
@@ -135,7 +134,7 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
         // block overrides
 
         // TODO: change method signature to return replaced attribute and make sure the Modeler handles it...
-        Object existingAttribute = attributes.get(attribute.getName());
+        T existingAttribute = attributes.get(attribute.getName());
         if (existingAttribute != null) {
             if (existingAttribute == attribute) {
                 return;
@@ -167,7 +166,7 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
      *
      * @since 4.0
      */
-    public void updateAttribute(Attribute attribute) {
+    public void updateAttribute(T attribute) {
         removeAttribute(attribute.getName());
         addAttribute(attribute);
     }
@@ -180,14 +179,14 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
      * Returns relationship with name <code>relName</code>. Will return null if no
      * relationship with this name exists in the entity.
      */
-    public Relationship getRelationship(String relName) {
+    public U getRelationship(String relName) {
         return relationships.get(relName);
     }
 
     /**
      * Adds new relationship to the entity.
      */
-    public void addRelationship(Relationship relationship) {
+    public void addRelationship(U relationship) {
         if (relationship.getName() == null) {
             throw new IllegalArgumentException("Attempt to insert unnamed relationship.");
         }
@@ -232,7 +231,7 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
     /**
      * Returns an unmodifiable map of relationships sorted by name.
      */
-    public Map<String, ? extends Relationship> getRelationshipMap() {
+    public Map<String, U> getRelationshipMap() {
         // create a new instance ... earlier attempts to cache it in the entity caused
         // serialization issues (esp. with Hessian).
         return Collections.unmodifiableMap(relationships);
@@ -245,12 +244,12 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
      * 
      * @since 1.1
      */
-    public Relationship getAnyRelationship(Entity targetEntity) {
+    public U getAnyRelationship(E targetEntity) {
         if (getRelationships().isEmpty()) {
             return null;
         }
 
-        for (Relationship r : getRelationships()) {
+        for (U r : getRelationships()) {
             if (r.getTargetEntity() == targetEntity) {
                 return r;
             }
@@ -261,7 +260,7 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
     /**
      * Returns an unmodifiable collection of Relationships that exist in this entity.
      */
-    public Collection<? extends Relationship> getRelationships() {
+    public Collection<U> getRelationships() {
         // create a new instance ... earlier attempts to cache it in the entity caused
         // serialization issues (esp. with Hessian).
         return Collections.unmodifiableCollection(relationships.values());
@@ -270,7 +269,7 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
     /**
      * Returns an unmodifiable sorted map of entity attributes.
      */
-    public Map<String, ? extends Attribute> getAttributeMap() {
+    public Map<String, T> getAttributeMap() {
         // create a new instance ... earlier attempts to cache it in the entity caused
         // serialization issues (esp. with Hessian).
         return Collections.unmodifiableMap(attributes);
@@ -279,7 +278,7 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
     /**
      * Returns an unmodifiable collection of entity attributes.
      */
-    public Collection<? extends Attribute> getAttributes() {
+    public Collection<T> getAttributes() {
         // create a new instance ... earlier attempts to cache it in the entity caused
         // serialization issues (esp. with Hessian).
         return Collections.unmodifiableCollection(attributes.values());
@@ -299,12 +298,11 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
      * 
      * @since 3.0
      */
-    @SuppressWarnings("unchecked")
-    public <T extends Attribute, U extends Relationship> PathComponent<T, U> lastPathComponent(
+    public PathComponent<T, U> lastPathComponent(
             Expression path,
-            Map aliasMap) {
+            Map<String, String> aliasMap) {
 
-        for (PathComponent component : resolvePath(path, aliasMap)) {
+        for (PathComponent<T, U> component : resolvePath(path, aliasMap)) {
             if (component.isLast()) {
                 // resolve aliases if needed
                 return lastPathComponent(component);
@@ -314,14 +312,13 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
         return null;
     }
 
-    @SuppressWarnings("unchecked")
-    private PathComponent lastPathComponent(PathComponent<Attribute, Relationship> component) {
+    private PathComponent<T, U> lastPathComponent(PathComponent<T, U> component) {
         
         if (!component.isAlias()) {
             return component;
         }
 
-        for (PathComponent subcomponent : component.getAliasedPath()) {
+        for (PathComponent<T, U> subcomponent : component.getAliasedPath()) {
             if (subcomponent.isLast()) {
                 return lastPathComponent(subcomponent);
             }
@@ -343,10 +340,9 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
      * 
      * @since 3.0
      */
-    @SuppressWarnings("unchecked")
-    public abstract <T extends Attribute, U extends Relationship> Iterable<PathComponent<T, U>> resolvePath(
+    public abstract Iterable<PathComponent<T, U>> resolvePath(
             Expression pathExp,
-            Map aliasMap);
+            Map<String, String> aliasMap);
 
     /**
      * Processes expression <code>pathExp</code> and returns an Iterator of path
@@ -375,7 +371,7 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
 
         private final StringTokenizer tokens;
         private final String path;
-        private Entity currentEntity;
+        private Entity<E,T,U> currentEntity;
 
         PathIterator(String path) {
             currentEntity = Entity.this;
@@ -394,7 +390,7 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
             }
             
             // see if this is an attribute
-            Attribute attr = currentEntity.getAttribute(pathComp);
+            T attr = currentEntity.getAttribute(pathComp);
             if (attr != null) {
                 // do a sanity check...
                 if (tokens.hasMoreTokens()) {
@@ -404,7 +400,7 @@ public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serial
                 return attr;
             }
 
-            Relationship rel = currentEntity.getRelationship(pathComp);
+            U rel = currentEntity.getRelationship(pathComp);
             if (rel != null) {
                 currentEntity = rel.getTargetEntity();
                 if (currentEntity != null || !tokens.hasMoreTokens()) { //otherwise an exception will be thrown
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java
index e614d306b..7fbb8e270 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java
@@ -32,7 +32,7 @@ import org.apache.cayenne.util.XMLEncoder;
 /**
  * An ObjAttribute is a mapping descriptor of a Java class property.
  */
-public class ObjAttribute extends Attribute implements ConfigurationNode {
+public class ObjAttribute extends Attribute<ObjEntity, ObjAttribute, ObjRelationship> implements ConfigurationNode {
 
     protected String type;
     protected boolean usedForLocking;
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java
index 117cdcfca..a33dcbfcd 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java
@@ -23,7 +23,6 @@ import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionException;
 import org.apache.cayenne.exp.ExpressionFactory;
@@ -52,7 +51,8 @@ import java.util.function.Function;
  * the information about the Java class itself, as well as its mapping to the
  * DbEntity layer.
  */
-public class ObjEntity extends Entity implements ObjEntityListener, ConfigurationNode {
+public class ObjEntity extends Entity<ObjEntity, ObjAttribute, ObjRelationship>
+        implements ObjEntityListener, ConfigurationNode {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ObjEntity.class);
 
@@ -406,7 +406,7 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
      */
     @Override
     public ObjAttribute getAttribute(String name) {
-        ObjAttribute attribute = (ObjAttribute) super.getAttribute(name);
+        ObjAttribute attribute = super.getAttribute(name);
         if (attribute != null) {
             return attribute;
         }
@@ -498,9 +498,8 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
         }
     }
 
-    @SuppressWarnings("unchecked")
     final Map<String, ObjAttribute> getAttributeMapInternal() {
-        return (Map<String, ObjAttribute>) super.getAttributeMap();
+        return super.getAttributeMap();
     }
 
     /**
@@ -539,9 +538,8 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
      * 
      * @since 1.1
      */
-    @SuppressWarnings("unchecked")
     public Collection<ObjAttribute> getDeclaredAttributes() {
-        return (Collection<ObjAttribute>) super.getAttributes();
+        return super.getAttributes();
     }
 
     /**
@@ -556,7 +554,7 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
      * @since 4.0
      */
     public ObjAttribute getDeclaredAttribute(String name) {
-        return (ObjAttribute) super.getAttribute(name);
+        return super.getAttribute(name);
     }
 
     /**
@@ -565,7 +563,7 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
      */
     @Override
     public ObjRelationship getRelationship(String name) {
-        ObjRelationship relationship = (ObjRelationship) super.getRelationship(name);
+        ObjRelationship relationship = super.getRelationship(name);
         if (relationship != null) {
             return relationship;
         }
@@ -581,7 +579,7 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
     @Override
     public Map<String, ObjRelationship> getRelationshipMap() {
         if (superEntityName == null) {
-            return getRelationshipMapInternal();
+            return super.getRelationshipMap();
         }
 
         Map<String, ObjRelationship> relationshipMap = new HashMap<>();
@@ -594,7 +592,7 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
      * hierarchy.
      */
     final void appendRelationships(Map<String, ObjRelationship> map) {
-        map.putAll(getRelationshipMapInternal());
+        map.putAll(super.getRelationshipMap());
 
         ObjEntity superEntity = getSuperEntity();
         if (superEntity != null) {
@@ -607,20 +605,14 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
         return getRelationshipMap().values();
     }
 
-    @SuppressWarnings("unchecked")
-    final Map<String, ObjRelationship> getRelationshipMapInternal() {
-        return (Map<String, ObjRelationship>) super.getRelationshipMap();
-    }
-
     /**
      * Returns a Collection of all relationships that belong to this ObjEntity,
      * excluding inherited attributes.
      * 
      * @since 1.1
      */
-    @SuppressWarnings("unchecked")
     public Collection<ObjRelationship> getDeclaredRelationships() {
-        return (Collection<ObjRelationship>) super.getRelationships();
+        return super.getRelationships();
     }
 
     /**
@@ -751,15 +743,6 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
         return superEntity != null && superEntity.isSubentityOf(entity);
     }
 
-    /**
-     * @since 3.0
-     */
-    @Override
-    @SuppressWarnings("unchecked")
-    public PathComponent<ObjAttribute, ObjRelationship> lastPathComponent(Expression path, Map aliasMap) {
-        return super.lastPathComponent(path, aliasMap);
-    }
-
     /**
      * Returns an Iterable instance over expression path components based on
      * this entity.
@@ -767,20 +750,10 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
      * @since 3.0
      */
     @Override
-    @SuppressWarnings("unchecked")
-    public Iterable<PathComponent<ObjAttribute, ObjRelationship>> resolvePath(final Expression pathExp,
-            final Map aliasMap) {
-
+    public Iterable<PathComponent<ObjAttribute, ObjRelationship>> resolvePath(Expression pathExp, Map<String, String> aliasMap) {
         if (pathExp.getType() == Expression.OBJ_PATH) {
-
-            return new Iterable<PathComponent<ObjAttribute, ObjRelationship>>() {
-
-                public Iterator iterator() {
-                    return new PathComponentIterator(ObjEntity.this, (String) pathExp.getOperand(0), aliasMap);
-                }
-            };
+            return () -> new PathComponentIterator<>(ObjEntity.this, (String) pathExp.getOperand(0), aliasMap);
         }
-
         throw new ExpressionException("Invalid expression type: '" + pathExp.expName() + "',  OBJ_PATH is expected.");
     }
 
@@ -856,8 +829,8 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
         return getDbEntity().translateToRelatedEntity(dbClone, dbPath);
     }
 
-    private PathComponentIterator createPathIterator(String path, Map<String, String> aliasMap) {
-        return new PathComponentIterator(ObjEntity.this, path, aliasMap);
+    private PathComponentIterator<ObjEntity, ObjAttribute, ObjRelationship> createPathIterator(String path, Map<String, String> aliasMap) {
+        return new PathComponentIterator<>(this, path, aliasMap);
     }
 
     /**
@@ -877,22 +850,22 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
         // something...
         // seems generally useful
 
-        String toDbPath(PathComponentIterator objectPathComponents) {
+        String toDbPath(PathComponentIterator<ObjEntity, ObjAttribute, ObjRelationship> objectPathComponents) {
             StringBuilder buf = new StringBuilder();
             while (objectPathComponents.hasNext()) {
-                PathComponent<Attribute, Relationship> component = objectPathComponents.next();
+                PathComponent<ObjAttribute, ObjRelationship> component = objectPathComponents.next();
 
-                Iterator<?> dbSubpath;
+                Iterator<? extends CayenneMapEntry> dbSubpath;
                 if(component.getAttribute() != null) {
-                    dbSubpath = ((ObjAttribute) component.getAttribute()).getDbPathIterator();
+                    dbSubpath = component.getAttribute().getDbPathIterator();
                     buildPath(dbSubpath, component, buf);
                 } else if(component.getRelationship() != null) {
-                    dbSubpath = ((ObjRelationship) component.getRelationship()).getDbRelationships().iterator();
+                    dbSubpath = component.getRelationship().getDbRelationships().iterator();
                     buildPath(dbSubpath, component, buf);
                 } else if(component.getAliasedPath() != null) {
-                    for(PathComponent<Attribute, Relationship> pathComponent : component.getAliasedPath()) {
+                    for(PathComponent<ObjAttribute, ObjRelationship> pathComponent : component.getAliasedPath()) {
                        if(pathComponent.getRelationship() != null) {
-                           dbSubpath = ((ObjRelationship) pathComponent.getRelationship()).getDbRelationships().iterator();
+                           dbSubpath = pathComponent.getRelationship().getDbRelationships().iterator();
                            buildPath(dbSubpath, pathComponent, buf);
                        }
                     }
@@ -904,7 +877,7 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
             return buf.toString();
         }
 
-        private void buildPath(Iterator<?> dbSubpath, PathComponent<Attribute, Relationship> component, StringBuilder buf) {
+        private void buildPath(Iterator<?> dbSubpath, PathComponent<ObjAttribute, ObjRelationship> component, StringBuilder buf) {
             while (dbSubpath.hasNext()) {
                 CayenneMapEntry subComponent = (CayenneMapEntry) dbSubpath.next();
                 if (buf.length() > 0) {
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java
index fd6d19c19..ee36fbf68 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java
@@ -39,7 +39,7 @@ import org.apache.cayenne.util.XMLEncoder;
  * Describes an association between two Java classes mapped as source and target
  * ObjEntity. Maps to a path of DbRelationships.
  */
-public class ObjRelationship extends Relationship implements ConfigurationNode {
+public class ObjRelationship extends Relationship<ObjEntity, ObjAttribute, ObjRelationship> implements ConfigurationNode {
 
     /**
      * Denotes a default type of to-many relationship collection which is a Java
@@ -60,7 +60,7 @@ public class ObjRelationship extends Relationship implements ConfigurationNode {
      * Db-relationships path that is set but not yet parsed (turned into
      * List&lt;DbRelationship&gt;) Used during map loading
      */
-    String deferredPath;
+    volatile String deferredPath;
 
     /**
      * Stores the type of collection mapped by a to-many relationship. Null for
@@ -193,7 +193,7 @@ public class ObjRelationship extends Relationship implements ConfigurationNode {
             return null;
         }
 
-        Entity source = getSourceEntity();
+        ObjEntity source = getSourceEntity();
 
         for (ObjRelationship relationship : target.getRelationships()) {
 
@@ -309,7 +309,7 @@ public class ObjRelationship extends Relationship implements ConfigurationNode {
         // entities with qualifiers may result in filtering even existing target
         // rows, so
         // such relationships are optional
-        if (isQualifiedEntity((ObjEntity) getTargetEntity())) {
+        if (isQualifiedEntity(getTargetEntity())) {
             return true;
         }
 
@@ -320,11 +320,8 @@ public class ObjRelationship extends Relationship implements ConfigurationNode {
             if (!dbRelationship.isFromPK()) {
                 return false;
             }
-
             DbRelationship reverseRelationship = dbRelationship.getReverseRelationship();
-            if (reverseRelationship.isToDependentPK()) {
-                return false;
-            }
+            return !reverseRelationship.isToDependentPK();
         }
 
         return true;
@@ -565,9 +562,7 @@ public class ObjRelationship extends Relationship implements ConfigurationNode {
      */
     void refreshFromDeferredPath() {
         if (deferredPath != null) {
-            
             synchronized(this) {
-                
                 // check if another thread just 
                 // loaded path from deferredPath
                 if (deferredPath != null){
@@ -609,8 +604,7 @@ public class ObjRelationship extends Relationship implements ConfigurationNode {
                 }
                 validPath.append(pathComponent.getName());
             }
-        } catch (ExpressionException ex) {
-
+        } catch (ExpressionException ignored) {
         }
 
         return validPath.toString();
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/PathComponentIterator.java b/cayenne-server/src/main/java/org/apache/cayenne/map/PathComponentIterator.java
index 3d2bee8ef..9a444b094 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/PathComponentIterator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/PathComponentIterator.java
@@ -31,16 +31,17 @@ import java.util.StringTokenizer;
 /**
  * @since 3.0
  */
-class PathComponentIterator implements Iterator<PathComponent<Attribute, Relationship>> {
+class PathComponentIterator<E extends Entity<E,T,U>, T extends Attribute<E,T,U>, U extends Relationship<E,T,U>>
+        implements Iterator<PathComponent<T, U>> {
 
     private final StringTokenizer toks;
     private final String path;
     private final Map<String, String> aliasMap;
 
     private EmbeddedAttribute embeddedAttribute;
-    private Entity currentEntity;
+    private Entity<E,T,U> currentEntity;
 
-    PathComponentIterator(Entity root, String path, Map<String, String> aliasMap) {
+    PathComponentIterator(Entity<E,T,U> root, String path, Map<String, String> aliasMap) {
         this.currentEntity = Objects.requireNonNull(root);
         this.path = Objects.requireNonNull(path);
         this.aliasMap = Objects.requireNonNull(aliasMap);
@@ -52,7 +53,7 @@ class PathComponentIterator implements Iterator<PathComponent<Attribute, Relatio
         return toks.hasMoreTokens();
     }
 
-    public PathComponent<Attribute, Relationship> next() {
+    public PathComponent<T, U> next() {
         String pathComp = toks.nextToken();
 
         JoinType relationshipJoinType = JoinType.INNER;
@@ -64,9 +65,10 @@ class PathComponentIterator implements Iterator<PathComponent<Attribute, Relatio
         }
 
         // see if this is an attribute
-        Attribute attr;
+        T attr;
         if(embeddedAttribute != null) {
-            attr = embeddedAttribute.getAttribute(pathComp);
+            // TODO: assert that this iterator is for ObjEntity
+            attr = (T)embeddedAttribute.getAttribute(pathComp);
             embeddedAttribute = null;
         } else {
             attr = currentEntity.getAttribute(pathComp);
@@ -84,13 +86,13 @@ class PathComponentIterator implements Iterator<PathComponent<Attribute, Relatio
             return new AttributePathComponent<>(attr);
         }
 
-        Relationship rel = currentEntity.getRelationship(pathComp);
+        U rel = currentEntity.getRelationship(pathComp);
         if (rel != null) {
             currentEntity = rel.getTargetEntity();
             return new RelationshipPathComponent<>(rel, relationshipJoinType, !hasNext());
         }
 
-        PathComponent<Attribute, Relationship> aliasedPathComponent = getAliasedPathComponent(pathComp);
+        PathComponent<T, U> aliasedPathComponent = getAliasedPathComponent(pathComp);
         if (aliasedPathComponent != null) {
             return aliasedPathComponent;
         }
@@ -98,7 +100,7 @@ class PathComponentIterator implements Iterator<PathComponent<Attribute, Relatio
         throw invalidPathException("Can't resolve path component", pathComp);
     }
 
-    private PathComponent<Attribute, Relationship> getAliasedPathComponent(String pathComp) {
+    private PathComponent<T, U> getAliasedPathComponent(String pathComp) {
         String aliasedPath = aliasMap.get(pathComp);
         if(aliasedPath == null) {
             return null;
@@ -115,15 +117,15 @@ class PathComponentIterator implements Iterator<PathComponent<Attribute, Relatio
         // the subpath, we have to fully traverse it, hence instead of lazy iterator
         // we might as well reuse obtained information in the AliasPathComponent
 
-        Iterator<PathComponent<Attribute, Relationship>> subpathIt =
-                new PathComponentIterator(currentEntity, aliasedPath, Collections.emptyMap());
+        Iterator<PathComponent<T, U>> subpathIt =
+                new PathComponentIterator<>(currentEntity, aliasedPath, Collections.emptyMap());
 
-        Collection<PathComponent<Attribute, Relationship>> parsedSubpath = new ArrayList<>(4);
+        Collection<PathComponent<T, U>> parsedSubpath = new ArrayList<>(4);
 
         while (subpathIt.hasNext()) {
-            PathComponent<Attribute, Relationship> subpathComponent = subpathIt.next();
+            PathComponent<T, U> subpathComponent = subpathIt.next();
 
-            Relationship subpathRelationship = subpathComponent.getRelationship();
+            U subpathRelationship = subpathComponent.getRelationship();
             if (subpathRelationship == null) {
                 throw invalidPathException(
                         "Expected a relationship in the aliased subpath. Alias [" + pathComp + "]",
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java b/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java
index 43fca42da..428cdb285 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java
@@ -31,11 +31,11 @@ import org.apache.cayenne.util.XMLSerializable;
  * "arcs" connecting entity "nodes". Relationships are directional, i.e. they have a
  * notion of source and target entity. This makes DataMap a "digraph".
  */
-public abstract class Relationship implements CayenneMapEntry, XMLSerializable,
-        Serializable {
+public abstract class Relationship<E extends Entity<E,T,U>, T extends Attribute<E,T,U>, U extends Relationship<E,T,U>>
+        implements CayenneMapEntry, XMLSerializable, Serializable {
 
     protected String name;
-    protected Entity sourceEntity;
+    protected Entity<E,T,U> sourceEntity;
 
     protected String targetEntityName;
     protected boolean toMany;
@@ -72,26 +72,26 @@ public abstract class Relationship implements CayenneMapEntry, XMLSerializable,
     /**
      * Returns relationship source entity.
      */
-    public Entity getSourceEntity() {
+    public Entity<E,T,U> getSourceEntity() {
         return sourceEntity;
     }
 
     /**
      * Sets relationship source entity.
      */
-    public void setSourceEntity(Entity sourceEntity) {
+    public void setSourceEntity(Entity<E,T,U> sourceEntity) {
         this.sourceEntity = sourceEntity;
     }
 
     /**
      * Returns a target entity of the relationship.
      */
-    public abstract Entity getTargetEntity();
+    public abstract Entity<E,T,U> getTargetEntity();
 
     /**
      * Sets relationship target entity. Internally calls <code>setTargetEntityName</code>.
      */
-    public void setTargetEntityName(Entity targetEntity) {
+    public void setTargetEntityName(Entity<E,?,?> targetEntity) {
         if (targetEntity != null) {
             setTargetEntityName(targetEntity.getName());
         } else {
@@ -133,7 +133,7 @@ public abstract class Relationship implements CayenneMapEntry, XMLSerializable,
             throw new IllegalArgumentException("Expected null or Entity, got: " + parent);
         }
 
-        setSourceEntity((Entity) parent);
+        setSourceEntity((Entity<E,T,U>) parent);
     }
 
     /**
@@ -142,7 +142,7 @@ public abstract class Relationship implements CayenneMapEntry, XMLSerializable,
      * Relationship class.
      */
     final MappingNamespace getNonNullNamespace() {
-        Entity entity = getSourceEntity();
+        Entity<E,?,?> entity = getSourceEntity();
 
         if (entity == null) {
             throw new CayenneRuntimeException("Relationship '%s' has no parent Entity.", getName());
@@ -180,7 +180,7 @@ public abstract class Relationship implements CayenneMapEntry, XMLSerializable,
      * null if no such relationship is found.
      * @since 3.1
      */
-    public abstract Relationship getReverseRelationship();
+    public abstract Relationship<E,T,U> getReverseRelationship();
     
     /**
      * Returns if relationship is mandatory
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/AttributeTest.java b/cayenne-server/src/test/java/org/apache/cayenne/map/AttributeTest.java
index 30ffbad76..2a57a2711 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/AttributeTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/AttributeTest.java
@@ -28,7 +28,7 @@ public class AttributeTest {
 
     @Test
     public void testName() throws Exception {
-        Attribute a = new MockAttribute();
+        MockAttribute a = new MockAttribute();
 
         String tstName = "tst_name";
         a.setName(tstName);
@@ -37,9 +37,9 @@ public class AttributeTest {
 
     @Test
     public void testEntity() throws Exception {
-        Attribute a = new MockAttribute();
+        MockAttribute a = new MockAttribute();
 
-        Entity tstEntity = new MockEntity();
+        MockEntity tstEntity = new MockEntity();
         a.setEntity(tstEntity);
         assertSame(tstEntity, a.getEntity());
     }
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/EntityIT.java b/cayenne-server/src/test/java/org/apache/cayenne/map/EntityIT.java
index ca1445877..ef1bb0492 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/EntityIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/EntityIT.java
@@ -49,14 +49,14 @@ public class EntityIT extends ServerCase {
 
     @Test
     public void testSerializability() throws Exception {
-        Entity entity = new MockEntity("entity");
+        MockEntity entity = new MockEntity("entity");
 
-        Entity d1 = Util.cloneViaSerialization(entity);
+        MockEntity d1 = Util.cloneViaSerialization(entity);
         assertEquals(entity.getName(), d1.getName());
 
         entity.addAttribute(new MockAttribute("abc"));
         entity.addRelationship(new MockRelationship("xyz"));
-        Entity d2 = Util.cloneViaSerialization(entity);
+        MockEntity d2 = Util.cloneViaSerialization(entity);
         assertNotNull(d2.getAttribute("abc"));
 
         // test that ref collection wrappers are still working
@@ -79,7 +79,7 @@ public class EntityIT extends ServerCase {
 
     @Test
     public void testName() {
-        Entity entity = new MockEntity();
+        MockEntity entity = new MockEntity();
         String tstName = "tst_name";
         entity.setName(tstName);
         assertEquals(tstName, entity.getName());
@@ -87,8 +87,8 @@ public class EntityIT extends ServerCase {
 
     @Test
     public void testAttribute() {
-        Entity entity = new MockEntity();
-        Attribute attribute = new MockAttribute("tst_name");
+        MockEntity entity = new MockEntity();
+        MockAttribute attribute = new MockAttribute("tst_name");
 
         entity.addAttribute(attribute);
         assertSame(attribute, entity.getAttribute(attribute.getName()));
@@ -103,8 +103,8 @@ public class EntityIT extends ServerCase {
 
     @Test
     public void testRelationship() {
-        Entity entity = new MockEntity();
-        Relationship rel = new MockRelationship("tst_name");
+        MockEntity entity = new MockEntity();
+        MockRelationship rel = new MockRelationship("tst_name");
 
         entity.addRelationship(rel);
         assertSame(rel, entity.getRelationship(rel.getName()));
@@ -119,13 +119,13 @@ public class EntityIT extends ServerCase {
 
     @Test
     public void testAttributeClashWithRelationship() {
-        Entity entity = new MockEntity();
-        Relationship rel = new MockRelationship("tst_name");
+        MockEntity entity = new MockEntity();
+        MockRelationship rel = new MockRelationship("tst_name");
 
         entity.addRelationship(rel);
 
         try {
-            Attribute attribute = new MockAttribute("tst_name");
+            MockAttribute attribute = new MockAttribute("tst_name");
             entity.addAttribute(attribute);
 
             fail("Exception should have been thrown due to clashing attribute and relationship names.");
@@ -136,13 +136,13 @@ public class EntityIT extends ServerCase {
 
     @Test
     public void testRelationshipClashWithAttribute() {
-        Entity entity = new MockEntity();
-        Attribute attribute = new MockAttribute("tst_name");
+        MockEntity entity = new MockEntity();
+        MockAttribute attribute = new MockAttribute("tst_name");
 
         entity.addAttribute(attribute);
 
         try {
-            Relationship rel = new MockRelationship("tst_name");
+            MockRelationship rel = new MockRelationship("tst_name");
             entity.addRelationship(rel);
 
             fail("Exception should have been thrown due to clashing attribute and relationship names.");
@@ -205,16 +205,16 @@ public class EntityIT extends ServerCase {
 
     @Test
     public void testRemoveAttribute() {
-        Entity entity = new MockEntity();
+        MockEntity entity = new MockEntity();
 
         entity.setName("test");
-        ObjAttribute attribute1 = new ObjAttribute("a1");
-        ObjAttribute attribute2 = new ObjAttribute("a2");
+        MockAttribute attribute1 = new MockAttribute("a1");
+        MockAttribute attribute2 = new MockAttribute("a2");
 
         entity.addAttribute(attribute1);
         entity.addAttribute(attribute2);
 
-        Collection<? extends Attribute> attributes = entity.getAttributes();
+        Collection<MockAttribute> attributes = entity.getAttributes();
         assertEquals(2, attributes.size());
 
         entity.removeAttribute("a1");
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/MockAttribute.java b/cayenne-server/src/test/java/org/apache/cayenne/map/MockAttribute.java
index fda7ec5e4..32596e493 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/MockAttribute.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/MockAttribute.java
@@ -24,7 +24,7 @@ import org.apache.cayenne.util.XMLEncoder;
 
 /**
  */
-public class MockAttribute extends Attribute {
+public class MockAttribute extends Attribute<MockEntity, MockAttribute, MockRelationship> {
 
     public MockAttribute() {
         super();
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/MockEntity.java b/cayenne-server/src/test/java/org/apache/cayenne/map/MockEntity.java
index 94db2e725..793cff03a 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/MockEntity.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/MockEntity.java
@@ -25,11 +25,12 @@ import java.util.Map;
 import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionException;
+import org.apache.cayenne.util.CayenneMapEntry;
 import org.apache.cayenne.util.XMLEncoder;
 
 /**
  */
-public class MockEntity extends Entity {
+public class MockEntity extends Entity<MockEntity, MockAttribute, MockRelationship> {
 
     public MockEntity() {
         super();
@@ -47,13 +48,12 @@ public class MockEntity extends Entity {
     }
 
     @Override
-    public Iterator resolvePathComponents(Expression pathExp) throws ExpressionException {
+    public Iterator<CayenneMapEntry> resolvePathComponents(Expression pathExp) throws ExpressionException {
         return null;
     }
     
     @Override
-    public <T extends Attribute, U extends Relationship> Iterable<PathComponent<T, U>> resolvePath(
-            Expression pathExp, Map joinAliases) {
+    public Iterable<PathComponent<MockAttribute, MockRelationship>> resolvePath(Expression pathExp, Map<String, String> joinAliases) {
         return null;
     }
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/MockRelationship.java b/cayenne-server/src/test/java/org/apache/cayenne/map/MockRelationship.java
index ea1ac9bde..0f06e89ee 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/MockRelationship.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/MockRelationship.java
@@ -22,7 +22,7 @@ package org.apache.cayenne.map;
 import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.util.XMLEncoder;
 
-public class MockRelationship extends Relationship {
+public class MockRelationship extends Relationship<MockEntity, MockAttribute, MockRelationship> {
 
     public MockRelationship() {
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/RelationshipTest.java b/cayenne-server/src/test/java/org/apache/cayenne/map/RelationshipTest.java
index 49c55462c..b7870ece8 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/RelationshipTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/RelationshipTest.java
@@ -28,7 +28,7 @@ public class RelationshipTest {
 
     @Test
     public void testName() throws Exception {
-        Relationship rel = new MockRelationship();
+        MockRelationship rel = new MockRelationship();
 
         String tstName = "tst_name";
         rel.setName(tstName);
@@ -37,16 +37,16 @@ public class RelationshipTest {
 
     @Test
     public void testSourceEntity() {
-        Relationship rel = new MockRelationship();
-        Entity tstEntity = new MockEntity();
+        MockRelationship rel = new MockRelationship();
+        MockEntity tstEntity = new MockEntity();
         rel.setSourceEntity(tstEntity);
         assertSame(tstEntity, rel.getSourceEntity());
     }
 
     @Test
     public void testTargetEntity() {
-        Relationship rel = new MockRelationship();
-        Entity tstEntity = new MockEntity();
+        MockRelationship rel = new MockRelationship();
+        MockEntity tstEntity = new MockEntity();
         tstEntity.setName("abc");
         rel.setTargetEntityName(tstEntity);
         assertSame("abc", rel.getTargetEntityName());
@@ -54,7 +54,7 @@ public class RelationshipTest {
 
     @Test
     public void testTargetEntityName() {
-        Relationship rel = new MockRelationship();
+        MockRelationship rel = new MockRelationship();
         rel.setTargetEntityName("abc");
         assertSame("abc", rel.getTargetEntityName());
     }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjAttributeTableModel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjAttributeTableModel.java
index 319a186d5..16ea15243 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjAttributeTableModel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjAttributeTableModel.java
@@ -22,7 +22,6 @@ package org.apache.cayenne.modeler.editor;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.map.Attribute;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.EmbeddedAttribute;
@@ -68,7 +67,7 @@ public class ObjAttributeTableModel extends CayenneTableModel<ObjAttributeWrappe
     public static final int COMMENT = 6;
     public static final int COLUMN_COUNT = 7;
 
-    private ObjEntity entity;
+    private final ObjEntity entity;
     private DbEntity dbEntity;
     private CellEditorForAttributeTable cellEditor;
     private CayenneTable table;
@@ -80,20 +79,16 @@ public class ObjAttributeTableModel extends CayenneTableModel<ObjAttributeWrappe
         this.dbEntity = entity.getDbEntity();
 
         // order using local comparator
-        Collections.sort(objectList, new AttributeComparator());
+        objectList.sort(new AttributeComparator());
     }
 
     private static List<ObjAttributeWrapper> wrapObjAttributes(Collection<ObjAttribute> attributes) {
-        List<ObjAttributeWrapper>  wrappedAttributes = new ArrayList<ObjAttributeWrapper>();
+        List<ObjAttributeWrapper>  wrappedAttributes = new ArrayList<>();
         for(ObjAttribute attr : attributes) {
             wrappedAttributes.add(new ObjAttributeWrapper(attr));
         }
         return wrappedAttributes;
     }
-    
-    protected void orderList() {
-        // NOOP
-    }
 
     public CayenneTable getTable() {
         return table;
@@ -415,19 +410,19 @@ public class ObjAttributeTableModel extends CayenneTableModel<ObjAttributeWrappe
         return entity;
     }
 
-    final class AttributeComparator implements Comparator {
+    final class AttributeComparator implements Comparator<ObjAttributeWrapper> {
 
-        public int compare(Object o1, Object o2) {
-            Attribute a1 = ((ObjAttributeWrapper) o1).getValue();
-            Attribute a2 = ((ObjAttributeWrapper) o2).getValue();
+        public int compare(ObjAttributeWrapper o1, ObjAttributeWrapper o2) {
+            ObjAttribute a1 = o1.getValue();
+            ObjAttribute a2 = o2.getValue();
 
             int delta = getWeight(a1) - getWeight(a2);
-
-            return (delta != 0) ? delta : Util.nullSafeCompare(true, a1.getName(), a2
-                    .getName());
+            return (delta != 0)
+                    ? delta
+                    : Util.nullSafeCompare(true, a1.getName(), a2.getName());
         }
 
-        private int getWeight(Attribute a) {
+        private int getWeight(ObjAttribute a) {
             return a.getEntity() == entity ? 1 : -1;
         }
     }
@@ -449,7 +444,7 @@ public class ObjAttributeTableModel extends CayenneTableModel<ObjAttributeWrappe
                 break;
             case DB_ATTRIBUTE:
             case DB_ATTRIBUTE_TYPE:
-                Collections.sort(objectList, new ObjAttributeTableComparator(sortCol));
+                objectList.sort(new ObjAttributeTableComparator(sortCol));
                 if (!isAscent) {
                     Collections.reverse(objectList);
                 }
@@ -459,7 +454,7 @@ public class ObjAttributeTableModel extends CayenneTableModel<ObjAttributeWrappe
 
     private class ObjAttributeTableComparator implements Comparator<ObjAttributeWrapper>{
 
-        private int sortCol;
+        private final int sortCol;
 
         public ObjAttributeTableComparator(int sortCol) {
             this.sortCol = sortCol;
@@ -479,27 +474,23 @@ public class ObjAttributeTableModel extends CayenneTableModel<ObjAttributeWrappe
                     valToCompare2 = getDBAttribute(o2, o2.getDbAttribute());
                     break;
                 case DB_ATTRIBUTE_TYPE:
-                    valToCompare1 = getDBAttributeType(o1, o1
-                            .getDbAttribute());
-                    valToCompare2 = getDBAttributeType(o2, o2
-                            .getDbAttribute());
-                    break;
-                default:
+                    valToCompare1 = getDBAttributeType(o1, o1.getDbAttribute());
+                    valToCompare2 = getDBAttributeType(o2, o2.getDbAttribute());
                     break;
             }
-            return (valToCompare1 == null) ? -1 : (valToCompare2 == null)
-                    ? 1
-                    : valToCompare1.compareTo(valToCompare2);
+            return (valToCompare1 == null)
+                    ? -1
+                    : (valToCompare2 == null)
+                        ? 1
+                        : valToCompare1.compareTo(valToCompare2);
         }
 
         private Integer compareObjAttributes(ObjAttributeWrapper o1, ObjAttributeWrapper o2) {
-            if ((o1 == null && o2 == null) || o1 == o2) {
+            if (o1 == o2) {
                 return 0;
-            }
-            else if (o1 == null && o2 != null) {
+            } else if (o1 == null) {
                 return -1;
-            }
-            else if (o1 != null && o2 == null) {
+            } else if (o2 == null) {
                 return 1;
             }
             return null;
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/wrapper/ObjAttributeWrapper.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/wrapper/ObjAttributeWrapper.java
index f6f64db45..7fd3027f0 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/wrapper/ObjAttributeWrapper.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/wrapper/ObjAttributeWrapper.java
@@ -36,13 +36,13 @@ import org.apache.cayenne.validation.ValidationResult;
  */
 public class ObjAttributeWrapper implements Wrapper<ObjAttribute> {
 
-    private ObjAttribute objAttribute;
-    private ValidationResult validationResult;
+    private final ObjAttribute objAttribute;
+    private final ValidationResult validationResult;
 
-    private ObjAttributeWrapperValidator validator = new ObjAttributeWrapperValidator();
+    private final ObjAttributeWrapperValidator validator = new ObjAttributeWrapperValidator();
 
     // TODO: for now name is only wrapped attribute we validating but this
-    // can be extended to other ObjAttribute fields as well
+    //       can be extended to other ObjAttribute fields as well
     private String name;
 
     public ObjAttributeWrapper(ObjAttribute objAttribute) {
@@ -98,7 +98,7 @@ public class ObjAttributeWrapper implements Wrapper<ObjAttribute> {
         return objAttribute.getEntity();
     }
 
-    public void setEntity(Entity entity) {
+    public void setEntity(ObjEntity entity) {
         objAttribute.setEntity(entity);
     }
 
@@ -120,7 +120,7 @@ public class ObjAttributeWrapper implements Wrapper<ObjAttribute> {
     }
 
     public Class<?> getJavaClass() {
-        return objAttribute.getClass();
+        return objAttribute.getJavaClass();
     }
 
     public String getType() {
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java
index 303ecc676..c7ef52e4d 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java
@@ -289,7 +289,7 @@ abstract class BaseGraphBuilder implements GraphBuilder, DataMapListener {
     /**
      * Post (i.e. after creation on entity cell) process of the entity
      */
-    protected void postProcessEntity(Entity entity, DefaultGraphCell cell) {
+    protected void postProcessEntity(Entity<?,?,?> entity, DefaultGraphCell cell) {
         for (Relationship rel : entity.getRelationships()) {
             if (rel.getSourceEntity() != null && rel.getTargetEntity() != null) {
                 DefaultEdge edge = createRelationshipCell(rel);
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/DbEntityCellMetadata.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/DbEntityCellMetadata.java
index 192377010..025bcf338 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/DbEntityCellMetadata.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/DbEntityCellMetadata.java
@@ -18,27 +18,23 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.graph;
 
-import java.util.Iterator;
-
-import org.apache.cayenne.map.Attribute;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.Entity;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
 
 /**
  * Descriptor of DbEntity Cell
  */
-class DbEntityCellMetadata extends EntityCellMetadata {
+class DbEntityCellMetadata extends EntityCellMetadata<DbEntity, DbAttribute, DbRelationship> {
     DbEntityCellMetadata(GraphBuilder builder, String entityName) {
         super(builder, entityName);
     }
     
     @Override
-    public Entity fetchEntity() {
-        Iterator<DataMap> it = builder.getDataDomain().getDataMaps().iterator();
-        while(it.hasNext()){
-            DataMap dm = (DataMap)it.next();
-            if(dm.getDbEntity(entityName)!=null){
+    public DbEntity fetchEntity() {
+        for (DataMap dm : builder.getDataDomain().getDataMaps()) {
+            if (dm.getDbEntity(entityName) != null) {
                 return dm.getDbEntity(entityName);
             }
         }
@@ -46,7 +42,7 @@ class DbEntityCellMetadata extends EntityCellMetadata {
     }
 
     @Override
-    protected boolean isPrimary(Attribute attr) {
-        return ((DbAttribute) attr).isPrimaryKey();
+    protected boolean isPrimary(DbAttribute attr) {
+        return attr.isPrimaryKey();
     }
 }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/EntityCellMetadata.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/EntityCellMetadata.java
index c51b75cb0..b9affa6ec 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/EntityCellMetadata.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/EntityCellMetadata.java
@@ -22,11 +22,12 @@ import java.io.Serializable;
 
 import org.apache.cayenne.map.Attribute;
 import org.apache.cayenne.map.Entity;
+import org.apache.cayenne.map.Relationship;
 
 /**
  * Abstract class to describe entity's cell 
  */
-abstract class EntityCellMetadata implements Serializable {
+abstract class EntityCellMetadata<E extends Entity<E, T, U>, T extends Attribute<E,T,U>, U extends Relationship<E,T,U>> implements Serializable {
     GraphBuilder builder;
     
     String entityName;
@@ -45,7 +46,7 @@ abstract class EntityCellMetadata implements Serializable {
     /**
      * Resolves entity
      */
-    public abstract Entity fetchEntity();
+    public abstract Entity<E,T,U> fetchEntity();
     
     final void rebuildLabel() {
         label = createLabel();
@@ -63,15 +64,15 @@ abstract class EntityCellMetadata implements Serializable {
      * Creates label for this cell
      */
     String createLabel() {
-        Entity entity = fetchEntity();
+        Entity<E,T,U> entity = fetchEntity();
         StringBuilder label = new StringBuilder("<html><center><u><b>").
                 append(entity.getName()).append("</b></u></center>");
-        for (Attribute attr : entity.getAttributes()) {
+        for (T attr : entity.getAttributes()) {
             if (isPrimary(attr)) {
                 label.append("<br><i>").append(attr.getName()).append("</i>");
             }
         }
-        for (Attribute attr : entity.getAttributes()) {
+        for (T attr : entity.getAttributes()) {
             if (!isPrimary(attr)) {
                 label.append("<br>").append(attr.getName());
             }
@@ -82,5 +83,5 @@ abstract class EntityCellMetadata implements Serializable {
     /**
      * Returns whether attribute is "primary" and should therefore be written in italic
      */
-    protected abstract boolean isPrimary(Attribute attr);
+    protected abstract boolean isPrimary(T attr);
 }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/ObjEntityCellMetadata.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/ObjEntityCellMetadata.java
index 648ee0597..2c265532a 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/ObjEntityCellMetadata.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/ObjEntityCellMetadata.java
@@ -18,26 +18,23 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.graph;
 
-import java.util.Iterator;
-
-import org.apache.cayenne.map.Attribute;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.Entity;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
 
 /**
  * Descriptor of ObjEntity Cell
  */
-class ObjEntityCellMetadata extends EntityCellMetadata {
+class ObjEntityCellMetadata extends EntityCellMetadata<ObjEntity, ObjAttribute, ObjRelationship> {
     ObjEntityCellMetadata(GraphBuilder builder, String entityName) {
         super(builder, entityName);
     }
     
     @Override
-    public Entity fetchEntity() {
-        Iterator<DataMap> it = builder.getDataDomain().getDataMaps().iterator();
-        while(it.hasNext()){
-            DataMap dm = (DataMap)it.next();
-            if(dm.getObjEntity(entityName)!=null){
+    public ObjEntity fetchEntity() {
+        for (DataMap dm : builder.getDataDomain().getDataMaps()) {
+            if (dm.getObjEntity(entityName) != null) {
                 return dm.getObjEntity(entityName);
             }
         }
@@ -45,7 +42,7 @@ class ObjEntityCellMetadata extends EntityCellMetadata {
     }
 
     @Override
-    protected boolean isPrimary(Attribute attr) {
+    protected boolean isPrimary(ObjAttribute attr) {
         return false;
     }
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/RelationshipUndoableEdit.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/RelationshipUndoableEdit.java
index 42a584af7..789a93273 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/RelationshipUndoableEdit.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/RelationshipUndoableEdit.java
@@ -35,12 +35,12 @@ public class RelationshipUndoableEdit extends CayenneUndoableEdit {
 
 	private static final long serialVersionUID = -1864303176024098961L;
 
-	private Relationship relationship;
-    private Relationship prevRelationship;
+	private Relationship<?,?,?> relationship;
+    private Relationship<?,?,?> prevRelationship;
     private ProjectController projectController;
     private boolean useDb;
 
-	public RelationshipUndoableEdit(Relationship relationship) {
+	public RelationshipUndoableEdit(Relationship<?,?,?> relationship) {
 		this.projectController = Application.getInstance().getFrameController().getProjectController();
 		this.relationship = relationship;
 		this.useDb = relationship instanceof DbRelationship;
@@ -57,16 +57,16 @@ public class RelationshipUndoableEdit extends CayenneUndoableEdit {
 		fireRelationshipEvent(prevRelationship, relationship);
 	}
 
-	private void fireRelationshipEvent(Relationship relToFire, Relationship currRel) {
+	private void fireRelationshipEvent(Relationship<?,?,?> relToFire, Relationship<?,?,?> currRel) {
 		if(useDb) {
-			fireDbRelationshipEvent(relToFire, currRel);
+			fireDbRelationshipEvent((DbRelationship) relToFire, (DbRelationship)currRel);
 		} else {
-			fireObjRelationshipEvent(relToFire, currRel);
+			fireObjRelationshipEvent((ObjRelationship) relToFire, (ObjRelationship) currRel);
 		}
 	}
 
-	private void fireDbRelationshipEvent(Relationship relToFire, Relationship currRel) {
-		DbEntity dbEntity = ((DbRelationship)currRel).getSourceEntity();
+	private void fireDbRelationshipEvent(DbRelationship relToFire, DbRelationship currRel) {
+		DbEntity dbEntity = currRel.getSourceEntity();
 		dbEntity.removeRelationship(currRel.getName());
 		dbEntity.addRelationship(relToFire);
 		projectController
@@ -74,8 +74,8 @@ public class RelationshipUndoableEdit extends CayenneUndoableEdit {
 						new RelationshipEvent(this, relToFire, relToFire.getSourceEntity(), MapEvent.ADD));
 	}
 
-	private void fireObjRelationshipEvent(Relationship relToFire, Relationship currRel) {
-		ObjEntity objEntity = ((ObjRelationship) currRel).getSourceEntity();
+	private void fireObjRelationshipEvent(ObjRelationship relToFire, ObjRelationship currRel) {
+		ObjEntity objEntity = currRel.getSourceEntity();
 		objEntity.removeRelationship(currRel.getName());
 		objEntity.addRelationship(relToFire);
 		projectController
@@ -93,14 +93,16 @@ public class RelationshipUndoableEdit extends CayenneUndoableEdit {
 		return "Undo Edit relationship";
 	}
 
-	private Relationship copyRelationship(Relationship relationship) {
-		return useDb ? getDbRelationship(relationship) : getObjRelationship(relationship);
+	private Relationship<?,?,?> copyRelationship(Relationship<?,?,?> relationship) {
+		return useDb
+				? getDbRelationship((DbRelationship) relationship)
+				: getObjRelationship((ObjRelationship) relationship);
 	}
 
-	private DbRelationship getDbRelationship(Relationship dbRelationship) {
+	private DbRelationship getDbRelationship(DbRelationship dbRelationship) {
 		DbRelationship rel = new DbRelationship();
 		rel.setName(dbRelationship.getName());
-		rel.setToDependentPK(((DbRelationship)dbRelationship).isToDependentPK());
+		rel.setToDependentPK(dbRelationship.isToDependentPK());
 		rel.setToMany(dbRelationship.isToMany());
 		rel.setTargetEntityName(dbRelationship.getTargetEntityName());
 		rel.setSourceEntity(dbRelationship.getSourceEntity());
@@ -108,16 +110,16 @@ public class RelationshipUndoableEdit extends CayenneUndoableEdit {
 		return rel;
 	}
 
-	private ObjRelationship getObjRelationship(Relationship objRelationship) {
+	private ObjRelationship getObjRelationship(ObjRelationship objRelationship) {
 		ObjRelationship rel = new ObjRelationship();
 		rel.setName(objRelationship.getName());
 		rel.setTargetEntityName(objRelationship.getTargetEntityName());
 		rel.setSourceEntity(objRelationship.getSourceEntity());
-		rel.setDeleteRule(((ObjRelationship)objRelationship).getDeleteRule());
-		rel.setUsedForLocking(((ObjRelationship)objRelationship).isUsedForLocking());
-		rel.setDbRelationshipPath(((ObjRelationship)objRelationship).getDbRelationshipPath());
-		rel.setCollectionType(((ObjRelationship)objRelationship).getCollectionType());
-		rel.setMapKey(((ObjRelationship)objRelationship).getMapKey());
+		rel.setDeleteRule(objRelationship.getDeleteRule());
+		rel.setUsedForLocking(objRelationship.isUsedForLocking());
+		rel.setDbRelationshipPath(objRelationship.getDbRelationshipPath());
+		rel.setCollectionType(objRelationship.getCollectionType());
+		rel.setMapKey(objRelationship.getMapKey());
 		return rel;
 	}
 }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeModel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeModel.java
index 24276ddd9..fb2812217 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeModel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/EntityTreeModel.java
@@ -33,7 +33,6 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Vector;
 
 /**
  * Swing TreeModel for Entity attributes and relationships
@@ -41,7 +40,7 @@ import java.util.Vector;
  * @since 1.1
  */
 public class EntityTreeModel implements TreeModel {
-    protected Entity root;
+    protected Entity<?,?,?> root;
     protected Map<Object, ConfigurationNode[]> sortedChildren;
 
     /**
@@ -49,7 +48,7 @@ public class EntityTreeModel implements TreeModel {
      */
     protected EntityTreeFilter filter;
 
-    public EntityTreeModel(Entity root) {
+    public EntityTreeModel(Entity<?,?,?> root) {
         this.root = root;
         sortedChildren = new HashMap<>();
     }
@@ -92,6 +91,7 @@ public class EntityTreeModel implements TreeModel {
         // do nothing...
     }
 
+    @SuppressWarnings({"unchecked", "rawtypes"})
     private ConfigurationNode[] sortedChildren(Object node) {
         Entity entity = entityForNonLeafNode(node);
 
@@ -103,19 +103,19 @@ public class EntityTreeModel implements TreeModel {
         ConfigurationNode[] sortedForNode = sortedChildren.get(node);
 
         if (sortedForNode == null) {
-            Collection<? extends Attribute> attributes = entity.getAttributes();
-            Collection<? extends Relationship> relationships = entity.getRelationships();
+            Collection<Attribute<?,?,?>> attributes = entity.getAttributes();
+            Collection<Relationship<?,?,?>> relationships = entity.getRelationships();
 
             List<ConfigurationNode> nodes = new ArrayList<>();
 
             // combine two collections in an array
-            for (Attribute attr : attributes) {
+            for (Attribute<?,?,?> attr : attributes) {
                 if (filter == null || filter.attributeMatch(node, attr)) {
                     nodes.add((ConfigurationNode)attr);
                 }
             }
 
-            for (Relationship rel : relationships) {
+            for (Relationship<?,?,?> rel : relationships) {
                 if (filter == null || filter.relationshipMatch(node, rel)) {
                     nodes.add((ConfigurationNode)rel);
                 }
@@ -140,19 +140,19 @@ public class EntityTreeModel implements TreeModel {
     /**
      * Removes children cache for specified entity.
      */
-    public void invalidateChildren(Entity entity) {
+    public void invalidateChildren(Entity<?,?,?> entity) {
         sortedChildren.remove(entity);
 
-        for (Relationship rel : entity.getRelationships()) {
+        for (Relationship<?,?,?> rel : entity.getRelationships()) {
             sortedChildren.remove(rel);
         }
     }
 
-    private Entity entityForNonLeafNode(Object node) {
+    private Entity<?,?,?> entityForNonLeafNode(Object node) {
         if (node instanceof Entity) {
-            return (Entity) node;
+            return (Entity<?,?,?>) node;
         } else if (node instanceof Relationship) {
-            return ((Relationship) node).getTargetEntity();
+            return ((Relationship<?,?,?>) node).getTargetEntity();
         }
 
         String className = (node != null) ? node.getClass().getName() : "null";
diff --git a/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOObjEntity.java b/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOObjEntity.java
index b25132415..53cba8228 100644
--- a/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOObjEntity.java
+++ b/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOObjEntity.java
@@ -25,6 +25,7 @@ import org.apache.cayenne.exp.ExpressionException;
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
 import org.apache.cayenne.map.Relationship;
 
 import java.util.ArrayList;
@@ -184,7 +185,7 @@ public class EOObjEntity extends ObjEntity {
 
                     buffer.append(chunk);
 
-                    Relationship r = entity.getRelationship(chunk);
+                    ObjRelationship r = entity.getRelationship(chunk);
                     if (r == null) {
                         throw new ExpressionException("Invalid path component: " + chunk);
                     }


[cayenne] 02/03: code cleanup

Posted by nt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit f7a44ff1decce0f9eb7c2c616b0595c92f35806f
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Thu Jul 14 10:45:33 2022 +0300

    code cleanup
---
 .../apache/cayenne/modeler/ProjectController.java  | 201 +++++++++------------
 1 file changed, 85 insertions(+), 116 deletions(-)

diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectController.java
index 14b7cb0b5..c203d4f0b 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectController.java
@@ -24,7 +24,6 @@ import java.awt.Component;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.EventListener;
 import java.util.EventObject;
 import java.util.HashSet;
@@ -139,7 +138,7 @@ public class ProjectController extends CayenneController {
      * A snapshot of the current state of the project controller. This was added
      * so that we could support history of recent objects.
      */
-    public class ControllerState {
+    public static class ControllerState {
 
         private boolean isRefiring;
         private DisplayEvent event;
@@ -750,9 +749,8 @@ public class ProjectController extends CayenneController {
             saveState(e);
         }
 
-        for (EventListener listener : listenerList.getListeners(DomainDisplayListener.class)) {
-            DomainDisplayListener temp = (DomainDisplayListener) listener;
-            temp.currentDomainChanged(e);
+        for (DomainDisplayListener listener : listenerList.getListeners(DomainDisplayListener.class)) {
+            listener.currentDomainChanged(e);
         }
 
         // call different methods depending on whether domain was opened or
@@ -775,11 +773,10 @@ public class ProjectController extends CayenneController {
             removeFromHistory(e);
         }
 
-        for (EventListener listener : listenerList.getListeners(DomainListener.class)) {
-            DomainListener temp = (DomainListener) listener;
+        for (DomainListener listener : listenerList.getListeners(DomainListener.class)) {
             switch (e.getId()) {
             case MapEvent.CHANGE:
-                temp.domainChanged(e);
+                listener.domainChanged(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid DomainEvent type: " + e.getId());
@@ -809,9 +806,8 @@ public class ProjectController extends CayenneController {
             saveState(e);
         }
 
-        EventListener[] list = listenerList.getListeners(DataNodeDisplayListener.class);
-        for (EventListener listener : list) {
-            ((DataNodeDisplayListener) listener).currentDataNodeChanged(e);
+        for (DataNodeDisplayListener listener : listenerList.getListeners(DataNodeDisplayListener.class)) {
+            listener.currentDataNodeChanged(e);
         }
     }
 
@@ -826,17 +822,16 @@ public class ProjectController extends CayenneController {
             removeFromHistory(e);
         }
 
-        for (EventListener listener : listenerList.getListeners(DataNodeListener.class)) {
-            DataNodeListener temp = (DataNodeListener) listener;
+        for (DataNodeListener listener : listenerList.getListeners(DataNodeListener.class)) {
             switch (e.getId()) {
             case MapEvent.ADD:
-                temp.dataNodeAdded(e);
+                listener.dataNodeAdded(e);
                 break;
             case MapEvent.CHANGE:
-                temp.dataNodeChanged(e);
+                listener.dataNodeChanged(e);
                 break;
             case MapEvent.REMOVE:
-                temp.dataNodeRemoved(e);
+                listener.dataNodeRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid DataNodeEvent type: " + e.getId());
@@ -867,10 +862,8 @@ public class ProjectController extends CayenneController {
             saveState(e);
         }
 
-        EventListener[] list = listenerList.getListeners(DataMapDisplayListener.class);
-        for (EventListener listener : list) {
-            DataMapDisplayListener temp = (DataMapDisplayListener) listener;
-            temp.currentDataMapChanged(e);
+        for (DataMapDisplayListener listener : listenerList.getListeners(DataMapDisplayListener.class)) {
+            listener.currentDataMapChanged(e);
         }
     }
 
@@ -885,17 +878,16 @@ public class ProjectController extends CayenneController {
             removeFromHistory(e);
         }
 
-        for (EventListener eventListener : listenerList.getListeners(DataMapListener.class)) {
-            DataMapListener listener = (DataMapListener) eventListener;
+        for (DataMapListener eventListener : listenerList.getListeners(DataMapListener.class)) {
             switch (e.getId()) {
             case MapEvent.ADD:
-                listener.dataMapAdded(e);
+                eventListener.dataMapAdded(e);
                 break;
             case MapEvent.CHANGE:
-                listener.dataMapChanged(e);
+                eventListener.dataMapChanged(e);
                 break;
             case MapEvent.REMOVE:
-                listener.dataMapRemoved(e);
+                eventListener.dataMapRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid DataMapEvent type: " + e.getId());
@@ -918,17 +910,16 @@ public class ProjectController extends CayenneController {
             removeFromHistory(e);
         }
 
-        for (EventListener listener : listenerList.getListeners(ObjEntityListener.class)) {
-            ObjEntityListener temp = (ObjEntityListener) listener;
+        for (ObjEntityListener listener : listenerList.getListeners(ObjEntityListener.class)) {
             switch (e.getId()) {
             case MapEvent.ADD:
-                temp.objEntityAdded(e);
+                listener.objEntityAdded(e);
                 break;
             case MapEvent.CHANGE:
-                temp.objEntityChanged(e);
+                listener.objEntityChanged(e);
                 break;
             case MapEvent.REMOVE:
-                temp.objEntityRemoved(e);
+                listener.objEntityRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid EntityEvent type: " + e.getId());
@@ -951,17 +942,16 @@ public class ProjectController extends CayenneController {
             removeFromHistory(e);
         }
 
-        for (EventListener listener : listenerList.getListeners(DbEntityListener.class)) {
-            DbEntityListener temp = (DbEntityListener) listener;
+        for (DbEntityListener listener : listenerList.getListeners(DbEntityListener.class)) {
             switch (e.getId()) {
             case MapEvent.ADD:
-                temp.dbEntityAdded(e);
+                listener.dbEntityAdded(e);
                 break;
             case MapEvent.CHANGE:
-                temp.dbEntityChanged(e);
+                listener.dbEntityChanged(e);
                 break;
             case MapEvent.REMOVE:
-                temp.dbEntityRemoved(e);
+                listener.dbEntityRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid EntityEvent type: " + e.getId());
@@ -980,17 +970,16 @@ public class ProjectController extends CayenneController {
             removeFromHistory(e);
         }
 
-        for (EventListener eventListener : listenerList.getListeners(QueryListener.class)) {
-            QueryListener listener = (QueryListener) eventListener;
+        for (QueryListener eventListener : listenerList.getListeners(QueryListener.class)) {
             switch (e.getId()) {
             case MapEvent.ADD:
-                listener.queryAdded(e);
+                eventListener.queryAdded(e);
                 break;
             case MapEvent.CHANGE:
-                listener.queryChanged(e);
+                eventListener.queryChanged(e);
                 break;
             case MapEvent.REMOVE:
-                listener.queryRemoved(e);
+                eventListener.queryRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid ProcedureEvent type: " + e.getId());
@@ -1009,17 +998,16 @@ public class ProjectController extends CayenneController {
             removeFromHistory(e);
         }
 
-        for (EventListener eventListener : listenerList.getListeners(ProcedureListener.class)) {
-            ProcedureListener listener = (ProcedureListener) eventListener;
+        for (ProcedureListener eventListener : listenerList.getListeners(ProcedureListener.class)) {
             switch (e.getId()) {
             case MapEvent.ADD:
-                listener.procedureAdded(e);
+                eventListener.procedureAdded(e);
                 break;
             case MapEvent.CHANGE:
-                listener.procedureChanged(e);
+                eventListener.procedureChanged(e);
                 break;
             case MapEvent.REMOVE:
-                listener.procedureRemoved(e);
+                eventListener.procedureRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid ProcedureEvent type: " + e.getId());
@@ -1194,9 +1182,8 @@ public class ProjectController extends CayenneController {
             saveState(e);
         }
 
-        for (EventListener listener : listenerList.getListeners(ObjEntityDisplayListener.class)) {
-            ObjEntityDisplayListener temp = (ObjEntityDisplayListener) listener;
-            temp.currentObjEntityChanged(e);
+        for (ObjEntityDisplayListener listener : listenerList.getListeners(ObjEntityDisplayListener.class)) {
+            listener.currentObjEntityChanged(e);
         }
     }
 
@@ -1219,9 +1206,8 @@ public class ProjectController extends CayenneController {
             saveState(e);
         }
 
-        for (EventListener listener : listenerList.getListeners(EmbeddableDisplayListener.class)) {
-            EmbeddableDisplayListener temp = (EmbeddableDisplayListener) listener;
-            temp.currentEmbeddableChanged(e);
+        for (EmbeddableDisplayListener listener : listenerList.getListeners(EmbeddableDisplayListener.class)) {
+            listener.currentEmbeddableChanged(e);
         }
     }
 
@@ -1243,9 +1229,8 @@ public class ProjectController extends CayenneController {
             saveState(e);
         }
 
-        for (EventListener eventListener : listenerList.getListeners(QueryDisplayListener.class)) {
-            QueryDisplayListener listener = (QueryDisplayListener) eventListener;
-            listener.currentQueryChanged(e);
+        for (QueryDisplayListener eventListener : listenerList.getListeners(QueryDisplayListener.class)) {
+            eventListener.currentQueryChanged(e);
         }
     }
 
@@ -1267,9 +1252,8 @@ public class ProjectController extends CayenneController {
             saveState(e);
         }
 
-        for (EventListener eventListener : listenerList.getListeners(ProcedureDisplayListener.class)) {
-            ProcedureDisplayListener listener = (ProcedureDisplayListener) eventListener;
-            listener.currentProcedureChanged(e);
+        for (ProcedureDisplayListener eventListener : listenerList.getListeners(ProcedureDisplayListener.class)) {
+            eventListener.currentProcedureChanged(e);
         }
     }
 
@@ -1311,9 +1295,8 @@ public class ProjectController extends CayenneController {
             saveState(e);
         }
 
-        for (EventListener listener : listenerList.getListeners(DbEntityDisplayListener.class)) {
-            DbEntityDisplayListener temp = (DbEntityDisplayListener) listener;
-            temp.currentDbEntityChanged(e);
+        for (DbEntityDisplayListener listener : listenerList.getListeners(DbEntityDisplayListener.class)) {
+            listener.currentDbEntityChanged(e);
         }
     }
 
@@ -1321,17 +1304,16 @@ public class ProjectController extends CayenneController {
     public void fireDbAttributeEvent(AttributeEvent e) {
         setDirty(true);
 
-        for (EventListener listener : listenerList.getListeners(DbAttributeListener.class)) {
-            DbAttributeListener temp = (DbAttributeListener) listener;
+        for (DbAttributeListener listener : listenerList.getListeners(DbAttributeListener.class)) {
             switch (e.getId()) {
             case MapEvent.ADD:
-                temp.dbAttributeAdded(e);
+                listener.dbAttributeAdded(e);
                 break;
             case MapEvent.CHANGE:
-                temp.dbAttributeChanged(e);
+                listener.dbAttributeChanged(e);
                 break;
             case MapEvent.REMOVE:
-                temp.dbAttributeRemoved(e);
+                listener.dbAttributeRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid AttributeEvent type: " + e.getId());
@@ -1353,9 +1335,8 @@ public class ProjectController extends CayenneController {
             System.arraycopy(e.getAttributes(), 0, currentState.dbAttrs, 0, currentState.dbAttrs.length);
         }
 
-        for (EventListener listener : listenerList.getListeners(DbAttributeDisplayListener.class)) {
-            DbAttributeDisplayListener temp = (DbAttributeDisplayListener) listener;
-            temp.currentDbAttributeChanged(e);
+        for (DbAttributeDisplayListener listener : listenerList.getListeners(DbAttributeDisplayListener.class)) {
+            listener.currentDbAttributeChanged(e);
         }
     }
 
@@ -1363,17 +1344,16 @@ public class ProjectController extends CayenneController {
     public void fireObjAttributeEvent(AttributeEvent e) {
         setDirty(true);
 
-        for (EventListener listener : listenerList.getListeners(ObjAttributeListener.class)) {
-            ObjAttributeListener temp = (ObjAttributeListener) listener;
+        for (ObjAttributeListener listener : listenerList.getListeners(ObjAttributeListener.class)) {
             switch (e.getId()) {
             case MapEvent.ADD:
-                temp.objAttributeAdded(e);
+                listener.objAttributeAdded(e);
                 break;
             case MapEvent.CHANGE:
-                temp.objAttributeChanged(e);
+                listener.objAttributeChanged(e);
                 break;
             case MapEvent.REMOVE:
-                temp.objAttributeRemoved(e);
+                listener.objAttributeRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid AttributeEvent type: " + e.getId());
@@ -1431,17 +1411,16 @@ public class ProjectController extends CayenneController {
             ((DbEntity) e.getEntity()).dbRelationshipChanged(e);
         }
 
-        for (EventListener listener : listenerList.getListeners(DbRelationshipListener.class)) {
-            DbRelationshipListener temp = (DbRelationshipListener) listener;
+        for (DbRelationshipListener listener : listenerList.getListeners(DbRelationshipListener.class)) {
             switch (e.getId()) {
             case MapEvent.ADD:
-                temp.dbRelationshipAdded(e);
+                listener.dbRelationshipAdded(e);
                 break;
             case MapEvent.CHANGE:
-                temp.dbRelationshipChanged(e);
+                listener.dbRelationshipChanged(e);
                 break;
             case MapEvent.REMOVE:
-                temp.dbRelationshipRemoved(e);
+                listener.dbRelationshipRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid RelationshipEvent type: " + e.getId());
@@ -1463,9 +1442,8 @@ public class ProjectController extends CayenneController {
             System.arraycopy(e.getRelationships(), 0, currentState.dbRels, 0, currentState.dbRels.length);
         }
 
-        for (EventListener listener : listenerList.getListeners(DbRelationshipDisplayListener.class)) {
-            DbRelationshipDisplayListener temp = (DbRelationshipDisplayListener) listener;
-            temp.currentDbRelationshipChanged(e);
+        for (DbRelationshipDisplayListener listener : listenerList.getListeners(DbRelationshipDisplayListener.class)) {
+            listener.currentDbRelationshipChanged(e);
         }
     }
 
@@ -1473,17 +1451,16 @@ public class ProjectController extends CayenneController {
     public void fireObjRelationshipEvent(RelationshipEvent e) {
         setDirty(true);
 
-        for (EventListener listener : listenerList.getListeners(ObjRelationshipListener.class)) {
-            ObjRelationshipListener temp = (ObjRelationshipListener) listener;
+        for (ObjRelationshipListener listener : listenerList.getListeners(ObjRelationshipListener.class)) {
             switch (e.getId()) {
             case MapEvent.ADD:
-                temp.objRelationshipAdded(e);
+                listener.objRelationshipAdded(e);
                 break;
             case MapEvent.CHANGE:
-                temp.objRelationshipChanged(e);
+                listener.objRelationshipChanged(e);
                 break;
             case MapEvent.REMOVE:
-                temp.objRelationshipRemoved(e);
+                listener.objRelationshipRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid RelationshipEvent type: " + e.getId());
@@ -1518,10 +1495,8 @@ public class ProjectController extends CayenneController {
             System.arraycopy(e.getRelationships(), 0, currentState.objRels, 0, currentState.objRels.length);
         }
 
-        EventListener[] list = listenerList.getListeners(ObjRelationshipDisplayListener.class);
-        for (EventListener listener : list) {
-            ObjRelationshipDisplayListener temp = (ObjRelationshipDisplayListener) listener;
-            temp.currentObjRelationshipChanged(e);
+        for (ObjRelationshipDisplayListener listener : listenerList.getListeners(ObjRelationshipDisplayListener.class)) {
+            listener.currentObjRelationshipChanged(e);
         }
     }
 
@@ -1620,17 +1595,16 @@ public class ProjectController extends CayenneController {
     public void fireCallbackMethodEvent(CallbackMethodEvent e) {
         setDirty(true);
 
-        for (EventListener listener : listenerList.getListeners(CallbackMethodListener.class)) {
-            CallbackMethodListener temp = (CallbackMethodListener) listener;
+        for (CallbackMethodListener listener : listenerList.getListeners(CallbackMethodListener.class)) {
             switch (e.getId()) {
             case MapEvent.ADD:
-                temp.callbackMethodAdded(e);
+                listener.callbackMethodAdded(e);
                 break;
             case MapEvent.CHANGE:
-                temp.callbackMethodChanged(e);
+                listener.callbackMethodChanged(e);
                 break;
             case MapEvent.REMOVE:
-                temp.callbackMethodRemoved(e);
+                listener.callbackMethodRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid CallbackEvent type: " + e.getId());
@@ -1657,17 +1631,16 @@ public class ProjectController extends CayenneController {
     public void fireEntityListenerEvent(EntityListenerEvent e) {
         setDirty(true);
 
-        for (EventListener listener : listenerList.getListeners(EntityListenerListener.class)) {
-            EntityListenerListener temp = (EntityListenerListener) listener;
+        for (EntityListenerListener listener : listenerList.getListeners(EntityListenerListener.class)) {
             switch (e.getId()) {
             case MapEvent.ADD:
-                temp.entityListenerAdded(e);
+                listener.entityListenerAdded(e);
                 break;
             case MapEvent.CHANGE:
-                temp.entityListenerChanged(e);
+                listener.entityListenerChanged(e);
                 break;
             case MapEvent.REMOVE:
-                temp.entityListenerRemoved(e);
+                listener.entityListenerRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid CallbackEvent type: " + e.getId());
@@ -1707,8 +1680,7 @@ public class ProjectController extends CayenneController {
                     .getInstance(ConfigurationNodeParentGetter.class);
             Object parent = parentGetter.getParent(paths[0]);
 
-            List<ConfigurationNode> result = new ArrayList<>();
-            result.addAll(Arrays.asList(paths));
+            List<ConfigurationNode> result = new ArrayList<>(Arrays.asList(paths));
 
             /*
              * Here we sort the list of objects to minimize the risk that
@@ -1716,7 +1688,7 @@ public class ProjectController extends CayenneController {
              * should go before Query, to increase chances that Query's root
              * would be set.
              */
-            Collections.sort(result, parent instanceof DataMap
+            result.sort(parent instanceof DataMap
                     ? Comparators.getDataMapChildrenComparator()
                     : Comparators.getDataDomainChildrenComparator());
 
@@ -1736,18 +1708,17 @@ public class ProjectController extends CayenneController {
 
     public void fireEmbeddableEvent(EmbeddableEvent e, DataMap map) {
         setDirty(true);
-        for (EventListener listener : listenerList.getListeners(EmbeddableListener.class)) {
-            EmbeddableListener temp = (EmbeddableListener) listener;
+        for (EmbeddableListener listener : listenerList.getListeners(EmbeddableListener.class)) {
 
             switch (e.getId()) {
             case MapEvent.ADD:
-                temp.embeddableAdded(e, map);
+                listener.embeddableAdded(e, map);
                 break;
             case MapEvent.CHANGE:
-                temp.embeddableChanged(e, map);
+                listener.embeddableChanged(e, map);
                 break;
             case MapEvent.REMOVE:
-                temp.embeddableRemoved(e, map);
+                listener.embeddableRemoved(e, map);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid RelationshipEvent type: " + e.getId());
@@ -1757,18 +1728,17 @@ public class ProjectController extends CayenneController {
 
     public void fireEmbeddableAttributeEvent(EmbeddableAttributeEvent e) {
         setDirty(true);
-        for (EventListener listener : listenerList.getListeners(EmbeddableAttributeListener.class)) {
-            EmbeddableAttributeListener temp = (EmbeddableAttributeListener) listener;
+        for (EmbeddableAttributeListener listener : listenerList.getListeners(EmbeddableAttributeListener.class)) {
 
             switch (e.getId()) {
             case MapEvent.ADD:
-                temp.embeddableAttributeAdded(e);
+                listener.embeddableAttributeAdded(e);
                 break;
             case MapEvent.CHANGE:
-                temp.embeddableAttributeChanged(e);
+                listener.embeddableAttributeChanged(e);
                 break;
             case MapEvent.REMOVE:
-                temp.embeddableAttributeRemoved(e);
+                listener.embeddableAttributeRemoved(e);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid RelationshipEvent type: " + e.getId());
@@ -1777,9 +1747,8 @@ public class ProjectController extends CayenneController {
     }
     
     public void fireProjectOnSaveEvent(ProjectOnSaveEvent e){
-    	for(EventListener listener : listenerList.getListeners(ProjectOnSaveListener.class)){
-    		ProjectOnSaveListener temp = (ProjectOnSaveListener) listener;
-    		temp.beforeSaveChanges(e);
+    	for(ProjectOnSaveListener listener : listenerList.getListeners(ProjectOnSaveListener.class)){
+            listener.beforeSaveChanges(e);
     	}
     }