Package org.auraframework.impl.source

Source Code of org.auraframework.impl.source.SourceFactory$LoaderKey

/*
* Copyright (C) 2013 salesforce.com, inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*         http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.auraframework.impl.source;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.auraframework.Aura;
import org.auraframework.adapter.ConfigAdapter;
import org.auraframework.def.DefDescriptor;
import org.auraframework.def.Definition;
import org.auraframework.def.DescriptorFilter;
import org.auraframework.impl.util.AuraUtil;
import org.auraframework.system.PrivilegedNamespaceSourceLoader;
import org.auraframework.system.Source;
import org.auraframework.system.SourceLoader;
import org.auraframework.throwable.AuraRuntimeException;

/**
* Locates source code and produces Source objects that can be used to read that
* code and associated metadata. Source creation is delegated to a SourceLoader
* that has registered to load Source for a particular namespace.
*/
public final class SourceFactory {

    /**
     * Immutable map of namespaces to loaders for this factory to use to load
     * Source.
     */
    private final Map<LoaderKey, SourceLoader> loaders;
    private static final String WILD = "*";

    private final Set<String> namespaces;

    public SourceFactory(Collection<SourceLoader> loaders) {
        Map<LoaderKey, SourceLoader> mutableLoaderMap = new HashMap<>();
        Set<String> mutableNamespaces = new HashSet<>();

        ConfigAdapter configAdapter = Aura.getConfigAdapter();
        for (SourceLoader loader : loaders) {
            for (String namespace : loader.getNamespaces()) {
                mutableNamespaces.add(namespace);
               
                // Track and system/privileged namespaces
                //
                // This code is rather broken, as this now assumes that we build source factories for every
                // loader. It is not fully compatible with having compiled registries, and we now have a hack
                // to make it work.
                //
                if (loader instanceof PrivilegedNamespaceSourceLoader) {
                  PrivilegedNamespaceSourceLoader privilegedLoader = (PrivilegedNamespaceSourceLoader)loader;
                  if (privilegedLoader.isPrivilegedNamespace(namespace)) {
                    configAdapter.addPrivilegedNamespace(namespace);
                  }
                }

                for (String prefix : loader.getPrefixes()) {
                    LoaderKey key = new LoaderKey(namespace, prefix);
                    if (mutableLoaderMap.containsKey(key)) {
                        throw new AuraRuntimeException(String.format(
                                "Namespace/Prefix combination %s claimed by 2 SourceLoaders : %s and %s", key
                                        .toString(), mutableLoaderMap.get(key).getClass().getName(), loader.getClass()
                                        .getName()));
                    }

                    mutableLoaderMap.put(key, loader);
                }
            }
        }
       
        this.namespaces = AuraUtil.immutableSet(mutableNamespaces);
        this.loaders = AuraUtil.immutableMap(mutableLoaderMap);
    }

    public Set<String> getNamespaces() {
        return namespaces;
    }

    public <D extends Definition> Source<D> getSource(DefDescriptor<D> descriptor) {
        LoaderKey key = new LoaderKey(descriptor.getNamespace(), descriptor.getPrefix());
        SourceLoader loader = loaders.get(key);
        if (loader == null) {
            return null;
        }
        return loader.getSource(descriptor);
    }

    @SuppressWarnings("unchecked")
    public <T extends Definition> Set<DefDescriptor<T>> find(DefDescriptor<T> matcher) {

        String namespace = matcher.getNamespace();
        Class<T> primaryInterface = (Class<T>) matcher.getDefType().getPrimaryInterface();
        if (WILD.equals(namespace)) {
            Set<DefDescriptor<T>> ret = new HashSet<DefDescriptor<T>>();
            for (String ns : namespaces) {
                ret.addAll(find(primaryInterface, matcher.getPrefix(), ns));
            }
            return ret;
        } else {
            return find(primaryInterface, matcher.getPrefix(), namespace);
        }
    }

    public Set<DefDescriptor<?>> find(DescriptorFilter matcher) {
        Set<DefDescriptor<?>> ret = new HashSet<DefDescriptor<?>>();

        for (Map.Entry<LoaderKey, SourceLoader> entry : this.loaders.entrySet()) {
            if (matcher.matchPrefix(entry.getKey().getPrefix())
                    && matcher.matchNamespace(entry.getKey().getNamespace())) {
                ret.addAll(entry.getValue().find(matcher));
            }
        }
        return ret;
    }

    private <T extends Definition> Set<DefDescriptor<T>> find(Class<T> primaryInterface, String prefix, String namespace) {
        LoaderKey key = new LoaderKey(namespace, prefix);
        SourceLoader loader = loaders.get(key);
        if (loader == null) {
            throw new AuraRuntimeException(String.format("Loader not found for %s", key));
        }
        return loader.find(primaryInterface, prefix, namespace);
    }

    private static class LoaderKey {
        private final String namespace;
        private final String prefix;
        private final int hashCode;

        private LoaderKey(String namespace, String prefix) {
            this.namespace = namespace;
            this.prefix = prefix;
            this.hashCode = AuraUtil.hashCode(namespace != null ? namespace.toLowerCase() : null, prefix.toLowerCase());
        }

        /**
         * @see java.lang.Object#hashCode()
         */
        @Override
        public int hashCode() {
            return hashCode;
        }

        /**
         * @see java.lang.Object#equals(java.lang.Object)
         */
        @Override
        public boolean equals(Object obj) {
            if (obj instanceof LoaderKey) {
                LoaderKey l = (LoaderKey) obj;
                if (prefix.equalsIgnoreCase(l.prefix) && l.namespace != null) {
                    return l.namespace.equalsIgnoreCase(namespace);
                }

            }
            return false;
        }

        /**
         * @see java.lang.Object#toString()
         */
        @Override
        public String toString() {
            return prefix + "://" + namespace;
        }

        /**
         * Gets the namespace for this instance.
         *
         * @return The namespace.
         */
        public String getNamespace() {
            return this.namespace;
        }

        /**
         * Gets the prefix for this instance.
         *
         * @return The prefix.
         */
        public String getPrefix() {
            return this.prefix;
        }
    }

}
TOP

Related Classes of org.auraframework.impl.source.SourceFactory$LoaderKey

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.