private static void ambiguousPUError(
      DeploymentUnit unit, String persistenceUnitName, PersistenceUnitMetadataHolder holder) {
    if (holder.getPersistenceUnits().size() > 1
        && (persistenceUnitName == null || persistenceUnitName.length() == 0)) {
      int numberOfDefaultPersistenceUnits = 0;

      // get number of persistence units that are marked as default
      for (PersistenceUnitMetadata persistenceUnit : holder.getPersistenceUnits()) {
        String defaultPU =
            persistenceUnit.getProperties().getProperty(Configuration.JPA_DEFAULT_PERSISTENCE_UNIT);
        if (Boolean.TRUE.toString().equals(defaultPU)) {
          numberOfDefaultPersistenceUnits++;
        }
      }
      ROOT_LOGGER.tracef(
          "checking for ambiguous persistence unit injection error, "
              + "number of persistence units marked default (%s) = %d",
          Configuration.JPA_DEFAULT_PERSISTENCE_UNIT, numberOfDefaultPersistenceUnits);
      // don't throw an error if there is exactly one default persistence unit
      if (numberOfDefaultPersistenceUnits != 1) {
        // AS7-2275 no unitName and there is more than one persistence unit;
        throw MESSAGES.noPUnitNameSpecifiedAndMultiplePersistenceUnits(
            holder.getPersistenceUnits().size(), unit);
      }
    }
  }
  /**
   * Simple test driver for parsing the specified persistence.xml file
   *
   * @param args
   */
  public static void main(String[] args) {
    try {
      String filename;
      if (args.length < 1) {
        filename = "persistence.xml";
      } else filename = args[0];
      System.out.println("will parse " + filename);
      XMLInputFactory xmlif = XMLInputFactory.newInstance();

      XMLStreamReader reader = xmlif.createXMLStreamReader(filename, new FileInputStream(filename));

      PersistenceUnitMetadataHolder h = parse(reader);
      System.out.println("result = " + h.getPersistenceUnits());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  private static PersistenceUnitMetadata getPersistenceUnit(
      DeploymentUnit current, final String absolutePath, String puName) {
    final String path;
    if (absolutePath.startsWith("../")) {
      path = absolutePath.substring(3);
    } else {
      path = absolutePath;
    }
    final VirtualFile parent =
        current.getAttachment(Attachments.DEPLOYMENT_ROOT).getRoot().getParent();
    final VirtualFile resolvedPath = parent.getChild(path);

    List<ResourceRoot> resourceRoots =
        DeploymentUtils.allResourceRoots(DeploymentUtils.getTopDeploymentUnit(current));

    for (ResourceRoot resourceRoot : resourceRoots) {
      if (resourceRoot.getRoot().equals(resolvedPath)) {
        PersistenceUnitMetadataHolder holder =
            resourceRoot.getAttachment(PersistenceUnitMetadataHolder.PERSISTENCE_UNITS);
        if (holder != null) {
          for (PersistenceUnitMetadata pu : holder.getPersistenceUnits()) {
            if (traceEnabled) {
              ROOT_LOGGER.tracef(
                  "getPersistenceUnit check '%s' against pu '%s'",
                  puName, pu.getPersistenceUnitName());
            }
            if (pu.getPersistenceUnitName().equals(puName)) {
              if (traceEnabled) {
                ROOT_LOGGER.tracef(
                    "getPersistenceUnit matched '%s' against pu '%s'",
                    puName, pu.getPersistenceUnitName());
              }
              return pu;
            }
          }
        }
      }
    }

    throw MESSAGES.persistenceUnitNotFound(absolutePath, puName, current);
  }
  /*
   * When finding the default persistence unit, the first persistence unit encountered is returned.
   */
  private static PersistenceUnitMetadata findWithinDeployment(
      DeploymentUnit unit, String persistenceUnitName) {
    if (traceEnabled) {
      ROOT_LOGGER.tracef("pu findWithinDeployment searching for %s", persistenceUnitName);
    }

    for (ResourceRoot root : DeploymentUtils.allResourceRoots(unit)) {
      PersistenceUnitMetadataHolder holder =
          root.getAttachment(PersistenceUnitMetadataHolder.PERSISTENCE_UNITS);
      if (holder == null || holder.getPersistenceUnits() == null) {
        if (traceEnabled) {
          ROOT_LOGGER.tracef(
              "pu findWithinDeployment skipping empty pu holder for %s", persistenceUnitName);
        }
        continue;
      }

      ambiguousPUError(unit, persistenceUnitName, holder);
      persistenceUnitName = defaultPersistenceUnitName(persistenceUnitName, holder);

      for (PersistenceUnitMetadata persistenceUnit : holder.getPersistenceUnits()) {
        if (traceEnabled) {
          ROOT_LOGGER.tracef(
              "findWithinDeployment check '%s' against pu '%s'",
              persistenceUnitName, persistenceUnit.getPersistenceUnitName());
        }
        if (persistenceUnitName == null
            || persistenceUnitName.length() == 0
            || persistenceUnit.getPersistenceUnitName().equals(persistenceUnitName)) {
          if (traceEnabled) {
            ROOT_LOGGER.tracef(
                "findWithinDeployment matched '%s' against pu '%s'",
                persistenceUnitName, persistenceUnit.getPersistenceUnitName());
          }
          return persistenceUnit;
        }
      }
    }
    return null;
  }
 /**
  * if no persistence unit name is specified, return name of default persistence unit
  *
  * @param persistenceUnitName that was specified to be used (null means to use the default
  *     persistence unit)
  * @param holder
  * @return
  */
 private static String defaultPersistenceUnitName(
     String persistenceUnitName, PersistenceUnitMetadataHolder holder) {
   if ((persistenceUnitName == null || persistenceUnitName.length() == 0)) {
     for (PersistenceUnitMetadata persistenceUnit : holder.getPersistenceUnits()) {
       String defaultPU =
           persistenceUnit.getProperties().getProperty(Configuration.JPA_DEFAULT_PERSISTENCE_UNIT);
       if (Boolean.TRUE.toString().equals(defaultPU)) {
         persistenceUnitName = persistenceUnit.getPersistenceUnitName();
       }
     }
   }
   return persistenceUnitName;
 }
  private static PersistenceUnitMetadata findWithinLibraryJar(
      DeploymentUnit unit, ResourceRoot moduleResourceRoot, String persistenceUnitName) {

    final ResourceRoot deploymentRoot = moduleResourceRoot;
    PersistenceUnitMetadataHolder holder =
        deploymentRoot.getAttachment(PersistenceUnitMetadataHolder.PERSISTENCE_UNITS);
    if (holder == null || holder.getPersistenceUnits() == null) {
      if (traceEnabled) {
        ROOT_LOGGER.tracef(
            "findWithinLibraryJar checking for '%s' found no persistence units",
            persistenceUnitName);
      }
      return null;
    }

    ambiguousPUError(unit, persistenceUnitName, holder);
    persistenceUnitName = defaultPersistenceUnitName(persistenceUnitName, holder);

    for (PersistenceUnitMetadata persistenceUnit : holder.getPersistenceUnits()) {
      if (traceEnabled) {
        ROOT_LOGGER.tracef(
            "findWithinLibraryJar check '%s' against pu '%s'",
            persistenceUnitName, persistenceUnit.getPersistenceUnitName());
      }
      if (persistenceUnitName == null
          || persistenceUnitName.length() == 0
          || persistenceUnit.getPersistenceUnitName().equals(persistenceUnitName)) {
        if (traceEnabled) {
          ROOT_LOGGER.tracef(
              "findWithinLibraryJar matched '%s' against pu '%s'",
              persistenceUnitName, persistenceUnit.getPersistenceUnitName());
        }
        return persistenceUnit;
      }
    }
    return null;
  }
  public static PersistenceUnitMetadataHolder parse(final XMLStreamReader reader)
      throws XMLStreamException {

    reader.require(START_DOCUMENT, null, null); // check for a bogus document and throw error

    // Read until the first start element
    Version version = null;
    while (reader.hasNext() && reader.next() != START_ELEMENT) {
      if (reader.getEventType() == DTD) {
        final String dtdLocation = readDTDLocation(reader);
        if (dtdLocation != null) {
          version = Version.forLocation(dtdLocation);
        }
      }
    }
    final String schemaLocation = readSchemaLocation(reader);
    if (schemaLocation != null) {
      version = Version.forLocation(schemaLocation);
    }
    if (version == null || Version.UNKNOWN.equals(version)) {
      // Look at the version attribute
      String versionString = null;
      final int count = reader.getAttributeCount();
      for (int i = 0; i < count; i++) {
        final String attributeNamespace = reader.getAttributeNamespace(i);
        if (attributeNamespace != null && !attributeNamespace.isEmpty()) {
          continue;
        }
        final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
        if (attribute == Attribute.VERSION) {
          versionString = reader.getAttributeValue(i);
        }
      }
      if ("1.0".equals(versionString)) {
        version = Version.JPA_1_0;
      } else if ("1".equals(versionString)) {
        version = Version.JPA_1_0;
      } else if ("2.0".equals(versionString)) {
        version = Version.JPA_2_0;
      } else if ("2".equals(versionString)) {
        version = Version.JPA_2_0;
      } else {
        version = Version.JPA_2_0;
      }
    }

    final int count = reader.getAttributeCount();
    for (int i = 0; i < count; i++) {
      final String value = reader.getAttributeValue(i);
      final String attributeNamespace = reader.getAttributeNamespace(i);
      if (attributeNamespace != null && !attributeNamespace.isEmpty()) {
        continue;
      }
      final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
      switch (attribute) {
        case VERSION:
          // log.info("version = " + value);
          // TODO:  handle version
          break;
        default:
          throw unexpectedAttribute(reader, i);
      }
    }
    final List<PersistenceUnitMetadata> PUs = new ArrayList<PersistenceUnitMetadata>();
    // until the ending PERSISTENCE tag
    while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
      final Element element = Element.forName(reader.getLocalName());
      switch (element) {
        case PERSISTENCEUNIT:
          PersistenceUnitMetadata pu = parsePU(reader, version);
          PUs.add(pu);
          JPA_LOGGER.readingPersistenceXml(pu.getPersistenceUnitName());
          break;

        default:
          throw unexpectedElement(reader);
      }
    }
    PersistenceUnitMetadataHolder result =
        new PersistenceUnitMetadataHolder().setPersistenceUnits(PUs);
    if (JPA_LOGGER.isTraceEnabled()) JPA_LOGGER.trace(result.toString());

    return result;
  }