@SuppressWarnings("unchecked")
  public static String getResourceOidFromFilter(List<? extends ObjectFilter> conditions)
      throws SchemaException {

    for (ObjectFilter f : conditions) {
      if (f instanceof RefFilter
          && ShadowType.F_RESOURCE_REF.equals(((RefFilter) f).getDefinition().getName())) {
        List<PrismReferenceValue> values = (List<PrismReferenceValue>) ((RefFilter) f).getValues();
        if (values.size() > 1) {
          throw new SchemaException(
              "More than one resource references defined in the search query.");
        }
        if (values.size() < 1) {
          throw new SchemaException("Search query does not have specified resource reference.");
        }
        return values.get(0).getOid();
      }
      if (NaryLogicalFilter.class.isAssignableFrom(f.getClass())) {
        String resourceOid = getResourceOidFromFilter(((NaryLogicalFilter) f).getConditions());
        if (resourceOid != null) {
          return resourceOid;
        }
      }
    }
    return null;
  }
  @SuppressWarnings("rawtypes")
  public static <T> T getValueFromFilter(
      List<? extends ObjectFilter> conditions, QName propertyName) throws SchemaException {
    ItemPath propertyPath = new ItemPath(propertyName);
    for (ObjectFilter f : conditions) {
      if (f instanceof EqualFilter && propertyPath.equivalent(((EqualFilter) f).getFullPath())) {
        List<? extends PrismValue> values = ((EqualFilter) f).getValues();
        if (values.size() > 1) {
          throw new SchemaException(
              "More than one " + propertyName + " defined in the search query.");
        }
        if (values.size() < 1) {
          throw new SchemaException("Search query does not have specified " + propertyName + ".");
        }

        return (T) ((PrismPropertyValue) values.get(0)).getValue();
      }
      if (NaryLogicalFilter.class.isAssignableFrom(f.getClass())) {
        T value = getValueFromFilter(((NaryLogicalFilter) f).getConditions(), propertyName);
        if (value != null) {
          return value;
        }
      }
    }

    return null;
  }
  public static ObjectFilter simplify(ObjectFilter filter) {
    if (filter == null) {
      return null;
    }
    if (filter instanceof AndFilter) {
      List<ObjectFilter> conditions = ((AndFilter) filter).getConditions();
      AndFilter simplifiedFilter = ((AndFilter) filter).cloneEmpty();
      for (ObjectFilter subfilter : conditions) {
        if (subfilter instanceof NoneFilter) {
          // AND with "false"
          return NoneFilter.createNone();
        } else if (subfilter instanceof AllFilter) {
          // AND with "true", just skip it
        } else {
          ObjectFilter simplifiedSubfilter = simplify(subfilter);
          simplifiedFilter.addCondition(simplifiedSubfilter);
        }
      }
      if (simplifiedFilter.isEmpty()) {
        return AllFilter.createAll();
      }
      return simplifiedFilter;

    } else if (filter instanceof OrFilter) {
      List<ObjectFilter> conditions = ((OrFilter) filter).getConditions();
      OrFilter simplifiedFilter = ((OrFilter) filter).cloneEmpty();
      for (ObjectFilter subfilter : conditions) {
        if (subfilter instanceof NoneFilter) {
          // OR with "false", just skip it
        } else if (subfilter instanceof AllFilter) {
          // OR with "true"
          return AllFilter.createAll();
        } else {
          ObjectFilter simplifiedSubfilter = simplify(subfilter);
          simplifiedFilter.addCondition(simplifiedSubfilter);
        }
      }
      if (simplifiedFilter.isEmpty()) {
        return AllFilter.createAll();
      }
      return simplifiedFilter;

    } else if (filter instanceof NotFilter) {
      ObjectFilter subfilter = ((NotFilter) filter).getFilter();
      ObjectFilter simplifiedSubfilter = simplify(subfilter);
      if (subfilter instanceof NoneFilter) {
        return AllFilter.createAll();
      } else if (subfilter instanceof AllFilter) {
        return NoneFilter.createNone();
      } else {
        NotFilter simplifiedFilter = ((NotFilter) filter).cloneEmpty();
        simplifiedFilter.setFilter(simplifiedSubfilter);
        return simplifiedFilter;
      }
    } else {
      // Cannot simplify
      return filter.clone();
    }
  }
 public static void assertNotRaw(ObjectFilter filter, final String message) {
   Visitor visitor =
       new Visitor() {
         @Override
         public void visit(ObjectFilter filter) {
           if (filter instanceof ValueFilter && ((ValueFilter) filter).isRaw()) {
             if (message == null) {
               throw new IllegalArgumentException(filter.toString());
             } else {
               throw new IllegalArgumentException(message + ": " + filter);
             }
           }
         }
       };
   filter.accept(visitor);
 }
 public static void assertPropertyOnly(ObjectFilter filter, final String message) {
   Visitor visitor =
       new Visitor() {
         @Override
         public void visit(ObjectFilter filter) {
           if (filter instanceof OrgFilter) {
             if (message == null) {
               throw new IllegalArgumentException(filter.toString());
             } else {
               throw new IllegalArgumentException(message + ": " + filter);
             }
           }
         }
       };
   filter.accept(visitor);
 }
 public static boolean hasAllDefinitions(ObjectFilter filter) {
   final MutableBoolean hasAllDefinitions = new MutableBoolean(true);
   Visitor visitor =
       new Visitor() {
         @Override
         public void visit(ObjectFilter filter) {
           if (filter instanceof ValueFilter) {
             ItemDefinition definition = ((ValueFilter<?>) filter).getDefinition();
             if (definition == null) {
               hasAllDefinitions.setValue(false);
             }
           }
         }
       };
   filter.accept(visitor);
   return hasAllDefinitions.booleanValue();
 }