001/**
002 * Copyright 2005-2018 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.uif.lifecycle.model;
017
018import java.lang.annotation.Annotation;
019import java.util.Map;
020import java.util.Map.Entry;
021
022import org.apache.commons.lang.StringUtils;
023import org.kuali.rice.krad.uif.component.ClientSideState;
024import org.kuali.rice.krad.uif.component.Component;
025import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
026import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleTaskBase;
027import org.kuali.rice.krad.uif.util.CopyUtils;
028import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
029import org.kuali.rice.krad.uif.view.View;
030import org.kuali.rice.krad.uif.view.ViewModel;
031
032/**
033 * Synchronize client side state for the component.
034 * 
035 * @author Kuali Rice Team (rice.collab@kuali.org)
036 */
037public class SyncClientSideStateTask extends ViewLifecycleTaskBase<Component> {
038
039    /**
040     * Default constructor.
041     */
042    public SyncClientSideStateTask() {
043        super(Component.class);
044    }
045
046    /**
047     * Updates the properties of the given component instance with the value found from the
048     * corresponding map of client state (if found)
049     * 
050     * {@inheritDoc}
051     */
052    @Override
053    protected void performLifecycleTask() {
054        Component component = (Component) getElementState().getElement();
055        ViewModel model = (ViewModel) ViewLifecycle.getModel();
056
057        // find the map of state that was sent for component (if any)
058        Map<String, Object> clientSideState = model.getClientStateForSyncing();
059        if (!(component instanceof View) && clientSideState.containsKey(component.getId())) {
060            @SuppressWarnings("unchecked")
061            Map<String, Object> componentState =
062                    (Map<String, Object>) clientSideState.get(component.getId());
063            clientSideState = componentState;
064        }
065
066        // if state was sent, match with fields on the component that are annotated to have client state
067        if ((clientSideState != null) && (!clientSideState.isEmpty())) {
068            Map<String, Annotation> annotatedFields = CopyUtils.getFieldsWithAnnotation(component.getClass(),
069                    ClientSideState.class);
070
071            for (Entry<String, Annotation> annotatedField : annotatedFields.entrySet()) {
072                ClientSideState clientSideStateAnnot = (ClientSideState) annotatedField.getValue();
073
074                String variableName = clientSideStateAnnot.variableName();
075                if (StringUtils.isBlank(variableName)) {
076                    variableName = annotatedField.getKey();
077                }
078
079                if (clientSideState.containsKey(variableName)) {
080                    Object value = clientSideState.get(variableName);
081                    ObjectPropertyUtils.setPropertyValue(component, annotatedField.getKey(), value);
082                }
083            }
084        }
085    }
086
087}