gt:         String remoteClz = extractChildTagAndTrim(element, "remote");
context: package org.jboss.windup.rules.apps.javaee.rules;
  
  import static org.joox.JOOX.$;
  
  import java.util.Collections;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.logging.Logger;
  import java.util.regex.Pattern;
  
  import org.apache.commons.lang.StringUtils;
  import org.jboss.windup.config.GraphRewrite;
  import org.jboss.windup.config.metadata.MetadataBuilder;
  import org.jboss.windup.config.phase.InitialAnalysisPhase;
  import org.jboss.windup.config.query.Query;
  import org.jboss.windup.config.ruleprovider.IteratingRuleProvider;
  import org.jboss.windup.graph.GraphContext;
  import org.jboss.windup.graph.service.GraphService;
  import org.jboss.windup.graph.service.Service;
  import org.jboss.windup.reporting.model.TechnologyTagLevel;
  import org.jboss.windup.reporting.model.TechnologyTagModel;
  import org.jboss.windup.reporting.service.ClassificationService;
  import org.jboss.windup.reporting.service.TechnologyTagService;
  import org.jboss.windup.rules.apps.java.decompiler.FernflowerDecompilerOperation;
  import org.jboss.windup.rules.apps.java.model.AmbiguousJavaClassModel;
  import org.jboss.windup.rules.apps.java.model.JavaClassFileModel;
  import org.jboss.windup.rules.apps.java.model.JavaClassModel;
  import org.jboss.windup.rules.apps.java.model.JavaSourceFileModel;
  import org.jboss.windup.rules.apps.java.model.PhantomJavaClassModel;
  import org.jboss.windup.rules.apps.java.service.JavaClassService;
  import org.jboss.windup.rules.apps.javaee.model.EjbDeploymentDescriptorModel;
  import org.jboss.windup.rules.apps.javaee.model.EjbEntityBeanModel;
  import org.jboss.windup.rules.apps.javaee.model.EjbMessageDrivenModel;
  import org.jboss.windup.rules.apps.javaee.model.EjbSessionBeanModel;
  import org.jboss.windup.rules.apps.javaee.model.EnvironmentReferenceModel;
  import org.jboss.windup.rules.apps.javaee.model.EnvironmentReferenceTagType;
  import org.jboss.windup.rules.apps.javaee.model.JmsDestinationModel;
  import org.jboss.windup.rules.apps.javaee.service.EnvironmentReferenceService;
  import org.jboss.windup.rules.apps.javaee.service.JmsDestinationService;
  import org.jboss.windup.rules.apps.xml.model.DoctypeMetaModel;
  import org.jboss.windup.rules.apps.xml.model.NamespaceMetaModel;
  import org.jboss.windup.rules.apps.xml.model.XmlFileModel;
  import org.jboss.windup.rules.apps.xml.service.XmlFileService;
  import org.jboss.windup.util.xml.DoctypeUtils;
  import org.jboss.windup.util.xml.NamespaceUtils;
  import org.ocpsoft.rewrite.config.ConditionBuilder;
  import org.ocpsoft.rewrite.context.EvaluationContext;
  import org.w3c.dom.Document;
  import org.w3c.dom.Element;
  
  /**
   * Discovers ejb-jar.xml files and parses the related metadata
   *
   * @author <a href="mailto:bradsdavis@gmail.com">Brad Davis</a>
   * @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a>
   *
   */
  public class DiscoverEjbConfigurationXmlRuleProvider extends IteratingRuleProvider<XmlFileModel>
  {
      private static final Logger LOG = Logger.getLogger(DiscoverEjbConfigurationXmlRuleProvider.class.getSimpleName());
  
      private static final String TECH_TAG = "EJB XML";
      private static final TechnologyTagLevel TECH_TAG_LEVEL = TechnologyTagLevel.INFORMATIONAL;
  
      private static final String dtdRegex = "(?i).*enterprise.javabeans.*";
  
      public DiscoverEjbConfigurationXmlRuleProvider()
      {
          super(MetadataBuilder.forProvider(DiscoverEjbConfigurationXmlRuleProvider.class)
                      .setPhase(InitialAnalysisPhase.class));
      }
  
      @Override
      public String toStringPerform()
      {
          return "Discover EJB-JAR XML Files";
      }
  
      @Override
      public ConditionBuilder when()
      {
          return Query.fromType(XmlFileModel.class).withProperty(XmlFileModel.ROOT_TAG_NAME, "ejb-jar");
      }
  
      public void perform(GraphRewrite event, EvaluationContext context, XmlFileModel payload)
      {
          try {
              Document doc = new XmlFileService(event.getGraphContext()).loadDocument(context, payload);
              extractMetadata(event, context, payload, doc);
          }
          catch (Exception ex)
          {
              payload.setParseError("Failed to parse EJB-JAR definitions: " + ex.getMessage());
          }
      }
  
      private void extractMetadata(GraphRewrite event, EvaluationContext context, XmlFileModel xmlModel, Document doc)
      {
          ClassificationService classificationService = new ClassificationService(event.getGraphContext());
          TechnologyTagService technologyTagService = new TechnologyTagService(event.getGraphContext());
          TechnologyTagModel technologyTag = technologyTagService.addTagToFileModel(xmlModel, TECH_TAG, TECH_TAG_LEVEL);
          classificationService.attachClassification(context, xmlModel, "EJB XML", "Enterprise Java Bean XML Descriptor.");
  
          // otherwise, it is a EJB-JAR XML.
          if (xmlModel.getDoctype() != null)
          {
              // check doctype.
              if (!processDoctypeMatches(xmlModel.getDoctype()))
              {
                  // move to next document.
                  return;
              }
              String version = processDoctypeVersion(xmlModel.getDoctype());
              extractMetadata(event, context, xmlModel, doc, version);
          }
          else
          {
              String namespace = $(doc).find("ejb-jar").namespaceURI();
              if (StringUtils.isBlank(namespace))
              {
                  namespace = doc.getFirstChild().getNamespaceURI();
              }
  
              String version = $(doc).attr("version");
  
              // if the version attribute isn't found, then grab it from the XSD name if we can.
              if (StringUtils.isBlank(version))
              {
                  for (NamespaceMetaModel ns : xmlModel.getNamespaces())
                  {
                      if (StringUtils.equals(ns.getURI(), namespace))
                      {
                          version = NamespaceUtils.extractVersion(ns.getSchemaLocation());
                      }
                  }
              }
  
              if (StringUtils.isNotBlank(version))
              {
                  technologyTag.setVersion(version);
              }
  
              extractMetadata(event, context, xmlModel, doc, version);
          }
      }
  
      private void extractMetadata(GraphRewrite event, EvaluationContext context, XmlFileModel xml, Document doc, String versionInformation)
      {
          EjbDeploymentDescriptorModel facet = GraphService.addTypeToModel(event.getGraphContext(), xml, EjbDeploymentDescriptorModel.class);
  
          if (StringUtils.isNotBlank(versionInformation))
          {
              facet.setSpecificationVersion(versionInformation);
          }
  
          // process all session beans...
          for (Element element : $(doc).find("session").get())
          {
              processSessionBeanElement(event, context, facet, element);
          }
  
          // process all message driven beans...
          for (Element element : $(doc).find("message-driven").get())
          {
              processMessageDrivenElement(event, context, facet, element);
          }
  
          // process all entity beans...
          for (Element element : $(doc).find("entity").get())
          {
              processEntityElement(event, context, facet, element);
          }
      }
  
      private boolean processDoctypeMatches(DoctypeMetaModel entry)
      {
          if (StringUtils.isNotBlank(entry.getPublicId()))
          {
              if (Pattern.matches(dtdRegex, entry.getPublicId()))
              {
                  return true;
              }
          }
  
          if (StringUtils.isNotBlank(entry.getSystemId()))
          {
              if (Pattern.matches(dtdRegex, entry.getSystemId()))
              {
                  return true;
              }
  
          }
          return false;
      }
  
      private String processDoctypeVersion(DoctypeMetaModel entry)
      {
          String publicId = entry.getPublicId();
          String systemId = entry.getSystemId();
  
          // extract the version information from the public / system ID.
          String versionInformation = DoctypeUtils.extractVersion(publicId, systemId);
          return versionInformation;
      }
  
      private void processSessionBeanElement(GraphRewrite event, EvaluationContext context, EjbDeploymentDescriptorModel ejbConfig, Element element)
      {
          JavaClassService javaClassService = new JavaClassService(event.getGraphContext());
  
          JavaClassModel home = null;
          JavaClassModel localHome = null;
          JavaClassModel remote = null;
          JavaClassModel local = null;
          JavaClassModel ejb = null;
  
          String ejbId = extractAttributeAndTrim(element, "id");
          String displayName = extractChildTagAndTrim(element, "display-name");
          String ejbName = extractChildTagAndTrim(element, "ejb-name");
  
          // get local class.
          String localClz = extractChildTagAndTrim(element, "local");
          if (localClz != null)
          {
              local = getOrCreatePhantom(event, context, javaClassService, localClz);
          }
  
          // get local home class.
          String localHomeClz = extractChildTagAndTrim(element, "local-home");
          if (localHomeClz != null)
          {
              localHome = getOrCreatePhantom(event, context, javaClassService, localHomeClz);
          }
  
          // get home class.
          String homeClz = extractChildTagAndTrim(element, "home");
          if (homeClz != null)
          {
              home = getOrCreatePhantom(event, context, javaClassService, homeClz);
          }
  
          // get remote class.
  