001    // Copyright 2010, 2011 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    // http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry5.internal.services.javascript;
016    
017    import java.text.DateFormatSymbols;
018    import java.util.Calendar;
019    import java.util.Collections;
020    import java.util.List;
021    import java.util.Locale;
022    
023    import org.apache.tapestry5.Asset;
024    import org.apache.tapestry5.SymbolConstants;
025    import org.apache.tapestry5.func.F;
026    import org.apache.tapestry5.func.Mapper;
027    import org.apache.tapestry5.internal.TapestryInternalUtils;
028    import org.apache.tapestry5.ioc.annotations.Symbol;
029    import org.apache.tapestry5.ioc.services.ThreadLocale;
030    import org.apache.tapestry5.json.JSONArray;
031    import org.apache.tapestry5.json.JSONObject;
032    import org.apache.tapestry5.services.AssetSource;
033    import org.apache.tapestry5.services.javascript.JavaScriptStack;
034    import org.apache.tapestry5.services.javascript.StylesheetLink;
035    
036    public class DateFieldStack implements JavaScriptStack
037    {
038        private final ThreadLocale threadLocale;
039    
040        private final boolean compactJSON;
041    
042        private final List<Asset> javaScriptStack;
043    
044        private final List<StylesheetLink> stylesheetStack;
045    
046        public DateFieldStack(ThreadLocale threadLocale, @Symbol(SymbolConstants.COMPACT_JSON)
047        boolean compactJSON, final AssetSource assetSource)
048        {
049            this.threadLocale = threadLocale;
050            this.compactJSON = compactJSON;
051    
052            Mapper<String, Asset> pathToAsset = new Mapper<String, Asset>()
053            {
054                public Asset map(String path)
055                {
056                    return assetSource.getExpandedAsset(path);
057                }
058            };
059    
060            Mapper<String, StylesheetLink> pathToStylesheetLink = F.combine(pathToAsset,
061                    TapestryInternalUtils.assetToStylesheetLink);
062    
063            javaScriptStack = F
064                    .flow("${tapestry.datepicker}/js/datepicker.js", "org/apache/tapestry5/corelib/components/datefield.js")
065                    .map(pathToAsset).toList();
066    
067            stylesheetStack = F.flow("${tapestry.datepicker}/css/datepicker.css").map(pathToStylesheetLink).toList();
068        }
069    
070        public String getInitialization()
071        {
072            Locale locale = threadLocale.getLocale();
073    
074            JSONObject spec = new JSONObject();
075    
076            DateFormatSymbols symbols = new DateFormatSymbols(locale);
077    
078            spec.put("months", new JSONArray((Object[])symbols.getMonths()));
079    
080            StringBuilder days = new StringBuilder();
081    
082            String[] weekdays = symbols.getWeekdays();
083    
084            Calendar c = Calendar.getInstance(locale);
085    
086            int firstDay = c.getFirstDayOfWeek();
087    
088            // DatePicker needs them in order from monday to sunday.
089    
090            for (int i = Calendar.MONDAY; i <= Calendar.SATURDAY; i++)
091            {
092                days.append(weekdays[i].substring(0, 1));
093            }
094    
095            days.append(weekdays[Calendar.SUNDAY].substring(0, 1));
096    
097            spec.put("days", days.toString().toLowerCase(locale));
098    
099            // DatePicker expects 0 to be monday. Calendar defines SUNDAY as 1, MONDAY as 2, etc.
100    
101            spec.put("firstDay", firstDay == Calendar.SUNDAY ? 6 : firstDay - 2);
102    
103            // TODO: Skip localization if locale is English?
104    
105            return String.format("Tapestry.DateField.initLocalization(%s);", spec.toString(compactJSON));
106        }
107    
108        public List<Asset> getJavaScriptLibraries()
109        {
110            return javaScriptStack;
111        }
112    
113        public List<StylesheetLink> getStylesheets()
114        {
115            return stylesheetStack;
116        }
117    
118        public List<String> getStacks()
119        {
120            return Collections.emptyList();
121        }
122    }