@Override
  @Transactional
  public NCSComponent addSubcomponent(
      final String type,
      final String foreignSource,
      final String foreignId,
      final NCSComponent subComponent,
      final boolean deleteOrphans) {
    final ComponentIdentifier subComponentId = getIdentifier(subComponent);

    LogUtils.debugf(
        this,
        "addSubcomponent(%s, %s, %s, %s, %s)",
        type,
        foreignSource,
        foreignId,
        subComponentId,
        Boolean.valueOf(deleteOrphans));

    final NCSComponent component = getComponent(type, foreignSource, foreignId);
    final ComponentIdentifier id = getIdentifier(component);
    final ComponentEventQueue ceq = new ComponentEventQueue();

    if (component == null) {
      throw new ObjectRetrievalFailureException(
          NCSComponent.class,
          "Unable to locate component with type="
              + type
              + ", foreignSource="
              + foreignSource
              + ", foreignId="
              + foreignId);
    }

    final NCSComponent updatedSubComponent =
        addOrUpdateComponents(subComponentId, subComponent, ceq, deleteOrphans);
    component.addSubcomponent(updatedSubComponent);

    m_componentDao.update(component);
    ceq.componentUpdated(id);

    try {
      ceq.sendAll(m_eventProxy);
    } catch (final EventProxyException e) {
      LogUtils.warnf(
          this,
          e,
          "Component %s added to %s, but an error occured while sending add/delete/update events.",
          subComponentId,
          id);
    }

    return getComponent(id);
  }
  private void handleOrphanedComponents(
      final NCSComponent parent,
      final ComponentIdentifier child,
      final ComponentEventQueue ceq,
      final boolean deleteOrphans) {
    final ComponentIdentifier parentId = getIdentifier(parent);
    final NCSComponent childComponent = getComponent(child);

    final Set<ComponentIdentifier> childChildren =
        getIdentifiers(childComponent.getSubcomponents());
    final Set<ComponentIdentifier> childParents =
        getIdentifiers(childComponent.getParentComponents());

    LogUtils.tracef(this, "handleOrphanedComponents: parent: %s", parentId);
    LogUtils.tracef(this, "handleOrphanedComponents: child: %s", child);
    LogUtils.tracef(this, "handleOrphanedComponents: child's children: %s", childChildren);
    LogUtils.tracef(this, "handleOrphanedComponents: child's parents: %s", childParents);

    if (childParents.size() == 1) {
      final ComponentIdentifier childParent = childParents.iterator().next();
      if (childParent.equals(parentId)) {
        LogUtils.tracef(
            this,
            "handleOrphanedComponents: child (%s) has only one parent (%s) and it's being deleted.",
            child,
            childParent);
        deleteComponent(child, ceq, deleteOrphans);
      } else {
        LogUtils.tracef(
            this,
            "handleOrphanedComponents: child (%s) has only one parent (%s) but it's not the one we expected. This is weird.",
            child,
            childParent);
        ceq.componentUpdated(childParent);
      }
    } else {
      LogUtils.tracef(
          this,
          "handleOrphanedComponents: child (%s) has more than one parent, sending updates for remaining parents.",
          child);
      for (final ComponentIdentifier childParent : childParents) {
        ceq.componentUpdated(childParent);
      }
    }
  }
 private ComponentIdentifier getIdentifier(final NCSComponent component) {
   return new ComponentIdentifier(
       component.getId(),
       component.getType(),
       component.getForeignSource(),
       component.getForeignId(),
       component.getName(),
       component.getDependenciesRequired());
 }
  private void deleteComponent(
      final ComponentIdentifier id, final ComponentEventQueue ceq, final boolean deleteOrphans) {
    final NCSComponent component = getComponent(id);

    if (component == null) {
      throw new WebApplicationException(Status.BAD_REQUEST);
    }

    final Set<NCSComponent> parentComponents = component.getParentComponents();
    final Set<ComponentIdentifier> childrenIdentifiers =
        getIdentifiers(component.getSubcomponents());

    // first, we deal with orphans
    if (deleteOrphans) {
      for (final ComponentIdentifier subId : childrenIdentifiers) {
        handleOrphanedComponents(component, subId, ceq, deleteOrphans);
      }
    }

    // first, we remove this component from each of its parents
    for (final NCSComponent parent : parentComponents) {
      parent.getSubcomponents().remove(component);
      m_componentDao.update(parent);
    }

    // then we delete this component
    component.setSubcomponents(EMPTY_COMPONENT_SET);
    m_componentDao.delete(component);

    // and any events or alarms depending on it
    deleteEvents(id.getForeignSource(), id.getForeignId());
    deleteAlarms(id.getForeignSource(), id.getForeignId());

    // alert that the component is deleted
    ceq.componentDeleted(getIdentifier(component));

    // then alert about the parents
    sendUpdateEvents(ceq, getIdentifiers(parentComponents));
  }