SourceTargetMap.java 12 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  org.apache.commons.collections.Predicate
 *  org.apache.commons.collections.Transformer
 *  org.apache.commons.collections.functors.AllPredicate
 *  org.apache.commons.collections.list.TransformedList
 *  org.apache.jackrabbit.util.Text
 */
package com.day.cq.wcm.msm.impl;

import com.day.cq.wcm.msm.impl.SourceTargetFilter;
import com.day.cq.wcm.msm.impl.Utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.AllPredicate;
import org.apache.commons.collections.list.TransformedList;
import org.apache.jackrabbit.util.Text;

final class SourceTargetMap {
    private final TreeMap<String, ConfigPoint> targetToSource = new TreeMap();
    private final TreeMap<String, Set<ConfigPoint>> sourceToTarget = new TreeMap();
    private final TreeMap<String, TreeConfig> targetToEntry = new TreeMap();

    SourceTargetMap() {
    }

    public boolean filterAt(String targetPath) {
        return this.targetToEntry.containsKey(targetPath);
    }

    public boolean descendantHasFilter(String targetPath) {
        SortedMap<String, ConfigPoint> lower = this.targetToSource.tailMap(targetPath);
        return lower.size() > 0 && Text.isDescendantOrEqual((String)targetPath, (String)lower.firstKey());
    }

    public void addSourTargetFilter(SourceTargetFilter stFilter) {
        String targetStart = stFilter.getTarget();
        TreeConfig added = new TreeConfig(stFilter);
        this.targetToEntry.put(targetStart, added);
        this.index(added);
    }

    public boolean remove(String targetPath) {
        TreeConfig removed = this.targetToEntry.remove(targetPath);
        if (removed != null) {
            this.unIndex(removed);
        }
        return removed != null;
    }

    public String getSource(String targetPath) {
        ConfigPoint endPoint = this.targetToSource.get(targetPath);
        if (endPoint != null && endPoint.isStart()) {
            return endPoint.getPath();
        }
        return null;
    }

    private void addAllConfigPoints(TreeMap<String, String> all, Set<String> entries, String relPath, Set<? extends ConfigPoint> configPoints) {
        for (ConfigPoint p : configPoints) {
            SourceTargetFilter filter;
            String key;
            String path;
            String string = path = relPath == null ? p.getPath() : Utils.appendPath(p.getPath(), relPath);
            if (p.isStart()) {
                all.put(path, p.getPath());
                entries.add(p.getPath());
            } else {
                String target = all.remove(p.getPath());
                if (target == null && (key = all.higherKey(p.getPath())) != null && Text.isDescendant((String)key, (String)p.getPath())) {
                    target = all.remove(key);
                }
                if (target != null) {
                    entries.remove(target);
                }
            }
            if (!p.isStart() || relPath == null || (filter = this.getContainingFilter(Utils.appendPath(p.getPath(), relPath))) != null && filter.getTarget().equals(p.getPath()) || (key = all.remove(path)) == null) continue;
            entries.remove(key);
        }
    }

    public Set<String> getTargets(String sourcePath) {
        HashSet<String> entries = new HashSet<String>();
        TreeMap<String, String> all = new TreeMap<String, String>();
        String relPath = null;
        String path = "/";
        String[] elements = sourcePath.split("/");
        for (int i = 1; i < (elements.length - 1) * 2; ++i) {
            if (i % 2 == 0) {
                path = path + "/";
            } else {
                String string = relPath = (path = path + elements[Math.round(i / 2) + i % 2]).equals(sourcePath) ? null : Utils.relativePath(path, sourcePath);
            }
            if (!this.sourceToTarget.containsKey(path)) continue;
            this.addAllConfigPoints(all, entries, relPath, this.sourceToTarget.get(path));
        }
        return entries;
    }

    public synchronized List<String> getTargetBranch(String targetPath) {
        List branchEntries = TransformedList.decorate(new ArrayList(), (Transformer)new Transformer(){

            public Object transform(Object input) {
                return ((TreeConfig)input).getTargetStartPoint().getPath();
            }
        });
        if (this.filterAt(targetPath)) {
            branchEntries.add(this.getConfig(targetPath));
        }
        branchEntries.addAll(this.getDescendants(targetPath, new Predicate[0]));
        return branchEntries;
    }

    public SourceTargetFilter getContainingFilter(String target) {
        if (!target.startsWith("/")) {
            throw new IllegalArgumentException("Target must be absolute");
        }
        if ("/".equals(target)) {
            return null;
        }
        String children = target + "/";
        ConfigPoint point = null;
        if (this.targetToSource.containsKey(children)) {
            point = this.targetToSource.get(children);
        } else if (this.targetToSource.containsKey(target)) {
            point = this.targetToSource.get(target);
        }
        if (point != null && point.isStart()) {
            return this.getConfig(target).config;
        }
        if (point != null) {
            return null;
        }
        return this.getContainingFilter(Text.getRelativeParent((String)target, (int)1));
    }

    public /* varargs */ void addSourceTargetFilter(String source, String target, boolean deep, String ... filter) {
        this.addSourTargetFilter(new SourceTargetFilter(source, target, deep, filter));
    }

    private void index(TreeConfig added) {
        String targetPath = added.config.getTarget();
        this.targetToSource.put(targetPath, added.getSourceStartPoint());
        for (EndPoint endPoint2 : added.getTargetEndPoints()) {
            this.targetToSource.put(endPoint2.getPath(), endPoint2);
        }
        this.addSourceMapping(added.getSourceStartPoint().getPath(), added.getTargetStartPoint());
        for (EndPoint endPoint2 : added.getSourceEndPoints()) {
            EndPoint targetPoint = added.getTargetEndPoint(endPoint2);
            if (targetPoint == null) continue;
            this.addSourceMapping(endPoint2.getPath(), targetPoint);
        }
    }

    private void unIndex(TreeConfig removed) {
        String targetPath = removed.config.getTarget();
        this.targetToSource.remove(targetPath);
        for (EndPoint endPoint2 : removed.getTargetEndPoints()) {
            this.targetToSource.remove(endPoint2.getPath());
        }
        this.unIndexSource(removed.getSourceStartPoint().getPath(), removed.getTargetStartPoint());
        for (EndPoint endPoint2 : removed.getSourceEndPoints()) {
            EndPoint targetPoint = removed.getTargetEndPoint(endPoint2);
            if (targetPoint == null) continue;
            this.unIndexSource(endPoint2.getPath(), removed.getTargetStartPoint());
        }
    }

    private void unIndexSource(String sourcePath, ConfigPoint targetPoint) {
        Set<ConfigPoint> entry = this.sourceToTarget.get(sourcePath);
        if (entry != null) {
            entry.remove(targetPoint);
            if (entry.isEmpty()) {
                this.sourceToTarget.remove(sourcePath);
            }
        }
    }

    private /* varargs */ List<TreeConfig> getDescendants(String target, Predicate ... predicates) {
        ArrayList<TreeConfig> descendants = new ArrayList<TreeConfig>();
        NavigableMap<String, TreeConfig> children = this.targetToEntry.tailMap(target, false);
        Predicate allPredicate = AllPredicate.getInstance((Predicate[])(predicates == null ? new Predicate[]{} : predicates));
        for (Map.Entry<String, TreeConfig> entry : children.entrySet()) {
            if (!Text.isDescendantOrEqual((String)target, (String)entry.getKey())) break;
            if (!allPredicate.evaluate((Object)entry.getValue())) continue;
            descendants.add(entry.getValue());
        }
        return descendants;
    }

    private void addSourceMapping(String sourcePath, ConfigPoint targetPoint) {
        Set all;
        if (this.sourceToTarget.containsKey(sourcePath)) {
            all = this.sourceToTarget.get(sourcePath);
        } else {
            all = new HashSet();
            this.sourceToTarget.put(sourcePath, all);
        }
        all.add(targetPoint);
    }

    TreeConfig getConfig(String target) {
        return this.targetToEntry.get(target);
    }

    public void clear() {
        this.targetToEntry.clear();
        this.sourceToTarget.clear();
        this.targetToSource.clear();
    }

    public int size() {
        return this.targetToEntry.size();
    }

    static class TreeConfig {
        private final SourceTargetFilter config;

        private TreeConfig(SourceTargetFilter config) {
            this.config = config;
        }

        StartPoint getTargetStartPoint() {
            return new StartPoint(this.config.getTarget());
        }

        StartPoint getSourceStartPoint() {
            return new StartPoint(this.config.getSource());
        }

        Set<EndPoint> getTargetEndPoints() {
            String target = this.config.getTarget();
            if (!this.config.isDeep()) {
                return Collections.singleton(new EndPoint(target + "/"));
            }
            HashSet<EndPoint> endPoints = new HashSet<EndPoint>(this.config.getExcludes().size());
            for (String relPath : this.config.getExcludes()) {
                endPoints.add(new EndPoint(Utils.appendPath(target, relPath)));
            }
            return endPoints;
        }

        Set<EndPoint> getSourceEndPoints() {
            String source = this.config.getSource();
            if (!this.config.isDeep()) {
                return Collections.singleton(new EndPoint(source + "/"));
            }
            HashSet<EndPoint> endPoints = new HashSet<EndPoint>(this.config.getExcludes().size());
            for (String relPath : this.config.getExcludes()) {
                endPoints.add(new EndPoint(Utils.appendPath(source, relPath)));
            }
            return endPoints;
        }

        EndPoint getTargetEndPoint(EndPoint source) {
            String path = source.getPath();
            if (path.startsWith(this.config.getSource())) {
                String relPath = path.substring(this.config.getSource().length());
                if (this.config.getExcludes().contains(relPath)) {
                    return new EndPoint(Utils.appendPath(this.config.getTarget(), relPath));
                }
            }
            return null;
        }

        boolean contains(String targetPath) {
            return this.config.contains(targetPath);
        }
    }

    private static class EndPoint
    extends ConfigPoint {
        private EndPoint(String path) {
            super(path);
        }

        @Override
        boolean isStart() {
            return false;
        }
    }

    private static class StartPoint
    extends ConfigPoint {
        public StartPoint(String path) {
            super(path);
        }

        @Override
        boolean isStart() {
            return true;
        }
    }

    static abstract class ConfigPoint
    implements Comparable<ConfigPoint> {
        private final String path;

        public ConfigPoint(String path) {
            this.path = path;
        }

        public String getPath() {
            return this.path;
        }

        @Override
        public int compareTo(ConfigPoint o) {
            return this.path.compareTo(o.path);
        }

        abstract boolean isStart();

        public int hashCode() {
            return this.getPath().hashCode();
        }

        public boolean equals(Object obj) {
            return obj instanceof ConfigPoint && ((ConfigPoint)obj).isStart() == this.isStart() && this.getPath().equals(((ConfigPoint)obj).getPath());
        }
    }

}