All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nz.co.senanque.vaadin.MaduraSessionManager Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c)2014 Prometheus Consulting
 *
 * 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 nz.co.senanque.vaadin;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import nz.co.senanque.logging.HashIdLogger;
import nz.co.senanque.permissionmanager.PermissionManager;
import nz.co.senanque.vaadin.application.MaduraConverterFactory;
import nz.co.senanque.vaadin.application.PropertyNotFoundException;
import nz.co.senanque.validationengine.FieldMetadata;
import nz.co.senanque.validationengine.LocaleAwareExceptionFactory;
import nz.co.senanque.validationengine.ObjectMetadata;
import nz.co.senanque.validationengine.ProxyField;
import nz.co.senanque.validationengine.SetterListener;
import nz.co.senanque.validationengine.ValidationEngine;
import nz.co.senanque.validationengine.ValidationObject;
import nz.co.senanque.validationengine.ValidationSession;
import nz.co.senanque.validationengine.choicelists.ChoiceBase;
import nz.co.senanque.validationengine.metadata.PropertyMetadata;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;

import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.server.UserError;
import com.vaadin.server.VaadinService;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.AbstractSelect;
import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Label;
import com.vaadin.ui.MenuBar.Command;
import com.vaadin.ui.MenuBar.MenuItem;
import com.vaadin.ui.UI;

/**
 * 
 * All of the Madura session management is done here. You register fields (or whole forms) with the manager.
 * Then you bind specific instances of the object graph to these fields.
 * There is one of these per Madura Session
 * 
 * @author Roger Parkinson
 * @version $Revision:$
 */
@Component("maduraSessionManager")
@Scope(value="vaadin-ui", proxyMode = ScopedProxyMode.TARGET_CLASS)
//@UIScope
public class MaduraSessionManager implements Serializable, MessageSourceAware
{
	private static final long serialVersionUID = -1L;
	private static Logger logger = LoggerFactory.getLogger(MaduraSessionManager.class);
	private Map m_fields = new HashMap<>();
	private Map m_labels = new HashMap<>();
    @Autowired(required=false) private transient ValidationEngine m_validationEngine;
    private transient ValidationSession m_validationSession;
    @Autowired private transient FieldFactory m_formFieldFactory;
    @Autowired transient PermissionManager m_permissionManager;
    @Autowired transient MaduraConverterFactory m_maduraConverterFactory;
    @Autowired private transient Hints m_hints;
    @Autowired private transient LocaleAwareExceptionFactory m_localeAwareExceptionFactory;
	private transient MessageSource m_messageSource;
	
	// Used for internal testing, should be left false.
    @Value("${nz.co.senanque.vaadin.application.MaduraSessionManager.suppressUpdates:false}")
    private transient boolean m_suppressUpdates;
    
    public MaduraSessionManager() {
    	HashIdLogger.log(this,"constructor");
    }
    
	@PostConstruct
	public void init() {
		VaadinSession session = VaadinSession.getCurrent();
		session.setConverterFactory(getMaduraConverterFactory());
		m_formFieldFactory.setMaduraSessionManager(this);
		HashIdLogger.log(this,session);
	}
    private class MenuItemWrapper extends AbstractComponent {
    	
    	private static final long serialVersionUID = -1L;
		private final MenuItemPainter m_menuItemPainter;

		private MenuItemWrapper(MenuItem menuItem, MenuItemPainter menuItemPainter)
		{
			m_menuItemPainter = menuItemPainter;
			setData(menuItem);
		}

		public MenuItemPainter getMenuItemPainter() {
			return m_menuItemPainter;
		}
    }

	private void registerWidget(AbstractComponent field) {
		int key = System.identityHashCode(field);
		if (m_fields.get(key) == null) {
			m_fields.put(key,field);
//			logger.debug("MaduraSessionManager {} Registering field {} {}",getValidationEngine().getIdentifier(),key,field.getCaption());
		}
	}
	private void registerWidget(MenuItem field, MenuItemPainter bp) {
		Collection fields = getFields();
		for (AbstractComponent foundField: fields)
		{
			if (foundField instanceof MenuItemWrapper)
			{
				MenuItemWrapper menuItemWrapper = (MenuItemWrapper)foundField;
				if (menuItemWrapper.getMenuItemPainter() == bp)
				{
					// we found this item already in the list so reuse it
					// rather than create a new entry. This saves us having to deregister and
					// recreate whenever the menu reconfigures.
					menuItemWrapper.setData(field);
					return;
				}
			}
		}
		registerWidget(new MenuItemWrapper(field, bp));
	}
	public void register(Label field) {
		int key = System.identityHashCode(field);
		if (m_labels.get(key) == null) {
			m_labels.put(key,field);
		}
	}
	public void deregister(AbstractComponent field) {
		m_fields.remove(System.identityHashCode(field));
		m_labels.remove(System.identityHashCode(field));
	}

	/**
	 * Check all the other fields to ensure they are still valid
	 * this includes any buttons that were registered because they
	 * get disabled if there are errors on the relevant form or
	 * if the required-ness is incomplete.
	 * 
	 * @param field
	 */
	public void updateOtherFields(AbstractComponent field) {
		
		if (m_suppressUpdates) {
			return;
		}
		PermissionManager permissionmanager = getPermissionManager();
		Collection fields = getFields();
		Collection