Skip to content

Latest commit

 

History

History
198 lines (140 loc) · 6.33 KB

README.md

File metadata and controls

198 lines (140 loc) · 6.33 KB

Unified Component Collection

The main idea behind Unified Component Collection is the ability to implement an application prototype that can be deployed to different environments and different front-end frameworks.

Current implementation supports Vaadin and draft implementation for Swing is available.

Sample

package foo.bar.view;

...
import foo.bar.model.Person;
...

public class PreviewMainView implements View<ComponentContainer>, MainView {

	private static final long serialVersionUID = 1L;
	private DataSource ds;

	public ComponentContainer getContent() {
		return createFirstContainer();
	}

	private ComponentContainer createFirstContainer() {
		HorizontalLayout result = new HorizontalLayout();

		result.setWidth(new Measure(MeasureUnit.PERCENTAGE, 50));
		result.setHeight(new Measure(MeasureUnit.PERCENTAGE, 100));

		Label title = new Label();
		title.setDataSource(getDataSource().getDataSource("name"));
		title.setHeight(new Measure(MeasureUnit.PERCENTAGE, 30));
		result.addComponent(title);

		TextField personName = new TextField();
		personName.setDataSource(getDataSource().getDataSource("name"));
		personName.setHeight(new Measure(MeasureUnit.PIXEL, 30));
		result.addComponent(personName);

		TextField personAge = new TextField();
		personAge.setDataSource(getDataSource().getDataSource("age"));
		personAge.setHeight(new Measure(MeasureUnit.PIXEL, 30));
		result.addComponent(personAge);

		result.setExpandRation(new float[] { 1, 1, 1 });

		MenuBar menu = new MenuBar();
		Menu m = new Menu();
		m.setText("Sample MenuItem");
		MenuOption menuOption = new MenuOption(new AbstractAction() {

			private static final long serialVersionUID = 1L;

			@Override
			protected void internalExecute(ActionParameters parameters) {
				ds.getDataSource("name").set("Action Executed");
			}

			@Override
			protected ActionUpdateEvent createActionEvent() {
				return new ActionUpdateEvent(this, this);
			}

		});
		menuOption.setText("Execute Action");
		List<MenuItem> options = Collections.<MenuItem> singletonList(menuOption);

		m.setOptions(options);
		menu.setOptions(Collections.<MenuItem> singletonList(m));

		result.addComponent(menu);

		getDataSource().set(new Person("Test Name", 28));

		return result;
	}

	public void initialize(ViewModel viewModel, StartupInfo startupInfo) {}

	public void onShown(ViewShowEvent event) {}

	public void close() {}

	public void onClose(ViewCloseEvent event) {}

	public ViewModel getModel() {
		return null;
	}

	private DataSource getDataSource() {
		if (ds == null) {
			ds = new BeanDataSourceBuilder(Person.class) //
					.addDataSource(new BeanDataSourceBuilder("representation")) //
					.addDataSource(new BeanDataSourceBuilder("name")) //
					.addDataSource(new BeanDataSourceBuilder("age")) //
					.build();
		}
		return ds; //
	}

}

The sample class exposed below show how could a view be implemented.

In order to have the view running, a initialization listener (kind of entry point) needs to be implemented and an application module needs to be declared.

A sample of initialization listener would be something like:

package foo.bar;

import javax.inject.Inject;

import com.spaeth.appbase.event.ApplicationInitListener;
import com.spaeth.appbase.event.ApplicationInitializationEvent;
import com.spaeth.appbase.service.ApplicationController;

import foo.bar.startup.MainViewStartupInfo;

public class PreviewInitListener implements ApplicationInitListener{

	@Inject
	private ApplicationController applicationController;
	
	public void applicationInitialized(ApplicationInitializationEvent event) {
		applicationController.process(new MainViewStartupInfo());
	}

}

This basically says to the application controller that there is an intention to show a view. A module for the current application would be something similar to:

package foo.bar;

import com.spaeth.appbase.core.annotations.ConfigurationMethod;
import com.spaeth.appbase.core.marker.Principal;
import com.spaeth.appbase.core.service.Binder;
import com.spaeth.appbase.core.service.ClassBasedRepositoryViewProvider;
import com.spaeth.appbase.core.service.Configurator.MappedConfiguration;
import com.spaeth.appbase.core.service.Configurator.OrderedConfiguration;
import com.spaeth.appbase.core.service.Module;
import com.spaeth.appbase.core.service.ScopeConstants;
import com.spaeth.appbase.event.ApplicationInitListener;
import com.spaeth.appbase.model.View;

import foo.bar.dao.PersonRepository;
import foo.bar.startup.MainViewStartupInfo;
import foo.bar.view.PreviewMainView;

public class PreviewModule implements Module {

	public void configure(final Binder binder) {
		binder.new Binding(PersonRepository.class).withScope(ScopeConstants.SESSION_SCOPE);
	}

	@ConfigurationMethod(ApplicationInitListener.class)
	@Principal
	public void configureApplicationInitListener(final OrderedConfiguration<ApplicationInitListener> config) {
		config.addInstance("init", PreviewInitListener.class);
	}

	@ConfigurationMethod(ClassBasedRepositoryViewProvider.class)
	public void configureClassBasedRepositoryViewProvider(final MappedConfiguration<Class<?>, Class<? extends View<?>>> config) {
		config.add(MainViewStartupInfo.class, PreviewMainView.class);
	}

}

The idea behind this process is basically that there is a bunch of views implementation available. Every time a a StartupInfo object is processed by the ApplicationController a suitable view implementation will be selected, instantiated, associated to a ViewModel (depending on implementation) and exposed by a ViewPort.

A startup implementation could hold contextualized information in order to setup a View, once it is used during view initialization public void initialize(ViewModel viewModel, StartupInfo startupInfo). A simple sample of a StartupInfo:

package foo.bar.startup;

import com.spaeth.appbase.model.StartupInfo;

public class MainViewStartupInfo extends StartupInfo {

    private final String fileName;

    public MainViewStartupInfo(String fileName) {
        this.fileName = fileName;
    }
    
    public String getFileName() {
        return fileName;
    }

}

In order to show a view, it is submited to a chain of ViewPorts, and it can decide whether or not to show the view based, among other things, on the View characterization. Sample of view characterizations are: ModalView, TitledView, MainView, IconedView