Java tutorial
/* * Copyright 2015 Gunnar Kappei. * * 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 io.github.moosbusch.permagon.configuration.builder.spi; import io.github.moosbusch.permagon.application.PermagonApplicationContext; import io.github.moosbusch.permagon.configuration.builder.PermagonBuilder; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXAlertTypeConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXBackgroundRepeatConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXBlendModeConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXBlurTypeConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXCacheHintConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXColorConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXContentDisplayConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXCullFaceConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXCycleMethodConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXDepthTestConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXDrawModeConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXFillRuleConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXFontPostureConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXFontSmoothingTypeConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXFontWeightConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXHPosConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXHorizontalDirectionConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXInputMethodHighlightConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXKeyCodeConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXModalityConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXNodeOrientationConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXOrientationConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXOverrunStyleConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXPageOrientationConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXPosConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXPrintColorConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXPrintQualityConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXPrintSidesConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXPriorityConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXScrollBarPolicyConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXSelectionModeConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXSideConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXStageStyleConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXStrokeLineCapConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXStrokeLineJoinConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXStrokeTypeConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXStyleOriginConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXTabClosingPolicyConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXTextAlignmentConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXTextBoundsTypeConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXTransferModeConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXTreeSortModeConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXVPosConverter; import io.github.moosbusch.permagon.configuration.builder.converter.impl.JavaFXVerticalDirectionConverter; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javafx.beans.DefaultProperty; import javafx.beans.property.MapProperty; import javafx.beans.property.SimpleMapProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.ObservableMap; import javafx.css.StyleOrigin; import javafx.fxml.JavaFXBuilderFactory; import javafx.geometry.HPos; import javafx.geometry.HorizontalDirection; import javafx.geometry.NodeOrientation; import javafx.geometry.Orientation; import javafx.geometry.Pos; import javafx.geometry.Side; import javafx.geometry.VPos; import javafx.geometry.VerticalDirection; import javafx.print.PageOrientation; import javafx.print.PrintColor; import javafx.print.PrintQuality; import javafx.print.PrintSides; import javafx.scene.CacheHint; import javafx.scene.DepthTest; import javafx.scene.Node; import javafx.scene.control.Accordion; import javafx.scene.control.Alert; import javafx.scene.control.ButtonBar; import javafx.scene.control.ContentDisplay; import javafx.scene.control.Menu; import javafx.scene.control.MenuBar; import javafx.scene.control.OverrunStyle; import javafx.scene.control.ScrollPane; import javafx.scene.control.ScrollPane.ScrollBarPolicy; import javafx.scene.control.SelectionMode; import javafx.scene.control.SplitPane; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.control.TitledPane; import javafx.scene.control.ToolBar; import javafx.scene.control.TreeSortMode; import javafx.scene.effect.BlendMode; import javafx.scene.effect.BlurType; import javafx.scene.input.InputMethodHighlight; import javafx.scene.input.KeyCode; import javafx.scene.input.TransferMode; import javafx.scene.layout.BackgroundRepeat; import javafx.scene.layout.Pane; import javafx.scene.layout.Priority; import javafx.scene.paint.Color; import javafx.scene.paint.CycleMethod; import javafx.scene.shape.CullFace; import javafx.scene.shape.DrawMode; import javafx.scene.shape.FillRule; import javafx.scene.shape.StrokeLineCap; import javafx.scene.shape.StrokeLineJoin; import javafx.scene.shape.StrokeType; import javafx.scene.text.FontPosture; import javafx.scene.text.FontSmoothingType; import javafx.scene.text.FontWeight; import javafx.scene.text.TextAlignment; import javafx.scene.text.TextBoundsType; import javafx.stage.Modality; import javafx.stage.StageStyle; import javafx.util.Builder; import javafx.util.BuilderFactory; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.beanutils.Converter; /** * * @author Gunnar Kappei */ @DefaultProperty("properties") public abstract class AbstractPermagonBuilder implements Map<String, Object>, PermagonBuilder<Object> { private static final long serialVersionUID = 6321535594458554960L; private transient final PermagonApplicationContext applicationContext; private transient final Class<?> type; private transient final BuilderFactory builderFactory; private transient final MapProperty<String, Object> properties; public AbstractPermagonBuilder(PermagonApplicationContext applicationContext, Class<?> type, BuilderFactory builderFactory) { this.applicationContext = applicationContext; this.type = type; this.builderFactory = builderFactory; this.properties = new SimpleMapProperty(FXCollections.observableHashMap()); init(); } public AbstractPermagonBuilder(PermagonApplicationContext applicationContext, Class<?> type) { this(applicationContext, type, new JavaFXBuilderFactory()); } private void init() { initConverters(); properties.put(NODE_CHILDREN_PROPERTY, FXCollections.observableArrayList()); properties.put(NODE_ITEMS_PROPERTY, FXCollections.observableArrayList()); properties.put(NODE_TABS_PROPERTY, FXCollections.observableArrayList()); properties.put(NODE_BUTTONS_PROPERTY, FXCollections.observableArrayList()); properties.put(NODE_MENUS_PROPERTY, FXCollections.observableArrayList()); } protected void initConverters() { setConverter(Color.class, new JavaFXColorConverter()); setConverter(Priority.class, new JavaFXPriorityConverter()); setConverter(ScrollBarPolicy.class, new JavaFXScrollBarPolicyConverter()); setConverter(VerticalDirection.class, new JavaFXVerticalDirectionConverter()); setConverter(TabPane.TabClosingPolicy.class, new JavaFXTabClosingPolicyConverter()); setConverter(DrawMode.class, new JavaFXDrawModeConverter()); setConverter(VPos.class, new JavaFXVPosConverter()); setConverter(StyleOrigin.class, new JavaFXStyleOriginConverter()); setConverter(CycleMethod.class, new JavaFXCycleMethodConverter()); setConverter(BlurType.class, new JavaFXBlurTypeConverter()); setConverter(TreeSortMode.class, new JavaFXTreeSortModeConverter()); setConverter(StrokeLineCap.class, new JavaFXStrokeLineCapConverter()); setConverter(Alert.AlertType.class, new JavaFXAlertTypeConverter()); setConverter(TextBoundsType.class, new JavaFXTextBoundsTypeConverter()); setConverter(Orientation.class, new JavaFXOrientationConverter()); setConverter(CacheHint.class, new JavaFXCacheHintConverter()); setConverter(CullFace.class, new JavaFXCullFaceConverter()); setConverter(BlendMode.class, new JavaFXBlendModeConverter()); setConverter(Pos.class, new JavaFXPosConverter()); setConverter(StageStyle.class, new JavaFXStageStyleConverter()); setConverter(InputMethodHighlight.class, new JavaFXInputMethodHighlightConverter()); setConverter(OverrunStyle.class, new JavaFXOverrunStyleConverter()); setConverter(TransferMode.class, new JavaFXTransferModeConverter()); setConverter(FontSmoothingType.class, new JavaFXFontSmoothingTypeConverter()); setConverter(StrokeLineJoin.class, new JavaFXStrokeLineJoinConverter()); setConverter(FontWeight.class, new JavaFXFontWeightConverter()); setConverter(PrintSides.class, new JavaFXPrintSidesConverter()); setConverter(KeyCode.class, new JavaFXKeyCodeConverter()); setConverter(HPos.class, new JavaFXHPosConverter()); setConverter(Side.class, new JavaFXSideConverter()); setConverter(PrintQuality.class, new JavaFXPrintQualityConverter()); setConverter(BackgroundRepeat.class, new JavaFXBackgroundRepeatConverter()); setConverter(PrintColor.class, new JavaFXPrintColorConverter()); setConverter(NodeOrientation.class, new JavaFXNodeOrientationConverter()); setConverter(FillRule.class, new JavaFXFillRuleConverter()); setConverter(DepthTest.class, new JavaFXDepthTestConverter()); setConverter(Modality.class, new JavaFXModalityConverter()); setConverter(FontPosture.class, new JavaFXFontPostureConverter()); setConverter(HorizontalDirection.class, new JavaFXHorizontalDirectionConverter()); setConverter(StrokeType.class, new JavaFXStrokeTypeConverter()); setConverter(TextAlignment.class, new JavaFXTextAlignmentConverter()); setConverter(SelectionMode.class, new JavaFXSelectionModeConverter()); setConverter(PageOrientation.class, new JavaFXPageOrientationConverter()); setConverter(ContentDisplay.class, new JavaFXContentDisplayConverter()); } protected abstract Map<Class<?>, Converter> getConverters(); protected PermagonApplicationContext getApplicationContext() { return applicationContext; } protected Class<?> getType() { return type; } protected BuilderFactory getBuilderFactory() { return builderFactory; } protected void buildPane(Pane pane) { if (containsKey(NODE_CHILDREN_PROPERTY)) { Object obj = Objects.requireNonNull(get(NODE_CHILDREN_PROPERTY)); if (obj instanceof ObservableMap) { ObservableMap propertiesMap = (ObservableMap) obj; Object childrenObj = Objects.requireNonNull(propertiesMap.get(NODE_CHILDREN_PROPERTY)); if (childrenObj instanceof ObservableList) { pane.getChildren().addAll((ObservableList) childrenObj); } } } } protected void buildTabPane(TabPane pane) { if (containsKey(NODE_TABS_PROPERTY)) { Object obj = Objects.requireNonNull(get(NODE_TABS_PROPERTY)); if (obj instanceof ObservableMap) { ObservableMap propertiesMap = (ObservableMap) obj; Object childrenObj = Objects.requireNonNull(propertiesMap.get(NODE_TABS_PROPERTY)); if (childrenObj instanceof ObservableList) { pane.getTabs().addAll((ObservableList) childrenObj); } } } } protected void buildTab(Tab pane) { if (containsKey(NODE_CONTENT_PROPERTY)) { Object obj = Objects.requireNonNull(get(NODE_CONTENT_PROPERTY)); if (obj instanceof ObservableMap) { ObservableMap propertiesMap = (ObservableMap) obj; Object childrenObj = Objects.requireNonNull(propertiesMap.get(NODE_CONTENT_PROPERTY)); if (childrenObj instanceof Node) { pane.setContent((Node) childrenObj); } } } } protected void buildSplitPane(SplitPane pane) { if (containsKey(NODE_ITEMS_PROPERTY)) { Object obj = Objects.requireNonNull(get(NODE_ITEMS_PROPERTY)); if (obj instanceof ObservableMap) { ObservableMap propertiesMap = (ObservableMap) obj; propertiesMap.values().stream().filter((propertyValue) -> (propertyValue instanceof ObservableList)) .forEach((propertyValue) -> { pane.getItems().addAll((ObservableList) propertyValue); }); } } } protected void buildToolBar(ToolBar pane) { if (containsKey(NODE_ITEMS_PROPERTY)) { Object obj = Objects.requireNonNull(get(NODE_ITEMS_PROPERTY)); if (obj instanceof ObservableMap) { ObservableMap propertiesMap = (ObservableMap) obj; propertiesMap.values().stream().filter((propertyValue) -> (propertyValue instanceof ObservableList)) .forEach((propertyValue) -> { pane.getItems().addAll((ObservableList) propertyValue); }); } } } protected void buildMenuBar(MenuBar pane) { if (containsKey(NODE_MENUS_PROPERTY)) { Object obj = Objects.requireNonNull(get(NODE_MENUS_PROPERTY)); if (obj instanceof ObservableMap) { ObservableMap propertiesMap = (ObservableMap) obj; propertiesMap.values().stream().filter((propertyValue) -> (propertyValue instanceof ObservableList)) .forEach((propertyValue) -> { pane.getMenus().addAll((ObservableList) propertyValue); }); } } } protected void buildMenu(Menu pane) { if (containsKey(NODE_ITEMS_PROPERTY)) { Object obj = Objects.requireNonNull(get(NODE_ITEMS_PROPERTY)); if (obj instanceof ObservableMap) { ObservableMap propertiesMap = (ObservableMap) obj; propertiesMap.values().stream().filter((propertyValue) -> (propertyValue instanceof ObservableList)) .forEach((propertyValue) -> { pane.getItems().addAll((ObservableList) propertyValue); }); } } } protected void buildScrollPane(ScrollPane pane) { if (containsKey(NODE_PROPERTIES_PROPERTY)) { Object obj = Objects.requireNonNull(get(NODE_PROPERTIES_PROPERTY)); if (obj instanceof ObservableMap) { ObservableMap propertiesMap = (ObservableMap) obj; for (Object propertyValue : propertiesMap.values()) { if (propertyValue instanceof Node) { pane.setContent((Node) propertyValue); return; } } } } } protected void buildTitledPane(TitledPane pane) { if (containsKey(NODE_PROPERTIES_PROPERTY)) { Object obj = Objects.requireNonNull(get(NODE_PROPERTIES_PROPERTY)); if (obj instanceof ObservableMap) { ObservableMap propertiesMap = (ObservableMap) obj; for (Object propertyValue : propertiesMap.values()) { if (propertyValue instanceof Node) { pane.setContent((Node) propertyValue); return; } } } } } protected void buildButtonBar(ButtonBar buttonBar) { if (containsKey(NODE_BUTTONS_PROPERTY)) { Object obj = Objects.requireNonNull(get(NODE_BUTTONS_PROPERTY)); if (obj instanceof ObservableMap) { ObservableMap propertiesMap = (ObservableMap) obj; propertiesMap.values().stream().filter((propertyValue) -> (propertyValue instanceof ObservableList)) .forEach((propertyValue) -> { buttonBar.getButtons().addAll((ObservableList) propertyValue); }); } } } protected void buildAccordion(Accordion accordion) { if (containsKey(NODE_PANES_PROPERTY)) { Object obj = Objects.requireNonNull(get(NODE_PANES_PROPERTY)); if (obj instanceof ObservableMap) { ObservableMap propertiesMap = (ObservableMap) obj; propertiesMap.values().stream().filter((propertyValue) -> (propertyValue instanceof ObservableList)) .forEach((propertyValue) -> { accordion.getPanes().addAll((ObservableList) propertyValue); }); } } } protected Object putListProperty(String propertyName, Object value) { Object result = null; Object childrenValue = Objects.requireNonNull(get(propertyName)); if (childrenValue instanceof ObservableMap) { ObservableMap propertiesMap = (ObservableMap) childrenValue; Object obj = Objects.requireNonNull(propertiesMap.get(propertyName)); if (obj instanceof ObservableList) { ObservableList childrenValueList = (ObservableList) obj; result = childrenValueList; if ((value instanceof Node) || (value instanceof Tab)) { if (!childrenValueList.contains(value)) { childrenValueList.add(value); properties.put(propertyName, childrenValueList); } } } } return result; } @Override public Object build() { Object result; Class<?> thype = getType(); BuilderFactory buylderFactory = getBuilderFactory(); PermagonApplicationContext applicationCtx = getApplicationContext(); Map<Class<?>, Converter> converterz = getConverters(); Builder<?> builder = buylderFactory.getBuilder(thype); if (builder != null) { result = builder.build(); applicationCtx.getBeanFactory().autowireBean(result); } else { result = applicationCtx.createBean(thype); } converterz.entrySet().stream().forEach((converterEntry) -> { ConvertUtils.register(converterEntry.getValue(), converterEntry.getKey()); }); if (result instanceof Pane) { Pane resultPane = (Pane) result; buildPane(resultPane); } else if (result instanceof ScrollPane) { ScrollPane resultPane = (ScrollPane) result; buildScrollPane(resultPane); } else if (result instanceof SplitPane) { SplitPane resultPane = (SplitPane) result; buildSplitPane(resultPane); } else if (result instanceof TabPane) { TabPane resultPane = (TabPane) result; buildTabPane(resultPane); } else if (result instanceof Tab) { Tab resultPane = (Tab) result; buildTab(resultPane); } else if (result instanceof ButtonBar) { ButtonBar resultPane = (ButtonBar) result; buildButtonBar(resultPane); } else if (result instanceof Accordion) { Accordion resultPane = (Accordion) result; buildAccordion(resultPane); } else if (result instanceof TitledPane) { TitledPane resultPane = (TitledPane) result; buildTitledPane(resultPane); } else if (result instanceof ToolBar) { ToolBar resultPane = (ToolBar) result; buildToolBar(resultPane); } else if (result instanceof MenuBar) { MenuBar resultPane = (MenuBar) result; buildMenuBar(resultPane); } try { BeanUtils.populate(result, this); } catch (IllegalAccessException | InvocationTargetException ex) { Logger.getLogger(AbstractPermagonBuilder.class.getName()).log(Level.SEVERE, null, ex); } return result; } @Override public void getConverter(Class<?> key) { getConverters().get(key); } @Override public void setConverter(Class<?> key, Converter value) { getConverters().put(key, value); } @Override public void removeConverter(Class<?> key, Converter value) { getConverters().remove(key, value); } public ObservableMap<String, Object> getProperties() { return properties; } @Override public Object put(String key, Object value) { Object result = null; if (value != null) { if (null != key) switch (key) { case NODE_CHILDREN_PROPERTY: return result = putListProperty(NODE_CHILDREN_PROPERTY, value); case NODE_ITEMS_PROPERTY: return result = putListProperty(NODE_ITEMS_PROPERTY, value); case NODE_TABS_PROPERTY: return result = putListProperty(NODE_TABS_PROPERTY, value); } } return properties.put(key, value); } @Override public int size() { return properties.size(); } @Override public boolean isEmpty() { return properties.isEmpty(); } @Override public boolean containsKey(Object key) { return properties.containsKey(key); } @Override public boolean containsValue(Object value) { return properties.containsValue(value); } @Override public Object get(Object key) { return properties.get(); } @Override public void putAll(Map<? extends String, ? extends Object> m) { properties.putAll(m); } @Override public void clear() { properties.clear(); } @Override public Set<String> keySet() { return properties.keySet(); } @Override public Collection<Object> values() { return properties.values(); } @Override public Set<Entry<String, Object>> entrySet() { return propertiesProperty().entrySet(); } public MapProperty propertiesProperty() { return properties; } @Override public Object remove(Object key) { return properties.remove(key); } }