LibraryCacheImpl.java 10 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  org.apache.jackrabbit.util.Text
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.granite.ui.clientlibs.impl;

import com.adobe.granite.ui.clientlibs.ClientLibrary;
import com.adobe.granite.ui.clientlibs.impl.ClientLibraryImpl;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.apache.jackrabbit.util.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LibraryCacheImpl {
    private static final Logger log = LoggerFactory.getLogger(LibraryCacheImpl.class);
    private static final Comparator<String> REV_PATH_COMPARATOR = new Comparator<String>(){

        @Override
        public int compare(String o1, String o2) {
            char[] ca2;
            char[] ca1 = o2.toCharArray();
            int n = ca1.length < (ca2 = o1.toCharArray()).length ? ca1.length : ca2.length;
            for (int i = 0; i < n; ++i) {
                if (ca1[i] == ca2[i]) continue;
                char c1 = ca1[i];
                char c2 = ca2[i];
                if (c1 == '/') {
                    c1 = '\u0001';
                } else if (c2 == '/') {
                    c2 = '\u0001';
                }
                return c1 - c2;
            }
            return ca1.length - ca2.length;
        }
    };
    private final Map<String, Map<String, ClientLibraryImpl>> libsByCategory = new TreeMap<String, Map<String, ClientLibraryImpl>>();
    private final Map<String, Set<String>> embeddersByCategory = new TreeMap<String, Set<String>>();
    private final Map<String, ClientLibraryImpl> libsByPath = new TreeMap<String, ClientLibraryImpl>();
    private final Map<String, Set<String>> libsPathsBySource = new HashMap<String, Set<String>>();
    private final Set<String> ancestorPaths = new HashSet<String>();

    public void clear() {
        this.libsByCategory.clear();
        this.libsByPath.clear();
        this.libsPathsBySource.clear();
        this.ancestorPaths.clear();
        this.embeddersByCategory.clear();
    }

    public ClientLibraryImpl getLibrary(String path) {
        return this.libsByPath.get(path);
    }

    public Map<String, ClientLibrary> getLibraries() {
        TreeMap<String, ClientLibraryImpl> libs = new TreeMap<String, ClientLibraryImpl>();
        for (ClientLibraryImpl lib2 : this.libsByPath.values()) {
            libs.put(lib2.getPath(), lib2.createCopy());
        }
        for (ClientLibraryImpl lib2 : libs.values()) {
            lib2.relink(libs);
        }
        return new TreeMap<String, ClientLibrary>((Map<String, ClientLibrary>)libs);
    }

    public boolean isAncestor(String path) {
        return this.ancestorPaths.contains(path);
    }

    public Set<String> getLibsPathsFromSource(String path) {
        return this.libsPathsBySource.get(path);
    }

    public ClientLibrary getClosesLib(String path) {
        while (path.length() > 1) {
            ClientLibrary lib = this.libsByPath.get(path);
            if (lib != null) {
                return lib;
            }
            path = Text.getRelativeParent((String)path, (int)1);
        }
        return null;
    }

    public Map<String, ClientLibraryImpl> getLibsByCategory(String[] categories, Set<String> notFound) {
        LinkedHashMap<String, ClientLibraryImpl> entries = new LinkedHashMap<String, ClientLibraryImpl>();
        for (String category : categories) {
            Map<String, ClientLibraryImpl> libs = this.libsByCategory.get(category);
            if (libs != null) {
                for (ClientLibraryImpl e : libs.values()) {
                    if (entries.containsKey(e.getPath())) continue;
                    entries.put(e.getPath(), e);
                }
                continue;
            }
            if (notFound == null) continue;
            notFound.add(category);
        }
        return entries;
    }

    public Map<String, ClientLibraryImpl> getEmbeddersByCategory(String[] categories, Set<String> notFound) {
        LinkedHashMap<String, ClientLibraryImpl> entries = new LinkedHashMap<String, ClientLibraryImpl>();
        for (String category : categories) {
            Set<String> embedders = this.embeddersByCategory.get(category);
            if (embedders == null || embedders.isEmpty()) continue;
            entries.putAll(this.getLibsByCategory(embedders.toArray(new String[embedders.size()]), notFound));
        }
        return entries;
    }

    public void rebuildAncestorPaths() {
        this.ancestorPaths.clear();
        Iterator<String> i$ = this.libsByPath.keySet().iterator();
        while (i$.hasNext()) {
            String p = i$.next();
            p = Text.getRelativeParent((String)p, (int)1);
            while (p.length() > 1) {
                this.ancestorPaths.add(p);
                p = Text.getRelativeParent((String)p, (int)1);
            }
        }
        log.info("Rebuilt {} ancestor paths", (Object)this.ancestorPaths.size());
        if (log.isDebugEnabled()) {
            for (String p : this.ancestorPaths) {
                log.debug("- {}", (Object)p);
            }
        }
    }

    public void addSourcePaths(ClientLibraryImpl lib) {
        String path = lib.getPath();
        for (String depPath : lib.getSourcePaths()) {
            Set<String> depEntry = this.libsPathsBySource.get(depPath);
            if (depEntry == null) {
                depEntry = new HashSet<String>();
                this.libsPathsBySource.put(depPath, depEntry);
            }
            depEntry.add(path);
        }
    }

    public void removeSourcePaths(ClientLibraryImpl lib) {
        String path = lib.getPath();
        for (String depPath : lib.getSourcePaths()) {
            Set<String> depSet = this.libsPathsBySource.get(depPath);
            if (depSet == null) continue;
            depSet.remove(path);
        }
    }

    public void add(ClientLibraryImpl lib) {
        this.libsByPath.put(lib.getPath(), lib);
        this.addSourcePaths(lib);
        for (String category : lib.getCategories()) {
            log.debug("assigned category {}", (Object)category);
            Map<String, ClientLibraryImpl> libs = this.libsByCategory.get(category);
            if (libs == null) {
                libs = new TreeMap<String, ClientLibraryImpl>(REV_PATH_COMPARATOR);
                this.libsByCategory.put(category, libs);
            }
            libs.put(lib.getPath(), lib);
        }
    }

    public void remove(String path) {
        ClientLibraryImpl e = this.libsByPath.remove(path);
        if (e != null) {
            log.info("Invalidating library {}", (Object)path);
            for (String tag : e.getCategories()) {
                Map<String, ClientLibraryImpl> libs = this.libsByCategory.get(tag);
                if (libs == null) continue;
                libs.remove(path);
            }
            this.removeSourcePaths(e);
        }
    }

    public void resolveLibraries() {
        for (ClientLibraryImpl lib : this.libsByPath.values()) {
            lib.clear();
        }
        HashSet<String> processed = new HashSet<String>();
        LinkedList<String> paths = new LinkedList<String>(this.libsByPath.keySet());
        while (!paths.isEmpty()) {
            this.resolveLib(processed, paths.remove(0));
        }
    }

    private ClientLibraryImpl resolveLib(Set<String> processed, String path) {
        ClientLibraryImpl lib = this.libsByPath.get(path);
        if (lib != null && !processed.contains(path)) {
            processed.add(path);
            HashSet<String> notFound = new HashSet<String>();
            for (String depPath : this.getLibsByCategory(lib.getDependentCategories(), notFound).keySet()) {
                ClientLibraryImpl dep = this.resolveLib(processed, depPath);
                if (dep == null) continue;
                lib.addDependency(dep);
            }
            if (notFound.size() > 0) {
                log.warn("Library {} specified dependencies that could not be resolved: {}", (Object)lib.getPath(), (Object)Text.implode((String[])notFound.toArray(new String[notFound.size()]), (String)","));
            }
            notFound.clear();
            LinkedHashMap<String, ClientLibraryImpl> embedded = new LinkedHashMap<String, ClientLibraryImpl>();
            for (String depPath2 : this.getLibsByCategory(lib.getEmbeddedCategories(), notFound).keySet()) {
                ClientLibraryImpl dep = this.resolveLib(processed, depPath2);
                if (dep == null) continue;
                embedded.put(dep.getPath(), dep);
            }
            if (notFound.size() > 0) {
                log.warn("Library {} specified embedded that could not be resolved: {}", (Object)lib.getPath(), (Object)Text.implode((String[])notFound.toArray(new String[notFound.size()]), (String)","));
            }
            for (String cat : lib.getEmbeddedCategories()) {
                Set<String> embedders = this.embeddersByCategory.get(cat);
                if (embedders == null) {
                    embedders = new HashSet<String>();
                    this.embeddersByCategory.put(cat, embedders);
                }
                embedders.addAll(Arrays.asList(lib.getCategories()));
            }
            while (!embedded.isEmpty()) {
                this.addEmbedded(lib, embedded, (String)embedded.keySet().iterator().next());
            }
        }
        return lib;
    }

    private void addEmbedded(ClientLibraryImpl lib, Map<String, ClientLibraryImpl> embeddeds, String path) {
        ClientLibraryImpl emb = embeddeds.remove(path);
        if (emb != null) {
            for (String depPath : emb.getDependencies(false).keySet()) {
                this.addEmbedded(lib, embeddeds, depPath);
            }
            lib.addEmbedded(emb);
        }
    }

    public void logStatus() {
        log.info("Cache contains {} libraries, sourced from {} files.", (Object)this.libsByPath.size(), (Object)this.libsPathsBySource.size());
    }

}