/*
 * Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
 * Haulmont Technology proprietary and confidential.
 * Use is subject to license terms.

 * Author: Dmitry Abramov
 * Created: 29.12.2008 17:16:49
 * $Id$
 */
package com.haulmont.cuba.web.gui.data;

import com.haulmont.chile.core.datatypes.Datatype;
import com.haulmont.chile.core.datatypes.Datatypes;
import com.haulmont.chile.core.model.Instance;
import com.haulmont.chile.core.model.MetaPropertyPath;
import com.haulmont.chile.core.model.Range;
import com.haulmont.chile.core.model.utils.InstanceUtils;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.global.MessageUtils;
import com.haulmont.cuba.core.global.UserSessionProvider;
import com.haulmont.cuba.gui.data.Datasource;
import com.haulmont.cuba.gui.data.DatasourceListener;
import com.vaadin.data.Property;

import java.text.ParseException;

public class PropertyWrapper extends AbstractPropertyWrapper {
    protected MetaPropertyPath propertyPath;

    private static final long serialVersionUID = 5863216328152195113L;

    public PropertyWrapper(Object item, MetaPropertyPath propertyPath, DsManager dsManager) {
        this.item = item;
        this.propertyPath = propertyPath;
        if (item instanceof Datasource) {
            dsManager.addListener(new DatasourceListener<Entity>() {
                public void itemChanged(Datasource<Entity> ds, Entity prevItem, Entity item) {
                    fireValueChangeEvent();
                }

                public void stateChanged(Datasource<Entity> ds, Datasource.State prevState, Datasource.State state) {
                }

                public void valueChanged(Entity source, String property, Object prevValue, Object value) {
                    if (property.equals(PropertyWrapper.this.propertyPath.toString()))
                        fireValueChangeEvent();
                }
            });
        }
    }

    public Object getValue() {
        final Instance instance = getInstance();
        Object value = instance == null ? null : InstanceUtils.getValueEx(instance, propertyPath.getPath());
        if (value == null && propertyPath.getRange().isDatatype()
                && propertyPath.getRange().asDatatype().equals(Datatypes.getInstance().get(Boolean.class))) {
            value = Boolean.FALSE;
        }
        return value;
    }

    protected Instance getInstance() {
        if (item instanceof Datasource) {
            final Datasource ds = (Datasource) item;
            if (Datasource.State.VALID.equals(ds.getState())) {
                return ds.getItem();
            } else {
                return null;
            }
        } else {
            return (Instance) item;
        }
    }

    public void setValue(Object newValue) throws ReadOnlyException, ConversionException {
        final Instance instance = getInstance();
        if (instance == null) throw new IllegalStateException("Instance is null");

        InstanceUtils.setValueEx(instance, propertyPath.getPath(), valueOf(newValue));
    }

    protected Object valueOf(Object newValue) throws Property.ConversionException {
        if (newValue == null)
            return newValue;
        final Range range = propertyPath.getRange();
        if (range == null) {
            return newValue;
        } else {
            final Object obj;
            if (range.isDatatype()) {
                Datatype<Object> datatype = range.asDatatype();
                if (newValue instanceof String) {
                    try {
                        obj = datatype.parse((String) newValue, UserSessionProvider.getLocale());
                    } catch (ParseException e) {
                        throw new Property.ConversionException(e);
                    }
                } else {
                    if (newValue.getClass().equals(datatype.getJavaClass())) {
                        return newValue;
                    } else {
                        Datatype newValueDatatype = Datatypes.get(newValue.getClass());
                        String str = newValueDatatype.format(newValue);
                        try {
                            obj = datatype.parse(str);
                        } catch (ParseException e) {
                            throw new Property.ConversionException(e);
                        }
                    }
                }
            } else {
                obj = newValue;
            }
            return obj;
        }
    }

    public Class getType() {
        return propertyPath.getRangeJavaClass();
    }

    @Override
    public String toString() {
        final Object value = getValue();
        return MessageUtils.format(value, propertyPath.getMetaProperty());
    }
}

@@ -1380,24 +1380,51 @@
 ntity%3E() %7B%0D%0A
+                @Override%0D%0A
             
@@ -1565,32 +1565,59 @@
            %7D%0D%0A%0D%0A
+                @Override%0D%0A
                 
@@ -1732,32 +1732,59 @@
            %7D%0D%0A%0D%0A
+                @Override%0D%0A
                 
@@ -2060,32 +2060,47 @@
     %7D%0D%0A    %7D%0D%0A%0D%0A
+    @Override%0D%0A
     public Objec
@@ -2419,22 +2419,8 @@
 pes.
-getInstance().
 get(
@@ -2892,32 +2892,47 @@
     %7D%0D%0A    %7D%0D%0A%0D%0A
+    @Override%0D%0A
     public void 
@@ -3048,32 +3048,34 @@
 getInstance();%0D%0A
+%0D%0A
         if (inst
@@ -3083,73 +3083,22 @@
 nce 
-=
+!
 = null)
- throw new IllegalStateException(%22Instance is null%22);%0D%0A%0D%0A
+%0D%0A    
     
@@ -4654,24 +4654,39 @@
 %7D%0D%0A    %7D%0D%0A%0D%0A
+    @Override%0D%0A
     public C

Fix PropertyWrapper for work with null instance