/** * * Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved. * * 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 com.speedment.tool.core.internal.controller; import com.speedment.common.injector.Injector; import com.speedment.common.injector.annotation.Inject; import com.speedment.common.injector.annotation.InjectKey; import com.speedment.generator.translator.component.CodeGenerationComponent; import com.speedment.generator.translator.component.TypeMapperComponent; import com.speedment.runtime.core.Speedment; import com.speedment.runtime.core.component.DbmsHandlerComponent; import com.speedment.runtime.core.component.InfoComponent; import com.speedment.runtime.core.db.DbmsType; import com.speedment.runtime.typemapper.TypeMapper; import com.speedment.tool.core.resource.SpeedmentIcon; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeView; import javafx.scene.paint.Color; import java.net.URL; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.ResourceBundle; import java.util.stream.Stream; import static com.speedment.common.mapstream.MapStream.comparing; import static com.speedment.tool.core.internal.util.CloseUtil.newCloseHandler; import static java.util.stream.Collectors.toList; /** * * @author Emil Forslund */ public final class ComponentsController implements Initializable { private @Inject InfoComponent infoComponent; private @Inject Speedment speedment; private @Inject Injector injector; private @FXML Label title; private @FXML Label header; private @FXML Button close; private @FXML TreeView<String> tree; @Override public void initialize(URL location, ResourceBundle resources) { title.setTextFill(Color.web("#45a6fc")); // TODO Use styleClass instead header.setText("Component Explorer"); final RootItem root = new RootItem(speedment); root.getChildren().addAll(components()); tree.setRoot(root); close.setOnAction(newCloseHandler()); } private List<TreeItem<String>> components() { return injector.injectables() .map(this::treeItem) .sorted(comparing(TreeItem::getValue)) .collect(toList()); } private class RootItem extends TreeItem<String> { public RootItem(Speedment speedment) { super( infoComponent.getTitle() + " (0x" + Integer.toHexString(System.identityHashCode(speedment)) + ")" ); setExpanded(true); setGraphic(SpeedmentIcon.BOX.view()); title.setText(infoComponent.getTitle()); } } private static class ComponentItem extends TreeItem<String> { public ComponentItem(Class<?> comp) { super(injectorKeyValue(comp).map(Class::getSimpleName).orElse(comp.getSimpleName()) + " (" + comp.getSimpleName() + ")" ); setExpanded(false); setGraphic(SpeedmentIcon.BRICKS.view()); } } private static Optional<? extends Class<?>> injectorKeyValue(Class<?> clazz) { return traverseAncestors(clazz) .map(c -> c.getAnnotation(InjectKey.class)) .filter(Objects::nonNull) .map(InjectKey::value) .findFirst(); } public static Stream<Class<?>> traverseAncestors(Class<?> clazz) { if (clazz.getSuperclass() == null) { // We have reached Object.class return Stream.of(clazz); } else { return Stream.concat( Stream.of(clazz), Stream.concat(traverseAncestors(clazz.getSuperclass()), Stream.of(clazz.getInterfaces())) ).distinct(); } } private static class TranslatorsItem extends TreeItem<String> { public TranslatorsItem() { super("Code Generators"); setExpanded(true); setGraphic(SpeedmentIcon.BOOK_OPEN.view()); } } private static class TranslatorItem extends TreeItem<String> { public TranslatorItem(String translatorKey) { super(translatorKey); setExpanded(true); setGraphic(SpeedmentIcon.BOOK_NEXT.view()); } } private static class DbmsTypesItem extends TreeItem<String> { public DbmsTypesItem() { super("Supported Databases"); setExpanded(true); setGraphic(SpeedmentIcon.DATABASE_CONNECT.view()); } } private static class DbmsTypeItem extends TreeItem<String> { public DbmsTypeItem(DbmsType dbmsType) { super(dbmsType.getName()); setExpanded(true); setGraphic(SpeedmentIcon.DATABASE.view()); } } private static class TypeMappersItem extends TreeItem<String> { public TypeMappersItem() { super("Installed Type Mappings"); setExpanded(true); setGraphic(SpeedmentIcon.PAGE_WHITE_CUP.view()); } } private static class TypeMapperItem extends TreeItem<String> { public TypeMapperItem(TypeMapper<?, ?> typeMapper) { super(typeMapper.getLabel()); setExpanded(true); setGraphic(SpeedmentIcon.CUP.view()); } } private TreeItem<String> treeItem(Class<?> comp) { final ComponentItem item = new ComponentItem(comp); // Show Translators if (CodeGenerationComponent.class.isAssignableFrom(comp)) { final TranslatorsItem translators = new TranslatorsItem(); injector.get(CodeGenerationComponent.class).ifPresent( cg -> { cg.translatorKeys() .sorted() .map(TranslatorItem::new) .forEachOrdered(translators.getChildren()::add); }); if (!translators.getChildren().isEmpty()) { item.getChildren().add(translators); } } // Show Dbms Types if (DbmsHandlerComponent.class.isAssignableFrom(comp)) { final DbmsTypesItem dbmsTypes = new DbmsTypesItem(); injector.get(DbmsHandlerComponent.class).ifPresent(dh -> { dh.supportedDbmsTypes() .sorted(DbmsType.COMPARATOR) .map(DbmsTypeItem::new) .forEachOrdered(dbmsTypes.getChildren()::add); }); if (!dbmsTypes.getChildren().isEmpty()) { item.getChildren().add(dbmsTypes); } } // Show Type Mappers if (TypeMapperComponent.class.isAssignableFrom(comp)) { final TypeMappersItem typeMappers = new TypeMappersItem(); injector.get(TypeMapperComponent.class).ifPresent(tm -> { tm.stream() .sorted(TypeMapper.COMPARATOR) .map(TypeMapperItem::new) .forEachOrdered(typeMappers.getChildren()::add); }); if (!typeMappers.getChildren().isEmpty()) { item.getChildren().add(typeMappers); } } return item; } }