Coverage Report - javax.faces.component.UIInput
 
Classes in this File Line Coverage Branch Coverage Complexity
UIInput
91%
260/286
81%
112/138
2.851
 
 1  
 /*
 2  
  * Copyright 2004-2011 the Seasar Foundation and the Others.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 13  
  * either express or implied. See the License for the specific language
 14  
  * governing permissions and limitations under the License.
 15  
  */
 16  
 package javax.faces.component;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.Iterator;
 20  
 import java.util.List;
 21  
 
 22  
 import javax.faces.application.FacesMessage;
 23  
 import javax.faces.context.FacesContext;
 24  
 import javax.faces.convert.Converter;
 25  
 import javax.faces.convert.ConverterException;
 26  
 import javax.faces.el.EvaluationException;
 27  
 import javax.faces.el.MethodBinding;
 28  
 import javax.faces.el.ValueBinding;
 29  
 import javax.faces.event.AbortProcessingException;
 30  
 import javax.faces.event.FacesEvent;
 31  
 import javax.faces.event.ValueChangeEvent;
 32  
 import javax.faces.event.ValueChangeListener;
 33  
 import javax.faces.internal.ConverterResource;
 34  
 import javax.faces.internal.FacesMessageUtil;
 35  
 import javax.faces.internal.UIComponentUtil;
 36  
 import javax.faces.internal.UIInputUtil;
 37  
 import javax.faces.internal.ValidatorLookupStrategy;
 38  
 import javax.faces.internal.ValidatorLookupStrategyUtil;
 39  
 import javax.faces.internal.ValidatorResource;
 40  
 import javax.faces.render.Renderer;
 41  
 import javax.faces.validator.Validator;
 42  
 import javax.faces.validator.ValidatorException;
 43  
 
 44  
 import org.seasar.framework.util.AssertionUtil;
 45  
 
 46  
 /**
 47  
  * @author shot
 48  
  * @author manhole
 49  
  */
 50  
 public class UIInput extends UIOutput implements EditableValueHolder {
 51  
 
 52  
     public static final String COMPONENT_FAMILY = "javax.faces.Input";
 53  
 
 54  
     public static final String COMPONENT_TYPE = "javax.faces.Input";
 55  
 
 56  
     public static final String CONVERSION_MESSAGE_ID = "javax.faces.component.UIInput.CONVERSION";
 57  
 
 58  
     public static final String REQUIRED_MESSAGE_ID = "javax.faces.component.UIInput.REQUIRED";
 59  
 
 60  2654
     private Object submittedValue = null;
 61  
 
 62  2654
     private boolean localValueSet = false;
 63  
 
 64  2654
     private boolean required = false;
 65  
 
 66  2654
     private boolean requiredSet = false;
 67  
 
 68  2654
     private boolean valid = false;
 69  
 
 70  2654
     private boolean validSet = false;
 71  
 
 72  2654
     private boolean immediate = false;
 73  
 
 74  2654
     private boolean immediateSet = false;
 75  
 
 76  2654
     private MethodBinding validatorBinding = null;
 77  
 
 78  2654
     private MethodBinding valueChangeMethod = null;
 79  
 
 80  2654
     private List validators = null;
 81  
 
 82  
     private static final String DEFAULT_RENDER_TYPE = "javax.faces.Text";
 83  
 
 84  1
     private static final Validator[] EMPTY_VALIDATOR_ARRAY = new Validator[0];
 85  
 
 86  2654
     public UIInput() {
 87  2654
         setRendererType(DEFAULT_RENDER_TYPE);
 88  2654
     }
 89  
 
 90  
     public String getFamily() {
 91  121
         return COMPONENT_FAMILY;
 92  
     }
 93  
 
 94  
     public Object getSubmittedValue() {
 95  239
         return submittedValue;
 96  
     }
 97  
 
 98  
     public void setSubmittedValue(Object submittedValue) {
 99  91
         this.submittedValue = submittedValue;
 100  91
     }
 101  
 
 102  
     public Object getValue() {
 103  347
         if (isLocalValueSet()) {
 104  173
             return getLocalValue();
 105  
         }
 106  174
         return super.getValue();
 107  
     }
 108  
 
 109  
     public void setValue(Object value) {
 110  195
         if ("".equals(value)) {
 111  30
             value = null;
 112  
         }
 113  195
         super.setValue(value);
 114  195
         setLocalValueSet(true);
 115  195
     }
 116  
 
 117  
     public boolean isLocalValueSet() {
 118  431
         return localValueSet;
 119  
     }
 120  
 
 121  
     public void setLocalValueSet(boolean localValueSet) {
 122  235
         this.localValueSet = localValueSet;
 123  235
     }
 124  
 
 125  
     public boolean isRequired() {
 126  234
         if (requiredSet) {
 127  63
             return required;
 128  
         }
 129  171
         Boolean value = (Boolean) ComponentUtil_.getValueBindingValue(this,
 130  
                 "required");
 131  171
         return (value != null) ? Boolean.TRUE.equals(value) : required;
 132  
     }
 133  
 
 134  
     public void setRequired(boolean required) {
 135  62
         this.required = required;
 136  62
         requiredSet = true;
 137  62
     }
 138  
 
 139  
     public boolean isValid() {
 140  256
         if (validSet) {
 141  236
             return valid;
 142  
         }
 143  20
         Boolean value = (Boolean) ComponentUtil_.getValueBindingValue(this,
 144  
                 "valid");
 145  20
         return (value != null) ? Boolean.TRUE.equals(value) : valid;
 146  
     }
 147  
 
 148  
     public void setValid(boolean valid) {
 149  194
         this.valid = valid;
 150  194
         validSet = true;
 151  194
     }
 152  
 
 153  
     public boolean isImmediate() {
 154  189
         if (immediateSet) {
 155  34
             return immediate;
 156  
         }
 157  155
         Boolean value = (Boolean) ComponentUtil_.getValueBindingValue(this,
 158  
                 "immediate");
 159  155
         return (value != null) ? Boolean.TRUE.equals(value) : immediate;
 160  
     }
 161  
 
 162  
     public void setImmediate(boolean immediate) {
 163  34
         this.immediate = immediate;
 164  34
         immediateSet = true;
 165  34
     }
 166  
 
 167  
     public MethodBinding getValidator() {
 168  41
         return validatorBinding;
 169  
     }
 170  
 
 171  
     public void setValidator(MethodBinding validatorBinding) {
 172  31
         this.validatorBinding = validatorBinding;
 173  31
     }
 174  
 
 175  
     public MethodBinding getValueChangeListener() {
 176  52
         return valueChangeMethod;
 177  
     }
 178  
 
 179  
     public void setValueChangeListener(MethodBinding valueChangeMethod) {
 180  41
         this.valueChangeMethod = valueChangeMethod;
 181  41
     }
 182  
 
 183  
     public void processDecodes(FacesContext context) {
 184  19
         AssertionUtil.assertNotNull("context", context);
 185  4
         if (!isRendered()) {
 186  0
             return;
 187  
         }
 188  4
         super.processDecodes(context);
 189  4
         if (isImmediate()) {
 190  3
             executeValidate(context);
 191  
         }
 192  3
     }
 193  
 
 194  
     public void processValidators(FacesContext context) {
 195  20
         AssertionUtil.assertNotNull("context", context);
 196  6
         if (!isRendered()) {
 197  0
             return;
 198  
         }
 199  6
         super.processValidators(context);
 200  6
         if (!isImmediate()) {
 201  5
             executeValidate(context);
 202  
         }
 203  5
     }
 204  
 
 205  
     public void processUpdates(FacesContext context) {
 206  19
         AssertionUtil.assertNotNull("context", context);
 207  4
         if (!isRendered()) {
 208  0
             return;
 209  
         }
 210  
         try {
 211  4
             updateModel(context);
 212  1
         } catch (RuntimeException e) {
 213  1
             context.renderResponse();
 214  1
             throw e;
 215  3
         }
 216  3
         super.processUpdates(context);
 217  3
         renderResponseIfNotValid(context);
 218  3
     }
 219  
 
 220  
     public void decode(FacesContext context) {
 221  20
         setValid(true);
 222  20
         super.decode(context);
 223  5
     }
 224  
 
 225  
     public void broadcast(FacesEvent event) throws AbortProcessingException {
 226  45
         super.broadcast(event);
 227  30
         if (event instanceof ValueChangeEvent) {
 228  15
             MethodBinding valueChangeListenerBinding = getValueChangeListener();
 229  15
             if (valueChangeListenerBinding != null) {
 230  
                 try {
 231  15
                     valueChangeListenerBinding.invoke(getFacesContext(),
 232  
                             new Object[] { event });
 233  0
                 } catch (EvaluationException e) {
 234  0
                     Throwable cause = e.getCause();
 235  0
                     if (cause != null &&
 236  
                             cause instanceof AbortProcessingException) {
 237  0
                         throw (AbortProcessingException) cause;
 238  
                     } else {
 239  0
                         throw e;
 240  
                     }
 241  15
                 }
 242  
             }
 243  
         }
 244  30
     }
 245  
 
 246  
     public void updateModel(FacesContext context) {
 247  6
         AssertionUtil.assertNotNull("context", context);
 248  6
         if (!isValid() || !isLocalValueSet()) {
 249  3
             return;
 250  
         }
 251  3
         final ValueBinding valueBinding = getValueBinding("value");
 252  3
         if (valueBinding == null) {
 253  0
             return;
 254  
         }
 255  
         try {
 256  3
             final Object localValue = getLocalValue();
 257  3
             valueBinding.setValue(context, localValue);
 258  2
             setValue(null);
 259  2
             setLocalValueSet(false);
 260  1
         } catch (RuntimeException e) {
 261  1
             Object[] args = { UIComponentUtil.getLabel(this) };
 262  1
             context.getExternalContext().log(e.getMessage(), e);
 263  1
             FacesMessageUtil.addErrorComponentMessage(context, this,
 264  
                     CONVERSION_MESSAGE_ID, args);
 265  1
             setValid(false);
 266  2
         }
 267  3
     }
 268  
 
 269  
     public void validate(FacesContext context) {
 270  22
         AssertionUtil.assertNotNull("context", context);
 271  22
         Object submittedValue = getSubmittedValue();
 272  22
         if (submittedValue == null) {
 273  2
             return;
 274  
         }
 275  20
         Object convertedValue = getConvertedValue(context, submittedValue);
 276  20
         if (!isValid()) {
 277  1
             return;
 278  
         }
 279  19
         validateValue(context, convertedValue);
 280  19
         if (!isValid()) {
 281  13
             return;
 282  
         }
 283  
 
 284  
         // Teeda Extension で target を指定した Converter をサポートするためのトリック。
 285  6
         if (isLocalValueSet() && getValue() == null) {
 286  0
             setLocalValueSet(false);
 287  0
             return;
 288  
         }
 289  
 
 290  6
         Object previous = getValue();
 291  6
         setValue(convertedValue);
 292  6
         setSubmittedValue(null);
 293  6
         if (compareValues(previous, convertedValue)) {
 294  3
             queueEvent(new ValueChangeEvent(this, previous, convertedValue));
 295  
         }
 296  6
     }
 297  
 
 298  
     protected Object getConvertedValue(FacesContext context,
 299  
             Object submittedValue) throws ConverterException {
 300  37
         Object value = submittedValue;
 301  
         try {
 302  37
             value = convertFromAnnotation(context, submittedValue);
 303  22
             if (value != null) {
 304  15
                 return value;
 305  
             }
 306  7
             Renderer renderer = getRenderer(context);
 307  7
             if (renderer != null) {
 308  2
                 value = convertFromRenderer(context, submittedValue, renderer);
 309  
             } else {
 310  5
                 value = convertFromType(context, submittedValue);
 311  
             }
 312  15
         } catch (ConverterException e) {
 313  15
             handleConverterException(context, e);
 314  7
         }
 315  22
         return value;
 316  
     }
 317  
 
 318  
     protected void handleConverterException(FacesContext context,
 319  
             ConverterException e) {
 320  15
         setValid(false);
 321  15
         FacesMessage facesMessage = e.getFacesMessage();
 322  15
         if (facesMessage != null) {
 323  15
             context.addMessage(getClientId(context), facesMessage);
 324  
         } else {
 325  0
             Object[] args = new Object[] { UIComponentUtil.getLabel(this) };
 326  0
             FacesMessageUtil.addErrorComponentMessage(context, this,
 327  
                     CONVERSION_MESSAGE_ID, args);
 328  
         }
 329  15
     }
 330  
 
 331  
     protected Object convertFromAnnotation(FacesContext context,
 332  
             Object submittedValue) {
 333  37
         ValueBinding vb = getValueBinding("value");
 334  37
         if (vb != null) {
 335  33
             String expression = vb.getExpressionString();
 336  33
             Converter converter = ConverterResource.getConverter(expression);
 337  33
             if (converter != null) {
 338  30
                 return converter
 339  
                         .getAsObject(
 340  
                                 context,
 341  
                                 this,
 342  
                                 (submittedValue instanceof String) ? (String) submittedValue
 343  
                                         : null);
 344  
             }
 345  
         }
 346  7
         return null;
 347  
     }
 348  
 
 349  
     protected Object convertFromRenderer(FacesContext context,
 350  
             Object submittedValue, Renderer renderer) throws ConverterException {
 351  2
         return renderer.getConvertedValue(context, this, submittedValue);
 352  
     }
 353  
 
 354  
     protected Object convertFromType(FacesContext context, Object submittedValue)
 355  
             throws ConverterException {
 356  5
         if (submittedValue instanceof String) {
 357  4
             Converter converter = getConverterWithType(context);
 358  4
             if (converter != null) {
 359  2
                 return converter
 360  
                         .getAsObject(
 361  
                                 context,
 362  
                                 this,
 363  
                                 (submittedValue instanceof String) ? (String) submittedValue
 364  
                                         : null);
 365  
             }
 366  
         }
 367  3
         return submittedValue;
 368  
     }
 369  
 
 370  
     protected void validateValue(FacesContext context, Object newValue) {
 371  52
         if (isValid() && isRequired() && UIInputUtil.isEmpty(newValue)) {
 372  14
             Object[] args = new Object[] { UIComponentUtil.getLabel(this) };
 373  14
             FacesMessageUtil.addErrorComponentMessage(context, this,
 374  
                     REQUIRED_MESSAGE_ID, args);
 375  14
             setValid(false);
 376  
         }
 377  52
         if (isValid() && !UIInputUtil.isEmpty(newValue)) {
 378  37
             validateFromAddedValidator(context, newValue);
 379  37
             validateFromBinding(context, newValue);
 380  
         }
 381  52
         validateForExtension(context, newValue);
 382  52
     }
 383  
 
 384  
     protected void validateForExtension(FacesContext context, Object value) {
 385  53
         Validator validator = null;
 386  53
         final ValidatorLookupStrategy strategy = ValidatorLookupStrategyUtil
 387  
                 .getValidatorLookupStrategy();
 388  53
         if (strategy != null) {
 389  0
             validator = strategy.findValidator(context, this, value);
 390  
         } else {
 391  53
             ValueBinding vb = this.getValueBinding("value");
 392  53
             if (vb != null) {
 393  32
                 String expression = vb.getExpressionString();
 394  32
                 validator = ValidatorResource.getValidator(expression);
 395  
             }
 396  
         }
 397  53
         if (validator == null) {
 398  37
             return;
 399  
         }
 400  
         try {
 401  16
             validator.validate(context, this, value);
 402  16
         } catch (ValidatorException e) {
 403  16
             handleValidationException(context, e);
 404  0
         }
 405  16
     }
 406  
 
 407  
     protected boolean compareValues(Object previous, Object value) {
 408  138
         if (previous == null && value == null) {
 409  11
             return false;
 410  
         }
 411  127
         if (previous == null || value == null) {
 412  46
             return true;
 413  
         }
 414  81
         return !previous.equals(value);
 415  
     }
 416  
 
 417  
     public void addValidator(Validator validator) {
 418  95
         AssertionUtil.assertNotNull("validator", validator);
 419  80
         if (validators == null) {
 420  33
             validators = new ArrayList();
 421  
         }
 422  80
         validators.add(validator);
 423  80
     }
 424  
 
 425  
     public Validator[] getValidators() {
 426  109
         if (validators == null) {
 427  18
             return EMPTY_VALIDATOR_ARRAY;
 428  
         }
 429  91
         return ((Validator[]) validators.toArray(new Validator[validators
 430  
                 .size()]));
 431  
     }
 432  
 
 433  
     public void removeValidator(Validator validator) {
 434  45
         if (validators != null) {
 435  30
             validators.remove(validator);
 436  
         }
 437  45
     }
 438  
 
 439  
     public void addValueChangeListener(ValueChangeListener listener) {
 440  60
         AssertionUtil.assertNotNull("listener", listener);
 441  45
         addFacesListener(listener);
 442  45
     }
 443  
 
 444  
     public ValueChangeListener[] getValueChangeListeners() {
 445  91
         return (ValueChangeListener[]) getFacesListeners(ValueChangeListener.class);
 446  
     }
 447  
 
 448  
     public void removeValueChangeListener(ValueChangeListener listener) {
 449  45
         removeFacesListener(listener);
 450  30
     }
 451  
 
 452  
     public Object saveState(FacesContext context) {
 453  76
         Object values[] = new Object[10];
 454  76
         values[0] = super.saveState(context);
 455  76
         values[1] = localValueSet ? Boolean.TRUE : Boolean.FALSE;
 456  76
         values[2] = required ? Boolean.TRUE : Boolean.FALSE;
 457  76
         values[3] = requiredSet ? Boolean.TRUE : Boolean.FALSE;
 458  76
         values[4] = valid ? Boolean.TRUE : Boolean.FALSE;
 459  76
         values[5] = immediate ? Boolean.TRUE : Boolean.FALSE;
 460  76
         values[6] = immediateSet ? Boolean.TRUE : Boolean.FALSE;
 461  76
         values[7] = saveAttachedState(context, validators);
 462  76
         values[8] = saveAttachedState(context, validatorBinding);
 463  76
         values[9] = saveAttachedState(context, valueChangeMethod);
 464  76
         return values;
 465  
     }
 466  
 
 467  
     public void restoreState(FacesContext context, Object state) {
 468  61
         Object values[] = (Object[]) state;
 469  61
         super.restoreState(context, values[0]);
 470  61
         localValueSet = ((Boolean) values[1]).booleanValue();
 471  61
         required = ((Boolean) values[2]).booleanValue();
 472  61
         requiredSet = ((Boolean) values[3]).booleanValue();
 473  61
         valid = ((Boolean) values[4]).booleanValue();
 474  61
         immediate = ((Boolean) values[5]).booleanValue();
 475  61
         immediateSet = ((Boolean) values[6]).booleanValue();
 476  61
         List restoredValidators = (List) restoreAttachedState(context,
 477  
                 values[7]);
 478  61
         if (restoredValidators != null) {
 479  15
             if (validators != null) {
 480  0
                 for (Iterator itr = restoredValidators.iterator(); itr
 481  0
                         .hasNext();) {
 482  0
                     validators.add(itr.next());
 483  
                 }
 484  
             } else {
 485  15
                 validators = restoredValidators;
 486  
             }
 487  
         }
 488  61
         validatorBinding = (MethodBinding) restoreAttachedState(context,
 489  
                 values[8]);
 490  61
         valueChangeMethod = (MethodBinding) restoreAttachedState(context,
 491  
                 values[9]);
 492  61
     }
 493  
 
 494  
     protected void executeValidate(FacesContext context) {
 495  
         try {
 496  9
             validate(context);
 497  2
         } catch (RuntimeException e) {
 498  2
             context.renderResponse();
 499  2
             throw e;
 500  7
         }
 501  7
         renderResponseIfNotValid(context);
 502  7
     }
 503  
 
 504  
     private Converter getConverterWithType(FacesContext context) {
 505  4
         Converter converter = getConverter();
 506  4
         if (converter != null) {
 507  1
             return converter;
 508  
         }
 509  3
         Class type = ComponentUtil_.getValueBindingType(this, "value");
 510  3
         if (ComponentUtil_.isPerformNoConversion(type)) {
 511  2
             return null;
 512  
         }
 513  
         try {
 514  1
             return ComponentUtil_.createConverter(context, type);
 515  0
         } catch (Exception ignore) {
 516  0
             return null;
 517  
         }
 518  
     }
 519  
 
 520  
     protected void renderResponseIfNotValid(FacesContext context) {
 521  10
         if (!isValid()) {
 522  3
             context.renderResponse();
 523  
         }
 524  10
     }
 525  
 
 526  
     protected void validateFromAddedValidator(FacesContext context, Object value) {
 527  37
         if (validators == null) {
 528  35
             return;
 529  
         }
 530  2
         for (Iterator itr = validators.iterator(); itr.hasNext();) {
 531  4
             Validator validator = (Validator) itr.next();
 532  
             try {
 533  4
                 validator.validate(context, this, value);
 534  1
             } catch (ValidatorException e) {
 535  1
                 handleValidationException(context, e);
 536  7
             }
 537  
         }
 538  2
     }
 539  
 
 540  
     protected void validateFromBinding(FacesContext context, Object value) {
 541  37
         if (validatorBinding == null) {
 542  35
             return;
 543  
         }
 544  
         try {
 545  2
             validatorBinding.invoke(context, new Object[] { context, this,
 546  
                     value });
 547  0
         } catch (EvaluationException e) {
 548  0
             Throwable cause = e.getCause();
 549  0
             if (cause instanceof ValidatorException) {
 550  0
                 ValidatorException ve = (ValidatorException) e.getCause();
 551  0
                 handleValidationException(context, ve);
 552  
             } else {
 553  0
                 throw e;
 554  
             }
 555  2
         }
 556  2
     }
 557  
 
 558  
     protected void handleValidationException(FacesContext context,
 559  
             ValidatorException e) {
 560  32
         setValid(false);
 561  32
         FacesMessage message = e.getFacesMessage();
 562  32
         if (message != null) {
 563  32
             message.setSeverity(FacesMessage.SEVERITY_ERROR);
 564  32
             context.addMessage(getClientId(context), message);
 565  
         }
 566  32
     }
 567  
 }