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

 * Author: Dmitry Abramov
 * Created: 22.12.2008 18:20:37
 * $Id$
 */
package com.haulmont.cuba.gui.xml.layout.loaders;

import com.haulmont.bali.util.ReflectionHelper;
import com.haulmont.cuba.gui.components.Component;
import com.haulmont.cuba.gui.components.Field;
import com.haulmont.cuba.gui.data.Datasource;
import com.haulmont.cuba.gui.xml.layout.ComponentsFactory;
import com.haulmont.cuba.gui.xml.layout.LayoutLoaderConfig;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Element;

import java.lang.reflect.Constructor;
import java.util.List;

public class AbstractFieldLoader extends ComponentLoader {
    protected LayoutLoaderConfig config;
    protected ComponentsFactory factory;

    public AbstractFieldLoader(Context context, LayoutLoaderConfig config, ComponentsFactory factory) {
        super(context);
        this.config = config;
        this.factory = factory;
    }

    public Component loadComponent(ComponentsFactory factory, Element element) throws InstantiationException, IllegalAccessException {
        final Field component = factory.createComponent(element.getName());

        assignXmlDescriptor(component, element);
        loadId(component, element);
        loadVisible(component, element);

        loadStyleName(component, element);

        loadCaption(component, element);
        loadEditable(component, element);
        loadRequired(component, element);

        loadDatasource(component, element);
        loadValidators(component, element);

        loadHeight(component, element);
        loadWidth(component, element);

        addAssignWindowTask(component);
        
        return component;
    }

    protected void loadDatasource(Field component, Element element) {
        final String datasource = element.attributeValue("datasource");
        if (!StringUtils.isEmpty(datasource)) {
            final Datasource ds = context.getDSContext().get(datasource);

            final String property = element.attributeValue("property");
            if (StringUtils.isEmpty(property))
                throw new IllegalStateException(
                        String.format(
                                "Can't set assign datasource '%s' for component '%s' due 'property' " +
                                "attribute is not defined",
                                datasource, component.getId()));

            component.setDatasource(ds, property);
        }
    }

    protected void loadRequired(Field component, Element element) {
        final String required = element.attributeValue("required");
        if (!StringUtils.isEmpty(required)) {
            component.setRequired(BooleanUtils.toBoolean(required));
        }
    }

    protected void loadValidators(Field component, Element element) {
        @SuppressWarnings({"unchecked"})
        final List<Element> validatorElements = element.elements("validator");
        
        for (Element validatorElement : validatorElements) {
            final String className = validatorElement.attributeValue("class");
            final Class<Field.Validator > aClass = ReflectionHelper.getClass(className);

            try {
                final Constructor<Field.Validator> constructor = aClass.getConstructor(Element.class);
                try {
                    final Field.Validator validator = constructor.newInstance(validatorElement);
                    component.addValidator(validator);
                } catch (Throwable e) {
                    throw new RuntimeException(e);
                }
            } catch (NoSuchMethodException e) {
                try {
                    final Field.Validator validator = aClass.newInstance();
                    component.addValidator(validator);
                } catch (Exception e1) {
                    throw new RuntimeException(e1);
                }
            }
        }
    }

}
@@ -1617,51 +1617,8 @@
 t);%0D
-%0A        loadRequired(component, element);%0D
 %0A%0D%0A 
@@ -1697,32 +1697,75 @@
 nent, element);%0D
+%0A        loadRequired(component, element);%0D
 %0A%0D%0A        loadH
@@ -1871,34 +1871,26 @@
 omponent);%0D%0A
-        
 %0D%0A
+
         retu
@@ -2499,16 +2499,24 @@
 y' %22 +%0D%0A
+        
         
@@ -2568,16 +2568,16 @@
 ined%22,%0D%0A
-
         
@@ -3180,18 +3180,10 @@
 );%0D%0A
-        
 %0D%0A
+
     
@@ -3316,24 +3316,24 @@
 (%22class%22);%0D%0A
+
             
@@ -3359,17 +3359,16 @@
 alidator
- 
 %3E aClass

fix required property