/** * Analogous to {@link #readPropertiesFromValuesStorage(ValuesStorage, Property[])} but adds the values to the * model as set values, i.e. marks the model as dirty with these values. */ public void setPropertiesFromValuesStorage(ValuesStorage values, Property<?>... properties) { if (values != null) { if (setValues == null) { setValues = newValuesStorage(); } for (Property<?> property : properties) { String key = property.getName(); if (values.containsKey(key)) { Object value = property.accept(valueCastingVisitor, values.get(key)); if (shouldSaveValue(key, value)) { this.setValues.put(property.getName(), value, true); } } } } }
/** * {@inheritDoc} */ @Override public void putAll(ValuesStorage other) { if (other instanceof MapValuesStorage) { values.putAll(((MapValuesStorage) other).values); } else { Set<Map.Entry<String, Object>> valuesSet = other.valueSet(); for (Map.Entry<String, Object> entry : valuesSet) { put(entry.getKey(), entry.getValue(), false); } } }
protected boolean shouldSaveValue(String name, Object newValue) { // we've already decided to save it, so overwrite old value if (setValues.containsKey(name)) { return true; } // values contains this key, we should check it out if (values != null && values.containsKey(name)) { Object value = values.get(name); if (value == null) { if (newValue == null) { return false; } } else if (value.equals(newValue)) { return false; } } // otherwise, good to save return true; }
putNull(key); } else if (value instanceof Boolean) { put(key, (Boolean) value); } else if (value instanceof Byte) { put(key, (Byte) value); } else if (value instanceof Double) { put(key, (Double) value); } else if (value instanceof Float) { put(key, (Float) value); } else if (value instanceof Integer) { put(key, (Integer) value); } else if (value instanceof Long) { put(key, (Long) value); } else if (value instanceof Short) { put(key, (Short) value); } else if (value instanceof String) { put(key, (String) value); } else if (value instanceof byte[]) { put(key, (byte[]) value); } else if (errorOnFail) { throw new UnsupportedOperationException("Could not handle type " + value.getClass());
/** * Clear the value for the given {@link Property} * * @param property the property to clear */ public void clearValue(Property<?> property) { if (setValues != null && setValues.containsKey(property.getName())) { setValues.remove(property.getName()); } if (values != null && values.containsKey(property.getName())) { values.remove(property.getName()); } }
@Override public Void visitBlob(Property<byte[]> property, ValuesStorage dst, Object value) { dst.put(property.getName(), (byte[]) value); return null; }
@SuppressWarnings("unchecked") private <TYPE> TYPE getFromValues(Property<TYPE> property, ValuesStorage values) { Object value = values.get(property.getName()); // Will throw a ClassCastException if the value could not be coerced to the correct type return (TYPE) property.accept(valueCastingVisitor, value); }
/** * Copies values from the given {@link ValuesStorage} into the model. The values will be added to the model as read * values (i.e. will not be considered set values or mark the model as dirty). */ public void readPropertiesFromValuesStorage(ValuesStorage values, Property<?>... properties) { prepareToReadProperties(); if (values != null) { for (Property<?> property : properties) { if (values.containsKey(property.getName())) { this.values.put(property.getName(), getFromValues(property, values), true); } } } }
private boolean valuesContainsKey(ValuesStorage values, Property<?> property) { return values != null && values.containsKey(property.getName()); }
/** * @return true if this model has values that have been changed */ public boolean isModified() { return setValues != null && setValues.size() > 0; }
/** * Transfers all set values into values. This usually occurs when a model is saved in the database so that future * saves will not need to write all the data again. Users should not usually need to call this method. */ public void markSaved() { if (values == null) { values = setValues; } else if (setValues != null) { values.putAll(setValues); } setValues = null; }
public void save(Property<?> property, ValuesStorage newStore, Object value) { if (value != null) { property.accept(this, newStore, value); } else { newStore.putNull(property.getName()); } }
/** * Use merged values to compare two models to each other. Must be of exactly the same class. */ @Override public boolean equals(Object other) { return other != null && getClass().equals(other.getClass()) && getMergedValues() .equals(((AbstractModel) other).getMergedValues()); }
@Override public int hashCode() { return getMergedValues().hashCode() ^ getClass().hashCode(); }
/** * Utility method to get the rowid of the model, if it exists. * * @return {@value #NO_ID} if this model was not added to the database */ public long getRowId() { Long id = null; String idPropertyName = getRowIdProperty().getName(); if (setValues != null && setValues.containsKey(idPropertyName)) { id = (Long) setValues.get(idPropertyName); } else if (values != null && values.containsKey(idPropertyName)) { id = (Long) values.get(idPropertyName); } if (id != null) { return id; } return NO_ID; }
@Override public Void visitString(Property<String> property, ValuesStorage dst, Object value) { dst.put(property.getName(), (String) value); return null; }
/** * @param property the {@link Property} to check * @return true if a value for this property has been read from the database or set by the user, and the "active" * value stored (i.e. the value that would be returned by a call to {@link #get(Property)}) is not null. Does not * take into account column default values. */ public boolean containsNonNullValue(Property<?> property) { if (valuesContainsKey(setValues, property)) { return setValues.get(property.getName()) != null; } else if (valuesContainsKey(values, property)) { return values.get(property.getName()) != null; } return false; }
/** * Copies values from the given {@link ValuesStorage} into the model. The values will be added to the model as read * values (i.e. will not be considered set values or mark the model as dirty). */ public void readPropertiesFromValuesStorage(ValuesStorage values, Property<?>... properties) { prepareToReadProperties(); if (values != null) { for (Property<?> property : properties) { if (values.containsKey(property.getName())) { this.values.put(property.getName(), getFromValues(property, values), true); } } } }
/** * Clear the value for the given {@link Property} * * @param property the property to clear */ public void clearValue(Property<?> property) { if (setValues != null && setValues.containsKey(property.getName())) { setValues.remove(property.getName()); } if (values != null && values.containsKey(property.getName())) { values.remove(property.getName()); } }