/**
   * Returns the CSPEC base that contains the top element attribute overrides and all pure additions
   *
   * @return A Cspec that acts as the base for the extension
   */
  public void alterTopElement(CSpecBuilder bld) throws CoreException {
    Version extVersion = base.getVersion();
    if (extVersion != null) bld.setVersion(extVersion);

    String ctype = base.getComponentTypeID();
    if (ctype != null) bld.setComponentTypeID(ctype);
  }
  /**
   * We will initialize file contents with a sample text.
   *
   * @throws SAXException
   */
  @Override
  protected InputStream openContentStream(String containerName, String fileName) {
    String name = containerName;
    int lastSlash = name.lastIndexOf('/');
    if (lastSlash >= 0) name = name.substring(lastSlash + 1);

    CSpecBuilder builder = new CSpecBuilder();
    builder.setName(name);
    builder.setComponentTypeID(INIT_COMPONENT_TYPE);
    builder.setVersion(Version.parseVersion(INIT_VERSION_STRING));

    CSpec cspec = new CSpec(builder);

    AccessibleByteArrayOutputStream bld = new AccessibleByteArrayOutputStream();
    try {
      Utils.serialize(cspec, bld);
    } catch (SAXException e) {
      throw new RuntimeException(
          Messages.cannot_create_a_new_buckminster_component_specification_file, e);
    }

    return bld.getInputStream();
  }
  public BOMNode collectNodes(
      Map<UUID, BOMNode> nodeMap, Stack<Resolution> circularDepTrap, boolean sameTop)
      throws CoreException {
    if (query.skipComponent()) return null;

    if (generatorNode != null) return generatorNode;

    if (resolution == null) return new UnresolvedNode(query.getQualifiedDependency());

    UUID myID = resolution.getId();
    BOMNode node = nodeMap.get(myID);
    if (node != null) return node;

    if (circularDepTrap.contains(resolution)) {
      if (query.allowCircularDependency()) return null;

      ArrayList<String> attrs = new ArrayList<String>(circularDepTrap.size());
      for (Resolution res : circularDepTrap) attrs.add(res.getCSpec().getName());
      attrs.add(resolution.getName());
      throw new CircularDependencyException(attrs);
    }

    boolean transitive = true;
    if (IComponentType.OSGI_BUNDLE.equals(resolution.getComponentTypeId())) {
      // We don't traverse the children of source bundles since that
      // dependency is synthesized
      transitive = !resolution.getName().endsWith(".source"); // $NON-NLS-1$
    }

    List<BOMNode> childNodes;
    int top = children.length;
    ComponentQuery cquery = query.getComponentQuery();
    if (transitive && top > 0) {
      try {
        ArrayList<BOMNode> childNodeArr = new ArrayList<BOMNode>(top);
        circularDepTrap.push(resolution);
        for (ResolverNode child : children) {
          boolean sameChildTop = cquery.equals(child.query.getComponentQuery());
          BOMNode childNode = child.collectNodes(nodeMap, circularDepTrap, sameChildTop);
          if (childNode == null) {
            // We encountered a skipped component or an allowed
            // circular dependency. This
            // means we must alter the resolution of this node
            //
            String depName = child.getQuery().getComponentRequest().getName();
            CSpec cspec = resolution.getCSpec();
            CSpecBuilder bld = new CSpecBuilder();
            bld.initFrom(cspec);
            for (IAttribute attr : cspec.getAttributes().values()) {
              for (IPrerequisite pq : attr.getPrerequisites()) {
                if (depName.equals(pq.getComponentName()))
                  ((TopLevelAttributeBuilder) bld.getAttribute(attr.getName()))
                      .removePrerequisite(pq);
              }
            }
            bld.removeDependency(depName);
            cspec = bld.createCSpec();
            resolution = new Resolution(cspec, resolution);
          } else childNodeArr.add(childNode);
        }
        circularDepTrap.pop();
        childNodes = childNodeArr;
      } catch (CircularDependencyException e) {
        if (query.allowCircularDependency()) return null;
        throw e;
      }
    } else childNodes = Collections.emptyList();

    node = new ResolvedNode(resolution, childNodes);
    if (!sameTop) node = BillOfMaterials.create(node, cquery);

    nodeMap.put(myID, node);
    return node;
  }
  public void alterCSpec(CSpecBuilder cspecBuilder) throws CoreException {
    for (String removedDep : removedDependencies) {
      cspecBuilder.getRequiredDependency(new ComponentRequest(removedDep, null, null));
      cspecBuilder.removeDependency(removedDep);
    }

    for (AlterDependency alterDep : alteredDependencies.values())
      alterDep.alterDependency(cspecBuilder.getRequiredDependency(alterDep));

    Collection<? extends IComponentRequest> addedDeps = base.getDependencies();
    for (IComponentRequest addedDep : addedDeps) cspecBuilder.addDependency(addedDep);

    for (IGenerator addedGenerator : base.getGeneratorList()) {
      GeneratorBuilder bld = cspecBuilder.createGeneratorBuilder();
      bld.initFrom(addedGenerator);
      cspecBuilder.addGenerator(bld);
    }

    for (String removedAttr : removedAttributes) {
      cspecBuilder.getRequiredAttribute(removedAttr);
      cspecBuilder.removeAttribute(removedAttr);
    }

    for (Map.Entry<String, String> renamedAttribute : renamedAttributes.entrySet()) {
      String oldName = renamedAttribute.getKey();
      AttributeBuilder bld = cspecBuilder.getRequiredAttribute(oldName);
      bld.setName(renamedAttribute.getValue());
      cspecBuilder.removeAttribute(oldName);
      cspecBuilder.addAttribute(bld);
    }

    for (AlterAttribute<?> alterAttr : alteredAttributes.values())
      alterAttr.alterAttribute(
          (TopLevelAttributeBuilder) cspecBuilder.getRequiredAttribute(alterAttr.getName()));

    Map<String, ? extends IAttribute> addedAttrs = base.getAttributes();
    for (IAttribute addedAttr : addedAttrs.values()) {
      AttributeBuilder attrBld;
      if (addedAttr instanceof IActionArtifact)
        attrBld = cspecBuilder.createActionArtifactBuilder();
      else if (addedAttr instanceof IAction) attrBld = cspecBuilder.createActionBuilder();
      else if (addedAttr instanceof IArtifact) attrBld = cspecBuilder.createArtifactBuilder();
      else attrBld = cspecBuilder.createGroupBuilder();
      attrBld.initFrom(addedAttr);
      cspecBuilder.addAttribute(attrBld);
    }

    // On the top element, we never override a value with NULL unless it is
    // explicitly set to the string "null"
    //
    cspecBuilder.setComponentTypeID(
        overrideCheckNull(cspecBuilder.getComponentTypeID(), base.getComponentTypeID()));
    cspecBuilder.setVersion(overrideCheckNull(cspecBuilder.getVersion(), base.getVersion()));

    Documentation origDoc = cspecBuilder.getDocumentation();
    Documentation baseDoc = base.getDocumentation();
    cspecBuilder.setDocumentation(origDoc == null ? baseDoc : origDoc.merge(baseDoc));
  }