001    package edu.nrao.sss.webapp.faces.component;
002    
003    import javax.faces.component.UIInput;
004    import javax.faces.context.FacesContext;
005    import javax.faces.context.ResponseWriter;
006    import javax.faces.el.ValueBinding;
007    
008    import edu.nrao.sss.measure.Frequency;
009    import edu.nrao.sss.measure.FrequencyRange;
010    import edu.nrao.sss.measure.FrequencyUnits;
011    import edu.nrao.sss.util.EnumerationUtility;
012    import edu.nrao.sss.util.FormatString;
013    import edu.nrao.sss.util.StringUtil;
014    
015    import java.io.IOException;
016    import java.util.Map;
017    import java.util.EnumSet;
018    import java.math.BigDecimal;
019    
020    import org.apache.log4j.Logger;
021    
022    public class FrequencyRangeUIComponent extends UIInput
023    {
024            private static final Logger log = Logger.getLogger(FrequencyRangeUIComponent.class);
025      private static final StringUtil sUtil = StringUtil.getInstance();
026            private static final EnumSet<FrequencyUnits> unitSet = EnumerationUtility.getSharedInstance().getSelectableSetFor(FrequencyUnits.class);
027    
028            private Boolean enabled = null;
029            
030            public void encodeBegin(FacesContext context)
031                    throws IOException
032            {
033                    FrequencyRange r = (FrequencyRange)getValue();
034                    String styleClass = (String)getAttributes().get("styleClass");
035                    String style = (String)getAttributes().get("style");
036                    
037                    ResponseWriter writer = context.getResponseWriter();
038                    
039        String clientId = getClientId(context);
040                    String startId = clientId + "start";
041                    String endId = clientId + "end";
042                    String unitId = clientId + "units";
043                    
044                    writer.startElement("span", this);
045                    writer.writeAttribute("class", styleClass, null);
046                    writer.writeAttribute("style", style, null);
047                    writer.writeAttribute("id", clientId, null);
048                    
049                    //Label and input field for Low frequency.
050                    writer.startElement("label", this);
051                    writer.writeAttribute("for", startId, null);
052                    writer.write(" from ");
053                    writer.endElement("label");
054                    
055                    FrequencyUnits lowUnits = r.getLowFrequency().getUnits();
056                    if (!lowUnits.equals(r.getHighFrequency().getUnits()))
057                    {
058                            r.convertTo(lowUnits);
059                    }
060                            
061        BigDecimal low = r.getLowFrequency().getValue();
062        String lowStr = sUtil.formatNoScientificNotation(low);
063    
064                    if (isEnabled())
065                    {
066                            writer.startElement("input", this);
067                            writer.writeAttribute("type", "text", null);
068                            writer.writeAttribute("id", startId, null);
069                            writer.writeAttribute("name", startId, null);
070                            writer.writeAttribute("value", lowStr, null);
071                            writer.writeAttribute("onblur", "iceSubmitPartial(form, this, event); return false;", null);
072                            writer.endElement("input");
073                    }
074                    
075                    else
076                    {
077                            writer.startElement("span", this);
078                            writer.writeAttribute("id", startId, null);
079                            writer.write(lowStr);
080                            writer.endElement("span");
081                    }
082                    
083                    //Label and input field for High frequency.
084                    writer.startElement("label", this);
085                    writer.writeAttribute("for", endId, null);
086                    writer.write(" to ");
087                    writer.endElement("label");
088                    
089        BigDecimal high = r.getHighFrequency().getValue();
090        String highStr = sUtil.formatNoScientificNotation(high);
091    
092                    if (isEnabled())
093                    {
094                            writer.startElement("input", this);
095                            writer.writeAttribute("type", "text", null);
096                            writer.writeAttribute("id", endId, null);
097                            writer.writeAttribute("name", endId, null);
098                            writer.writeAttribute("value", highStr, null);
099                            writer.writeAttribute("onblur", "iceSubmitPartial(form, this, event); return false;", null);
100                            writer.endElement("input");
101                    }
102                    
103                    else
104                    {
105                            writer.startElement("span", this);
106                            writer.writeAttribute("id", endId, null);
107                            writer.write(highStr);
108                            writer.endElement("span");
109                    }
110                    
111                    //Label and select menu for frequency units.
112                    writer.startElement("label", this);
113                    writer.writeAttribute("for", unitId, null);
114                    writer.write(" in ");
115                    writer.endElement("label");
116                    
117                    if (isEnabled())
118                    {
119                            writer.startElement("select", this);
120                            writer.writeAttribute("name", unitId, null);
121                            writer.writeAttribute("onchange", "iceSubmitPartial(form, this, event); return false;", null);
122                            
123                            //Write out the option elements.
124                            for (FrequencyUnits unit : unitSet)
125                            {
126                                    writer.startElement("option", this);
127                                    if(unit.equals(lowUnits))
128                                    {
129                                            writer.writeAttribute("selected", "selected", null);
130                                    }
131                                    
132                                    writer.writeAttribute("label", unit.getSymbol(), null);
133                                    writer.writeAttribute("value", unit.getSymbol(), null);
134                                    
135                                    writer.write(unit.getSymbol());
136                                    writer.endElement("option");
137                            }
138                            
139                            writer.endElement("select");
140                    }
141                    
142                    else
143                    {
144                            writer.startElement("span", this);
145                            writer.writeAttribute("id", unitId, null);
146                            writer.write(lowUnits.getSymbol());
147                            writer.endElement("span");
148                    }
149                    writer.endElement("span");
150            }
151            
152            public void decode(FacesContext context)
153            {
154                    String startId = getClientId(context) + "start";
155                    String endId = getClientId(context) + "end";
156                    String unitId = getClientId(context) + "units";
157                    
158                    Map parms = context.getExternalContext().getRequestParameterMap();
159                    String start = (String)parms.get(startId);
160                    String end = (String)parms.get(endId);
161                    String unit = (String)parms.get(unitId);
162                    
163                    if (start == null || end == null || unit == null)
164        {
165          log.debug("calling setSubmittedValue(null)!");
166                            setSubmittedValue(null);
167        }
168                    
169                    else
170        {
171          log.debug("Submitting: " + start + unit + " - " + end + unit);
172          setValid(true);
173    
174          // Adding code to automatically adjust the 2 frequencies if only 1 is
175          // input and it causes the start to be > the end.
176          try
177          {
178            Frequency sf = Frequency.parse(start);
179            Frequency ef = Frequency.parse(end);
180    
181            if (sf.compareTo(ef) > 0)
182              end = start;
183          }
184    
185          // Ignore exceptions and just set the submitted value... it'll be
186          // re-parsed and those exceptions will be caught appropriately.
187          catch (Exception e) {}
188    
189                            setSubmittedValue(start + unit + FormatString.ENDPOINT_SEPARATOR + end + unit);
190        }
191            }
192            
193            public Boolean isEnabled()
194            {
195                    if (this.enabled != null)
196                            return this.enabled;
197                    
198                    ValueBinding vb = getValueBinding("enabled");
199                    if (vb != null)
200                    {
201                            Object val = vb.getValue(getFacesContext());
202                            
203                            if (val instanceof Boolean && val != null)
204                                    return (Boolean)val;
205                    }
206                    
207                    //else
208                    return Boolean.TRUE;
209            }
210            
211            public void setEnabled(Boolean e)
212            {
213                    this.enabled = e;
214            }
215            
216            public Object saveState(FacesContext context)
217            {
218                    Object[] state = new Object[2];
219                    state[0] = super.saveState(context);
220                    state[1] = this.enabled;
221                    
222                    return state;
223            }
224            
225            public void restoreState(FacesContext context, Object state)
226            {
227                    Object[] myState = (Object[])state;
228                    super.restoreState(context, myState[0]);
229                    setEnabled((Boolean)myState[1]);
230            }
231            
232            /**
233             * Overridden to be empty.
234             */
235            public void encodeEnd(FacesContext context) throws IOException {}
236            
237            /**
238             * Overridden to be empty.
239             */
240            public void encodeChildren(FacesContext context) throws IOException {}
241    
242      protected Object getConvertedValue(FacesContext ctx, Object v)
243      {
244        Object c = super.getConvertedValue(ctx, v);
245        log.debug("getConvertedValue returned: " + c);
246        return c;
247      }
248    
249      public void updateModel(javax.faces.context.FacesContext context)
250      {
251        log.debug("in updateModel: valid=" + isValid());
252        super.updateModel(context);
253      }
254    
255      public void processValidators(javax.faces.context.FacesContext context)
256      {
257        log.debug("before processValidators: valid=" + isValid());
258        super.processValidators(context);
259        log.debug("after processValidators: valid=" + isValid());
260      }
261    }