@Override
 @Transactional
 public void deleteResourceRole(String resourceId, String roleId) {
   final ResourceEntity entity = resourceDao.findById(resourceId);
   final RoleEntity roleEntity = roleDao.findById(roleId);
   entity.remove(roleEntity);
   resourceDao.save(entity);
 }
 @Override
 @Transactional
 public void deleteChildResource(String resourceId, String childResourceId) {
   final ResourceEntity parent = resourceDao.findById(resourceId);
   final ResourceEntity child = resourceDao.findById(childResourceId);
   parent.removeChildResource(child);
   resourceDao.save(parent);
 }
 @Override
 @Transactional
 public void deleteResourceGroup(String resourceId, String groupId) {
   final ResourceEntity entity = resourceDao.findById(resourceId);
   final GroupEntity groupEntity = groupDao.findById(groupId);
   entity.remove(groupEntity);
   resourceDao.save(entity);
 }
 @Override
 @Transactional
 public void addChildResource(String parentResourceId, String childResourceId) {
   final ResourceEntity parent = resourceDao.findById(parentResourceId);
   final ResourceEntity child = resourceDao.findById(childResourceId);
   parent.addChildResource(child);
   resourceDao.save(parent);
 }
 @Override
 @Transactional(readOnly = true)
 public int getNumOfParentResources(String resourceId) {
   final ResourceEntity example = new ResourceEntity();
   final ResourceEntity child = new ResourceEntity();
   child.setId(resourceId);
   example.addChildResource(child);
   return resourceDao.count(example);
 }
 @Override
 @Transactional(readOnly = true)
 public List<ResourceEntity> getParentResources(String resourceId, int from, int size) {
   final ResourceEntity example = new ResourceEntity();
   final ResourceEntity child = new ResourceEntity();
   child.setId(resourceId);
   example.addChildResource(child);
   return resourceDao.getByExample(example, from, size);
 }
 @Override
 @Transactional(readOnly = true)
 public List<ResourceEntity> getChildResources(String resourceId, int from, int size) {
   final ResourceEntity example = new ResourceEntity();
   final ResourceEntity parent = new ResourceEntity();
   parent.setId(resourceId);
   example.addParentResource(parent);
   final List<ResourceEntity> resultList = resourceDao.getByExample(example, from, size);
   return resultList;
 }
 private ResourceEntity getNewAdminResource(
     final ResourceEntity entity, final String requestorId) {
   final ResourceEntity adminResource = new ResourceEntity();
   adminResource.setName(
       String.format(
           "RES_ADMIN_%s_%s", entity.getName(), RandomStringUtils.randomAlphanumeric(2)));
   adminResource.setResourceType(resourceTypeDao.findById(adminResourceTypeId));
   adminResource.addUser(userDAO.findById(requestorId));
   return adminResource;
 }
 @Override
 @Transactional
 public void addRequiredAttributes(ResourceEntity resource) {
   if (resource != null
       && resource.getType() != null
       && StringUtils.isNotBlank(resource.getType().getId())) {
     MetadataElementSearchBean sb = new MetadataElementSearchBean();
     sb.addTypeId(resource.getType().getId());
     List<MetadataElementEntity> elementList = elementDAO.getByExample(sb, -1, -1);
     if (CollectionUtils.isNotEmpty(elementList)) {
       for (MetadataElementEntity element : elementList) {
         if (element.isRequired()) {
           resourcePropDao.save(AttributeUtil.buildResAttribute(resource, element));
         }
       }
     }
   }
 }
 private ApproverAssociationEntity createDefaultApproverAssociations(
     final ResourceEntity entity, final String requestorId) {
   final ApproverAssociationEntity association = new ApproverAssociationEntity();
   association.setAssociationEntityId(entity.getId());
   association.setAssociationType(AssociationType.RESOURCE);
   association.setApproverLevel(Integer.valueOf(0));
   association.setApproverEntityId(requestorId);
   association.setApproverEntityType(AssociationType.USER);
   return association;
 }
 private boolean causesCircularDependency(
     final ResourceEntity parent,
     final ResourceEntity child,
     final Set<ResourceEntity> visitedSet) {
   boolean retval = false;
   if (parent != null && child != null) {
     if (!visitedSet.contains(child)) {
       visitedSet.add(child);
       if (CollectionUtils.isNotEmpty(parent.getParentResources())) {
         for (final ResourceEntity entity : parent.getParentResources()) {
           retval = entity.getId().equals(child.getId());
           if (retval) {
             break;
           }
           causesCircularDependency(parent, entity, visitedSet);
         }
       }
     }
   }
   return retval;
 }
  @Override
  @Transactional
  public void validateResource2ResourceAddition(final String parentId, final String memberId)
      throws BasicDataServiceException {
    if (StringUtils.isBlank(parentId) || StringUtils.isBlank(memberId)) {
      throw new BasicDataServiceException(
          ResponseCode.INVALID_ARGUMENTS, "Parent ResourceId or Child ResourceId is null");
    }

    final ResourceEntity parent = resourceDao.findById(parentId);
    final ResourceEntity child = resourceDao.findById(memberId);

    if (parent == null || child == null) {
      throw new BasicDataServiceException(ResponseCode.OBJECT_NOT_FOUND);
    }

    if (causesCircularDependency(parent, child, new HashSet<ResourceEntity>())) {
      throw new BasicDataServiceException(ResponseCode.CIRCULAR_DEPENDENCY);
    }

    if (parent.hasChildResoruce(child)) {
      throw new BasicDataServiceException(ResponseCode.RELATIONSHIP_EXISTS);
    }

    if (StringUtils.equals(parentId, memberId)) {
      throw new BasicDataServiceException(ResponseCode.CANT_ADD_YOURSELF_AS_CHILD);
    }

    if (parent.getResourceType() != null && !parent.getResourceType().isSupportsHierarchy()) {
      throw new BasicDataServiceException(
          ResponseCode.RESOURCE_TYPE_NOT_SUPPORTS_HIERARCHY,
          parent.getResourceType().getDescription());
    }

    if (child.getResourceType() != null && !child.getResourceType().isSupportsHierarchy()) {
      throw new BasicDataServiceException(
          ResponseCode.RESOURCE_TYPE_NOT_SUPPORTS_HIERARCHY,
          child.getResourceType().getDescription());
    }
  }
  @Override
  @Transactional
  public void validateResourceDeletion(final String resourceId) throws BasicDataServiceException {
    final ResourceEntity entity = resourceDao.findById(resourceId);
    if (entity != null) {

      final List<ManagedSysEntity> managedSystems = managedSysDAO.findByResource(resourceId);
      if (CollectionUtils.isNotEmpty(managedSystems)) {
        throw new BasicDataServiceException(
            ResponseCode.LINKED_TO_MANAGED_SYSTEM, managedSystems.get(0).getName());
      }

      final List<ContentProviderEntity> contentProviders =
          contentProviderDAO.getByResourceId(resourceId);
      if (CollectionUtils.isNotEmpty(contentProviders)) {
        throw new BasicDataServiceException(
            ResponseCode.LINKED_TO_CONTENT_PROVIDER, contentProviders.get(0).getName());
      }

      final List<URIPatternEntity> uriPatterns = uriPatternDAO.getByResourceId(resourceId);
      if (CollectionUtils.isNotEmpty(uriPatterns)) {
        throw new BasicDataServiceException(
            ResponseCode.LINKED_TO_URI_PATTERN, uriPatterns.get(0).getPattern());
      }

      final List<AuthProviderEntity> authProviders = authProviderDAO.getByResourceId(resourceId);
      if (CollectionUtils.isNotEmpty(authProviders)) {
        throw new BasicDataServiceException(
            ResponseCode.LINKED_TO_AUTHENTICATION_PROVIDER, authProviders.get(0).getName());
      }

      final List<MetadataElementEntity> metadataElements = elementDAO.getByResourceId(resourceId);
      if (CollectionUtils.isNotEmpty(metadataElements)) {
        throw new BasicDataServiceException(
            ResponseCode.LINKED_TO_METADATA_ELEMENT, metadataElements.get(0).getAttributeName());
      }

      final List<MetadataElementPageTemplateEntity> pageTemplates =
          templateDAO.getByResourceId(resourceId);
      if (CollectionUtils.isNotEmpty(pageTemplates)) {
        throw new BasicDataServiceException(
            ResponseCode.LINKED_TO_PAGE_TEMPLATE, pageTemplates.get(0).getName());
      }

      final ResourceEntity searchBean = new ResourceEntity();
      searchBean.setAdminResource(new ResourceEntity(resourceId));
      final List<ResourceEntity> adminOfResources = resourceDao.getByExample(searchBean);
      if (CollectionUtils.isNotEmpty(adminOfResources)) {
        throw new BasicDataServiceException(
            ResponseCode.RESOURCE_IS_AN_ADMIN_OF_RESOURCE, adminOfResources.get(0).getName());
      }

      final RoleEntity roleSearchBean = new RoleEntity();
      roleSearchBean.setAdminResource(new ResourceEntity(resourceId));
      final List<RoleEntity> adminOfRoles = roleDao.getByExample(roleSearchBean);
      if (CollectionUtils.isNotEmpty(adminOfRoles)) {
        throw new BasicDataServiceException(
            ResponseCode.RESOURCE_IS_AN_ADMIN_OF_ROLE, adminOfRoles.get(0).getName());
      }

      final GroupEntity groupSearchBean = new GroupEntity();
      groupSearchBean.setAdminResource(new ResourceEntity(resourceId));
      final List<GroupEntity> adminOfGroups = groupDao.getByExample(groupSearchBean);
      if (CollectionUtils.isNotEmpty(adminOfGroups)) {
        throw new BasicDataServiceException(
            ResponseCode.RESOURCE_IS_AN_ADMIN_OF_GROUP, adminOfGroups.get(0).getName());
      }

      final OrganizationEntity orgSearchBean = new OrganizationEntity();
      orgSearchBean.setAdminResource(new ResourceEntity(resourceId));
      final List<OrganizationEntity> adminOfOrgs = orgDAO.getByExample(orgSearchBean);
      if (CollectionUtils.isNotEmpty(adminOfOrgs)) {
        throw new BasicDataServiceException(
            ResponseCode.RESOURCE_IS_AN_ADMIN_OF_ORG, adminOfOrgs.get(0).getName());
      }
    }
  }
  private void mergeAttribute(final ResourceEntity bean, final ResourceEntity dbObject) {

    /*
     * if the incoming bean is from the database, there is no reason to do any merging
     * This was written to avoid merging  of attributes when you call findById on the resourceService,
     * and then save the same object (see ManagedSystemServiceImpl.updateMangagedSys)
     */
    if (bean.getResourceProps() != null
        && bean.getResourceProps() instanceof PersistentCollection) {
      return;
    }
    Set<ResourcePropEntity> beanProps =
        (bean.getResourceProps() != null)
            ? bean.getResourceProps()
            : new HashSet<ResourcePropEntity>();
    Set<ResourcePropEntity> dbProps =
        (dbObject.getResourceProps() != null)
            ? new HashSet<ResourcePropEntity>(dbObject.getResourceProps())
            : new HashSet<ResourcePropEntity>();

    /* update */
    Iterator<ResourcePropEntity> dbIteroator = dbProps.iterator();
    while (dbIteroator.hasNext()) {
      final ResourcePropEntity dbProp = dbIteroator.next();

      boolean contains = false;
      for (final ResourcePropEntity beanProp : beanProps) {
        if (StringUtils.equals(dbProp.getId(), beanProp.getId())) {
          dbProp.setValue(beanProp.getValue());
          dbProp.setElement(getEntity(beanProp.getElement()));
          dbProp.setName(beanProp.getName());
          dbProp.setIsMultivalued(beanProp.getIsMultivalued());
          // renewedProperties.add(dbProp);
          contains = true;
          break;
        }
      }

      /* remove */
      if (!contains) {
        dbIteroator.remove();
      }
    }

    /* add */
    final Set<ResourcePropEntity> toAdd = new HashSet<>();
    for (final ResourcePropEntity beanProp : beanProps) {
      boolean contains = false;
      dbIteroator = dbProps.iterator();
      while (dbIteroator.hasNext()) {
        final ResourcePropEntity dbProp = dbIteroator.next();
        if (StringUtils.equals(dbProp.getId(), beanProp.getId())) {
          contains = true;
        }
      }

      if (!contains) {
        beanProp.setResource(bean);
        beanProp.setElement(getEntity(beanProp.getElement()));
        toAdd.add(beanProp);
      }
    }
    dbProps.addAll(toAdd);

    bean.setResourceProps(dbProps);
  }
  @Override
  @Transactional
  public void save(ResourceEntity entity, final String requestorId) {
    if (entity.getResourceType() != null) {
      entity.setResourceType(resourceTypeDao.findById(entity.getResourceType().getId()));
    }

    /* admin resource can't have an admin resource - do this check here */
    boolean isAdminResource =
        StringUtils.equals(entity.getResourceType().getId(), adminResourceTypeId);

    if (entity.getType() != null && StringUtils.isNotBlank(entity.getType().getId())) {
      entity.setType(typeDAO.findById(entity.getType().getId()));
    } else {
      entity.setType(null);
    }

    if (StringUtils.isNotBlank(entity.getId())) {
      final ResourceEntity dbObject = resourceDao.findById(entity.getId());
      entity.setAdminResource(dbObject.getAdminResource());
      entity.setApproverAssociations(dbObject.getApproverAssociations());

      if (isAdminResource) {
        entity.setAdminResource(null);
      } else if (entity.getAdminResource() == null) {
        final ResourceEntity adminResource = getNewAdminResource(entity, requestorId);
        entity.setAdminResource(adminResource);
        if (CollectionUtils.isEmpty(dbObject.getApproverAssociations())) {
          entity.addApproverAssociation(createDefaultApproverAssociations(entity, requestorId));
        }
      }
      entity.setChildResources(dbObject.getChildResources());
      entity.setParentResources(dbObject.getParentResources());
      entity.setUsers(dbObject.getUsers());
      entity.setGroups(dbObject.getGroups());
      entity.setRoles(dbObject.getRoles());

      // elementDAO.flush();
      mergeAttribute(entity, dbObject);

    } else {
      boolean addApproverAssociation = false;
      if (isAdminResource) {
        entity.setAdminResource(null);
      } else {
        entity.setAdminResource(getNewAdminResource(entity, requestorId));
        addApproverAssociation = true;
      }
      resourceDao.save(entity);

      if (addApproverAssociation) {
        entity.addApproverAssociation(createDefaultApproverAssociations(entity, requestorId));
      }

      addRequiredAttributes(entity);
    }

    resourceDao.merge(entity);
  }