org.apache.flex.compiler.internal.css.CSSManager.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.flex.compiler.internal.css.CSSManager.java

Source

/*
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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.apache.flex.compiler.internal.css;

import static org.apache.flex.compiler.internal.css.semantics.CSSSemanticAnalyzer.*;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.io.FilenameUtils;

import org.apache.flex.compiler.config.Configuration;
import org.apache.flex.compiler.css.ICSSDocument;
import org.apache.flex.compiler.css.ICSSManager;
import org.apache.flex.compiler.css.ICSSRule;
import org.apache.flex.compiler.definitions.IClassDefinition;
import org.apache.flex.compiler.definitions.IDefinition;
import org.apache.flex.compiler.filespecs.IFileSpecification;
import org.apache.flex.compiler.internal.caches.CSSDocumentCache;
import org.apache.flex.compiler.internal.caches.CacheStoreKeyBase;
import org.apache.flex.compiler.internal.css.codegen.CSSCompilationSession;
import org.apache.flex.compiler.internal.projects.FlexProject;
import org.apache.flex.compiler.internal.scopes.ASProjectScope;
import org.apache.flex.compiler.internal.units.EmbedCompilationUnit;
import org.apache.flex.compiler.problems.CSSUnresolvedClassReferenceProblem;
import org.apache.flex.compiler.problems.ICompilerProblem;
import org.apache.flex.compiler.units.ICompilationUnit;
import org.apache.flex.swc.ISWC;
import org.apache.flex.swc.ISWCManager;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

/**
 * Project-level CSS manager.
 */
public class CSSManager implements ICSSManager {

    /**
     * Find all the dependency class definitions and compilation units
     * introduced by the given CSS rules. This method is basically an
     * aggregation of {@link CSSSemanticAnalyzer#resolveDependencies()}.
     * 
     * @param session CSS compilation session that stores resolved embed
     * compilation units.
     * @param flexProject Flex project.
     * @param cssRules Resolve class dependencies in these CSS rules.
     * @param problems Problem collection.
     */
    static void getClassDefinitionDependencies(final CSSCompilationSession session, final FlexProject flexProject,
            final ImmutableSet<ICSSRule> cssRules, final Set<IClassDefinition> classReferences,
            final Set<EmbedCompilationUnit> embedCompilationUnits, final Collection<ICompilerProblem> problems) {
        for (final ICSSRule matchedRule : cssRules) {
            resolveDependencies(session.resolvedEmbedProperties, matchedRule, flexProject, classReferences,
                    embedCompilationUnits, problems);
        }
    }

    /**
     * Find compilation units for the given definition set. A definition might
     * not have a compilation unit, but a compiler problem must already be
     * logged for it in {@code problems} before this method is called.
     * 
     * @param flexProject Flex project.
     * @param classDefinitions Class definitions.
     * @param problems Problems collection.
     * @return A set of compilation unit for the given class definitions.
     */
    static ImmutableSet<ICompilationUnit> getCompilationUnitsForDefinitions(final FlexProject flexProject,
            final Set<IClassDefinition> classDefinitions, final Collection<ICompilerProblem> problems) {
        final ImmutableSet.Builder<ICompilationUnit> builder = new ImmutableSet.Builder<ICompilationUnit>();
        for (final IClassDefinition classDefinition : classDefinitions) {
            final ASProjectScope scope = flexProject.getScope();
            final ICompilationUnit compilationUnit = scope.getCompilationUnitForDefinition(classDefinition);
            if (compilationUnit != null)
                builder.add(compilationUnit);
            else
                assert problemCreatedForUnresolvedClassReference(problems,
                        classDefinition) : "Can't find compilation unit for class '"
                                + classDefinition.getQualifiedName()
                                + "'. Expected a 'CSSUnresolvedClassReference'.";
        }
        return builder.build();
    }

    /**
     * Check that a {@link CSSUnresolvedClassReferenceProblem} problem is created for
     * the given class definition.
     * 
     * @param problems Problems collection.
     * @param classDefinition {@link IClassDefinition} definition of the unresolved class.
     * @return True if there's a problem for the unresolved class definition.
     */
    static boolean problemCreatedForUnresolvedClassReference(final Collection<ICompilerProblem> problems,
            final IClassDefinition classDefinition) {
        for (final ICompilerProblem problem : problems) {
            if (problem instanceof CSSUnresolvedClassReferenceProblem) {
                final CSSUnresolvedClassReferenceProblem unresolved = (CSSUnresolvedClassReferenceProblem) problem;
                if (unresolved.qname.equals(classDefinition.getQualifiedName()))
                    return true;
            }
        }
        return false;
    }

    /** Owner project. */
    private final FlexProject flexProject;

    /**
     * Initialize a CSS manager.
     * 
     * @param flexProject Owner project.
     */
    public CSSManager(final FlexProject flexProject) {
        assert flexProject != null;
        this.flexProject = flexProject;
    }

    @Override
    public Collection<ICSSDocument> getCSSFromStyleModules() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Collection<ICSSDocument> getCSSFromSWCDefaultStyle() {
        final Collection<ICSSDocument> result = new ArrayList<ICSSDocument>();
        for (final ISWC swc : flexProject.getLibraries()) {
            final ICSSDocument css = getDefaultCSS(swc.getSWCFile());
            if (css != null)
                result.add(css);
        }
        return result;
    }

    @Override
    public ICSSDocument getDefaultCSS(final File swcFile) {
        final ISWCManager swcManager = flexProject.getWorkspace().getSWCManager();
        final CSSDocumentCache cache = swcManager.getCSSDocumentCache();
        final ISWC swc = swcManager.get(swcFile);
        return cache.getDefaultsCSS(swc, flexProject.getCompatibilityVersion());
    }

    @Override
    public Collection<ICompilationUnit> getDependentCompilationUnitsFromCSS(final CSSCompilationSession session,
            final ICSSDocument cssDocument, final Collection<IDefinition> definitions,
            final Collection<ICompilerProblem> problems) {
        assert cssDocument != null : "Expected CSS document to get CSS dependencies.";
        assert definitions != null : "Expected a set of definitions to activate CSS rules.";
        assert problems != null : "Expected problems collection. Do not ignore problems.";

        final ImmutableSet<String> qnames = buildQNameToDefinitionMap(getClassDefinitionSet(definitions)).keySet();

        // IFilter (ICSSRule[], IClassDefinition[]) -> (ICSSRule[] applies to IClassDefinition[])
        final ImmutableSet<ICSSRule> matchedRules = getMatchedRules(session, flexProject, cssDocument, qnames,
                problems);

        // Find IClassDefinition(ClassReference) and CompilationUnit(Embed) from the matched ICSSRule[] 
        final Set<IClassDefinition> classReferences = new HashSet<IClassDefinition>();
        final Set<EmbedCompilationUnit> embedCompilationUnits = new HashSet<EmbedCompilationUnit>();
        getClassDefinitionDependencies(session, flexProject, matchedRules, classReferences, // output
                embedCompilationUnits, // output
                problems);

        // Find ICompilationUnit[] for IClassDefinition(ClassReference)[]
        final ImmutableSet<ICompilationUnit> classReferenceCompilationUnits = getCompilationUnitsForDefinitions(
                flexProject, classReferences, problems);

        // Only "activated" rules are included in code generation.
        for (final ICSSRule rule : matchedRules) {
            session.activatedRules.add(rule);
        }

        // Compilation units from ClassReference() and Embed().
        return new ImmutableSet.Builder<ICompilationUnit>().addAll(classReferenceCompilationUnits)
                .addAll(embedCompilationUnits).build();
    }

    @Override
    public Collection<ICSSDocument> getCSSFromThemes(final Collection<ICompilerProblem> problems) {
        final ImmutableList.Builder<ICSSDocument> builder = new ImmutableList.Builder<ICSSDocument>();
        final ISWCManager swcManager = flexProject.getWorkspace().getSWCManager();
        final CSSDocumentCache cssCache = swcManager.getCSSDocumentCache();
        for (final IFileSpecification themeFile : flexProject.getThemeFiles()) {
            try {
                final ICSSDocument css;
                final String extension = FilenameUtils.getExtension(themeFile.getPath());
                if ("swc".equalsIgnoreCase(extension)) {
                    final ISWC swc = swcManager.get(new File(themeFile.getPath()));
                    css = cssCache.getDefaultsCSS(swc, flexProject.getCompatibilityVersion());
                } else if ("css".equalsIgnoreCase(extension)) {
                    final CacheStoreKeyBase key = CSSDocumentCache.createKey(themeFile.getPath());
                    css = cssCache.get(key);
                } else {
                    continue;
                }

                // Ignore theme file without a defaults CSS.
                if (css != null && css != CSSDocumentCache.EMPTY_CSS_DOCUMENT)
                    builder.add(css);
            } catch (CSSDocumentCache.ProblemParsingCSSRuntimeException cssError) {
                problems.addAll(cssError.cssParserProblems);
            }

        }
        return builder.build();
    }

    @Override
    public boolean isFlex3CSS() {
        final Integer compatibilityVersion = flexProject.getCompatibilityVersion();
        if (compatibilityVersion == null)
            return false;
        else if (compatibilityVersion > Configuration.MXML_VERSION_3_0)
            return false;
        else
            return true;
    }

    @Override
    public ICSSDocument getCSS(String cssFilename) {
        final CSSDocumentCache cache = flexProject.getWorkspace().getSWCManager().getCSSDocumentCache();
        final CacheStoreKeyBase key = CSSDocumentCache.createKey(cssFilename);
        final ICSSDocument css = cache.get(key);

        if (CSSDocumentCache.EMPTY_CSS_DOCUMENT == css)
            return null;
        else
            return css;
    }
}