From 4147d4267b8cbb0d4d4eb8230328a490fed25aa0 Mon Sep 17 00:00:00 2001 From: stephanrauh Date: Tue, 25 Nov 2014 23:51:39 +0100 Subject: [PATCH] re-established compatibility to Apache MyFaces (issue #6) --- meta/bootsfaces-b.full.taglib.xml | 1 - pom.xml | 7 +- src/net/bootsfaces/component/DatePicker.java | 830 +++++++++++-------- 3 files changed, 466 insertions(+), 372 deletions(-) diff --git a/meta/bootsfaces-b.full.taglib.xml b/meta/bootsfaces-b.full.taglib.xml index 35e22c124..789cc1ec4 100644 --- a/meta/bootsfaces-b.full.taglib.xml +++ b/meta/bootsfaces-b.full.taglib.xml @@ -1881,7 +1881,6 @@ panelGrid net.bootsfaces.component.PanelGrid - Unique identifier of the component in a namingContainer. diff --git a/pom.xml b/pom.xml index d54887f37..0f298b039 100644 --- a/pom.xml +++ b/pom.xml @@ -60,14 +60,14 @@ Mojarra 2.2.8-02 - true + false com.sun.faces jsf-api 2.2.8-02 - provided + compile com.sun.faces @@ -80,13 +80,14 @@ MyFaces 2.2.4 - false + true org.apache.myfaces.core myfaces-api 2.2.4 + compile diff --git a/src/net/bootsfaces/component/DatePicker.java b/src/net/bootsfaces/component/DatePicker.java index ca8538e20..91aab999d 100644 --- a/src/net/bootsfaces/component/DatePicker.java +++ b/src/net/bootsfaces/component/DatePicker.java @@ -19,7 +19,6 @@ package net.bootsfaces.component; -import com.sun.faces.util.MessageFactory; import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; @@ -27,17 +26,24 @@ import java.util.Date; import java.util.Locale; import java.util.Map; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import javax.el.ValueExpression; +import javax.faces.application.Application; import javax.faces.application.FacesMessage; import javax.faces.application.ResourceDependencies; import javax.faces.application.ResourceDependency; import javax.faces.component.FacesComponent; +import javax.faces.component.UIComponent; import javax.faces.component.html.HtmlInputText; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.convert.Converter; import javax.faces.convert.ConverterException; -import net.bootsfaces.render.A; + import net.bootsfaces.C; +import net.bootsfaces.render.A; import net.bootsfaces.render.H; import net.bootsfaces.render.JQ; import net.bootsfaces.render.R; @@ -47,385 +53,473 @@ * @author thecoder4.eu */ -@ResourceDependencies({ - @ResourceDependency(library="bsf", name="css/core.css", target="head"), - @ResourceDependency(library="bsf", name="css/jq.ui.core.css", target="head"), - @ResourceDependency(library="bsf", name="css/jq.ui.theme.css", target="head"), - @ResourceDependency(library="bsf", name="css/jq.ui.datepicker.css", target="head"), - @ResourceDependency(library="bsf", name="css/bsf.css", target="head"), - @ResourceDependency(library="bsf", name="jq/jquery.js", target="head"), - @ResourceDependency(library="bsf", name="jq/ui/datepicker.js", target="head"), - @ResourceDependency(library="bsf", name="js/bsf.js", target="head"), - @ResourceDependency(library="bsf", name="jq/ui/core.js", target="body") - +@ResourceDependencies({ @ResourceDependency(library = "bsf", name = "css/core.css", target = "head"), + @ResourceDependency(library = "bsf", name = "css/jq.ui.core.css", target = "head"), + @ResourceDependency(library = "bsf", name = "css/jq.ui.theme.css", target = "head"), + @ResourceDependency(library = "bsf", name = "css/jq.ui.datepicker.css", target = "head"), + @ResourceDependency(library = "bsf", name = "css/bsf.css", target = "head"), + @ResourceDependency(library = "bsf", name = "jq/jquery.js", target = "head"), + @ResourceDependency(library = "bsf", name = "jq/ui/datepicker.js", target = "head"), + @ResourceDependency(library = "bsf", name = "js/bsf.js", target = "head"), + @ResourceDependency(library = "bsf", name = "jq/ui/core.js", target = "body") + }) @FacesComponent(C.DATEPICKER_COMPONENT_TYPE) public class DatePicker extends HtmlInputText { - - /** - *

The standard component type for this component.

- */ - public static final String COMPONENT_TYPE =C.DATEPICKER_COMPONENT_TYPE; - /** - *

The component family for this component.

- */ - public static final String COMPONENT_FAMILY = C.BSFCOMPONENT; - - public static final String ADDON="input-group-addon"; - public static final String CALENDAR="calendar"; - - /** - * Selected Locale - */ - private Locale sloc; - //private TimeZone stz; - /** - * selected Date Format - */ - private String sdf; - private String mode; - - public DatePicker() { - setRendererType(null); // this component renders itself - } + /** + *

+ * The standard component type for this component. + *

+ */ + public static final String COMPONENT_TYPE = C.DATEPICKER_COMPONENT_TYPE; + /** + *

+ * The component family for this component. + *

+ */ + public static final String COMPONENT_FAMILY = C.BSFCOMPONENT; - @Override - public void decode(FacesContext fc) { - String subVal = fc.getExternalContext().getRequestParameterMap().get(getClientId(fc)); + public static final String ADDON = "input-group-addon"; + public static final String CALENDAR = "calendar"; - if(subVal != null) { - this.setSubmittedValue(subVal);this.setValid(true); - } - } + /** + * Selected Locale + */ + private Locale sloc; + // private TimeZone stz; + /** + * selected Date Format + */ + private String sdf; + private String mode; - @Override - protected Object getConvertedValue(FacesContext fc, Object sval) throws ConverterException { - if(sval==null) { return null; } - - String val = (String) sval; - //If the Trimmed submitted value is empty, return null - if(val.trim().length()==0) { return null; } - - Converter converter = getConverter(); - - //If the user supplied a converter, use it - if(converter != null) { - return converter.getAsObject(fc, this, val); - } - //Else we use our own converter - sloc = selectLocale(fc.getViewRoot().getLocale(), A.asString(getAttributes().get(A.LOCALE)) ); - sdf = selectDateFormat(sloc, A.asString(getAttributes().get(A.DTFORMAT)) ); - SimpleDateFormat format = null; - Object date=null; - try { - format = new SimpleDateFormat(sdf, sloc); - - format.setTimeZone(java.util.TimeZone.getDefault()); - - date = format.parse(val); ((Date) date).setHours(12); - - } - catch (ParseException e) { - this.setValid(false); - throw new ConverterException( - MessageFactory.getMessage("javax.faces.converter.DateTimeConverter.DATE", FacesMessage.SEVERITY_ERROR, - new Object[] { val, sdf, MessageFactory.getLabel(fc, this) }) - ); - } - - return date; - } - - - - @Override - public void encodeBegin(FacesContext fc) throws IOException { - /* - * Popup - * - * - * - * Inline - * Adds a Div and Uses a Hidden Input - */ - - encodeHTML(fc); - - } - - /** - * Encodes the HTML for this context - * @param fc - * @throws IOException - */ - private void encodeHTML(FacesContext fc) throws IOException { - Map attrs = getAttributes(); - String clientId = getClientId(fc); - ResponseWriter rw = fc.getResponseWriter(); - //stz = selectTimeZone(attrs.get(A.TZ)); - - sloc = selectLocale(fc.getViewRoot().getLocale(), A.asString(attrs.get(A.LOCALE)) ); - sdf = selectDateFormat(sloc, A.asString(attrs.get(A.DTFORMAT)) ); - - //Debugging Locale and dateformat - //rw.write("DEBUG sloc='"+sloc+"', sdf='"+sdf+"' "); - - String dpId; - - Object v=getSubmittedValue(); - if(v==null) { v=this.getValue();} - - /* - * 6 modes: - * 1) inline - * 2) popup (no icons) - * 3) popup-icon - * 4) icon-popup - * 5) toggle-icon (Default) - * 6) icon-toggle - */ - mode = A.asString(attrs.get(A.MODE),A.TOGGLEICON); - boolean inline= mode.equals(A.INLINE); - - if (inline) { //inline => div with ID - dpId = clientId + C.USCORE + H.DIV; - rw.startElement(H.DIV, this); - rw.writeAttribute(H.ID, dpId, null); - rw.endElement(H.DIV); - } else { //popup - dpId = clientId; - - if (!mode.equals(A.POPUP)) { // with icon => div with prepend/append style - rw.startElement(H.DIV, this); - rw.writeAttribute(H.CLASS, "input-group", H.CLASS); - if (mode.equals(A.ICONPOP)||mode.equals(A.ICONTOGGLE)) { - R.addonIcon(rw, this, CALENDAR, false); - } - } - } - String type = inline ? H.HIDDEN : H.TEXT; - - rw.startElement(H.INPUT, null); - rw.writeAttribute(H.ID, clientId, null); - rw.writeAttribute(H.NAME, clientId, null); - rw.writeAttribute(H.TYPE, type, null); - rw.writeAttribute(H.CLASS, "form-control", H.CLASS); - if(v!=null) { rw.writeAttribute(H.VALUE, getDateAsString(v,sdf, sloc), null); } - - String ph=A.asString(attrs.get(A.PHOLDER)); - if(ph!=null) { rw.writeAttribute(H.PHOLDER, ph, null); } - - if(A.toBool(attrs.get(A.DISABLED))) { rw.writeAttribute(A.DISABLED, A.DISABLED, null); } - if(A.toBool(attrs.get(A.READONLY))) { rw.writeAttribute(A.READONLY, A.READONLY, null); } - rw.endElement(H.INPUT); - - - encodeJS(fc, rw, clientId,dpId); - if (mode.equals(A.POPICON)||mode.equals(A.TOGGLEICON)) { R.addonIcon(rw, this, CALENDAR, false); } - - if(!inline && !mode.equals(A.POPUP)) { - rw.endElement(H.DIV); - JQ.datePickerToggler(rw, clientId, clientId+C.USCORE+ADDON); - - } //Closes the popup prepend/append style div - - } - private void encodeJS(FacesContext fc, ResponseWriter rw, String cId, String dpId) throws IOException { - Map attrs = getAttributes(); - - StringBuilder sb = new StringBuilder(150); - sb.append(JQ.DTFORMAT).append(C.COLON).append(C.QUOTE+convertFormat(sdf)+C.QUOTE).append(C.COMMA); - - if(A.toInt(attrs.get(JQ.NUMOFMONTHS))>0) { - sb.append(JQ.NUMOFMONTHS).append(C.COLON).append(attrs.get(JQ.NUMOFMONTHS)).append(C.COMMA); - } - if(A.toInt(attrs.get(JQ.FIRSTDAY))>0) { - sb.append(JQ.FIRSTDAY).append(C.COLON).append(attrs.get(JQ.FIRSTDAY)).append(C.COMMA); - } - if(A.toBool(attrs.get(JQ.SHOWBUTS))) { - sb.append(JQ.SHOWBUTS).append(C.COLON).append(C.TRUE).append(C.COMMA); - } - if(A.toBool(attrs.get(JQ.CHNGMONTH))) { - sb.append(JQ.CHNGMONTH).append(C.COLON).append(C.TRUE).append(C.COMMA); - } - if(A.toBool(attrs.get(JQ.CHNGYEAR))) { - sb.append(JQ.CHNGYEAR).append(C.COLON).append(C.TRUE).append(C.COMMA); - } - if(A.toBool(attrs.get(JQ.SHOWWK))) { - sb.append(JQ.SHOWWK).append(C.COLON).append(C.TRUE).append(C.COMMA); - } - - if (mode.equals(A.TOGGLEICON)||mode.equals(A.ICONTOGGLE)) { - sb.append(JQ.SHOWON).append(C.COLON).append(C.QUOTE+H.BUTTON+C.QUOTE).append(C.COMMA); - } + public DatePicker() { + setRendererType(null); // this component renders itself + } - /* - * Attributes that need decoding the Date - */ - if(attrs.get(JQ.MINDATE)!=null) { - sb.append(JQ.MINDATE+C.COLON+C.QUOTE).append(getDateAsString(attrs.get(JQ.MINDATE), sdf, sloc)).append(C.QUOTE); - } - if(attrs.get(JQ.MAXDATE)!=null) { - sb.append(JQ.MAXDATE+C.COLON+C.QUOTE).append(getDateAsString(attrs.get(JQ.MAXDATE), sdf, sloc)).append(C.QUOTE); - } - - //If user specifies a specific language to use then we render the datepicker using this language - //else we use the selected locale language - String l=A.asString(attrs.get(JQ.LANG)); - if(l==null) { l=sloc.getLanguage(); } - JQ.datePicker(rw,cId, dpId, sb.toString(),l); - } - - public static String getDateAsString(Object dt, String format, Locale locale) { - if (dt == null) { - return null; - } + @Override + public void decode(FacesContext fc) { + String subVal = fc.getExternalContext().getRequestParameterMap().get(getClientId(fc)); - if (dt instanceof String) { - return (String) dt; - } else if (dt instanceof Date) { - SimpleDateFormat dtFormat = new SimpleDateFormat(format, locale); - dtFormat.setTimeZone(java.util.TimeZone.getDefault()); - //dateFormat.setTimeZone(tz); + if (subVal != null) { + this.setSubmittedValue(subVal); + this.setValid(true); + } + } - return dtFormat.format((Date) dt); - } else { - throw new IllegalArgumentException("Value could be either String or java.util.Date"); - } - } - - //Pass the attrs timezone value - /*public static TimeZone selectTimeZone(Object utz) { - java.util.TimeZone selTimeZone; - if (utz != null) { - if (utz instanceof String) { - selTimeZone = java.util.TimeZone.getTimeZone((String) utz); - } else if (utz instanceof java.util.TimeZone) { - selTimeZone = (java.util.TimeZone) utz; - } else { - throw new IllegalArgumentException("TimeZone should be either String or java.util.TimeZone"); - } - } else { - selTimeZone = java.util.TimeZone.getDefault(); - } - return selTimeZone; - }*/ - - //Pass facesContext.getViewRoot().getLocale() and attrs locale value - public Locale selectLocale(Locale vrloc, Object loc) { - java.util.Locale selLocale = vrloc; - - if (loc != null) { - if (loc instanceof String) { - selLocale = toLocale((String) loc); - } else if (loc instanceof java.util.Locale) { - selLocale = (java.util.Locale) loc; - } else { - throw new IllegalArgumentException("Type:" + loc.getClass() + " is not a valid locale type for DatePicker:" + this.getClientId()); - } - } + @Override + protected Object getConvertedValue(FacesContext fc, Object sval) throws ConverterException { + if (sval == null) { + return null; + } - return selLocale; - } - - /** - * Selects the Date Pattern to use based on the given Locale if the input format is null - * - * @param locale Locale (may be the result of a call to selectLocale) - * @param format Input format String - * @return Date Pattern eg. dd/MM/yyyy - */ - public static String selectDateFormat(Locale locale, String format) { - String selFormat; - - if (format == null) { - selFormat = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale)).toPattern(); - //Since DateFormat.SHORT is silly, return a smart format - if(selFormat.equals("M/d/yy")) { return "MM/dd/yyyy"; } - if(selFormat.equals("d/M/yy")) { return "dd/MM/yyyy"; } - } else { - selFormat = format; - } + String val = (String) sval; + // If the Trimmed submitted value is empty, return null + if (val.trim().length() == 0) { + return null; + } - return selFormat; - } - + Converter converter = getConverter(); + + // If the user supplied a converter, use it + if (converter != null) { + return converter.getAsObject(fc, this, val); + } + // Else we use our own converter + sloc = selectLocale(fc.getViewRoot().getLocale(), A.asString(getAttributes().get(A.LOCALE))); + sdf = selectDateFormat(sloc, A.asString(getAttributes().get(A.DTFORMAT))); + SimpleDateFormat format = null; + Object date = null; + try { + format = new SimpleDateFormat(sdf, sloc); + + format.setTimeZone(java.util.TimeZone.getDefault()); + + date = format.parse(val); + ((Date) date).setHours(12); + + } catch (ParseException e) { + this.setValid(false); + throw new ConverterException(getMessage("javax.faces.converter.DateTimeConverter.DATE", val, sdf, getLabel(fc))); + } + + return date; + } + + @Override + public void encodeBegin(FacesContext fc) throws IOException { + /* + * Popup + * + * Inline Adds a Div and Uses a Hidden Input + */ + + encodeHTML(fc); + + } + + /** + * Encodes the HTML for this context + * + * @param fc + * @throws IOException + */ + private void encodeHTML(FacesContext fc) throws IOException { + Map attrs = getAttributes(); + String clientId = getClientId(fc); + ResponseWriter rw = fc.getResponseWriter(); + // stz = selectTimeZone(attrs.get(A.TZ)); + + sloc = selectLocale(fc.getViewRoot().getLocale(), A.asString(attrs.get(A.LOCALE))); + sdf = selectDateFormat(sloc, A.asString(attrs.get(A.DTFORMAT))); + + // Debugging Locale and dateformat + // rw.write("DEBUG sloc='"+sloc+"', sdf='"+sdf+"' "); + + String dpId; + + Object v = getSubmittedValue(); + if (v == null) { + v = this.getValue(); + } + + /* + * 6 modes: 1) inline 2) popup (no icons) 3) popup-icon 4) icon-popup 5) toggle-icon (Default) 6) icon-toggle + */ + mode = A.asString(attrs.get(A.MODE), A.TOGGLEICON); + boolean inline = mode.equals(A.INLINE); + + if (inline) { // inline => div with ID + dpId = clientId + C.USCORE + H.DIV; + rw.startElement(H.DIV, this); + rw.writeAttribute(H.ID, dpId, null); + rw.endElement(H.DIV); + } else { // popup + dpId = clientId; + + if (!mode.equals(A.POPUP)) { // with icon => div with prepend/append style + rw.startElement(H.DIV, this); + rw.writeAttribute(H.CLASS, "input-group", H.CLASS); + if (mode.equals(A.ICONPOP) || mode.equals(A.ICONTOGGLE)) { + R.addonIcon(rw, this, CALENDAR, false); + } + } + } + String type = inline ? H.HIDDEN : H.TEXT; + + rw.startElement(H.INPUT, null); + rw.writeAttribute(H.ID, clientId, null); + rw.writeAttribute(H.NAME, clientId, null); + rw.writeAttribute(H.TYPE, type, null); + rw.writeAttribute(H.CLASS, "form-control", H.CLASS); + if (v != null) { + rw.writeAttribute(H.VALUE, getDateAsString(v, sdf, sloc), null); + } + + String ph = A.asString(attrs.get(A.PHOLDER)); + if (ph != null) { + rw.writeAttribute(H.PHOLDER, ph, null); + } + + if (A.toBool(attrs.get(A.DISABLED))) { + rw.writeAttribute(A.DISABLED, A.DISABLED, null); + } + if (A.toBool(attrs.get(A.READONLY))) { + rw.writeAttribute(A.READONLY, A.READONLY, null); + } + rw.endElement(H.INPUT); + + encodeJS(fc, rw, clientId, dpId); + if (mode.equals(A.POPICON) || mode.equals(A.TOGGLEICON)) { + R.addonIcon(rw, this, CALENDAR, false); + } + + if (!inline && !mode.equals(A.POPUP)) { + rw.endElement(H.DIV); + JQ.datePickerToggler(rw, clientId, clientId + C.USCORE + ADDON); + + } // Closes the popup prepend/append style div + + } + + private void encodeJS(FacesContext fc, ResponseWriter rw, String cId, String dpId) throws IOException { + Map attrs = getAttributes(); + + StringBuilder sb = new StringBuilder(150); + sb.append(JQ.DTFORMAT).append(C.COLON).append(C.QUOTE + convertFormat(sdf) + C.QUOTE).append(C.COMMA); + + if (A.toInt(attrs.get(JQ.NUMOFMONTHS)) > 0) { + sb.append(JQ.NUMOFMONTHS).append(C.COLON).append(attrs.get(JQ.NUMOFMONTHS)).append(C.COMMA); + } + if (A.toInt(attrs.get(JQ.FIRSTDAY)) > 0) { + sb.append(JQ.FIRSTDAY).append(C.COLON).append(attrs.get(JQ.FIRSTDAY)).append(C.COMMA); + } + if (A.toBool(attrs.get(JQ.SHOWBUTS))) { + sb.append(JQ.SHOWBUTS).append(C.COLON).append(C.TRUE).append(C.COMMA); + } + if (A.toBool(attrs.get(JQ.CHNGMONTH))) { + sb.append(JQ.CHNGMONTH).append(C.COLON).append(C.TRUE).append(C.COMMA); + } + if (A.toBool(attrs.get(JQ.CHNGYEAR))) { + sb.append(JQ.CHNGYEAR).append(C.COLON).append(C.TRUE).append(C.COMMA); + } + if (A.toBool(attrs.get(JQ.SHOWWK))) { + sb.append(JQ.SHOWWK).append(C.COLON).append(C.TRUE).append(C.COMMA); + } + + if (mode.equals(A.TOGGLEICON) || mode.equals(A.ICONTOGGLE)) { + sb.append(JQ.SHOWON).append(C.COLON).append(C.QUOTE + H.BUTTON + C.QUOTE).append(C.COMMA); + } + + /* + * Attributes that need decoding the Date + */ + if (attrs.get(JQ.MINDATE) != null) { + sb.append(JQ.MINDATE + C.COLON + C.QUOTE).append(getDateAsString(attrs.get(JQ.MINDATE), sdf, sloc)).append(C.QUOTE); + } + if (attrs.get(JQ.MAXDATE) != null) { + sb.append(JQ.MAXDATE + C.COLON + C.QUOTE).append(getDateAsString(attrs.get(JQ.MAXDATE), sdf, sloc)).append(C.QUOTE); + } + + // If user specifies a specific language to use then we render the datepicker using this language + // else we use the selected locale language + String l = A.asString(attrs.get(JQ.LANG)); + if (l == null) { + l = sloc.getLanguage(); + } + JQ.datePicker(rw, cId, dpId, sb.toString(), l); + } + + public static String getDateAsString(Object dt, String format, Locale locale) { + if (dt == null) { + return null; + } + + if (dt instanceof String) { + return (String) dt; + } else if (dt instanceof Date) { + SimpleDateFormat dtFormat = new SimpleDateFormat(format, locale); + dtFormat.setTimeZone(java.util.TimeZone.getDefault()); + // dateFormat.setTimeZone(tz); + + return dtFormat.format((Date) dt); + } else { + throw new IllegalArgumentException("Value could be either String or java.util.Date"); + } + } + + // Pass the attrs timezone value + /* + * public static TimeZone selectTimeZone(Object utz) { java.util.TimeZone selTimeZone; if (utz != null) { if (utz instanceof String) { + * selTimeZone = java.util.TimeZone.getTimeZone((String) utz); } else if (utz instanceof java.util.TimeZone) { selTimeZone = + * (java.util.TimeZone) utz; } else { throw new IllegalArgumentException("TimeZone should be either String or java.util.TimeZone"); } } + * else { selTimeZone = java.util.TimeZone.getDefault(); } return selTimeZone; } + */ + + // Pass facesContext.getViewRoot().getLocale() and attrs locale value + public Locale selectLocale(Locale vrloc, Object loc) { + java.util.Locale selLocale = vrloc; + + if (loc != null) { + if (loc instanceof String) { + selLocale = toLocale((String) loc); + } else if (loc instanceof java.util.Locale) { + selLocale = (java.util.Locale) loc; + } else { + throw new IllegalArgumentException("Type:" + loc.getClass() + " is not a valid locale type for DatePicker:" + + this.getClientId()); + } + } + + return selLocale; + } + + /** + * Selects the Date Pattern to use based on the given Locale if the input format is null + * + * @param locale + * Locale (may be the result of a call to selectLocale) + * @param format + * Input format String + * @return Date Pattern eg. dd/MM/yyyy + */ + public static String selectDateFormat(Locale locale, String format) { + String selFormat; + + if (format == null) { + selFormat = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale)).toPattern(); + // Since DateFormat.SHORT is silly, return a smart format + if (selFormat.equals("M/d/yy")) { + return "MM/dd/yyyy"; + } + if (selFormat.equals("d/M/yy")) { + return "dd/MM/yyyy"; + } + } else { + selFormat = format; + } + + return selFormat; + } + + /** + * Implementation from Apache Commons Lang + * + * @param str + * @return + */ + public static Locale toLocale(String str) { + if (str == null) { + return null; + } + int len = str.length(); + if (len != 2 && len != 5 && len < 7) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + char ch0 = str.charAt(0); + char ch1 = str.charAt(1); + if (ch0 < 'a' || ch0 > 'z' || ch1 < 'a' || ch1 > 'z') { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + if (len == 2) { + return new Locale(str, ""); + } else { + if (str.charAt(2) != '_') { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + char ch3 = str.charAt(3); + if (ch3 == '_') { + return new Locale(str.substring(0, 2), "", str.substring(4)); + } + char ch4 = str.charAt(4); + if (ch3 < 'A' || ch3 > 'Z' || ch4 < 'A' || ch4 > 'Z') { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + if (len == 5) { + return new Locale(str.substring(0, 2), str.substring(3, 5)); + } else { + if (str.charAt(5) != '_') { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + return new Locale(str.substring(0, 2), str.substring(3, 5), str.substring(6)); + } + } + } + + /** + * Converts a java Date format to a jQuery date format + * + * @param format + * Format to be converted + * @return converted format + */ + public static String convertFormat(String format) { + if (format == null) + return null; + else { + // day of week + format = format.replaceAll("EEE", "D"); + // year + format = format.replaceAll("yy", "y"); + + // month + if (format.indexOf("MMM") != -1) { + format = format.replaceAll("MMM", "M"); + } else { + format = format.replaceAll("M", "m"); + } + return format; + } + } + + @Override + public String getFamily() { + return COMPONENT_FAMILY; + } + + /** + *

+ * Creates and returns a FacesMessage for the specified Locale. + *

+ * Simplified and streamlined version of the implementation of Mojarra 2.2.8-b02 (see MessageFactory). + * + * @param locale + * - the target Locale + * @param messageId + * - the key of the message in the resource bundle + * @param params + * - substittion parameters + * + * @return a localized FacesMessage with the severity of FacesMessage.SEVERITY_ERROR + */ + public static FacesMessage getMessage(String messageId, String... params) { + String summary = null; + String detail = null; + ResourceBundle bundle; + String bundleName; + FacesContext context = FacesContext.getCurrentInstance(); + Locale locale = context.getViewRoot().getLocale(); + + // see if we have a user-provided bundle + Application app = (FacesContext.getCurrentInstance().getApplication()); + if (null != (bundleName = app.getMessageBundle())) { + if (null != (bundle = ResourceBundle.getBundle(bundleName, locale, Thread.currentThread().getContextClassLoader()))) { + // see if we have a hit + try { + summary = bundle.getString(messageId); + detail = bundle.getString(messageId + "_detail"); + } catch (MissingResourceException e) { + // ignore + } + } + } + + // we couldn't find a summary in the user-provided bundle + if (null == summary) { + // see if we have a summary in the app provided bundle + bundle = ResourceBundle.getBundle(FacesMessage.FACES_MESSAGES, locale, Thread.currentThread().getContextClassLoader()); + if (null == bundle) { + throw new NullPointerException(); + } + // see if we have a hit + try { + summary = bundle.getString(messageId); + detail = bundle.getString(messageId + "_detail"); + } catch (MissingResourceException e) { + // ignore + } + } + + for (int i = 0; i < params.length; i++) { + summary = summary.replace("{" + i + "}", params[i]); + detail = detail.replace("{" + i + "}", params[i]); + } + + // At this point, we have a summary and a bundle. + FacesMessage ret = new FacesMessage(FacesMessage.SEVERITY_ERROR, summary, detail); + ret.setSeverity(FacesMessage.SEVERITY_ERROR); + return ret; + } + /** - * Implementation from Apache Commons Lang - * @param str - * @return + *

Returns the label property from the specified + * component.

+ * Simplified and adapted version of the implementation of Mojarra 2.2.8-b02 (see MessageFactory). + * + * @param context - the FacesContext for the current request + * @param component - the component of interest + * + * @return the label, if any, of the component */ - public static Locale toLocale(String str) { - if(str == null) { - return null; + public String getLabel(FacesContext context) { + Object o = getAttributes().get("label"); + if (o == null || (o instanceof String && ((String) o).length() == 0)) { + ValueExpression vex = getValueExpression("label"); + if (null != vex) return (String)vex.getValue(context.getELContext()); } - int len = str.length(); - if(len != 2 && len != 5 && len < 7) { - throw new IllegalArgumentException("Invalid locale format: " + str); - } - char ch0 = str.charAt(0); - char ch1 = str.charAt(1); - if(ch0 < 'a' || ch0 > 'z' || ch1 < 'a' || ch1 > 'z') { - throw new IllegalArgumentException("Invalid locale format: " + str); - } - if(len == 2) { - return new Locale(str, ""); - } else { - if(str.charAt(2) != '_') { - throw new IllegalArgumentException("Invalid locale format: " + str); - } - char ch3 = str.charAt(3); - if(ch3 == '_') { - return new Locale(str.substring(0, 2), "", str.substring(4)); - } - char ch4 = str.charAt(4); - if(ch3 < 'A' || ch3 > 'Z' || ch4 < 'A' || ch4 > 'Z') { - throw new IllegalArgumentException("Invalid locale format: " + str); - } - if(len == 5) { - return new Locale(str.substring(0, 2), str.substring(3, 5)); - } else { - if(str.charAt(5) != '_') { - throw new IllegalArgumentException("Invalid locale format: " + str); - } - return new Locale(str.substring(0, 2), str.substring(3, 5), str.substring(6)); - } - } - } - - /** - * Converts a java Date format to a jQuery date format - * - * @param format Format to be converted - * @return converted format - */ - public static String convertFormat(String format) { - if(format == null) - return null; - else { - //day of week - format = format.replaceAll("EEE", "D"); - //year - format = format.replaceAll("yy", "y"); - - //month - if(format.indexOf("MMM") != -1) { - format = format.replaceAll("MMM", "M"); - } else { - format = format.replaceAll("M", "m"); - } - return format; - } - } - - @Override - public String getFamily() { - return COMPONENT_FAMILY; + // Use the "clientId" if there was no label specified. + return (String) getClientId(context); } - -} +} \ No newline at end of file