static void extractJpaClasses( final URLClassLoader classLoader, final List<String> classes, final JpaDependencyDiagramModel dependencyModel, final String includePatternString, final String excludePatternString) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { String[] includePatterns = includePatternString.split(","); String[] excludePatterns = excludePatternString.split(","); boolean hasAnyPatterns = !(includePatterns.length == 1 && includePatterns[0].isEmpty()) || !(excludePatterns.length == 1 && excludePatterns[0].isEmpty()); Map<String, Map<String, JpaDependencyType>> jpaDependencyCache = new HashMap<String, Map<String, JpaDependencyType>>(); for (String className : classes) { if (UmlGeneratorUtility.isIncluded( className, hasAnyPatterns, includePatterns, excludePatterns)) { Class<?> loadClass = classLoader.loadClass(className); // check if its an persistent entity if (isPersistentEntity(loadClass)) { System.out.println("Parsing persistent class " + loadClass.getSimpleName()); // extract class info JpaClassModel classModel = new JpaClassModel(loadClass.getName()); // determine class types extractJpaClassAnnotations(loadClass, classModel); // extract fields extractColumnsAndEntityDependencies( dependencyModel, loadClass, classModel, jpaDependencyCache, hasAnyPatterns, includePatterns, excludePatterns); // extract interfaces extractInterfaces( loadClass, classModel, hasAnyPatterns, includePatterns, excludePatterns); // extract parent class Class<?> superclass = loadClass.getSuperclass(); if (superclass != null && !superclass.equals(Object.class) && UmlGeneratorUtility.isIncluded( superclass.getName(), hasAnyPatterns, includePatterns, excludePatterns)) { classModel.setParent(superclass.getName()); } // add prepared class model to class diagram dependencyModel.addClass(classModel); } } } }
protected static void extractColumn(final JpaClassModel classModel, final Annotation annotation) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { // get column name from annotation attribute Method method = annotation.annotationType().getDeclaredMethod("name"); Object value = method.invoke(annotation, (Object[]) null); classModel.addColumn(String.valueOf(value)); }
private static void extractJpaClassAnnotations( final Class<?> loadClass, final JpaClassModel classModel) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { classModel.setType(loadClass); classModel.setJpaEntityType(JpaEntityType.ENTITY); if (loadClass.isAnnotationPresent(MappedSuperclass.class)) { classModel.setJpaEntityType(JpaEntityType.MAPPED_SUPER_CLASS); } else if (loadClass.isAnnotationPresent(Table.class)) { classModel.setJpaEntityType(JpaEntityType.TABLE); // extract the table name Annotation annotation = loadClass.getAnnotation(Table.class); classModel.setTableName( String.valueOf( annotation .annotationType() .getDeclaredMethod("name") .invoke(annotation, (Object[]) null))); } }
private static void extractInterfaces( final Class<?> loadClass, final JpaClassModel classModel, final boolean hasAnyPatterns, final String[] includePatterns, final String[] excludePatterns) { for (Class interfaceClass : loadClass.getInterfaces()) { if (UmlGeneratorUtility.isIncluded( interfaceClass.getName(), hasAnyPatterns, includePatterns, excludePatterns)) { classModel.addInterface(interfaceClass.getName()); } } }
private static void updateDependencyCache( final JpaDependencyDiagramModel diagramModel, final Map<String, Map<String, JpaDependencyType>> jpaDependencyCache, final JpaClassModel classModel, final String dependentClassName, JpaDependencyType dependencyType) { // check if the dependent class already has the mapping JpaClassModel dependentClass = diagramModel.getClass(dependentClassName); Map<String, JpaDependencyType> cache = jpaDependencyCache.get(dependentClassName); if (cache != null && dependentClass != null) { JpaDependencyType type = cache.get(classModel.getName()); if (type != null) { int result = type.compareTo(dependencyType); // check if higher priority JPA mapping already exists between // the classes if (result < 0 || result == 0 && type != JpaDependencyType.ONE_TO_MANY) { return; } if (result == 0 && type == JpaDependencyType.ONE_TO_MANY) { // the one-to-many relationship is present both the sides so // convert it to many-to-many dependencyType = JpaDependencyType.MANY_TO_MANY; } // remove entry from the cache and JpaClassModel of the // associated class cache.remove(classModel.getName()); dependentClass.removeJpaDependency(classModel.getName()); } } // no mapping or lower priority mapping exists between the entities so create new entry in cache cache = jpaDependencyCache.get(classModel.getName()); if (cache == null) { cache = new HashMap<String, JpaDependencyType>(3); } cache.put(dependentClass.getName(), dependencyType); classModel.addJpaDependency(dependentClassName, dependencyType); }
private static void extractColumnsAndEntityDependencies( final JpaDependencyDiagramModel dependencyModel, final Class<?> loadClass, final JpaClassModel classModel, final Map<String, Map<String, JpaDependencyType>> jpaDependencyCache, final boolean hasAnyPatterns, final String[] includePatterns, final String[] excludePatterns) { for (Field field : loadClass.getDeclaredFields()) { try { Class<?> fieldType = field.getType(); if (UmlGeneratorUtility.isIncluded( fieldType.getName(), hasAnyPatterns, includePatterns, excludePatterns)) { // check for spring dependencies if (field.isAnnotationPresent(Column.class)) { extractColumn(classModel, field.getAnnotation(Column.class)); } else if (field.isAnnotationPresent(OneToMany.class)) { for (Type type : ((ParameterizedType) field.getGenericType()).getActualTypeArguments()) { if (type instanceof Class) { updateDependencyCache( dependencyModel, jpaDependencyCache, classModel, ((Class<?>) type).getName(), JpaDependencyType.ONE_TO_MANY); } } } else if (field.isAnnotationPresent(ManyToOne.class)) { updateDependencyCache( dependencyModel, jpaDependencyCache, classModel, fieldType.getName(), JpaDependencyType.MANY_TO_ONE); } else if (field.isAnnotationPresent(OneToOne.class)) { updateDependencyCache( dependencyModel, jpaDependencyCache, classModel, fieldType.getName(), JpaDependencyType.ONE_TO_ONE); } else if (field.isAnnotationPresent(ManyToMany.class)) { updateDependencyCache( dependencyModel, jpaDependencyCache, classModel, fieldType.getName(), JpaDependencyType.MANY_TO_MANY); } else if (field.isAnnotationPresent(Id.class)) { classModel.addIdColumn(field.getName()); } } } catch (Exception e) { // no need to do anything continue; } catch (NoClassDefFoundError error) { // no need to do anything continue; } } }