core/src/main/java/org/sakaiproject/nakamura/api/lite/StorageClientUtils.java
@SuppressWarnings("unchecked")
    public static <K, V> Map<K, V> getFilterMap(Map<K, V> source, Map<K, V> modified, Set<K> include, Set<K> exclude, boolean includingRemoveProperties ) {
       if ((modified == null || modified.size() == 0) && (include == null) && ( exclude == null || exclude.size() == 0)) {
           if ( source instanceof ImmutableMap ) {
               return source;
           } else {
               return ImmutableMap.copyOf(source);
           }
        }

        Builder<K, V> filteredMap = new ImmutableMap.Builder<K, V>();
        for (Entry<K, V> e : source.entrySet()) {
            K k = e.getKey();
            if (include == null || include.contains(k)) {
                if (exclude == null || !exclude.contains(k)) {
                    if ( modified != null && modified.containsKey(k) ) {
                        V o = modified.get(k);
                        if (o instanceof Map) {
                            filteredMap.put(k,
                                    (V) getFilterMap((Map<K, V>) o, null, null, exclude, includingRemoveProperties));
                        } else if ( includingRemoveProperties ) {
                            filteredMap.put(k, o);
                        } else if ( !(o instanceof RemoveProperty) ) {
                            filteredMap.put(k, o);
                        }
                    } else {
                        Object o = e.getValue();
                        if (o instanceof Map) {
                            filteredMap.put(k,
                                    (V) getFilterMap((Map<K, V>) e.getValue(), null, null, exclude, includingRemoveProperties));
                        } else {
                            filteredMap.put(k, e.getValue());
                        }
                    }
                }
            }
        }
        if ( modified != null ) {
            // process additions
            for (Entry<K, V> e : modified.entrySet()) {
                K k = e.getKey();
                if ( !source.containsKey(k)) {
                    V v = e.getValue();
                    if ( !(v instanceof RemoveProperty) && v != null ) {
                        filteredMap.put(k,v);
                    }
                }
            }
        }
        return filteredMap.build();
    }
@SuppressWarnings("unchecked")
    public static <K, V> Map<K, V> getFilterMap(Map<K, V> source, Map<K, V> modified, Set<K> include, Set<K> exclude, boolean includingRemoveProperties ) {
       if ((modified == null || modified.size() == 0) && (include == null) && ( exclude == null || exclude.size() == 0)) {
           if ( source instanceof ImmutableMap ) {
               return source;
           } else {
               return ImmutableMap.copyOf(source);
           }
        }

        Builder<K, V> filteredMap = new ImmutableMap.Builder<K, V>();
        for (Entry<K, V> e : source.entrySet()) {
            K k = e.getKey();
            if (include == null || include.contains(k)) {
                if (exclude == null || !exclude.contains(k)) {
                    if ( modified != null && modified.containsKey(k) ) {
                        V o = modified.get(k);
                        if (o instanceof Map) {
                            filteredMap.put(k,
                                    (V) getFilterMap((Map<K, V>) o, null, null, exclude, includingRemoveProperties));
                        } else if ( includingRemoveProperties ) {
                            filteredMap.put(k, o);
                        } else if ( !(o instanceof RemoveProperty) ) {
                            filteredMap.put(k, o);
                        }
                    } else {
                        Object o = e.getValue();
                        if (o instanceof Map) {
                            filteredMap.put(k,
                                    (V) getFilterMap((Map<K, V>) e.getValue(), null, null, exclude, includingRemoveProperties));
                        } else {
                            filteredMap.put(k, e.getValue());
                        }
                    }
                }
            }
        }
        if ( modified != null ) {
            // process additions
            for (Entry<K, V> e : modified.entrySet()) {
                K k = e.getKey();
                if ( !source.containsKey(k)) {
                    V v = e.getValue();
                    if ( !(v instanceof RemoveProperty) && v != null ) {
                        filteredMap.put(k,v);
                    }
                }
            }
        }
        return filteredMap.build();
    }
Converts to an Immutable map, with keys that are in the filter not
transfered. Nested maps are also transfered.

@param <K> the type of the key
@param <V> the type of the value
@param source a map of values to start with
@param modified a map to oveeride values in source
@param include if not null, only include these keys in the returned map
@param exclude if not null, exclude these keys from the returned map
@return a map with the modifications applied and filtered by the includes and excludes