public Acl readAclById(ObjectIdentity id) throws NotFoundException {
    DefaultAclAuthorizationStrategy strategy = new DefaultAclAuthorizationStrategy();
    AclImpl acl = new AclImpl(id, id.getIdentifier(), strategy, DEFAULT_AUDIT_LOGGER);

    // Get data about saved object from database and then remove it from Hibernate cache if
    // necessary
    boolean isObjectLoaded =
        HibernateUtil.currentSession().contains(((TransferObjectIdentity) id).getTransferObject());
    ITransferObject dto = loadObject(id);
    dto
        .getOwnerId(); // this is to force fetch of entire object from database so that further
                       // getter calls don't fail
    if (!isObjectLoaded) {
      HibernateUtil.evictFullObject(dto);
    }

    // Add object levels to ACL
    addAclLevel(secCfg.getWriteMatrix(), acl, id.getJavaType(), dto, BasePermission.WRITE);
    addAclLevel(secCfg.getDeleteMatrix(), acl, id.getJavaType(), dto, BasePermission.DELETE);
    addAclLevel(secCfg.getReadMatrix(), acl, id.getJavaType(), dto, BasePermission.READ);

    // Lock ACL so that nobody can change it any more
    strategy.freeze();

    return acl;
  }
  private void addAclLevel(
      Map<AclMatrixKey, AclMatrixValue> matrix,
      AclImpl acl,
      Class type,
      ITransferObject dto,
      Permission perm) {
    Principal principal = SpringUtils.getPrincipal();
    Sid sid = new PrincipalSid(principal.getUsername());
    AclMatrixKey key = new AclMatrixKey(type, principal.getRoleId());
    AclMatrixValue level = matrix.get(key);

    log.debug(
        "addAclLevel -"
            + " permission=["
            + perm.getPattern()
            + "]"
            + " type="
            + type.getSimpleName()
            + " id="
            + dto.getId()
            + " ownerId="
            + dto.getOwnerId()
            + " departmentId="
            + dto.getDepartmentId()
            + " userId="
            + principal.getId()
            + " roleId="
            + principal.getRoleId()
            + " level="
            + level);
    if (level == null) {
      throw new UnsupportedOperationException("Write permission level for " + key + " not defined");
    }

    switch (level) {
      case ALL:
        acl.insertAce(null, perm, sid, true);
        break;

      case OWN:
        if (isIgnoreUnownedObjects() && (dto.getOwnerId() == null)) {
          acl.insertAce(null, perm, sid, true);
          log.warn(
              "addAclLevel - allowing permission ["
                  + perm.getPattern()
                  + "] on object "
                  + type.getSimpleName()
                  + "["
                  + dto.getId()
                  + "] "
                  + "because it is not owned by any user and ignoreUnownedObjects=true in DefaultAclService");
        } else {
          if (dto.getOwnerId() == principal.getId()) {
            acl.insertAce(null, perm, sid, true);
          }
        }
        break;

      case AREA:
        if (isIgnoreUnownedObjects() && (dto.getDepartmentId() == null)) {
          acl.insertAce(null, perm, sid, true);
          log.warn(
              "addAclLevel - allowing permission ["
                  + perm.getPattern()
                  + "] on object "
                  + type.getSimpleName()
                  + "["
                  + dto.getId()
                  + "] "
                  + "because it is not owned by any department and ignoreUnownedObjects=true in DefaultAclService");
        } else {
          if (dto.getDepartmentId() == principal.getDepartmentId()) {
            acl.insertAce(null, perm, sid, true);
          }
        }
        break;

      case DENY:
        // Do nothing
        break;

      default:
        throw new UnsupportedOperationException(
            "AclMatrixValue(" + level + ") not supported by write permission in readAclById()");
    }
  }