public static String generateJpaDependencies(
      final URLClassLoader classLoader, final URL jarUrl, final UmlOptions options) {
    JpaDependencyDiagramModel dependencyModel = new JpaDependencyDiagramModel();
    try {
      List<String> classes = new ArrayList<String>();
      final JarFile jarFile = new JarFile(jarUrl.getFile());
      if (jarFile != null) {
        Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
          JarEntry jarEntry = entries.nextElement();
          String jarEntryName = jarEntry.getName();
          if (jarEntryName.endsWith(".class") && !jarEntryName.contains("Test")) {
            String className = jarEntryName.replace('/', '.').replace(".class", "");
            classes.add(className);
          }
        }
        jarFile.close();
      }

      // Parse all the classes for UML
      extractJpaClasses(
          classLoader,
          classes,
          dependencyModel,
          options.getIncludePatterns(),
          options.getExcludePatterns());

    } catch (Exception e) {
      e.printStackTrace();
    }
    return dependencyModel.getUml();
  }
  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);
        }
      }
    }
  }
  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);
  }