001    package edu.nrao.sss.webapp.faces.component;
002    
003    import javax.faces.component.UIComponent;
004    import javax.faces.component.UIInput;
005    import javax.faces.component.NamingContainer;
006    import javax.faces.context.FacesContext;
007    import javax.faces.context.ResponseWriter;
008    import javax.faces.el.ValueBinding;
009    
010    import edu.nrao.sss.math.Polynomial;
011    import edu.nrao.sss.math.PolynomialTerm;
012    import edu.nrao.sss.util.StringUtil;
013    
014    import java.io.IOException;
015    import java.util.Map;
016    import java.util.Iterator;
017    
018    import org.apache.log4j.Logger;
019    
020    public class PolynomialUIComponent extends UIInput implements NamingContainer
021    {
022            private Boolean enabled = null;
023            private static Logger log = Logger.getLogger(PolynomialUIComponent.class);
024            
025            public void encodeBegin(FacesContext context)
026                    throws IOException
027            {
028                    Polynomial poly = (Polynomial)getValue();
029    
030                    String styleClass = (String)getAttributes().get("styleClass");
031                    String style = (String)getAttributes().get("style");
032    
033                    ResponseWriter writer = context.getResponseWriter();
034    
035        String id = getClientId(getFacesContext());
036                    String termIdPrefix = id + "term";
037                    
038                    writer.startElement("div", this);
039        writer.writeAttribute("id", id, null);
040                    if (styleClass != null)
041                            writer.writeAttribute("class", styleClass, null);
042    
043                    if (style != null)
044                            writer.writeAttribute("style", style, null);
045    
046                    StringUtil su = StringUtil.getInstance();
047                    if (isEnabled())
048                    {
049                            for (Iterator<PolynomialTerm> values = poly.getTerms().values().iterator(); values.hasNext();)
050                            {
051                                    PolynomialTerm t = values.next();
052                                    String tid = termIdPrefix + t.getExponent();
053    
054                                    writer.startElement("input", this);
055                                    writer.writeAttribute("type", "text", null);
056                                    writer.writeAttribute("size", "5", null);
057                                    writer.writeAttribute("id", tid, null);
058                                    writer.writeAttribute("name", tid, null);
059                                    writer.writeAttribute("value", su.formatNoScientificNotation(t.getCoefficient()), null);
060            writer.writeAttribute("onblur", "iceSubmitPartial(form, this, event); return false;", null);
061                                    writer.endElement("input");
062    
063                                    writer.write(" x");
064                                    writer.startElement("sup", this);
065                                    writer.write(String.valueOf(t.getExponent()));
066                                    writer.endElement("sup");
067    
068                                    if (values.hasNext())
069                                            writer.write(" + ");
070                            }
071                    }
072    
073                    else
074                    {
075                            for (Iterator<PolynomialTerm> values = poly.getTerms().values().iterator(); values.hasNext();)
076                            {
077                                    PolynomialTerm t = values.next();
078                                    String tid = termIdPrefix + t.getExponent();
079    
080                                    writer.startElement("span", this);
081                                    writer.writeAttribute("id", tid, null);
082                                    writer.write(su.formatNoScientificNotation(t.getCoefficient()) + "x");
083    
084                                    writer.startElement("sup", this);
085                                    writer.write(String.valueOf(t.getExponent()));
086                                    writer.endElement("sup");
087    
088                                    if (values.hasNext())
089                                            writer.write(" + ");
090    
091                                    writer.endElement("span");
092                            }
093                    }
094    
095                    writer.endElement("div");
096    
097                    //Start a div, then let our child UICommand render itself.
098                    writer.startElement("div", this);
099                    if (styleClass != null)
100                            writer.writeAttribute("class", styleClass, null);
101    
102                    if (style != null)
103                            writer.writeAttribute("style", style, null);
104            }
105            
106            public void encodeEnd(FacesContext context)
107                    throws IOException
108            {
109                    ResponseWriter writer = context.getResponseWriter();
110                    if (isEnabled())
111                    {
112                            String coeffId = getClientId(getFacesContext()) + "newTermCoef";
113                            String expId = getClientId(getFacesContext()) + "newTermExp";
114    
115                            //Now we add an input field and selectOneMenu.
116                            writer.startElement("input", this);
117                            writer.writeAttribute("type", "text", null);
118                            writer.writeAttribute("size", "5", null);
119                            writer.writeAttribute("id", coeffId, null);
120                            writer.writeAttribute("name", coeffId, null);
121                            writer.writeAttribute("value", "0", null);
122                            writer.endElement("input");
123    
124                            writer.startElement("select", this);
125                            writer.writeAttribute("name", expId, null);
126                            
127                            writer.startElement("option", this);
128                            writer.writeAttribute("value", "1", null);
129                            writer.write("x");
130                            writer.endElement("option");
131    
132                            writer.startElement("option", this);
133                            writer.writeAttribute("value", "2", null);
134    
135                            writer.write("x");
136                            writer.startElement("sup", this);
137                            writer.write("2");
138                            writer.endElement("sup");
139    
140                            writer.endElement("option");
141    
142                            writer.startElement("option", this);
143                            writer.writeAttribute("value", "3", null);
144    
145                            writer.write("x");
146                            writer.startElement("sup", this);
147                            writer.write("3");
148                            writer.endElement("sup");
149    
150                            writer.endElement("option");
151    
152                            writer.startElement("option", this);
153                            writer.writeAttribute("value", "4", null);
154    
155                            writer.write("x");
156                            writer.startElement("sup", this);
157                            writer.write("4");
158                            writer.endElement("sup");
159    
160                            writer.endElement("option");
161    
162                            writer.startElement("option", this);
163                            writer.writeAttribute("value", "5", null);
164    
165                            writer.write("x");
166                            writer.startElement("sup", this);
167                            writer.write("5");
168                            writer.endElement("sup");
169    
170                            writer.endElement("option");
171    
172                            writer.endElement("select");
173                    }
174                    
175                    writer.endElement("div");
176            }
177            
178            public void decode(FacesContext context)
179            {
180                    Map parms = context.getExternalContext().getRequestParameterMap();
181    
182                    String termIdPrefix = getClientId(getFacesContext()) + "term";
183                    int prefixLength = termIdPrefix.length();
184    
185                    StringBuilder poly = new StringBuilder();
186    
187                    StringUtil su = StringUtil.getInstance();
188    
189                    for (Iterator keys = parms.keySet().iterator(); keys.hasNext();)
190                    {
191                            String key = (String)keys.next();
192    
193                            //Found a term entry, append the exponent and value
194                            //(coefficient) to the submitted value.
195                            if (key.startsWith(termIdPrefix))
196                            {
197                                    //Take from the end of the prefix to the end of the string to
198                                    //be the exponent.
199                                    String exp = key.substring(prefixLength);
200                                    String coefStr = ((String)parms.get(key)).trim();
201    
202                                    Double coef;
203                                    try { coef = Double.parseDouble(coefStr); }
204                                    catch(NumberFormatException nfe) { coef = null; }
205                                    
206                                    if (coef != null && coef != 0)
207                                            poly.append(su.formatNoScientificNotation(coef) + "x^" + exp + " + ");
208                            }
209                    }
210    
211                    //remove the last " + "
212                    if (poly.length() >= 3)
213                            poly.setLength(poly.length() - 3);
214                    
215                    log.debug("Polynomial w/o extra terms: " + poly);
216                    if (getChildCount() == 1)
217                    {
218                            String buttonId = ((UIComponent)getChildren().get(0)).getClientId(context);
219                            log.debug("\tchild buttonId: " + buttonId);
220    
221                            //If the add term button was hit....
222                            if (parms.get(buttonId) != null)
223                            {
224                                    log.debug("\tAdding Extra term");
225                                    //Now we have to check to see if they entered a new term.
226                                    String newCoefId = getClientId(getFacesContext()) + "newTermCoef";
227                                    String newExpId = getClientId(getFacesContext()) + "newTermExp";
228    
229                                    String newCoefStr = (String)parms.get(newCoefId);
230                                    if (newCoefStr != null)
231                                            newCoefStr = newCoefStr.trim();
232    
233                                    String newExp = (String)parms.get(newExpId);
234                                    if (newExp != null)
235                                            newExp = newExp.trim();
236    
237                                    //if there's a valid non-zero value for the coeff, add it as a term.
238                                    Double newCoef;
239                                    try { newCoef = Double.parseDouble(newCoefStr); }
240                                    catch(NumberFormatException nfe) { newCoef = null; }
241                                    
242                                    if (newCoef != null && newCoef != 0)
243                                    {
244                                            if (poly.length() > 0)
245                                                    poly.append(" + ");
246    
247                                            poly.append(su.formatNoScientificNotation(newCoef) + "x^" + newExp);
248                                    }
249                            }
250                    }
251                    
252                    log.debug("Polynomial before the set submit: " + poly);
253                    
254        setValid(true);
255                    setSubmittedValue(poly.toString());
256            }
257            
258            public Boolean isEnabled()
259            {
260                    if (this.enabled != null)
261                            return this.enabled;
262                    
263                    ValueBinding vb = getValueBinding("enabled");
264                    if (vb != null)
265                    {
266                            Object val =  vb.getValue(getFacesContext());
267                            
268                            if (val instanceof Boolean && val != null)
269                                    return (Boolean)val;
270                    }
271                    
272                    //else
273                    return Boolean.TRUE;
274            }
275            
276            public void setEnabled(Boolean e)
277            {
278                    this.enabled = e;
279            }
280            
281            /**
282             * Adds the enabled status of this component to the state being saved.
283             */
284            public Object saveState(FacesContext context)
285            {
286                    Object[] state = new Object[2];
287                    state[0] = super.saveState(context);
288                    state[1] = this.enabled;
289                    return state;
290            }
291            
292            /**
293             * restores the enabled status of this component
294             */
295            public void restoreState(FacesContext context, Object state)
296            {
297                    Object[] mystate = (Object[])state;
298                    super.restoreState(context, mystate[0]);
299                    
300                    this.enabled = (Boolean)mystate[1];
301            }
302    }