/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package de.unioninvestment.eai.portal.support.vaadin.container; import java.util.Arrays; import com.vaadin.data.Property; /** * Erweiterte Schnittstelle für {@link Property}, die für das CRUD-Portlet * benötigt wird. * * @author carsten.mjartan */ public class GenericProperty<T> implements Property<T> { /** * wird geworfen beim Versuch {@code null} als Wert von * {@link GenericProperty} zu setzen. */ public static class RequiredException extends RuntimeException { private static final long serialVersionUID = 1L; public RequiredException(String message) { super(message); } } private static final long serialVersionUID = 1L; private final Column metaData; private boolean readOnly; private GenericItem item; private T value; private T newValue; public GenericProperty(Column column, T value) { this.metaData = column; this.readOnly = metaData.isReadOnly(); this.value = value; this.newValue = value; } /** * @return <code>true</code>, falls das Property nicht NULLable ist */ public boolean isRequired() { return metaData.isRequired(); } /** * @return <code>true</code>, falls das Property seit dem letzten commit() * geändert wurde */ public boolean isModified() { return (this.value == null && newValue != null) || (this.value != null && !this.value.equals(newValue)); } /** * Informiert das Property, dass der Feldinhalt in das Backend übernommen * wurde. Der Modified-Status wird zurückgesetzt. */ public void commit() { if (isModified()) { this.value = newValue; } } @Override public T getValue() { return isModified() ? newValue : value; } @Override public void setValue(T newValue) throws ReadOnlyException { if (isReadOnly()) { throw new ReadOnlyException("Field " + metaData.getName() + " is readOnly"); } if (newValue != null && !getType().isAssignableFrom(newValue.getClass())) { throw new RuntimeException("Cannot convert value of type '" + newValue.getClass().getName() + "' to type '" + getType().getName() + "'"); } if (isRequired() && newValue == null) { throw new RequiredException("Field " + metaData.getName() + " is required"); } this.newValue = newValue; item.getContainer().itemChangeNotification(item); } @SuppressWarnings("unchecked") @Override public Class<? extends T> getType() { return (Class<? extends T>) metaData.getType(); } @Override public boolean isReadOnly() { return readOnly; } @Override public void setReadOnly(boolean newStatus) { this.readOnly = metaData.isReadOnly() || newStatus; } public void setItem(GenericItem item) { this.item = item; } public String getName() { return metaData.getName(); } @Override public String toString() { Object val = getValue(); if (val == null) { return null; } if (val.getClass().isArray()) { return Arrays.toString((Object[]) val); } return val.toString(); } }