You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by an...@apache.org on 2012/03/21 20:33:47 UTC

svn commit: r1303525 [3/3] - in /myfaces/trinidad/trunk: src/site/xdoc/devguide/ trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/ trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ trinidad-api/src/main/xrts/org/apache/myfaces/...

Added: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/DirectionFilteringVariantExtractor.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/DirectionFilteringVariantExtractor.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/DirectionFilteringVariantExtractor.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/DirectionFilteringVariantExtractor.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,72 @@
+/*
+ * 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.myfaces.trinidadinternal.skin.pregen.variant;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.myfaces.trinidad.context.LocaleContext;
+import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetNode;
+
+/**
+ * A SkinVariantExtractor that filters LocaleContexts based on reading direction
+ */
+final class DirectionFilteringVariantExtractor implements SkinVariantExtractor<LocaleContext>
+{
+  /**
+   * Creates a filtering variant extractor.
+   * @param wrapped the LocaleContext variant extractor to filter
+   * @param rtlOnly if true, getVariants() only returns rtl LocaleContexts.
+   *        Otherwise, only ltr LocaleContexts are returned.
+   */
+  DirectionFilteringVariantExtractor(
+    SkinVariantExtractor<LocaleContext> wrapped,
+    boolean rtlOnly
+    )
+  {
+    _wrapped = wrapped;
+    _rtlOnly = rtlOnly;
+  }
+
+  @Override
+  public List<LocaleContext> getVariants()
+  {
+    List<LocaleContext> locales = _wrapped.getVariants();
+    List<LocaleContext> filteredLocales = new ArrayList<LocaleContext>(locales.size());
+      
+    for (LocaleContext locale : locales)
+    {
+      if (locale.isRightToLeft() == _rtlOnly)
+      {
+        filteredLocales.add(locale);
+      }
+    }
+      
+    return filteredLocales;
+  }
+
+  @Override
+  public void visit(StyleSheetNode styleSheet)
+  {
+    _wrapped.visit(styleSheet);
+  }
+    
+  private final SkinVariantExtractor<LocaleContext> _wrapped;
+  private final boolean _rtlOnly;
+}

Added: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/FixedVariantExtractor.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/FixedVariantExtractor.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/FixedVariantExtractor.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/FixedVariantExtractor.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,81 @@
+/*
+ * 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.myfaces.trinidadinternal.skin.pregen.variant;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetNode;
+
+/**
+ * Trivial SkinVariantExtractor implementation that returns a fixed
+ * value.
+ * 
+ * Used by SkinVariants in cases where the variants to pregenerate
+ * are explicitly configured.
+ */
+final class FixedVariantExtractor <T> implements SkinVariantExtractor
+{
+
+  /**
+   * Returns a SkinVariantExtractor for single value.
+   * 
+   * @param defaultValue the value that the created SkinVariantExtractor
+   *   will return from getVariants().
+   */
+  public static <T> SkinVariantExtractor<T> extractor(T defaultValue)
+  {
+    return new FixedVariantExtractor<T>(Arrays.asList(defaultValue));
+  }
+
+  /**
+   * Returns a SkinVariantExtractor for a collection of values.
+   *
+   * @param values the values that the created SkinVariantExtractor
+   *   will return from getVariants.
+   */
+  public static <T> SkinVariantExtractor<T> extractor(Collection<T> values)
+  {
+    return new FixedVariantExtractor<T>(new ArrayList<T>(values));
+  }
+
+  @Override
+  public List<T> getVariants()
+  {
+    return _values;
+  }
+
+  @Override
+  public void visit(StyleSheetNode styleSheet)
+  {
+    // This is a no-op since we're just going to return the fixed
+    // set of values that was passed into the constructor.
+  }
+
+  private FixedVariantExtractor(
+    List<T> values)
+  {
+    _values = Collections.unmodifiableList(values);
+  }
+  
+  private final List<T> _values;
+}

Added: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/LocaleVariantExtractor.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/LocaleVariantExtractor.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/LocaleVariantExtractor.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/LocaleVariantExtractor.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,106 @@
+/*
+ * 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.myfaces.trinidadinternal.skin.pregen.variant;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Locale;
+import java.util.TreeSet;
+
+import org.apache.myfaces.trinidad.context.LocaleContext;
+import org.apache.myfaces.trinidadinternal.share.nls.LocaleContextImpl;
+import org.apache.myfaces.trinidadinternal.share.nls.NullLocaleContext;
+import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetNode;
+
+/**
+ * An @-rule processor for extracting @locale rule metadata.
+ */
+final class LocaleVariantExtractor implements SkinVariantExtractor<LocaleContext>
+{
+  public LocaleVariantExtractor()
+  {
+    _locales = new TreeSet<Locale>(_LOCALE_COMPARATOR);
+  }
+  
+  @Override
+  public void visit(StyleSheetNode node)
+  {
+    Collection<Locale> nodeLocales = node.getLocales();
+    
+    for (Locale locale : nodeLocales)
+    {
+      _locales.add(locale);
+    }    
+  }
+
+  /**
+   * Returns a list containing LocaleContexts corresponding
+   * to all processed @locale rules.
+   */
+  public List<LocaleContext> getVariants()
+  {
+    List<LocaleContext> localeContexts = _toLocaleContexts(_locales);
+    return localeContexts;
+  }
+
+  // Converts from Locale to LocaleContext, from Collection -> List, and
+  // adds in entries for null locales.
+  private static List<LocaleContext> _toLocaleContexts(Collection<Locale> locales)
+  {
+    int size = locales.size() + 2;
+    List<LocaleContext> localeContexts = new ArrayList<LocaleContext>(size);
+    _addNullLocaleContexts(localeContexts);
+    _addLocaleContexts(localeContexts, locales);
+    
+    return localeContexts;
+  }
+
+  private static void _addNullLocaleContexts(Collection<LocaleContext> localeContexts)
+  {
+    localeContexts.add(NullLocaleContext.getLeftToRightContext());
+    localeContexts.add(NullLocaleContext.getRightToLeftContext());
+  }
+  
+  private static void _addLocaleContexts(
+    Collection<LocaleContext> localeContexts,
+    Collection<Locale>        locales
+    )
+  {
+    for (Locale locale : locales)
+    {
+      localeContexts.add(new LocaleContextImpl(locale));
+    }
+  }
+
+  private static final class LocaleComparator implements Comparator<Locale>
+  {
+    @Override
+    public int compare(Locale locale1, Locale locale2)
+    {
+      return locale1.toString().compareTo(locale2.toString());
+    }
+  }
+
+  private final Collection<Locale> _locales;
+
+  private static final Comparator<Locale> _LOCALE_COMPARATOR = new LocaleComparator();
+}

Added: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/PlatformVariantExtractor.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/PlatformVariantExtractor.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/PlatformVariantExtractor.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/PlatformVariantExtractor.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,95 @@
+/*
+ * 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.myfaces.trinidadinternal.skin.pregen.variant;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.myfaces.trinidadinternal.agent.TrinidadAgent;
+import org.apache.myfaces.trinidadinternal.style.util.NameUtils;
+import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetNode;
+
+ /**
+  * An @-rule processor for extracting @platform rule metadata.
+  */
+final class PlatformVariantExtractor implements SkinVariantExtractor<Integer>
+{
+   public PlatformVariantExtractor()
+   {
+     _platforms = new HashSet<Integer>();
+   }
+
+   @Override
+   public void visit(StyleSheetNode node)
+   {
+     Collection<Integer> nodePlatforms = node.getPlatforms();
+     
+     for (Integer platform : nodePlatforms)
+     {
+       _platforms.add(platform);
+     }     
+   }
+
+  /**
+   * Returns a list containing platforms corresponding
+   * to all processed @platform rules.
+   */
+  public List<Integer> getVariants()
+  {
+    ArrayList<Integer> platforms = new ArrayList<Integer>(_platforms.size() + 1);
+
+    // The "unknown" platform shouldn't be found by the document search,
+    // but does need to be included during pregeneration.    
+    if (!_platforms.contains(TrinidadAgent.OS_UNKNOWN))
+    {
+      platforms.add(TrinidadAgent.OS_UNKNOWN);      
+    }
+    
+    platforms.addAll(_platforms);
+
+    // Sort by name to make logger output/progress easier to monitor    
+    _sortByPlatformName(platforms);
+
+    return platforms;
+  }
+  
+  private static void _sortByPlatformName(List<Integer> platforms)
+  {
+    Collections.sort(platforms,
+      new Comparator<Integer>() {
+        @Override
+        public int compare(Integer platform1, Integer platform2)
+        {
+          String name1 = NameUtils.getPlatformName(platform1);
+          String name2 = NameUtils.getPlatformName(platform2);
+          assert(name1 != null);
+          assert(name2 != null);
+          
+          return name1.compareTo(name2);
+        }
+      });
+  }
+
+  private final Collection<Integer> _platforms;
+}

Added: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/SkinVariant.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/SkinVariant.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/SkinVariant.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/SkinVariant.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,98 @@
+/*
+ * 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.myfaces.trinidadinternal.skin.pregen.variant;
+
+import org.apache.myfaces.trinidad.context.AccessibilityProfile;
+import org.apache.myfaces.trinidad.context.LocaleContext;
+
+import org.apache.myfaces.trinidadinternal.skin.pregen.config.PregenConfig.ContainerType;
+import org.apache.myfaces.trinidadinternal.skin.pregen.config.PregenConfig.RequestType;
+import org.apache.myfaces.trinidadinternal.skin.pregen.config.PregenConfig.StyleClassType;
+
+/**
+ * Represents a single unique combination of variants/properties that
+ * influence which styles are selected/included during skin generation.
+ */
+public final class SkinVariant
+{
+  /**
+   * Creates a unique skin variant.
+   */
+  public SkinVariant(
+    LocaleContext         localeContext,
+    int                   platform,
+    ApplicationAndVersion appAndVersion,
+    AccessibilityProfile  accProfile,
+    ContainerType         containerType,
+    RequestType           requestType,
+    StyleClassType        styleClassType
+    )
+  {
+    _localeContext = localeContext;
+    _platform = platform;
+    _appAndVersion = appAndVersion;
+    _accProfile = accProfile;
+    _containerType = containerType;
+    _requestType = requestType;
+    _styleClassType = styleClassType;
+  }
+  
+  public LocaleContext getLocaleContext()
+  {
+    return _localeContext;
+  }
+  
+  public int getPlatform()
+  {
+    return _platform;
+  }
+
+  public ApplicationAndVersion getApplicationAndVersion()
+  {
+     return _appAndVersion;
+  }
+  
+  public AccessibilityProfile getAccessibilityProfile()
+  {
+    return _accProfile;
+  }
+  
+  public ContainerType getContainerType()
+  {
+    return _containerType;
+  }
+  
+  public RequestType getRequestType()
+  {
+    return _requestType;
+  }
+  
+  public StyleClassType getStyleClassType()
+  {
+    return _styleClassType;
+  }
+
+  private final LocaleContext         _localeContext;
+  private final int                   _platform;
+  private final ApplicationAndVersion _appAndVersion;
+  private final AccessibilityProfile  _accProfile;
+  private final ContainerType         _containerType;
+  private final RequestType           _requestType;
+  private final StyleClassType        _styleClassType;
+}

Added: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/SkinVariantExtractor.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/SkinVariantExtractor.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/SkinVariantExtractor.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/SkinVariantExtractor.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,42 @@
+/*
+ * 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.myfaces.trinidadinternal.skin.pregen.variant;
+
+import java.util.List;
+
+import org.apache.myfaces.trinidadinternal.style.util.StyleSheetVisitUtils.StyleSheetVisitor;
+
+/**
+ * StyleSheetVisitor that is used to extract variant (eg. @-rule)
+ * metadata from a skin style sheet document.
+ * 
+ * SkinVariantExtractors are typically single use - ie. they are 
+ * used for a single call to StyleSheetVisitUtils.visitStyleSheets(),
+ * after which visited variants are retrieved via a call to getVariants().
+ *
+ * @see org.apache.myfaces.trinidadinternal.style.util.StyleSheetVisitUtils
+ */
+interface SkinVariantExtractor <T> extends StyleSheetVisitor
+{
+  /**
+   * Called after the style sheet visit to retrieve the variants
+   * that were seen.
+   */
+  public List<T> getVariants();
+}

Added: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/SkinVariants.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/SkinVariants.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/SkinVariants.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/SkinVariants.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,289 @@
+/*
+ * 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.myfaces.trinidadinternal.skin.pregen.variant;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+
+import java.util.List;
+
+import java.util.NoSuchElementException;
+
+import org.apache.myfaces.trinidad.context.AccessibilityProfile;
+import org.apache.myfaces.trinidad.context.LocaleContext;
+import org.apache.myfaces.trinidadinternal.agent.TrinidadAgent;
+import org.apache.myfaces.trinidadinternal.agent.TrinidadAgent.Application;
+import org.apache.myfaces.trinidadinternal.share.nls.NullLocaleContext;
+import org.apache.myfaces.trinidadinternal.skin.pregen.config.PregenConfig;
+import org.apache.myfaces.trinidadinternal.skin.pregen.config.PregenConfig.ContainerType;
+import org.apache.myfaces.trinidadinternal.skin.pregen.config.PregenConfig.RequestType;
+import org.apache.myfaces.trinidadinternal.skin.pregen.config.PregenConfig.StyleClassType;
+import org.apache.myfaces.trinidadinternal.style.util.StyleSheetVisitUtils;
+import org.apache.myfaces.trinidadinternal.style.util.StyleSheetVisitUtils.StyleSheetVisitor;
+import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetDocument;
+import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetNode;
+import org.apache.myfaces.trinidadinternal.util.nls.LocaleUtils;
+
+/**
+ * Produces the unique combinations of variants for a skin.  These variants
+ * are exposed via iteration - ie. clients interact with this class as an 
+ * Iterable.
+ */
+public final class SkinVariants implements Iterable<SkinVariant>
+{
+  public SkinVariants(
+    StyleSheetDocument document,
+    PregenConfig       config
+    )
+  {
+    SkinVariantExtractor<Integer> platformExtractor = _getPlatformExtractor(config);
+    SkinVariantExtractor<ApplicationAndVersion> agentExtractor = _getAgentExtractor(config);
+    SkinVariantExtractor<LocaleContext> localeExtractor = _getLocaleExtractor(config);    
+    SkinVariantExtractor<AccessibilityProfile> accExtractor = _getAccessibilityExtractor(config);
+    
+    _extractVariants(document,
+                    localeExtractor,
+                    platformExtractor,
+                    agentExtractor,
+                    accExtractor);
+    
+    _localeContexts = localeExtractor.getVariants();
+    _platforms = platformExtractor.getVariants();
+    _appAndVersions = agentExtractor.getVariants();
+    _accProfiles = accExtractor.getVariants();
+
+    _containerTypes = new ArrayList<ContainerType>(config.getContainerTypes());
+    _requestTypes = new ArrayList<RequestType>(config.getRequestTypes());
+    _styleClassTypes = new ArrayList<StyleClassType>(config.getStyleClassTypes());
+  }
+
+  public Iterator<SkinVariant> iterator()
+  {
+    return new VariantsIterator();
+  }
+
+  private SkinVariantExtractor<Integer> _getPlatformExtractor(PregenConfig config)
+  {
+    Collection<Integer> platforms = config.getPlatformVariants();
+    
+    if (platforms == PregenConfig.ALL_VARIANTS)
+    {
+      return new PlatformVariantExtractor();
+    }
+
+    return (platforms.isEmpty()) ?
+      FixedVariantExtractor.extractor(TrinidadAgent.OS_UNKNOWN) :
+      FixedVariantExtractor.extractor(platforms);
+  }
+  
+  private SkinVariantExtractor<ApplicationAndVersion> _getAgentExtractor(PregenConfig config)
+  {
+    Collection<Application> agentApplications = config.getAgentApplicationVariants();
+    
+    if (agentApplications.isEmpty())
+    {
+      return FixedVariantExtractor.extractor(ApplicationAndVersion.UNKNOWN);
+    }
+    
+    if (agentApplications == PregenConfig.ALL_VARIANTS)
+    {
+      agentApplications = null;
+    }
+
+    // We need to go through AgentVariantExtractor even in the case where
+    // PregenConfig provides a fixed set of agents to pregenerate since
+    // wee need to visit style sheets to determine agent versions.
+    return new AgentVariantExtractor(agentApplications);
+  }
+
+  private SkinVariantExtractor<LocaleContext> _getLocaleExtractor(PregenConfig config)
+  {
+    SkinVariantExtractor<LocaleContext> localeExtractor;
+    Collection<LocaleContext> locales = config.getLocaleVariants();
+    
+    if (locales == PregenConfig.ALL_VARIANTS)
+    {
+      localeExtractor = new LocaleVariantExtractor();
+    }
+    else
+    {
+      if (locales.isEmpty())
+      {
+        locales = Arrays.asList(NullLocaleContext.getLeftToRightContext(),
+                                NullLocaleContext.getRightToLeftContext());
+      }
+      
+      localeExtractor = FixedVariantExtractor.extractor(locales);
+    }
+
+    return _filterDirections(localeExtractor, config);
+  }
+
+  private SkinVariantExtractor<LocaleContext> _filterDirections(
+    SkinVariantExtractor<LocaleContext> localeExtractor,
+    PregenConfig                        config
+    )
+  {
+    Collection<Integer> directions = config.getReadingDirectionVariants();
+    
+    if ((directions == PregenConfig.ALL_VARIANTS) || (directions.size() > 1))
+    {
+      return localeExtractor;
+    }
+    
+    boolean rtlOnly = directions.contains(LocaleUtils.DIRECTION_RIGHTTOLEFT);
+
+    return new DirectionFilteringVariantExtractor(localeExtractor, rtlOnly);
+  }
+  
+  private SkinVariantExtractor<AccessibilityProfile> _getAccessibilityExtractor(
+    PregenConfig config
+    )
+  {
+    Collection<AccessibilityProfile> accessibilityProfiles =
+      config.getAccessibilityVariants();
+    
+    if (accessibilityProfiles == PregenConfig.ALL_VARIANTS)
+    {
+      return new AccessibilityVariantExtractor();
+    }
+    
+    return (accessibilityProfiles.isEmpty() ?
+      FixedVariantExtractor.extractor(AccessibilityProfile.getDefaultInstance()) :
+      FixedVariantExtractor.extractor(accessibilityProfiles));
+      
+  }
+
+  private void _extractVariants(
+    StyleSheetDocument      document,
+    StyleSheetVisitor...    visitors
+    )
+  {
+    Collection<StyleSheetNode> styleSheets = document.getStyleSheetsAsCollection();
+    StyleSheetVisitor compoundVisitor = 
+      StyleSheetVisitUtils.compoundStyleSheetVisitor(Arrays.asList(visitors));
+
+    StyleSheetVisitUtils.visitStyleSheets(styleSheets, compoundVisitor);    
+  }
+
+  private class VariantsIterator implements Iterator<SkinVariant>
+  {
+    @Override
+    public boolean hasNext()
+    {
+      return ((_localeIndex < _localeContexts.size())         &&
+               (_platformIndex < _platforms.size())           &&
+               (_appAndVersionIndex < _appAndVersions.size()) &&
+               (_accProfileIndex < _accProfiles.size())       &&
+               (_containerTypeIndex < _containerTypes.size()) &&
+               (_requestTypeIndex < _requestTypes.size())     &&
+               (_styleClassTypeIndex < _styleClassTypes.size()));
+    }
+
+    @Override
+    public SkinVariant next()
+    {
+      SkinVariant variant = _getNextVariant();
+      _nextIndex();
+      
+      return variant;
+    }
+
+    @Override
+    public void remove()
+    {
+      throw new UnsupportedOperationException();
+    }
+    
+    private SkinVariant _getNextVariant()
+    {
+      if (!hasNext())
+      {
+        throw new NoSuchElementException();
+      }
+      
+      return new SkinVariant(_localeContexts.get(_localeIndex),
+                             _platforms.get(_platformIndex),
+                             _appAndVersions.get(_appAndVersionIndex),
+                             _accProfiles.get(_accProfileIndex),
+                             _containerTypes.get(_containerTypeIndex),
+                             _requestTypes.get(_requestTypeIndex),
+                             _styleClassTypes.get(_styleClassTypeIndex));
+    }
+    
+    private void _nextIndex()
+    {
+      _localeIndex++;
+        
+      if (_localeIndex == _localeContexts.size())
+      {
+        _localeIndex = 0;
+        _accProfileIndex++;
+      }
+      
+      if (_accProfileIndex == _accProfiles.size())
+      {
+        _accProfileIndex = 0;
+        _containerTypeIndex++;
+      }
+      
+      if (_containerTypeIndex == _containerTypes.size())
+      {
+        _containerTypeIndex = 0;
+        _requestTypeIndex++;
+      }
+      
+      if (_requestTypeIndex == _requestTypes.size())
+      {
+        _requestTypeIndex = 0;
+        _styleClassTypeIndex++;
+      }
+
+      if (_styleClassTypeIndex == _styleClassTypes.size())
+      {
+        _styleClassTypeIndex = 0;
+        _appAndVersionIndex++;        
+      }
+
+      if (_appAndVersionIndex == _appAndVersions.size())
+      {
+        _appAndVersionIndex = 0;
+        _platformIndex++;
+      }
+    }
+
+    private int _localeIndex = 0;
+    private int _platformIndex = 0;
+    private int _appAndVersionIndex = 0;
+    private int _accProfileIndex = 0;
+    private int _containerTypeIndex = 0;
+    private int _requestTypeIndex = 0;
+    private int _styleClassTypeIndex = 0;
+  }
+
+  private final List<LocaleContext>         _localeContexts;
+  private final List<Integer>               _platforms;
+  private final List<ApplicationAndVersion> _appAndVersions;
+  private final List<AccessibilityProfile>  _accProfiles;
+  private final List<ContainerType>         _containerTypes;
+  private final List<RequestType>           _requestTypes;
+  private final List<StyleClassType>        _styleClassTypes;
+}

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/StyleContext.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/StyleContext.java?rev=1303525&r1=1303524&r2=1303525&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/StyleContext.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/StyleContext.java Wed Mar 21 19:33:45 2012
@@ -59,4 +59,10 @@ public interface StyleContext
    * @return true if the current request is secure (an https request), false otherwise
    */
   public boolean isRequestSecure();
+  
+  /**
+   * Returns a StyleSheetNamingStrategy value that indicates how generated
+   * style sheet files should be named.
+   */
+  public StyleSheetNamingStrategy getNamingStrategy();
 }

Added: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/StyleSheetNamingStrategy.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/StyleSheetNamingStrategy.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/StyleSheetNamingStrategy.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/StyleSheetNamingStrategy.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,77 @@
+/*
+ * 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.myfaces.trinidadinternal.style;
+
+import java.util.Map;
+
+import org.apache.myfaces.trinidad.util.Enums;
+
+/**
+ * Enum used by StyleSheetContext.getStyleSheetNaming() to indicate what
+ * type of names should be used for generated style file names.
+ */
+public enum StyleSheetNamingStrategy
+{
+  /**
+   * Indicates that short names should be used for generated style sheet files.
+   */
+  SHORT("short"),
+  
+  /**
+   * Indicates that stable (possibly longer) names should be used for generated
+   * style sheet files.
+   */
+  STABLE("stable");
+  
+  StyleSheetNamingStrategy(String displayName)
+  {
+    _displayName = displayName;
+  }
+
+  /**
+   * Returns the display name for this enum constant.
+   */
+  public String displayName()
+  {
+    return _displayName;
+  }
+
+  /**
+   * Performs a reverse lookup of an StyleSheetNames constant based on
+   * its display name.
+   * 
+   * @param displayName the display name of the Accessibility constant to return.
+   * @return the non-null Accessibility constant associated with the display name.
+   * @throws IllegalArgumentException if displayName does not correspond
+   *   to some Accessibility constant.
+   * @throws NullPointerException if displayName is null. 
+   */
+  public static StyleSheetNamingStrategy valueOfDisplayName(String displayName)
+  {
+    return Enums.stringToEnum(_displayNameMap, displayName, StyleSheetNamingStrategy.class);
+  }
+
+  private final String _displayName;
+  private static final Map<String, StyleSheetNamingStrategy> _displayNameMap;
+    
+  static
+  {   
+    _displayNameMap = Enums.createDisplayNameMap(StyleSheetNamingStrategy.class);
+  }
+}

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/cache/FileSystemStyleCache.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/cache/FileSystemStyleCache.java?rev=1303525&r1=1303524&r2=1303525&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/cache/FileSystemStyleCache.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/cache/FileSystemStyleCache.java Wed Mar 21 19:33:45 2012
@@ -59,9 +59,11 @@ import org.apache.myfaces.trinidadintern
 import org.apache.myfaces.trinidadinternal.share.expl.Coercions;
 import org.apache.myfaces.trinidadinternal.style.StyleContext;
 import org.apache.myfaces.trinidadinternal.style.StyleProvider;
+import org.apache.myfaces.trinidadinternal.style.StyleSheetNamingStrategy;
 import org.apache.myfaces.trinidadinternal.style.UnmodifiableStyle;
 import org.apache.myfaces.trinidadinternal.style.util.CSSGenerationUtils;
 import org.apache.myfaces.trinidadinternal.style.util.NameUtils;
+import org.apache.myfaces.trinidadinternal.style.util.StableNameUtils;
 import org.apache.myfaces.trinidadinternal.style.util.StyleWriterFactory;
 import org.apache.myfaces.trinidadinternal.style.xml.parse.IconNode;
 import org.apache.myfaces.trinidadinternal.style.xml.parse.PropertyNode;
@@ -250,6 +252,11 @@ public class FileSystemStyleCache implem
     StyleSheetDocument document
     )
   {
+    if (context.getNamingStrategy() == StyleSheetNamingStrategy.STABLE)
+    {
+      return StableNameUtils.getContextName(context, document);
+    }
+    
     StringBuilder buffer = new StringBuilder();
 
     String contextName = NameUtils.getContextName(context, document);
@@ -286,6 +293,50 @@ public class FileSystemStyleCache implem
     return buffer.toString();
   }
 
+  /**
+   * Specifies behavior in the event that the skin is reported
+   * as "dirty".
+   */
+  protected enum ClearOnDirty
+  {
+    /**
+     * Clear the entry cache, but leave other values alone.
+     * Used during skin pregeneration to free up entry cache
+     * memory without forcing skin documents to be reparsed.
+     */
+    ENTRIES,
+    
+    /**
+     * Clear all data.  This is the standard runtime behavior.
+     */
+    ALL;
+  }
+
+  /**
+   * Determines what data to clear when a "dirty" skin is detected - ie.
+   * when StyleContext.isDirty() returns true.
+   * 
+   * Typically when StyleContext reports that the skin has been dirtied, 
+   * we want to release all data, including the entry caches, the style
+   * sheet document, the short style class map, etc...
+   * 
+   * During skin pregeneration, in order to prevent the entry caches from
+   * becoming fully populated, we need to clear these out from time to time.
+   * The skin pregeneration service thus reports dirty == true periodically
+   * while pregeneration is being peformed.  When this occurs, we do not
+   * want to throw out all data - eg. we do not want to be forced to re-parse
+   * the skin document.  Instead, we simply want to clear the entry caches.
+   * This protected hook allows the skin pregeneration service to tune
+   * the dirty handling behavior.
+   * 
+   * @return by default, returns ClearOnDirty.ALL, forcing all data to be
+   *   cleared.
+   */
+  protected ClearOnDirty getClearOnDirty()
+  {
+    return ClearOnDirty.ALL;
+  }
+
   // Returns the current StyleSheetDocument - used by StyleMapImpl only
   StyleSheetDocument __getStyleSheetDocument()
   {
@@ -314,11 +365,19 @@ public class FileSystemStyleCache implem
       {
         _cache = null;
         _entryCache = null;
-        _document = null;
-        _reusableStyleMap = null;
-        _reusableSelectorMap = null;
-        _shortStyleClassMap = null;
-        _namespacePrefixes  = null;
+        
+        if (!isDirty || (getClearOnDirty() == ClearOnDirty.ALL))
+        {
+          _document = null;
+          _reusableStyleMap = null;
+          _reusableSelectorMap = null;
+          _shortStyleClassMap = null;
+          _namespacePrefixes  = null;
+        }
+        else
+        {
+          isDirty = false;
+        }
       }
 
       // We get references to our two caches (the "normal" cache,
@@ -1337,7 +1396,7 @@ public class FileSystemStyleCache implem
     {
       _styleSheets = new StyleSheetNode[styleSheets.length];
       System.arraycopy(styleSheets, 0, _styleSheets, 0, styleSheets.length);
-      _short = true;
+      _short = !context.isDisableStyleCompression();
       _portlet = context.isPortletMode();
       _secureRequest = context.isRequestSecure();
     }

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/CSSUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/CSSUtils.java?rev=1303525&r1=1303524&r2=1303525&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/CSSUtils.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/CSSUtils.java Wed Mar 21 19:33:45 2012
@@ -137,7 +137,15 @@ public class CSSUtils
     // applied in a non-Faces environment, this dependency seems
     // accpetable.
     FacesContext facesContext = FacesContext.getCurrentInstance();
-    assert(facesContext != null);
+    
+    // We now have one use case where access to a FacesContext may
+    // not be available: unit tests.  For this case, any base uri
+    // will do, since we won't be requesting the style sheet via
+    // a uri.
+    if (facesContext == null)
+    {
+      return styleSheetName;
+    }
 
     ExternalContext externalContext = facesContext.getExternalContext();
     String contextPath = externalContext.getRequestContextPath();

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/NameUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/NameUtils.java?rev=1303525&r1=1303524&r2=1303525&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/NameUtils.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/NameUtils.java Wed Mar 21 19:33:45 2012
@@ -206,7 +206,7 @@ public class NameUtils
       name = _PLATFORM_ANDROID;
       break;
     case TrinidadAgent.OS_UNKNOWN:
-      // This case is only here to avoid the default assertion
+      name = _PLATFORM_UNKNOWN;
       break;
     default:
       // New or invalid os id
@@ -705,6 +705,8 @@ public class NameUtils
   
   private static final String _PLATFORM_ANDROID = "android";
 
+  private static final String _PLATFORM_UNKNOWN = "unknown";
+
   // Accessibility constants
   private static final String _ACC_HIGH_CONTRAST = "hc";
 

Added: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/StableNameUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/StableNameUtils.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/StableNameUtils.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/StableNameUtils.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,615 @@
+/*
+ * 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.myfaces.trinidadinternal.style.util;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import java.util.Collections;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+
+import java.util.TreeSet;
+
+import org.apache.myfaces.trinidad.context.Version;
+import org.apache.myfaces.trinidad.util.Range;
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidadinternal.agent.TrinidadAgent.Application;
+import org.apache.myfaces.trinidadinternal.skin.AgentAtRuleMatcher;
+import org.apache.myfaces.trinidadinternal.style.StyleContext;
+import org.apache.myfaces.trinidadinternal.style.util.StyleSheetVisitUtils.StyleSheetVisitor;
+import org.apache.myfaces.trinidadinternal.style.xml.XMLConstants;
+import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetDocument;
+import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetNode;
+import org.apache.myfaces.trinidadinternal.util.nls.LocaleUtils;
+
+/**
+ * This class serves one purpose: it provides a replacement for NameUtils.getContextName()
+ * that produces "stable" file names.  This ensures that generated style sheets will be
+ * named in a consistent manner that is not dependent on the order in which requests arrives.
+ * 
+ * See the "Structure of Stable Style Sheet Names" section in the Skinning chapter of the
+ * Trinidad Developer's Guide for the specification of stable style sheet names.
+ */
+public final class StableNameUtils
+{
+  /**
+   * Similar to NameUtils.getContextName(), but produces stable names.
+   * 
+   * @param context the current style context
+   * @param document the skin document
+   * @return a name suitable for inclusion in a generated style sheet file name.
+   */
+  public static String getContextName(
+    StyleContext       context,
+    StyleSheetDocument document
+    )
+  {
+    return new ContextNameProducer(context, document).getName();
+  }
+  
+  // Helper class that produces context-specific file names.
+  private static final class ContextNameProducer
+  {
+    // The ContextNameProducer implementation is designed for modularity/code 
+    // cleanliness more than performance.  Each name that is produced generates
+    // a fairly large number of temporary objects (most iterators).  This seems
+    // acceptable as we only generate each name once per generated file, when the
+    // file is initially written.  If performance/temporary object creation
+    // ever become an issue, we can optimize/refactor.
+
+    public ContextNameProducer(
+      StyleContext       context,
+      StyleSheetDocument document
+      )
+    {
+      _context = context;
+      _documentId = document.getDocumentId(context);
+      _styleSheets = document.getStyleSheetsAsCollection(context);
+    }
+
+    /**
+     * Returns the context-specific file name.
+     */
+    public String getName()
+    {
+      // We're going to collect all required info (eg. platform, agent,
+      // locale, etc...) in a single StyleSheetVisitUtils.visit(), during
+      // which we delegate to a number of "naming" StyleSheetVisitors
+      // to collect the info that we need to produce a name.
+      Collection<NamingStyleSheetVisitor> visitors = _getVisitors();
+
+      _visitStyleSheets(visitors);
+
+      return _toName(visitors);
+    }
+
+    private Collection<NamingStyleSheetVisitor> _getVisitors()
+    {
+      return Arrays.<NamingStyleSheetVisitor>asList(
+               new PlatformNameExtractor(),
+               new ApplicationNameExtractor(_context.getAgent().getVersion()),
+               new LocaleNameExtractor(),
+               new DirectionNameExtractor(),
+               new AccessibilityNameExtractor());
+    }
+
+    private void _visitStyleSheets(Collection<? extends StyleSheetVisitor> visitors)
+    {
+      StyleSheetVisitor compoundVisitor = StyleSheetVisitUtils.compoundStyleSheetVisitor(visitors);
+      StyleSheetVisitUtils.visitStyleSheets(_styleSheets, compoundVisitor);      
+    }
+
+    private String _toName(Collection<NamingStyleSheetVisitor> visitors)
+    {
+      // Picking a slightly large initial size in the hopes that this will
+      // avoid reallocations.
+      StringBuilder builder = new StringBuilder(100);
+      
+      _appendSkinIdentifierSection(builder);
+      _appendVariantsSection(builder, visitors);
+      _appendContextualSection(builder);
+      _appendSuffix(builder);
+      
+      return builder.toString();
+    }
+
+    private void _appendSkinIdentifierSection(StringBuilder builder)
+    {
+      // The document id is actually just the content/version hash.  The skin
+      // id is later prepended in SkinStyleProvider.getTargetStyleSheetName().
+      builder.append(_documentId);
+      
+      // Double-separator to make it easier to write regular
+      // expressions against the interesting portion of the name
+      // (eg. for uri rewriting purposes).
+      builder.append(_SEPARATOR);
+      builder.append(_SEPARATOR);      
+    }
+    
+    private void _appendVariantsSection(
+      StringBuilder builder,
+      Collection<NamingStyleSheetVisitor> visitors
+      )
+    {
+      for (NamingStyleSheetVisitor visitor : visitors)
+      {
+        visitor.appendName(builder);
+        builder.append(_SEPARATOR);
+      }
+      
+      // Another double-dash separator to aid regular expression
+      // targeting.  This may come in handy if we ever end up
+      // introducing new variants that we want to add to the
+      // visit-based names section.
+      builder.append(_SEPARATOR);
+    }
+
+    private void _appendContextualSection(StringBuilder builder)
+    {
+      builder.append(_context.isPortletMode() ? "p" : "s");
+      builder.append(_SEPARATOR);
+      builder.append(_context.isRequestSecure() ? "s" : "n");
+      builder.append(_SEPARATOR);
+      builder.append(_context.isDisableStyleCompression() ? "u" : "c");
+    }
+    
+    private void _appendSuffix(StringBuilder builder)
+    {
+      builder.append(".css");
+    }
+
+    private final StyleContext               _context;
+    private final String                     _documentId;
+    private final Collection<StyleSheetNode> _styleSheets;    
+  }
+  
+  // Extension of StyleSheetVisitor that contributes to name generation
+  private interface NamingStyleSheetVisitor extends StyleSheetVisitor
+  {
+    /**
+     * Appends the the file name that is being built up in the specified
+     * StringBuilder.
+     */
+    public void appendName(StringBuilder builder);
+  }
+
+  // Abstract base class for NamingStyleSheetVisitors that operate on the 
+  // collections coughed up by StyleSheetNode.  Handles three possible
+  // scenarios:
+  //
+  // 1. There is no explicit match - eg. the skin does not define any @locale
+  //    rules, so StyleSheetNode.getLocales() is always empty.  In this case,
+  //    we always append the default match path token.
+  // 2. There is a single match - eg. the skin defines "@locale ja" and this
+  //    StyleSheetNode is visited.  In this case, we append the string representation
+  //    of the matched value.
+  // 3. There is a multiple match (and no single match) - eg. the skin defines
+  //    "@locale ja, cz, ko" and this StyleSheetNode is visited.  In this case,
+  //    we append a concatenation of the string representation of each value,
+  //    separated by the underscore character.
+  private abstract static class CollectionNameExtractor<E> implements NamingStyleSheetVisitor
+  {
+    /**
+     * Returns the collection of values that contribute to the name.
+     */
+    abstract protected Collection<E> getCollectionValues(StyleSheetNode styleSheet);
+    
+    @Override
+    public void visit(StyleSheetNode styleSheet)
+    {
+      Collection<E> newValues = getCollectionValues(styleSheet);
+      if (!newValues.isEmpty())
+      {
+        if (_values == null)
+        {
+          // Need to make a copy since we'll be modifying this collection.
+          _values = new HashSet<E>(newValues);
+        }
+        else
+        {
+          mergeValues(styleSheet, _values, newValues);
+
+          // We should never reach a state where the collected values
+          // is empty.  This would indicate that our style sheet node
+          // matching logic is wrong - eg. we matched a style sheet
+          // node with "@locale ja" and a second style sheet node with
+          // "@locale ko".  Make some noise if we hit this.
+          if (_values.isEmpty())
+          {
+            _fail();
+          }
+        }
+      }
+    }
+
+    /**
+     * Merges previously collected values with a new collection of values,
+     * storing the result in oldValues.
+     * 
+     * By default, the intersection of the two collections is retained.
+     */
+    protected void mergeValues(
+      StyleSheetNode styleSheet,
+      Collection<E>  oldValues,
+      Collection<E>  newValues
+      )
+    {
+      oldValues.retainAll(newValues);
+    }
+
+    @Override
+    public void appendName(StringBuilder builder)
+    {
+      if (_values == null)
+      {
+        builder.append(_DEFAULT_PATH_TOKEN);
+      }
+      else
+      {
+        assert(_values != null);
+        assert(!_values.isEmpty());
+        
+        Collection<String> names = _toNames(_values);
+        _appendNames(builder, names);
+      }
+    }
+    
+    private Collection<String> _toNames(Collection<E> values)
+    {
+      Collection<String> names = new TreeSet<String>();
+      
+      for (E value : values)
+      {
+        String name = toName(value);
+        assert(name != null);
+        
+        names.add(name);
+      }
+      
+      return names;
+    }
+
+    /**
+     * Converts the specified value to a name to include in the 
+     * file name.
+     */
+    protected String toName(E value)
+    {
+      return value.toString();
+    }
+
+    private void _appendNames(StringBuilder builder, Collection<String> names)
+    {
+      assert(names != null);
+      assert(!names.isEmpty());
+      
+      Iterator<String> iter = names.iterator();
+      while (iter.hasNext())
+      {
+        builder.append(iter.next());
+        
+        if (iter.hasNext())
+        {
+          builder.append("_");
+        }
+      }
+    }
+    
+    private Collection<E> _values = null;
+  }
+
+  // NamingStyleSheetVisitor that extracts the platform name.
+  private static final class PlatformNameExtractor extends CollectionNameExtractor<Integer>
+  {
+    @Override
+    protected Collection<Integer> getCollectionValues(StyleSheetNode styleSheet)
+    {
+      return styleSheet.getPlatforms();
+    }
+    
+    @Override
+    protected String toName(Integer platform)
+    {
+      return NameUtils.getPlatformName(platform);
+    }
+  }
+
+  // NamingStyleSheetVisitor that extracts the agent application name
+  private static class ApplicationNameExtractor extends CollectionNameExtractor<Application>
+  {
+    public ApplicationNameExtractor(Version agentVersion)
+    {
+      assert(agentVersion != null);
+
+      _agentVersion = agentVersion;
+      _matchedVersions = Version.ALL_VERSIONS;
+    }
+
+    @Override
+    protected String toName(Application agentApplication)
+    {
+      return agentApplication.getAgentName();
+    }
+
+    @Override
+    protected Collection<Application> getCollectionValues(StyleSheetNode styleSheet)
+    {
+      AgentAtRuleMatcher agentMatcher = styleSheet.getAgentMatcher();
+      if (agentMatcher == null)
+      {
+        return Collections.emptySet();
+      }
+      
+      return agentMatcher.getAllApplications();
+    }
+
+    @Override
+    protected void mergeValues(
+      StyleSheetNode          styleSheet,
+      Collection<Application> oldAgentApplications,
+      Collection<Application> newAgentApplications
+      )
+    {
+      super.mergeValues(styleSheet, oldAgentApplications, newAgentApplications);
+
+      // In addition to merging application values, we also need to keep track of
+      // versions that we have seen, since this may be included in the generated
+      // file name.  Note that we only care about versions for cases where we've
+      // got an exact agent application match (ie. in cases where we actually know
+      // which application we are targeted.)
+      Application newAgentApplication = _getSingleAgentApplication(newAgentApplications);
+      if (newAgentApplication != null)
+      {
+        _mergeVersions(styleSheet.getAgentMatcher(), newAgentApplication);
+      }
+    }
+
+    // If the collection contains a single entry, returns the single value.
+    // Otherwise, returns null;
+    private Application _getSingleAgentApplication(Collection<Application> agentApplications)
+    {
+      if (agentApplications.size() == 1)
+      {
+         Iterator<Application> iter = agentApplications.iterator();
+         if (iter.hasNext())
+         {
+           return iter.next();
+         }
+      }
+      
+      return null;
+    }
+
+    private void _mergeVersions(
+      AgentAtRuleMatcher agentMatcher,
+      Application        agentApplication
+      )
+    {
+      assert(agentMatcher != null);
+      assert(agentApplication != null);
+
+      Range<Version> matchedVersions =
+        agentMatcher.getMatchedVersionsForApplication(agentApplication, _agentVersion);
+      _matchedVersions = _matchedVersions.intersect(matchedVersions);
+
+      // We should never see an empty range at this point since the two
+      // ranges that we intersected both contains _agentVersion.
+      if (_matchedVersions.isEmpty())
+      {
+        _fail();
+      }
+    }
+
+    @Override
+    public void appendName(StringBuilder builder)
+    {
+      // This super call will handle appending the agent name segment.
+      // However, we also need to ensure that the agent version is added.
+      super.appendName(builder);
+      
+      // Tack on a value for the version field.  (All stable names need to
+      // have the same # of fields in order to support allow uris/names to
+      // be easily targeted by uri rewriting regular expressions.)
+      builder.append(_SEPARATOR);
+      _appendVersionName(builder);      
+    }
+
+    private void _appendVersionName(StringBuilder builder)
+    {
+      Version startVersion = _matchedVersions.getStart();
+      Version endVersion = _matchedVersions.getEnd();
+      boolean startMin = startVersion.equals(Version.MIN_VERSION);
+      boolean endMax = endVersion.equals(Version.MAX_VERSION);
+      
+      if (startMin && endMax)
+      {
+        builder.append(_DEFAULT_PATH_TOKEN);
+      }
+      else if (startMin)
+      {
+        builder.append(endVersion);
+        builder.append("m");
+      }
+      else if (endMax)
+      {
+        builder.append(startVersion);
+        builder.append("p");
+      }
+      else
+      {
+        builder.append(startVersion);
+      }
+    }
+
+    private final Version  _agentVersion;
+    private Range<Version> _matchedVersions;
+  }
+
+  // NamingStyleSheetVisitor that extracts the locale name.
+  private static final class LocaleNameExtractor extends CollectionNameExtractor<Locale>
+  {
+    @Override
+    protected Collection<Locale> getCollectionValues(StyleSheetNode styleSheet)
+    {
+      return styleSheet.getLocales();
+    }
+
+    @Override
+    protected void mergeValues(
+      StyleSheetNode     styleSheet,
+      Collection<Locale> oldLocales,
+      Collection<Locale> newLocales
+      )
+    {
+      assert(oldLocales != null);
+      assert(newLocales != null);
+
+      // We can't simply use Collection.retainAll() because we need to
+      // compensate for partial locales - ie. if "ja" is present in
+      // oldLocales and we encounter "ja_JP", Collection.retainAll()
+      // would result in the empty set, where as we want to replace "ja"
+      // with "ja_JP".
+      
+      for (Locale newLocale : newLocales)
+      {
+        _retainLocale(oldLocales, newLocale); 
+      }
+    }
+    
+    // We only want to retain the new locale if:
+    //
+    // a) it exist in the old locales, or...
+    // b) one of its "super" locales exists in the old locales.
+    //
+    // In the case of b), we want to remove the super-locale and
+    // repalce it with the new, more-specific locale.
+    private void _retainLocale(Collection<Locale> oldLocales, Locale newLocale)
+    {
+      // We could optimize by explicitly checking whether the new locale actually
+      // specifies a country/variant, but prefer to keep the code simple.
+      Locale langOnlyLocale = _toLanguageOnlyLocale(newLocale);
+      Locale langAndCountryLocale = _toLanguageAndCountryLocale(newLocale);
+      
+      if (oldLocales.contains(langOnlyLocale) || oldLocales.contains(langAndCountryLocale))
+      {
+        oldLocales.remove(langOnlyLocale);
+        oldLocales.remove(langAndCountryLocale);
+        oldLocales.add(newLocale);
+      }
+    }
+    
+    private Locale _toLanguageOnlyLocale(Locale locale)
+    {
+      return new Locale(locale.getLanguage());
+    }
+
+    private Locale _toLanguageAndCountryLocale(Locale locale)
+    {
+      return new Locale(locale.getLanguage(), locale.getCountry());
+    }
+  }
+  
+  // NamingStyleSheetVisitor that extracts the direction name
+  private static class DirectionNameExtractor implements NamingStyleSheetVisitor
+  {
+    @Override
+    public void visit(StyleSheetNode styleSheet)
+    {
+      int direction = styleSheet.getReadingDirection();   
+      if (direction != LocaleUtils.DIRECTION_DEFAULT)
+      {
+        assert((_direction == LocaleUtils.DIRECTION_DEFAULT) || (_direction == direction));
+        _direction = direction;
+      }
+    }
+
+    @Override
+    public void appendName(StringBuilder builder)
+    {
+      String name = (_direction == LocaleUtils.DIRECTION_DEFAULT) ? 
+                      _DEFAULT_PATH_TOKEN : 
+                      NameUtils.getDirectionName(_direction);
+      
+      builder.append(name);
+    }
+    
+    private int _direction = LocaleUtils.DIRECTION_DEFAULT;
+  }
+
+  // NamingStyleSheetVisitor that extracts the accessibility name
+  private static final class AccessibilityNameExtractor extends CollectionNameExtractor<String>
+  {
+    @Override
+    protected Collection<String> getCollectionValues(StyleSheetNode styleSheet)
+    {
+      return styleSheet.getAccessibilityProperties();
+    }
+    
+    protected void mergeValues(
+      StyleSheetNode styleSheet,
+      Collection<String> oldAccessibilityProperties,
+      Collection<String> newAccessibilityProperties
+      )
+    {
+      oldAccessibilityProperties.addAll(newAccessibilityProperties);
+    }
+    
+    @Override
+    protected String toName(String accessibilityProperty)
+    {
+      String name = null;
+      
+      if (XMLConstants.ACC_HIGH_CONTRAST.equals(accessibilityProperty))
+      {
+        name = "hc";
+      }
+      
+      if (XMLConstants.ACC_LARGE_FONTS.equals(accessibilityProperty))
+      {
+        name = "lf";
+      }
+      
+      assert(name != null);
+
+      return name;
+    }
+  }
+  
+  private static void _fail()
+  {
+    String message = _LOG.getMessage("SKIN_GENERATION_ERROR");
+    throw new IllegalStateException(message);
+  }
+
+  private StableNameUtils()
+  {
+  }
+  
+  private static final char _SEPARATOR = '-';
+
+  private static final String _DEFAULT_PATH_TOKEN = "d";
+  
+  private static final TrinidadLogger _LOG =
+    TrinidadLogger.createTrinidadLogger(StableNameUtils.class);  
+  
+}

Added: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/StyleSheetVisitUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/StyleSheetVisitUtils.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/StyleSheetVisitUtils.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/StyleSheetVisitUtils.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,98 @@
+/*
+ * 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.myfaces.trinidadinternal.style.util;
+
+import java.util.Collection;
+
+import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetNode;
+
+/**
+ * A utility class that supports traversal/visiting of a collection of StyleSheetNodes.
+ */
+public final class StyleSheetVisitUtils
+{
+  /**
+   * StyleSheetNode visitor contract.
+   */
+  public interface StyleSheetVisitor
+  {
+    /**
+     * Invoked when a new style sheet is visited.
+     */
+    public void visit(StyleSheetNode styleSheet);
+  }
+
+  /**
+   * Creates a StyleSheetVisitor that will invoke an arbitrary number
+   * of visitors
+   * 
+   * @param visitors a non-null collection of StyleSheetVisitors to encapsulate.
+   */
+  public static StyleSheetVisitor compoundStyleSheetVisitor(
+    Collection<? extends StyleSheetVisitor> visitors
+    )
+  {
+    return new CompoundVisitor(visitors);  
+  }
+  
+  /**
+   * Traverses the specified style sheets and invokes a visitor for each.
+   * 
+   * @param styleSheets the non-null style sheets to visit
+   * @param visitor the non-null visitor to invoke
+   */
+  public static void visitStyleSheets(
+    Iterable<StyleSheetNode> styleSheets,
+    StyleSheetVisitor        visitor
+    )
+  {
+    assert(styleSheets != null);
+    assert(visitor != null);
+
+    for (StyleSheetNode styleSheet : styleSheets)
+    {
+      visitor.visit(styleSheet);
+    }
+  }
+
+  private static final class CompoundVisitor implements StyleSheetVisitor
+  {
+    public CompoundVisitor(Collection<? extends StyleSheetVisitor> visitors)
+    {
+      assert(visitors != null);
+      _visitors = visitors;
+    }
+
+    @Override
+    public void visit(StyleSheetNode styleSheet)
+    {
+      for (StyleSheetVisitor visitor : _visitors)
+      {
+        visitor.visit(styleSheet);
+      }
+    }
+    
+    private final Collection<? extends StyleSheetVisitor> _visitors;
+  }
+
+  private StyleSheetVisitUtils()
+  {
+  }
+}

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/xml/parse/StyleSheetDocument.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/xml/parse/StyleSheetDocument.java?rev=1303525&r1=1303524&r2=1303525&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/xml/parse/StyleSheetDocument.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/xml/parse/StyleSheetDocument.java Wed Mar 21 19:33:45 2012
@@ -171,15 +171,20 @@ public class StyleSheetDocument
    */
   public Iterator<StyleSheetNode> getStyleSheets()
   {
+    return getStyleSheetsAsCollection().iterator();
+  }
+  
+  public Collection<StyleSheetNode> getStyleSheetsAsCollection()
+  {
     if(_styleSheets==null)
     {
       // -= Simon Lessard =- 
       // TODO: Collections.emptyList() maybe?
-      return  (Arrays.asList(new StyleSheetNode[0])).iterator();
+      return  (Arrays.asList(new StyleSheetNode[0]));
     }
     else
     {
-      return (Arrays.asList(_styleSheets)).iterator();
+      return (Arrays.asList(_styleSheets));
     }
   }
 
@@ -189,10 +194,14 @@ public class StyleSheetDocument
    */
   public Iterator<StyleSheetNode> getStyleSheets(StyleContext context)
   {
-    StyleSheetList styleSheets = _getStyleSheets(context);
-    return styleSheets.styleSheets().iterator();
+    return getStyleSheetsAsCollection(context).iterator();
   }
   
+  public Collection<StyleSheetNode> getStyleSheetsAsCollection(StyleContext context)
+  {
+    return _getStyleSheets(context).styleSheets();
+  }
+
   /**
    * Returns an Iterator of StyleNode objects for the specified context.
    */

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/Range.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/Range.java?rev=1303525&r1=1303524&r2=1303525&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/Range.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/Range.java Wed Mar 21 19:33:45 2012
@@ -23,6 +23,9 @@ package org.apache.myfaces.trinidadinter
  * Used for SelectRangeChoiceBar to allow the app developer to customize
  * the labels to not use numbers, but to use the data model.
  * @version $Name:  $ ($Revision: adfrt/faces/adf-faces-impl/src/main/java/oracle/adfinternal/view/faces/util/Range.java#0 $) $Date: 10-nov-2005.18:49:12 $
+ * 
+ * @deprecated
+ * @see org.apache.myfaces.trinidad.util.Range
  */
 public final class Range
 {

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/resources/META-INF/org.apache.myfaces.trinidad.render.InternalView.properties
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/resources/META-INF/org.apache.myfaces.trinidad.render.InternalView.properties?rev=1303525&r1=1303524&r2=1303525&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/resources/META-INF/org.apache.myfaces.trinidad.render.InternalView.properties (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/resources/META-INF/org.apache.myfaces.trinidad.render.InternalView.properties Wed Mar 21 19:33:45 2012
@@ -13,3 +13,4 @@
 # limitations under the License.
 
 /__ADFv__=org.apache.myfaces.trinidadinternal.renderkit.core.pages.GenericEntry
+/-tr-pregenerate-skins=org.apache.myfaces.trinidadinternal.skin.pregen.SkinPregenerationService

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts?rev=1303525&r1=1303524&r2=1303525&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/resource/LoggerBundle.xrts Wed Mar 21 19:33:45 2012
@@ -1168,4 +1168,30 @@ The skin {0} specified on the requestMap
 
 <resource key="CSS_SYNTAX_ERROR">Syntax error in skin file currently being processed due to mismatch in the number of open and close braces. The skin file will not be processed correctly. To know the name of file being processed, set log level to 'INFO'.</resource>
 
+<resource key="SKIN_PREGEN_ENABLED">A non-skin pregeneration request was received while skin pregeneration is enabled.  To interact with the application, please disable the skin pregeneration service.</resource>
+
+<resource key="SKIN_PREGEN_DISABLED">Skin pregeneration failed: the skin pregeneration service is disabled.  To enable skin pregeneration, set the {0} system property to one of: {1}</resource>
+
+<resource key="SKIN_PREGEN_FAILED">Skin pregeneration failed: {0}</resource>
+
+<resource key="SKIN_PREGEN_REQUESTED_SKIN_INVALID">{0} is not valid skin id.</resource>
+
+<resource key="SKIN_PREGEN_NO_TARGET_DIRECTORY">No target directory found.  Please specify a target directory via the {0} system property.</resource>
+
+<resource key="SKIN_PREGEN_RESPONSE_TITLE">Skin Pregeneration Service</resource>
+
+<resource key="SKIN_PREGEN_RESPONSE">Skin pregeneration completed in {0}ms.</resource>
+
+<resource key="SKIN_PREGEN_NO_DOCUMENT">No StyleSheetDocument found for skin {0}.</resource>
+
+<resource key="SKIN_PREGEN_STARTING">Starting pregeneration of skin {0}</resource>
+
+<resource key="SKIN_PREGEN_VARIANT">Pregenerating {0}/{1} style sheets for skin {2}.</resource>
+
+<resource key="SKIN_PREGEN_COMPLETED">Completed pregeneration of skin {0}.  Generated {1} files for {2} of {3} skin variants in {4} ms.  (Pregeneration output written to {5}.)</resource>
+
+<resource key="ILLEGAL_SYSTEM_PROPERTY_VALUE">{0} is not a valid value for system property {1}.  Valid values are: {2}</resource>
+
+<resource key="SKIN_GENERATION_ERROR">An unexpected error occurred while generating a skin style sheet, possibly indicating a Trinidad defect.  Please report this failure to the Apache MyFaces development team.</resource>
+
 </resources>

Added: myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/SkinTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/SkinTestCase.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/SkinTestCase.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/SkinTestCase.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,87 @@
+/*
+ *  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.myfaces.trinidadinternal.skin;
+
+import junit.framework.TestCase;
+
+import org.apache.myfaces.trinidadinternal.style.util.StyleSheetVisitUtils;
+import org.apache.myfaces.trinidadinternal.style.util.StyleSheetVisitUtils.StyleSheetVisitor;
+import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetDocument;
+
+/**
+ * Base class for tests that need to work with parsed skins (ie. with
+ * StyleSheetDocuments).
+ */
+public class SkinTestCase extends TestCase
+{
+  /**
+   * Enum for built-in test skins.
+   */
+  public enum TestSkin
+  {
+    EMPTY("empty"),
+    ACCESSIBILITY_HIGH_CONTRAST("acc-high-contrast"),
+    ACCESSIBILITY_LARGE_FONTS("acc-large-fonts");
+    
+    TestSkin(String skinName)
+    {
+      _skinName = skinName; 
+    }
+  
+    /**
+     * Returns a resource name suitable for use with
+     * ClassLoader.getResource().
+     */
+    public String getResourceName()
+    {
+      return _RESOURCE_PATH + _skinName + _SUFFIX;
+    }
+
+    private final String _skinName;
+  }
+
+  public SkinTestCase(String string)
+  {
+    super(string);
+  }
+  
+  /**
+   * Returns the StyleSheetDocument for the specified test skin.
+   */
+  protected StyleSheetDocument getSkinDocument(TestSkin testSkin)
+  {
+    return SkinTestUtils.parseSkin(testSkin.getResourceName());
+  }
+
+  /**
+   * Performs a visit of all style sheet nodes in the specified test
+   * skin
+   */
+  protected void visitStyleSheets(TestSkin testSkin, StyleSheetVisitor visitor)
+  {
+    StyleSheetDocument document = getSkinDocument(testSkin);
+    
+    StyleSheetVisitUtils.visitStyleSheets(document.getStyleSheetsAsCollection(), visitor);
+  }
+
+  private static final String _RESOURCE_PATH =
+    "org/apache/myfaces/trinidadinternal/skin/testSkins/";
+  
+  private static final String _SUFFIX = ".css";
+}

Added: myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/SkinTestUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/SkinTestUtils.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/SkinTestUtils.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/SkinTestUtils.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,67 @@
+/*
+ *  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.myfaces.trinidadinternal.skin;
+
+import java.io.IOException;
+
+import org.apache.myfaces.trinidad.share.io.NameResolver;
+import org.apache.myfaces.trinidadinternal.share.io.ClassResourceNameResolver;
+import org.apache.myfaces.trinidadinternal.share.xml.ParseContext;
+import org.apache.myfaces.trinidadinternal.share.xml.ParseContextImpl;
+import org.apache.myfaces.trinidadinternal.style.xml.parse.StyleSheetDocument;
+
+/**
+ * Utilities for testing skinning
+ */
+public final class SkinTestUtils
+{
+  /**
+   * Parses a skin css document.
+   * 
+   * @param resourceName name of the document resource, which is located via a call
+   *   to ClassLoader.getResource().
+   * @return the StyleSheetDocument for the skin.
+   * @throws IllegalStateException if an IOException occurs during parsing.
+   */
+  public static StyleSheetDocument parseSkin(String resourceName)
+    throws IllegalStateException
+  {
+    ParseContext parseContext = new ParseContextImpl();
+    NameResolver nameResolver = new ClassResourceNameResolver(null);
+    StyleSheetEntry entry = null;
+
+    try
+    {
+      entry = SkinStyleSheetParserUtils.parseCSSSource(parseContext,
+                                                       nameResolver,
+                                                       resourceName,
+                                                       StyleSheetEntry.class);
+    }
+    catch (IOException e)
+    {
+      throw new IllegalStateException(e);
+    }
+
+    return entry.getDocument();    
+  }
+
+  private SkinTestUtils()
+  {
+  }
+}

Added: myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/AccessibilityVariantExtractorTest.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/AccessibilityVariantExtractorTest.java?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/AccessibilityVariantExtractorTest.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/test/java/org/apache/myfaces/trinidadinternal/skin/pregen/variant/AccessibilityVariantExtractorTest.java Wed Mar 21 19:33:45 2012
@@ -0,0 +1,85 @@
+/*
+ *  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.myfaces.trinidadinternal.skin.pregen.variant;
+
+import java.util.Collection;
+
+import junit.framework.Test;
+
+import junit.framework.TestSuite;
+
+import org.apache.myfaces.trinidad.context.AccessibilityProfile;
+import org.apache.myfaces.trinidad.context.AccessibilityProfile.ColorContrast;
+import org.apache.myfaces.trinidad.context.AccessibilityProfile.FontSize;
+import org.apache.myfaces.trinidadinternal.skin.SkinTestCase;
+
+public class AccessibilityVariantExtractorTest extends SkinTestCase
+{
+  public static final Test suite()
+  {
+    return new TestSuite(AccessibilityVariantExtractorTest.class);
+  }
+
+  public static void main(String[] args)
+    throws Throwable
+  {
+    junit.textui.TestRunner.run(suite());
+  }
+  
+  public AccessibilityVariantExtractorTest(String string)
+  {
+    super(string);
+  }
+
+  public void testEmpty()
+  {
+    AccessibilityVariantExtractor extractor = new AccessibilityVariantExtractor();
+    visitStyleSheets(TestSkin.EMPTY, extractor);
+    
+    Collection<AccessibilityProfile> profiles = extractor.getVariants();
+    assertEquals(profiles.size(), 1);
+    
+    _assertContainsDefaultProfile(profiles);
+  }
+  
+  public void testLargeFonts()
+  {
+    AccessibilityVariantExtractor extractor = new AccessibilityVariantExtractor();    
+    visitStyleSheets(TestSkin.ACCESSIBILITY_LARGE_FONTS, extractor);
+
+    Collection<AccessibilityProfile> profiles = extractor.getVariants();    
+    assertEquals(profiles.size(), 2);
+    _assertContainsDefaultProfile(profiles);
+    _assertContainsLargeFontsProfile(profiles);
+  }
+  
+  private void _assertContainsDefaultProfile(Collection<AccessibilityProfile> profiles)
+  {
+    assertTrue("contains default acc profile",
+               profiles.contains(AccessibilityProfile.getDefaultInstance()));    
+  }
+
+  private void _assertContainsLargeFontsProfile(Collection<AccessibilityProfile> profiles)
+  {
+    AccessibilityProfile profile = AccessibilityProfile.getInstance(ColorContrast.STANDARD,
+                                                                    FontSize.LARGE);
+    
+    assertTrue("contains large fonts acc profile", profiles.contains(profile));
+  }
+}

Added: myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/testSkins/acc-large-fonts.css
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/testSkins/acc-large-fonts.css?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/testSkins/acc-large-fonts.css (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/testSkins/acc-large-fonts.css Wed Mar 21 19:33:45 2012
@@ -0,0 +1,25 @@
+/**
+    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.
+	   
+**/
+
+.foo { font-size: small }
+
+@accessibility-profile large-fonts {
+  .foo { font-size: large }
+}

Added: myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/testSkins/empty.css
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/testSkins/empty.css?rev=1303525&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/testSkins/empty.css (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/skin/testSkins/empty.css Wed Mar 21 19:33:45 2012
@@ -0,0 +1,21 @@
+/**
+    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.
+	   
+**/
+
+.foo { background-color: red }