// Test attribute-property transparency public boolean doTestAttributesTransparency(ValueHolder vh, UIComponent newComp) { assertEquals(vh.getValue(), (String) newComp.getAttributes().get("value")); vh.setValue("foo"); assertEquals("foo", (String) newComp.getAttributes().get("value")); vh.setValue(null); assertNull((String) newComp.getAttributes().get("value")); newComp.getAttributes().put("value", "bar"); assertEquals("bar", vh.getValue()); newComp.getAttributes().put("value", null); assertNull(vh.getValue()); assertEquals(vh.getConverter(), (String) newComp.getAttributes().get("converter")); vh.setConverter(new LongConverter()); assertNotNull((Converter) newComp.getAttributes().get("converter")); assertTrue(newComp.getAttributes().get("converter") instanceof LongConverter); vh.setConverter(null); assertNull(newComp.getAttributes().get("converter")); newComp.getAttributes().put("converter", new ShortConverter()); assertNotNull(vh.getConverter()); assertTrue(vh.getConverter() instanceof ShortConverter); newComp.getAttributes().put("converter", null); assertNull(vh.getConverter()); return true; }
// Check that the properties on the specified components are equal @Override protected void checkProperties(UIComponent comp1, UIComponent comp2) { super.checkProperties(comp1, comp2); ValueHolder vh1 = (ValueHolder) comp1; ValueHolder vh2 = (ValueHolder) comp2; assertEquals(vh1.getValue(), vh2.getValue()); checkNumberConverter( (NumberConverter) vh1.getConverter(), (NumberConverter) vh2.getConverter()); }
// Test setting properties to valid values public void testPropertiesValid() throws Exception { super.testPropertiesValid(); ValueHolder vh = (ValueHolder) component; // value vh.setValue("foo.bar"); assertEquals("expected value", "foo.bar", vh.getValue()); vh.setValue(null); assertNull("erased value", vh.getValue()); // converter vh.setConverter(new LongConverter()); assertTrue("expected converter", vh.getConverter() instanceof LongConverter); vh.setConverter(null); assertNull("erased converter", vh.getConverter()); }
/** * Fetches a value from the shared cache. If values were wrapped, then they will be unwrapped * before being returned. If code requires direct access to the wrapper object as well, then this * call should not be used. * * <p>If a TransactionStats instance is passed in, then cache access stats are tracked, otherwise * - if null is passed in then stats are not tracked. * * @param key the key * @return Returns the value or <tt>null</tt> */ @SuppressWarnings("unchecked") public static <KEY extends Serializable, VAL> VAL getSharedCacheValue( SimpleCache<KEY, ValueHolder<VAL>> sharedCache, KEY key, TransactionStats stats) { final long startNanos = stats != null ? System.nanoTime() : 0; Object possibleWrapper = sharedCache.get(key); final long endNanos = stats != null ? System.nanoTime() : 0; if (possibleWrapper == null) { if (stats != null) { stats.record(startNanos, endNanos, OpType.GET_MISS); } return null; } else if (possibleWrapper instanceof ValueHolder) { if (stats != null) { stats.record(startNanos, endNanos, OpType.GET_HIT); } ValueHolder<VAL> wrapper = (ValueHolder<VAL>) possibleWrapper; return wrapper.getValue(); } else { if (stats != null) { stats.record(startNanos, endNanos, OpType.GET_MISS); } throw new IllegalStateException( "All entries for TransactionalCache must be put using TransactionalCache.putSharedCacheValue."); } }
public void doPostCommit( SimpleCache<Serializable, ValueHolder<BV>> sharedCache, Serializable key, boolean mutable, boolean allowEqualsCheck, boolean readOnly, TransactionStats stats) { ValueHolder<BV> sharedObjValueHolder = sharedCache.get(key); if (sharedObjValueHolder == null) { // Someone removed the value if (!mutable) { // We can assume that our value is correct because it's immutable TransactionalCache.putSharedCacheValue(sharedCache, key, value, stats); } else { // The value is mutable, so we must behave pessimistically i.e. leave the shared cache // empty } } else if (!mutable) { // We assume the configuration is correct and therefore, that we do not need to compare // the cached value with the updated value. This applies to null as well. } else if (allowEqualsCheck && EqualsHelper.nullSafeEquals(value, sharedObjValueHolder.getValue())) { // The value we want to write is the same as the one in the shared cache. // Don't write it unnecessarily. } else if (EqualsHelper.nullSafeEquals(originalValueHolder, sharedObjValueHolder)) { // The value in the cache did not change from what we observed before. // Update the value. TransactionalCache.putSharedCacheValue(sharedCache, key, value, stats); } else { // The shared value moved on in a way that was not possible to // validate. We pessimistically remove the entry. sharedCache.remove(key); } }
public void doPostCommit( SimpleCache<Serializable, ValueHolder<BV>> sharedCache, Serializable key, boolean mutable, boolean allowEqualsCheck, boolean readOnly, TransactionStats stats) { ValueHolder<BV> sharedObjValueHolder = sharedCache.get(key); if (sharedObjValueHolder == null) { // Nothing has changed, write it through TransactionalCache.putSharedCacheValue(sharedCache, key, value, stats); } else if (!mutable) { // Someone else put the object there // The assumption is that the value will be correct because the values are immutable // Don't write it unnecessarily. } else if (allowEqualsCheck && EqualsHelper.nullSafeEquals(value, sharedObjValueHolder.getValue())) { // The value we want to write is the same as the one in the shared cache. // Don't write it unnecessarily. } else { // The shared value moved on in a way that was not possible to // validate. We pessimistically remove the entry. sharedCache.remove(key); } }
// Test a pristine ValueHolderBase instance @Override public void testPristine() { super.testPristine(); ValueHolder vh = (ValueHolder) component; // Validate properties assertNull("no value", vh.getValue()); assertNull("no converter", vh.getConverter()); }
/** * Algorithm works as follows; - If it's an input component, submitted value is checked first * since it'd be the value to be used in case validation errors terminates jsf lifecycle - Finally * the value of the component is retrieved from backing bean and if there's a converter, converted * value is returned * * <p>- If the component is not a value holder, toString of component is used to support Facelets * UIInstructions. * * @param facesContext FacesContext instance * @param component UIComponent instance whose value will be returned * @return End text */ public static String getStringValueToRender(FacesContext facesContext, UIComponent component) { if (component instanceof ValueHolder) { if (component instanceof EditableValueHolder) { Object submittedValue = ((EditableValueHolder) component).getSubmittedValue(); if (submittedValue != null) { return submittedValue.toString(); } } ValueHolder valueHolder = (ValueHolder) component; Object value = valueHolder.getValue(); if (value == null) return ""; // first ask the converter if (valueHolder.getConverter() != null) { return valueHolder.getConverter().getAsString(facesContext, component, value); } // Try to guess else { ValueExpression expr = component.getValueExpression("value"); if (expr != null) { Class<?> valueType = expr.getType(facesContext.getELContext()); if (valueType != null) { Converter converterForType = facesContext.getApplication().createConverter(valueType); if (converterForType != null) return converterForType.getAsString(facesContext, component, value); } } } // No converter found just return the value as string return value.toString(); } else { // This would get the plain texts on UIInstructions when using Facelets String value = component.toString(); if (value != null) return value.trim(); else return ""; } }