org.yes.cart.web.page.component.customer.address.AddressForm.java Source code

Java tutorial

Introduction

Here is the source code for org.yes.cart.web.page.component.customer.address.AddressForm.java

Source

/*
 * Copyright 2009 Denys Pavlov, Igor Azarnyi
 *
 *    Licensed 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 org.yes.cart.web.page.component.customer.address;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.AbstractChoice;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.SubmitLink;
import org.apache.wicket.markup.html.link.AbstractLink;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yes.cart.constants.ServiceSpringKeys;
import org.yes.cart.domain.entity.*;
import org.yes.cart.domain.i18n.I18NModel;
import org.yes.cart.shoppingcart.ShoppingCart;
import org.yes.cart.shoppingcart.ShoppingCartCommand;
import org.yes.cart.shoppingcart.ShoppingCartCommandFactory;
import org.yes.cart.util.ShopCodeContext;
import org.yes.cart.web.application.ApplicationDirector;
import org.yes.cart.web.page.AbstractWebPage;
import org.yes.cart.web.page.component.customer.dynaform.EditorFactory;
import org.yes.cart.web.page.component.util.CountryModel;
import org.yes.cart.web.page.component.util.CountryRenderer;
import org.yes.cart.web.page.component.util.StateModel;
import org.yes.cart.web.page.component.util.StateRenderer;
import org.yes.cart.web.support.constants.StorefrontServiceSpringKeys;
import org.yes.cart.web.support.i18n.I18NWebSupport;
import org.yes.cart.web.support.service.AddressBookFacade;
import org.yes.cart.web.util.WicketUtil;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Form to create / edit customer address.
 * Igor Azarny iazarny@yahoo.com
 * Date: 12/10/11
 * Time: 18:01
 */
public class AddressForm extends Form<Address> {

    private static final Logger LOG = LoggerFactory.getLogger(AddressForm.class);

    // ------------------------------------- MARKUP IDs BEGIN ---------------------------------- //
    private final static String FIELDS = "fields";
    private final static String NAME = "name";
    private final static String EDITOR = "editor";
    private final static String COUNTRY = "country";
    private final static String STATE = "state";
    private final static String ADD_ADDRESS = "addAddress";
    private final static String CANCEL_LINK = "cancel";
    // ------------------------------------- MARKUP IDs END ---------------------------------- //

    private final static int SMALL_LENGTH = 16;
    private final static int MEDIUM_LENGTH = 128;
    private final static int LARGE_LENGTH = 256;

    @SpringBean(name = StorefrontServiceSpringKeys.ADDRESS_BOOK_FACADE)
    private AddressBookFacade addressBookFacade;

    @SpringBean(name = ServiceSpringKeys.CART_COMMAND_FACTORY)
    private ShoppingCartCommandFactory shoppingCartCommandFactory;

    @SpringBean(name = StorefrontServiceSpringKeys.I18N_SUPPORT)
    private I18NWebSupport i18NWebSupport;

    private final EditorFactory editorFactory = new EditorFactory();

    private final Class<? extends Page> successPage;
    private final PageParameters successPageParameters;

    private final List<AttrValue> values;

    /**
     * Create address form.
     *
     * @param s                      form id
     * @param addressIModel          address model.
     * @param addressType            address type
     * @param successPage            success page class
     * @param successPageParameters  success page parameters
     * @param cancelPage             optional cancel page class
     * @param cancelPageParameters   optional  cancel page parameters
     */
    public AddressForm(final String s, final IModel<Address> addressIModel, final String addressType,
            final Class<? extends Page> successPage, final PageParameters successPageParameters,
            final Class<? extends Page> cancelPage, final PageParameters cancelPageParameters) {

        super(s, addressIModel);

        this.successPage = successPage;
        this.successPageParameters = successPageParameters;

        final Address address = addressIModel.getObject();

        preprocessAddress(address);
        final boolean creating = address.getAddressId() == 0L;

        final List<State> stateList = getStateList(address.getCountryCode());
        final List<Country> countryList = addressBookFacade.getAllCountries(ShopCodeContext.getShopCode(),
                addressType);

        RepeatingView fields = new RepeatingView(FIELDS);

        add(fields);

        final String lang = getLocale().getLanguage();
        values = addressBookFacade.getShopCustomerAddressAttributes(address.getCustomer(),
                ApplicationDirector.getCurrentShop(), addressType);

        final Map<String, AttrValue> valuesMap = new HashMap<String, AttrValue>();
        for (final AttrValue av : values) {
            valuesMap.put(av.getAttribute().getVal(), av);
            try {
                final Object val = PropertyUtils.getProperty(address, av.getAttribute().getVal());
                av.setVal(val != null ? String.valueOf(val) : null);
            } catch (Exception e) {
                LOG.error("Unable to get address property for {}, prop {}", av.getAttribute(),
                        av.getAttribute().getVal());
            }
        }

        final AttrValue stateCode = valuesMap.get("stateCode");
        final AbstractChoice<State, State> stateDropDownChoice = new DropDownChoice<State>(STATE,
                new StateModel(new PropertyModel(stateCode, "val"), stateList), stateList)
                        .setChoiceRenderer(new StateRenderer());
        final boolean needState = !stateList.isEmpty();
        stateDropDownChoice.setRequired(needState);
        stateDropDownChoice.setVisible(needState);

        final AttrValue countryCode = valuesMap.get("countryCode");
        final AbstractChoice<Country, Country> countryDropDownChoice = new DropDownChoice<Country>(COUNTRY,
                new CountryModel(new PropertyModel(countryCode, "val"), countryList), countryList) {

            @Override
            protected void onSelectionChanged(final Country country) {
                super.onSelectionChanged(country);
                stateDropDownChoice.setChoices(getStateList(country.getCountryCode()));
                final boolean needState = !stateDropDownChoice.getChoices().isEmpty();
                stateDropDownChoice.setRequired(needState);
                stateDropDownChoice.setVisible(needState);
                if (valuesMap.containsKey("stateCode")) {
                    valuesMap.get("stateCode").setVal(StringUtils.EMPTY);
                }
            }

            @Override
            protected boolean wantOnSelectionChangedNotifications() {
                return true;
            }

        }.setChoiceRenderer(new CountryRenderer());
        countryDropDownChoice.setRequired(true);

        for (final AttrValue attrValue : values) {

            WebMarkupContainer row;

            if ("countryCode".equals(attrValue.getAttribute().getVal())) {
                row = new WebMarkupContainer(fields.newChildId());
                row.add(getLabel(attrValue, lang));
                row.add(new Fragment("editor", "countryCodeEditor", this).add(countryDropDownChoice));
            } else if ("stateCode".equals(attrValue.getAttribute().getVal())) {
                row = new WebMarkupContainer(fields.newChildId()) {
                    @Override
                    public boolean isVisible() {
                        return stateDropDownChoice.isVisible();
                    }
                };
                row.add(getLabel(attrValue, lang));
                row.add(new Fragment("editor", "stateCodeEditor", this).add(stateDropDownChoice));
            } else {
                row = new WebMarkupContainer(fields.newChildId());
                row.add(getLabel(attrValue, lang));
                row.add(getEditor(attrValue, false));
            }

            fields.add(row);

        }

        final AbstractLink submit = new SubmitLink(ADD_ADDRESS) {

            @Override
            public void onSubmit() {

                final Address addr = getModelObject();

                final boolean isNew = addr.getAddressId() == 0;

                final ShoppingCart cart = ((AbstractWebPage) getPage()).getCurrentCart();
                if (isNew || cart.getLogonState() == ShoppingCart.LOGGED_IN) {

                    for (final AttrValue value : values) {
                        try {
                            PropertyUtils.setProperty(addr, value.getAttribute().getVal(), value.getVal());
                        } catch (Exception e) {
                            LOG.error("Unable to set address property for {}, prop {}", value.getAttribute(),
                                    value.getAttribute().getVal());
                        }
                    }

                    final Shop shop = ((AbstractWebPage) getPage()).getCurrentCustomerShop();
                    addressBookFacade.createOrUpdate(addr, shop);

                    // if we just added new address that became new default or we modified an address that is in the cart
                    // reset address
                    if (isNew && addr.isDefaultAddress()
                            || Long.valueOf(addr.getAddressId()).equals(cart.getOrderInfo().getBillingAddressId())
                            || Long.valueOf(addr.getAddressId())
                                    .equals(cart.getOrderInfo().getDeliveryAddressId())) {
                        final String key = Address.ADDR_TYPE_BILLING.equals(addressType)
                                ? ShoppingCartCommand.CMD_SETADDRESES_P_BILLING_ADDRESS
                                : ShoppingCartCommand.CMD_SETADDRESES_P_DELIVERY_ADDRESS;
                        shoppingCartCommandFactory.execute(ShoppingCartCommand.CMD_SETADDRESES, cart,
                                (Map) new HashMap() {
                                    {
                                        put(ShoppingCartCommand.CMD_SETADDRESES,
                                                ShoppingCartCommand.CMD_SETADDRESES);
                                        put(key, addr);
                                    }
                                });
                    }
                }
                setResponsePage(successPage, successPageParameters);
            }

        };

        add(submit);
        submit.add(new Label("addAddressLabel",
                WicketUtil.createStringResourceModel(this, creating ? "create" : "save")));

        final Component cancel = new SubmitLink(CANCEL_LINK) {

            @Override
            public void onSubmit() {
                setResponsePage(cancelPage, cancelPageParameters);
            }

        }.setDefaultFormProcessing(false).setVisible(cancelPage != null);

        add(cancel);

    }

    /**
     * Fill some data in case of new {@link Address}
     *
     * @param address     address to preprocess
     */
    private void preprocessAddress(final Address address) {
        if (address.getAddressId() == 0) {
            fillAddressWithGeoIpData(address);
        }
    }

    /**
     * Fill new Address with Geo Ip data.
     * At this moment only profile data are supplied. No geo ip.
     * INTEGRATION POINT with tag cloud, that will have geo ip data
     *
     * @param address  address to fill
     */
    private void fillAddressWithGeoIpData(final Address address) {
        // CPOINT
    }

    /**
     * Get states inside selected country.
     *
     * @param countryCode country ot retrieve the states.
     * @return state list inside selected country.
     */
    private List<State> getStateList(final String countryCode) {
        return addressBookFacade.getStatesByCountry(countryCode);
    }

    private Label getLabel(final AttrValue attrValue, final String lang) {

        final I18NModel model = i18NWebSupport.getFailoverModel(attrValue.getAttribute().getDisplayName(),
                attrValue.getAttribute().getName());
        final String prop = attrValue.getAttribute().getVal();

        final Label rez = new Label(NAME, new AbstractReadOnlyModel<String>() {

            private final I18NModel m = model;

            @Override
            public String getObject() {
                final String lang = getLocale().getLanguage();
                final String name = m.getValue(lang);
                if (StringUtils.isNotBlank(name)) {
                    return name;
                }
                return getLocalizer().getString(prop, AddressForm.this);
            }
        });

        return rez;
    }

    /**
     * Get the particular editor for given attribute value. Type of editor depends from type of attribute value.
     *
     * @param attrValue give {@link org.yes.cart.domain.entity.AttrValue}
     * @param readOnly  if true this component is read only
     *
     * @return editor
     */
    protected Component getEditor(final AttrValue attrValue, final Boolean readOnly) {

        return editorFactory.getEditor(EDITOR, this, getLocale().getLanguage(), attrValue, readOnly);
    }

}