content: /*
   *  Licensed to the Apache Software Foundation (ASF) under one or more
   *  contributor license agreements.  See the NOTICE file distributed with
   *  this work for additional information regarding copyright ownership.
   *  The ASF licenses this file to You under the Apache License, Version 2.0
   *  (the "License"); you may not use this file except in compliance with
   *  the License.  You may obtain a copy of the License at
   *
   *      https://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.ivy.osgi.p2;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.net.URI;
  import java.net.URISyntaxException;
  import java.text.ParseException;
  import java.util.ArrayList;
  import java.util.List;
  
  import javax.xml.parsers.ParserConfigurationException;
  
  import org.apache.ivy.osgi.core.BundleCapability;
  import org.apache.ivy.osgi.core.BundleInfo;
  import org.apache.ivy.osgi.core.BundleRequirement;
  import org.apache.ivy.osgi.core.ExportPackage;
  import org.apache.ivy.osgi.core.ManifestParser;
  import org.apache.ivy.osgi.p2.PropertiesParser.PropertiesHandler;
  import org.apache.ivy.osgi.util.DelegatingHandler;
  import org.apache.ivy.osgi.util.Version;
  import org.apache.ivy.osgi.util.VersionRange;
  import org.apache.ivy.util.Message;
  import org.apache.ivy.util.XMLHelper;
  import org.xml.sax.Attributes;
  import org.xml.sax.SAXException;
  import org.xml.sax.SAXParseException;
  
  public class P2MetadataParser implements XMLInputParser {
  
      private final P2Descriptor p2Descriptor;
  
      private int logLevel = Message.MSG_INFO;
  
      public P2MetadataParser(P2Descriptor p2Descriptor) {
          this.p2Descriptor = p2Descriptor;
      }
  
      public void setLogLevel(int logLevel) {
          this.logLevel = logLevel;
      }
  
      public void parse(InputStream in) throws IOException, ParseException, SAXException {
          RepositoryHandler handler = new RepositoryHandler(p2Descriptor);
          try {
              XMLHelper.parse(in, null, handler, null);
          } catch (ParserConfigurationException e) {
              throw new SAXException(e);
          }
      }
  
      private class RepositoryHandler extends DelegatingHandler {
  
          // private static final String P2_TIMESTAMP = "p2.timestamp";
  
          private static final String REPOSITORY = "repository";
  
          // private static final String NAME = "name";
          //
          // private static final String TYPE = "type";
          //
          // private static final String VERSION = "version";
          //
          // private static final String DESCRIPTION = "description";
          //
          // private static final String PROVIDER = "provider";
  
          public RepositoryHandler(final P2Descriptor p2Descriptor) {
              super(REPOSITORY);
              // addChild(new PropertiesHandler(P2_TIMESTAMP),
              // new ChildElementHandler<PropertiesHandler>() {
              // public void childHandled(PropertiesHandler child) {
              // String timestamp = child.properties.get(P2_TIMESTAMP);
              // if (timestamp != null) {
              // p2Descriptor.setTimestamp(Long.parseLong(timestamp));
              // }
              // }
              // });
              addChild(new UnitsHandler(), new ChildElementHandler<UnitsHandler>() {
                  @Override
                  public void childHandled(UnitsHandler child) {
                      for (BundleInfo bundle : child.bundles) {
                          p2Descriptor.addBundle(bundle);
                      }
                  }
              });
              addChild(new ReferencesHandler(), new ChildElementHandler<ReferencesHandler>() {
                  @Override
                  public void childHandled(ReferencesHandler child) {
                  }
              });
          }
  
          // protected void handleAttributes(Attributes atts) {
          // String name = atts.getValue(NAME);
          // String type = atts.getValue(TYPE);
          // String version = atts.getValue(VERSION);
          // String description = atts.getValue(DESCRIPTION);
          // String provider = atts.getValue(PROVIDER);
          // }
      }
  
      private class ReferencesHandler extends DelegatingHandler {
  
          private static final String REFERENCES = "references";
  
          private static final String SIZE = "size";
  
          List<URI> repositoryUris;
  
          public ReferencesHandler() {
              super(REFERENCES);
              addChild(new RepositoryReferenceHandler(),
                  new ChildElementHandler<RepositoryReferenceHandler>() {
                      @Override
                      public void childHandled(RepositoryReferenceHandler child) {
                          repositoryUris.add(child.uri);
                      }
                  });
          }
  
          @Override
          protected void handleAttributes(Attributes atts) throws SAXException {
              int size = Integer.parseInt(atts.getValue(SIZE));
              repositoryUris = new ArrayList<>(size);
          }
      }
  
      private class RepositoryReferenceHandler extends DelegatingHandler {
  
          private static final String REPOSITORY = "repository";
  
          // private static final String TYPE = "type";
          //
          // private static final String OPTIONS = "options";
          //
          // private static final String NAME = "name";
  
          private static final String URI = "uri";
  
          private static final String URL = "url";
  
          public RepositoryReferenceHandler() {
              super(REPOSITORY);
          }
  
          // int type;
          //
          // int options;
          //
          // String name;
  
          URI uri;
  
          @Override
          protected void handleAttributes(Attributes atts) throws SAXException {
              // type = Integer.parseInt(atts.getValue(TYPE));
              // options = Integer.parseInt(atts.getValue(OPTIONS));
              // name = atts.getValue(NAME);
  
              String uriAtt = atts.getValue(URI);
              String urlAtt = atts.getValue(URL);
  
              if (uriAtt != null) {
                  try {
                      uri = new URI(uriAtt);
                  } catch (URISyntaxException e) {
                      throw new SAXParseException("Invalid uri attribute " + uriAtt + "("
                              + e.getMessage() + ")", getLocator());
                  }
              }
              if (uri != null && urlAtt != null) {
                  try {
                      uri = new URI(urlAtt);
                  } catch (URISyntaxException e) {
                      throw new SAXParseException("Invalid url attribute " + urlAtt + "("
                              + e.getMessage() + ")", getLocator());
                  }
              }
          }
      }
  
      private class UnitsHandler extends DelegatingHandler {
  
          private static final String UNITS = "units";
  
          private static final String SIZE = "size";
  
          List<BundleInfo> bundles;
  
          public UnitsHandler() {
              super(UNITS);
              addChild(new UnitHandler(), new ChildElementHandler<UnitHandler>() {
                  @Override
                  public void childHandled(UnitHandler child) {
                      if (child.bundleInfo != null && !child.bundleInfo.getCapabilities().isEmpty()) {
                          bundles.add(child.bundleInfo);
                      }
                  }
              });
          }
  
          @Override
          protected void handleAttributes(Attributes atts) {
              int size = Integer.parseInt(atts.getValue(SIZE));
              bundles = new ArrayList<>(size);
          }
  
      }
  
      class UnitHandler extends DelegatingHandler {
  
          private static final String CATEGORY_PROPERTY = "org.eclipse.equinox.p2.type.category";
  
          private static final String UNIT = "unit";
  
          private static final String ID = "id";
  
          private static final String VERSION = "version";
  
          // private static final String SINGLETON = "singleton";
  
          BundleInfo bundleInfo;
  
          public UnitHandler() {
              super(UNIT);
              // addChild(new UpdateHandler(), new ChildElementHandler() {
              // public void childHandled(DelegatingHandler child) {
              // }
              // });
              addChild(new PropertiesHandler(CATEGORY_PROPERTY),
                  new ChildElementHandler<PropertiesHandler>() {
                      @Override
                      public void childHandled(PropertiesHandler child) {
                          String category = child.properties.get(CATEGORY_PROPERTY);
                          if (category != null && Boolean.valueOf(category)) {
                              // this is a category definition, this is useless, skip this unit
                              child.getParent().skip();
                              bundleInfo = null;
                          }
                      }
                  });
              addChild(new ProvidesHandler(), new ChildElementHandler<ProvidesHandler>() {
                  @Override
                  public void childHandled(ProvidesHandler child) {
                      if ("source".equals(child.eclipseType)) {
                          // this is some source of some bundle
                          bundleInfo.setSource(true);
                          // we need to parse the manifest in the touchpointData to figure out the
                          // targeted bundle
                          // in case we won't have the proper data in the manifest, prepare the source
                          // data from the convention
                          String symbolicName = bundleInfo.getSymbolicName();
                          if (symbolicName.endsWith(".source")) {
                              bundleInfo.setSymbolicNameTarget(symbolicName.substring(0,
                                  symbolicName.length() - 7));
                              bundleInfo.setVersionTarget(bundleInfo.getVersion());
                          }
                      }
                      for (BundleCapability capability : child.capabilities) {
                          bundleInfo.addCapability(capability);
                      }
                  }
              });
              addChild(new FilterHandler(), new ChildElementHandler<FilterHandler>() {
                  @Override
                  public void childHandled(FilterHandler child) {
                  }
              });
              addChild(new RequiresHandler(), new ChildElementHandler<RequiresHandler>() {
                  @Override
                  public void childHandled(RequiresHandler child) {
                      for (BundleRequirement requirement : child.requirements) {
                          bundleInfo.addRequirement(requirement);
                      }
                  }
              });
              addChild(new HostRequirementsHandler(),
                  new ChildElementHandler<HostRequirementsHandler>() {
                      @Override
                      public void childHandled(HostRequirementsHandler child) {
                      }
                  });
              addChild(new MetaRequirementsHandler(),
                  new ChildElementHandler<MetaRequirementsHandler>() {
                      @Override
                      public void childHandled(MetaRequirementsHandler child) {
                      }
                  });
              addChild(new ArtifactsHandler(), new ChildElementHandler<ArtifactsHandler>() {
                  @Override
                  public void childHandled(ArtifactsHandler child) {
                  }
              });
              // addChild(new TouchpointHandler(), new ChildElementHandler() {
              // public void childHandled(DelegatingHandler child) {
              // }
              // });
              addChild(new TouchpointDataHandler(), new ChildElementHandler<TouchpointDataHandler>() {
                  @Override
                  public void childHandled(TouchpointDataHandler child) throws SAXParseException {
                      if (child.zipped != null) {
                          bundleInfo.setHasInnerClasspath(child.zipped);
                      }
                      if (!bundleInfo.isSource()) {
                          // we only care about parsing the manifest if it is a source
                          return;
                      }
                      if (child.manifest != null) {
                          // Eclipse may have serialized a little bit weirdly
                          String manifest = ManifestParser.formatLines(child.manifest.trim());
                          BundleInfo embeddedInfo;
                          try {
                              embeddedInfo = ManifestParser.parseManifest(manifest);
                          } catch (IOException e) {
                              if (logLevel >= Message.MSG_VERBOSE) {
                                  Message.verbose(
                                      "The Manifest of the source bundle "
                                              + bundleInfo.getSymbolicName() + " could not be parsed",
                                      e);
                              }
                              return;
                          } catch (ParseException e) {
                              if (logLevel >= Message.MSG_VERBOSE) {
                                  Message.verbose(
                                      "The Manifest of the source bundle "
                                              + bundleInfo.getSymbolicName() + " is ill formed", e);
                              }
                              return;
                          }
                          if (!embeddedInfo.isSource()) {
                              if (logLevel >= Message.MSG_VERBOSE) {
                                  Message.verbose("The Manifest of the source bundle "
                                          + bundleInfo.getSymbolicName()
                                          + " is not declaring being a source.");
                              }
                              return;
                          }
                          String symbolicNameTarget = embeddedInfo.getSymbolicNameTarget();
                          if (symbolicNameTarget == null) {
                              if (logLevel >= Message.MSG_VERBOSE) {
                                  Message.verbose("The Manifest of the source bundle "
                                          + bundleInfo.getSymbolicName()
                                          + " is not declaring a target symbolic name.");
                              }
                              return;
                          }
                          Version versionTarget = embeddedInfo.getVersionTarget();
                          if (versionTarget == null) {
                              if (logLevel >= Message.MSG_VERBOSE) {
                                  Message.verbose("The Manifest of the source bundle "
                                          + bundleInfo.getSymbolicName()
                                          + " is not declaring a target version.");
                              }
                              return;
                          }
                          bundleInfo.setSymbolicNameTarget(symbolicNameTarget);
                          bundleInfo.setVersionTarget(versionTarget);
                      }
                  }
              });
              // addChild(new LicensesHandler(), new ChildElementHandler() {
              // public void childHandled(DelegatingHandler child) {
              // }
              // });
              // addChild(new CopyrightHandler(), new ChildElementHandler() {
              // public void childHandled(DelegatingHandler child) {
              // }
              // });
              // addChild(new ChangesHandler(), new ChildElementHandler() {
              // public void childHandled(DelegatingHandler child) {
              // }
              // });
  
          }
  
          @Override
          protected void handleAttributes(Attributes atts) throws SAXException {
              String id = atts.getValue(ID);
              String version = atts.getValue(VERSION);
              // Boolean singleton = Boolean.valueOf(atts.getValue(SINGLETON));
              bundleInfo = new BundleInfo(id, new Version(version));
          }
  
      }
  
      // static class UpdateHandler extends DelegatingHandler {
      //
      // private static final String UPDATE = "update";
      //
      // private static final String ID = "id";
      //
      // private static final String RANGE = "range";
      //
      // private static final String SEVERITY = "severity";
      //
      // public UpdateHandler() {
      // super(UPDATE);
      // }
      //
      // protected void handleAttributes(Attributes atts) {
      // String id = atts.getValue(ID);
      // String range = atts.getValue(RANGE);
      // String severity = atts.getValue(SEVERITY);
      // }
      //
      // }
  
      private static class FilterHandler extends DelegatingHandler {
  
          private static final String FILTER = "filter";
  
          public FilterHandler() {
              super(FILTER);
              setBufferingChar(true);
          }
  
      }
  
      private static String namespace2Type(String namespace) {
          if (namespace == null) {
              return null;
          }
          if (namespace.equals("java.package")) {
              return BundleInfo.PACKAGE_TYPE;
          }
          if (namespace.equals("osgi.bundle")) {
              return BundleInfo.BUNDLE_TYPE;
          }
          return null;
      }
  
      private class ProvidesHandler extends DelegatingHandler {
  
          private static final String PROVIDES = "provides";
  
          private static final String SIZE = "size";
  
          List<BundleCapability> capabilities;
  
          String eclipseType;
  
          public ProvidesHandler() {
              super(PROVIDES);
              addChild(new ProvidedHandler(), new ChildElementHandler<ProvidedHandler>() {
                  @Override
                  public void childHandled(ProvidedHandler child) {
                      if (child.namespace.equals("org.eclipse.equinox.p2.eclipse.type")) {
                          eclipseType = child.name;
                      } else {
                          String type = namespace2Type(child.namespace);
                          if (type == null) {
                              if (logLevel >= Message.MSG_DEBUG) {
                                  Message.debug("Unsupported provided capability " + child.namespace
                                          + " " + child.name + " " + child.version);
                              }
                              return;
                          }
                          BundleCapability capability;
                          if (BundleInfo.PACKAGE_TYPE.equals(type)) {
                              capability = new ExportPackage(child.name, child.version);
                          } else {
                              capability = new BundleCapability(type, child.name, child.version);
                          }
                          capabilities.add(capability);
                      }
                  }
              });
          }
  
          @Override
          protected void handleAttributes(Attributes atts) {
              int size = Integer.parseInt(atts.getValue(SIZE));
              capabilities = new ArrayList<>(size);
          }
  
      }
  
      private static class ProvidedHandler extends DelegatingHandler {
  
          private static final String PROVIDED = "provided";
  
          private static final String NAMESPACE = "namespace";
  
          private static final String NAME = "name";
  
          private static final String VERSION = "version";
  
          String namespace;
  
          String name;
  
          Version version;
  
          public ProvidedHandler() {
              super(PROVIDED);
          }
  
          @Override
          protected void handleAttributes(Attributes atts) throws SAXException {
              namespace = atts.getValue(NAMESPACE);
              name = atts.getValue(NAME);
              version = new Version(atts.getValue(VERSION));
          }
  
      }
  
      abstract class AbstractRequirementHandler extends DelegatingHandler {
  
          private static final String SIZE = "size";
  
          List<BundleRequirement> requirements;
  
          public AbstractRequirementHandler(String name) {
              super(name);
              addChild(new RequiredHandler(), new ChildElementHandler<RequiredHandler>() {
                  @Override
                  public void childHandled(RequiredHandler child) {
                      String name = child.name;
                      VersionRange range = child.range;
                      String type = namespace2Type(child.namespace);
                      if (type == null) {
                          if (logLevel >= Message.MSG_DEBUG) {
                              Message.debug("Unsupported required capability " + child.namespace
                                      + " " + name + " " + range);
                          }
                      } else {
                          String resolution = child.optional ? "optional" : null;
                          requirements.add(new BundleRequirement(type, name, range, resolution));
                      }
                  }
              });
          }
  
          @Override
          protected void handleAttributes(Attributes atts) {
              int size = Integer.parseInt(atts.getValue(SIZE));
              requirements = new ArrayList<>(size);
          }
  
      }
  
      private class RequiresHandler extends AbstractRequirementHandler {
  
          private static final String REQUIRES = "requires";
  
          public RequiresHandler() {
              super(REQUIRES);
          }
  
      }
  
      private class RequiredHandler extends DelegatingHandler {
  
          private static final String REQUIRED = "required";
  
          private static final String NAMESPACE = "namespace";
  
          private static final String NAME = "name";
  
          private static final String RANGE = "range";
  
          private static final String OPTIONAL = "optional";
  
          // private static final String GREEDY = "greedy";
  
          String namespace;
  
          String name;
  
          VersionRange range;
  
          // String filter;
          //
          // boolean greedy;
  
          boolean optional;
  
          public RequiredHandler() {
              super(REQUIRED);
              // addChild(new FilterHandler(), new ChildElementHandler<FilterHandler>() {
              // public void childHandled(FilterHandler child) {
              // filter = child.getBufferedChars().trim();
              // }
              // });
          }
  
          @Override
          protected void handleAttributes(Attributes atts) throws SAXParseException {
              namespace = atts.getValue(NAMESPACE);
              name = atts.getValue(NAME);
              try {
                  range = new VersionRange(atts.getValue(RANGE));
              } catch (ParseException e) {
                  throw new RuntimeException(e);
              }
              // greedy = getOptionalBooleanAttribute(atts, GREEDY, Boolean.TRUE).booleanValue();
              optional = getOptionalBooleanAttribute(atts, OPTIONAL, Boolean.FALSE);
          }
  
      }
  
      private class HostRequirementsHandler extends AbstractRequirementHandler {
  
          private static final String HOST_REQUIREMENTS = "hostRequirements";
  
          public HostRequirementsHandler() {
              super(HOST_REQUIREMENTS);
          }
  
      }
  
      private class MetaRequirementsHandler extends AbstractRequirementHandler {
  
          private static final String META_REQUIREMENTS = "metaRequirements";
  
          public MetaRequirementsHandler() {
              super(META_REQUIREMENTS);
          }
  
      }
  
      private class ArtifactsHandler extends DelegatingHandler {
  
          private static final String ARTIFACTS = "artifacts";
  
          private static final String SIZE = "size";
  
          List<P2Artifact> artifacts;
  
          public ArtifactsHandler() {
              super(ARTIFACTS);
              addChild(new ArtifactHandler(), new ChildElementHandler<ArtifactHandler>() {
                  @Override
                  public void childHandled(ArtifactHandler child) {
                      artifacts.add(child.artifact);
                  }
              });
          }
  
          @Override
          protected void handleAttributes(Attributes atts) {
              int size = Integer.parseInt(atts.getValue(SIZE));
              artifacts = new ArrayList<>(size);
          }
  
      }
  
      private class ArtifactHandler extends DelegatingHandler {
  
          private static final String ARTIFACT = "artifact";
  
          private static final String ID = "id";
  
          private static final String VERSION = "version";
  
          private static final String CLASSIFIER = "classifier";
  
          P2Artifact artifact;
  
          public ArtifactHandler() {
              super(ARTIFACT);
          }
  
          @Override
          protected void handleAttributes(Attributes atts) throws SAXException {
              String id = atts.getValue(ID);
              String version = atts.getValue(VERSION);
              String classifier = atts.getValue(CLASSIFIER);
              artifact = new P2Artifact(id, new Version(version), classifier);
          }
  
      }
  
      // private static class TouchpointHandler extends DelegatingHandler {
      //
      // private static final String TOUCHPOINT = "touchpoint";
      //
      // private static final String ID = "id";
      //
      // private static final String VERSION = "version";
      //
      // public TouchpointHandler() {
      // super(TOUCHPOINT);
      // }
      //
      // protected void handleAttributes(Attributes atts) {
      // String id = atts.getValue(ID);
      // String version = atts.getValue(VERSION);
      // }
      //
      // }
  
      private class TouchpointDataHandler extends DelegatingHandler {
  
          private static final String TOUCHPOINTDATA = "touchpointData";
  
          // private static final String SIZE = "size";
  
          String manifest;
  
          Boolean zipped;
  
          public TouchpointDataHandler() {
              super(TOUCHPOINTDATA);
              addChild(new InstructionsHandler(), new ChildElementHandler<InstructionsHandler>() {
                  @Override
                  public void childHandled(InstructionsHandler child) {
                      manifest = child.manifest;
                      zipped = child.zipped;
                  }
              });
          }
  
          @Override
          protected void handleAttributes(Attributes atts) {
              // String size = atts.getValue(SIZE);
          }
  
      }
  
      private class InstructionsHandler extends DelegatingHandler {
  
          private static final String INSTRUCTIONS = "instructions";
  
          // private static final String SIZE = "size";
  
          String manifest;
  
          Boolean zipped;
  
          public InstructionsHandler() {
              super(INSTRUCTIONS);
              addChild(new InstructionHandler(), new ChildElementHandler<InstructionHandler>() {
                  @Override
                  public void childHandled(InstructionHandler child) {
                      manifest = null;
                      zipped = null;
                      String buffer = child.getBufferedChars().trim();
                      if ("manifest".equals(child.key)) {
                          manifest = buffer;
                      } else if ("zipped".equals(child.key) && buffer.length() != 0) {
                          zipped = Boolean.valueOf(buffer);
                      }
                  }
              });
          }
  
          @Override
          protected void handleAttributes(Attributes atts) {
              // String size = atts.getValue(SIZE);
          }
  
      }
  
      private class InstructionHandler extends DelegatingHandler {
  
          private static final String INSTRUCTION = "instruction";
  
          private static final String KEY = "key";
  
          String key;
  
          public InstructionHandler() {
              super(INSTRUCTION);
              setBufferingChar(true);
          }
  
          @Override
          protected void handleAttributes(Attributes atts) {
              key = atts.getValue(KEY);
          }
  
      }
  
      // private static class LicensesHandler extends DelegatingHandler {
      //
      // private static final String LICENSES = "licenses";
      //
      // private static final String SIZE = "size";
      //
      // public LicensesHandler() {
      // super(LICENSES);
      // addChild(new LicenseHandler(), new ChildElementHandler() {
      // public void childHandled(DelegatingHandler child) {
      // }
      // });
      // }
      //
      // protected void handleAttributes(Attributes atts) {
      // String size = atts.getValue(SIZE);
      // }
      //
      // }
  
      // private static class LicenseHandler extends DelegatingHandler {
      //
      // private static final String LICENSE = "license";
      //
      // private static final String URI = "uri";
      //
      // private static final String URL = "url";
      //
      // public LicenseHandler() {
      // super(LICENSE);
      // setBufferingChar(true);
      // }
      //
      // protected void handleAttributes(Attributes atts) {
      // String uri = atts.getValue(URI);
      // String url = atts.getValue(URL);
      // }
      //
      // }
  
      // private static class CopyrightHandler extends DelegatingHandler {
      //
      // private static final String COPYRIGHT = "copyright";
      //
      // private static final String URI = "uri";
      //
      // private static final String URL = "url";
      //
      // public CopyrightHandler() {
      // super(COPYRIGHT);
      // }
      //
      // protected void handleAttributes(Attributes atts) {
      // String uri = atts.getValue(URI);
      // String url = atts.getValue(URL);
      // }
      //
      // }
  
      // private class ChangesHandler extends DelegatingHandler {
      //
      // private static final String CHANGES = "changes";
      //
      // private static final String SIZE = "size";
      //
      // public ChangesHandler() {
      // super(CHANGES);
      // addChild(new ChangeHandler(), new ChildElementHandler<ChangeHandler>() {
      // public void childHandled(ChangeHandler child) {
      // }
      // });
      // }
      //
      // protected void handleAttributes(Attributes atts) {
      // int size = Integer.parseInt(atts.getValue(SIZE));
      // }
      // }
  
      // private class ChangeHandler extends DelegatingHandler {
      //
      // private static final String CHANGE = "change";
      //
      // public ChangeHandler() {
      // super(CHANGE);
      // }
      // }
  
      // private class FromHandler extends AbstractRequirementHandler {
      //
      // private static final String FROM = "from";
      //
      // public FromHandler() {
      // super(FROM);
      // }
      //
      // }
  
      // private class ToHandler extends AbstractRequirementHandler {
      //
      // private static final String TO = "to";
      //
      // public ToHandler() {
      // super(TO);
      // }
      //
      // }
  
      // private class PatchScopeHandler extends DelegatingHandler {
      //
      // private static final String PATCH_SCOPE = "patchScope";
      //
      // private static final String SIZE = "size";
      //
      // public PatchScopeHandler() {
      // super(PATCH_SCOPE);
      // addChild(new PatchScopeHandler(), new ChildElementHandler<PatchScopeHandler>() {
      // public void childHandled(PatchScopeHandler child) {
      // }
      // });
      // }
      //
      // protected void handleAttributes(Attributes atts) {
      // int size = Integer.parseInt(atts.getValue(SIZE));
      // }
      // }
  
      // private class ScopeHandler extends DelegatingHandler {
      //
      // private static final String SCOPE = "scope";
      //
      // public ScopeHandler() {
      // super(SCOPE);
      // addChild(new RequiresHandler(), new ChildElementHandler<RequiresHandler>() {
      // public void childHandled(RequiresHandler child) {
      // }
      // });
      // }
      // }
  
      // private class LifeCycleHandler extends AbstractRequirementHandler {
      //
      // private static final String LIFE_CYCLE = "lifeCycle";
      //
      // public LifeCycleHandler() {
      // super(LIFE_CYCLE);
      // }
      // }
  
  }
  