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    import javax.faces.convert.ConverterException;
008    import javax.faces.application.FacesMessage;
009    
010    import org.apache.log4j.Logger;
011    
012    import edu.nrao.sss.model.project.scan.ScanIntent;
013    import edu.nrao.sss.model.project.scan.ScanMode;
014    import edu.nrao.sss.util.EnumerationUtility;
015    
016    import java.io.IOException;
017    import java.util.Set;
018    import java.util.Map;
019    import java.util.HashSet;
020    
021    /**
022     * Renders a table with 2 columns: A column of check boxes and a column of
023     * ScanIntent names. All the checked Intents get added to a set, and that set
024     * is bound to the value attribute.
025     */
026    public class ScanIntentsUIComponent extends UIInput
027    {
028            private static Logger log = Logger.getLogger(ScanIntentsUIComponent.class);
029            private static final Set<ScanIntent> defaultScanIntents = EnumerationUtility.getSharedInstance().getSelectableSetFor(ScanIntent.class);
030            private Boolean enabled = null;
031            private ScanMode scanMode = null;
032            
033            @SuppressWarnings("unchecked")
034            public void encodeBegin(FacesContext context)
035                    throws IOException
036            {
037                    Set<ScanIntent> intents = (Set<ScanIntent>)getValue();
038                    String styleClass = (String)getAttributes().get("styleClass");
039                    String style = (String)getAttributes().get("style");
040                    
041                    ResponseWriter writer = context.getResponseWriter();
042                    
043                    writer.startElement("table", this);
044                    writer.writeAttribute("class", styleClass, null);
045                    writer.writeAttribute("style", style, null);
046                    
047                    String clientId = getClientId(context);
048                    Set<ScanIntent> values = null;
049                    
050                    ScanMode sm = getScanMode();
051                    if (sm != null)
052                    {
053                            values = sm.getValidIntents();
054                    }
055                    
056                    else
057                    {
058                            values = defaultScanIntents;
059                    }
060    
061                    if (isEnabled())
062                    {
063                            for (ScanIntent si : values)
064                            {
065                                    String siId = clientId + "_" + si.toString();
066    
067                                    writer.startElement("tr", this);
068    
069                                    //Write out the checkbox.
070                                    writer.startElement("td", this);
071    
072                                    writer.startElement("input", this);
073                                    writer.writeAttribute("name", siId, null);
074                                    writer.writeAttribute("id", siId, null);
075                                    writer.writeAttribute("type", "checkbox", null);
076    
077                                    if (intents.contains(si))
078                                            writer.writeAttribute("checked", "true", null);
079    
080                                    //changes to/from Calibration intents triggers interface changes,
081                                    //so we have to make sure we have an onchange submit the form here.  
082                                    if (si.name().contains("CALIBRATION"))
083                                    {
084                                            writer.writeAttribute("onchange",
085                                                "this.form.elements['autoScroll'].value=getScrolling();this.form.submit();",
086                                                    null
087                                            );
088                                    }
089                                    
090                                    writer.endElement("input");
091    
092                                    writer.endElement("td");
093    
094                                    //Write out the name of the Intent
095                                    writer.startElement("td", this);
096                                    writer.startElement("label", this);
097                                    writer.writeAttribute("for", siId, null);
098                                    writer.write(si.toString());
099                                    writer.endElement("label");
100                                    writer.endElement("td");
101    
102                                    writer.endElement("tr");
103                            }
104                    }
105    
106                    else
107                    {
108                            for (ScanIntent si : values)
109                            {
110                                    String siId = clientId + "_" + si.toString();
111    
112                                    writer.startElement("tr", this);
113    
114                                    //Write out the checkbox.
115                                    writer.startElement("td", this);
116    
117                                    writer.startElement("input", this);
118                                    writer.writeAttribute("name", siId, null);
119                                    writer.writeAttribute("type", "checkbox", null);
120                                    writer.writeAttribute("disabled", "true", null);
121                                    writer.writeAttribute("value", (intents.contains(si))? "on" : "off", null);
122                                    writer.endElement("input");
123    
124                                    writer.endElement("td");
125    
126                                    //Write out the name of the Intent
127                                    writer.startElement("td", this);
128                                    writer.write(si.toString());
129                                    writer.endElement("td");
130    
131                                    writer.endElement("tr");
132                            }
133                    }
134    
135                    writer.endElement("table");
136            }
137            
138            /**
139             * Overridden to be empty.
140             */
141            public void encodeEnd(FacesContext context)
142                    throws IOException
143            {
144            
145            }
146            
147            /**
148             * Overridden to be empty.
149             */
150            public void encodeChildren(FacesContext context)
151                    throws IOException
152            {
153            
154            }
155            
156            public void decode(FacesContext context)
157            {
158                    Map parms = context.getExternalContext().getRequestParameterMap();
159                    String clientId = getClientId(context);
160                    Set<ScanIntent> intents = new HashSet<ScanIntent>();
161                    ScanMode sm = getScanMode();
162                    
163                    Set<ScanIntent> values = null;
164                    if (sm != null)
165                    {
166                            values = sm.getValidIntents();
167                    }
168                    
169                    else
170                    {
171                            values = defaultScanIntents;
172                    }
173                    
174                    //Look for ALL values instead of trying to parse numbers off of strings.
175                    for (ScanIntent si : values)
176                    {
177                            String siId = clientId + "_" + si.toString();
178    
179                            String value = (String)parms.get(siId);
180                            //if value is on, then add corresponding ScanIntent to the set.
181                            if (value != null && value.compareToIgnoreCase("on") == 0)
182                            {
183                                    intents.add(si);
184                            }
185                    }
186    
187                    setSubmittedValue(intents);
188            }
189            
190            protected Object getConvertedValue(FacesContext context, Object newSubmittedValue)
191                    throws ConverterException
192            {
193                    if (newSubmittedValue instanceof Set)
194                    {
195                            return newSubmittedValue;
196                    }
197    
198                    else
199                    {
200                            log.warn("Couldn't convert value of type: " + newSubmittedValue.getClass());
201                            throw new ConverterException(new FacesMessage("Couldn't convert value of type: " + newSubmittedValue.getClass()));
202                    }
203            }
204    
205            public boolean isEnabled()
206            {
207                    if (this.enabled != null)
208                            return this.enabled;
209                    
210                    ValueBinding vb = getValueBinding("enabled");
211                    if (vb != null)
212                    {
213                            Object val = vb.getValue(getFacesContext());
214                            
215                            if (val instanceof Boolean && val != null)
216                                    return (Boolean)val;
217                    }
218                    
219                    //else
220                    return Boolean.TRUE;
221            }
222            
223            public void setEnabled(Boolean e)
224            {
225                    this.enabled = e;
226            }
227            
228            public ScanMode getScanMode()
229            {
230                    if (this.scanMode != null)
231                            return this.scanMode;
232                    
233                    ValueBinding vb = getValueBinding("scanMode");
234                    if (vb != null)
235                    {
236                            Object val = vb.getValue(getFacesContext());
237                            
238                            if (val instanceof ScanMode && val != null)
239                                    return (ScanMode)val;
240                    }
241                    
242                    //else
243                    return null;
244            }
245            
246            public void setScanMode(ScanMode sm)
247            {
248                    this.scanMode = sm;
249            }
250                    
251            public Object saveState(FacesContext context)
252            {
253                    Object[] state = new Object[3];
254                    state[0] = super.saveState(context);
255                    state[1] = this.enabled;
256                    state[2] = this.scanMode;
257                    
258                    return state;
259            }
260            
261            public void restoreState(FacesContext context, Object state)
262            {
263                    Object[] myState = (Object[])state;
264                    super.restoreState(context, myState[0]);
265                    setEnabled((Boolean)myState[1]);
266                    setScanMode((ScanMode)myState[2]);
267            }
268    }