modules/helpers/pluginGen/pom.xml | 15
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Generator.java | 295
++++++++++
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/PluginGen.java | 4
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Prop.java | 114
+++
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java | 2
5 files changed, 427 insertions(+), 3 deletions(-)
New commits:
commit eb3c52f1ba91a70fa7bdb45405849a1af4aa524a
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Jul 15 10:18:15 2013 +0200
Add a JavaFX frontend to the PluginGenerator.
diff --git a/modules/helpers/pluginGen/pom.xml b/modules/helpers/pluginGen/pom.xml
index e9a5e29..5aa512c 100644
--- a/modules/helpers/pluginGen/pom.xml
+++ b/modules/helpers/pluginGen/pom.xml
@@ -22,6 +22,14 @@
<build>
<plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
@@ -98,6 +106,13 @@
<artifactId>rhq-pluginAnnotations</artifactId>
<version>4.8.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>com.oracle</groupId>
+ <artifactId>javafx</artifactId>
+ <version>2.0</version>
+ <systemPath>${java.home}/lib/jfxrt.jar</systemPath>
+ <scope>system</scope>
+ </dependency>
</dependencies>
</project>
diff --git
a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Generator.java
b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Generator.java
new file mode 100644
index 0000000..06f3fec
--- /dev/null
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Generator.java
@@ -0,0 +1,295 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.helpers.pluginGen;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javafx.application.Application;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.collections.ObservableList;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.Scene;
+import javafx.scene.control.*;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+import javafx.scene.paint.Color;
+import javafx.scene.text.Font;
+import javafx.scene.text.FontPosture;
+import javafx.scene.text.FontWeight;
+import javafx.scene.text.Text;
+import javafx.scene.text.TextAlignment;
+import javafx.stage.DirectoryChooser;
+import javafx.stage.Stage;
+
+/**
+ * JavaFX version of the plugin generator
+ * @author Heiko W. Rupp
+ */
+public class Generator extends Application{
+
+ Props props = new Props();
+ private Text errorMessage;
+ private Stage primaryStage;
+
+ public static void main(String[] args) {
+ launch(args);
+ }
+
+
+ @Override
+ public void start(Stage stage) throws Exception {
+ primaryStage = stage;
+
+ Button createButton = new Button();
+ createButton.setText("Create!");
+ createButton.setAlignment(Pos.BOTTOM_RIGHT);
+ createButton.setOnAction(new EventHandler<ActionEvent>() {
+ @Override
+ public void handle(ActionEvent actionEvent) {
+
+ PluginGen pluginGen = new PluginGen();
+ pluginGen.postprocess(props);
+ try {
+ pluginGen.generate(props);
+ setInfoMessage("Generated!");
+
+ }
+ catch (Exception e) {
+ setErrorMessage("Error during generation: " +
e.getMessage());
+ }
+ }
+ });
+
+ GridPane pluginLevelPane = new GridPane();
+ pluginLevelPane.setPadding(new Insets(10));
+ Text pluginLevelDescription = new Text("Plugin level properties");
+ pluginLevelDescription.setTextAlignment(TextAlignment.CENTER);
+ pluginLevelDescription.setFont(Font.font("Arial", FontWeight.BOLD,
14));
+
+ Text resourceLevelDescription = new Text("ResourceType level
properties");
+ resourceLevelDescription.setTextAlignment(TextAlignment.CENTER);
+ resourceLevelDescription.setFont(Font.font("Arial", FontWeight.BOLD,
14));
+
+ Text descriptionDescription = new Text("Field description");
+ descriptionDescription.setTextAlignment(TextAlignment.CENTER);
+ descriptionDescription.setFont(Font.font("Arial", FontWeight.BOLD,
14));
+
+ HBox msgBox = getMessagesBox();
+
+ GridPane resourceLevelPane = new GridPane();
+ resourceLevelPane.setPadding(new Insets(10));
+ Text descriptionText = new Text();
+ descriptionText.setFont(Font.font("Arial", FontPosture.ITALIC,12));
+
+ VBox innerBox = new VBox();
+ innerBox.setAlignment(Pos.CENTER_LEFT);
+ innerBox.setPadding(new Insets(25, 25, 25, 25));
+ innerBox.setSpacing(8);
+
+ addFields(pluginLevelPane, true, descriptionText);
+ addFields(resourceLevelPane, false, descriptionText);
+
+ ObservableList<Node> children = innerBox.getChildren();
+ children.add(pluginLevelDescription);
+ children.add(pluginLevelPane);
+ children.add(resourceLevelDescription);
+ children.add(resourceLevelPane);
+
+
+ ScrollPane scrollPane = new ScrollPane();
+ scrollPane.setContent(innerBox);
+
+ BorderPane outerBox = new BorderPane();
+ outerBox.setTop(msgBox);
+ outerBox.setPadding(new Insets(5));
+ outerBox.setCenter(scrollPane);
+
+ VBox descriptionBox = new VBox();
+ descriptionBox.getChildren().add(descriptionDescription);
+ descriptionBox.getChildren().add(descriptionText);
+ outerBox.setBottom(descriptionBox);
+
+ outerBox.setRight(createButton);
+
+
+ stage.setScene(new Scene(outerBox, 600, 550));
+ stage.show();
+ }
+
+ private HBox getMessagesBox() {
+ HBox msgBox = new HBox();
+ Label label = new Label("Messages:");
+ msgBox.getChildren().add(label);
+ errorMessage = new Text();
+ errorMessage.setFont(Font.font("Arial", FontWeight.SEMI_BOLD, 12));
+ errorMessage.setId("errorMessage");
+ msgBox.getChildren().add(errorMessage);
+ return msgBox;
+ }
+
+ private int addFields(final GridPane root, boolean pluginLevel, final Text
descriptionField) {
+
+ int row = 0;
+ for (final Prop prop : Prop.values()) {
+
+ if (!prop.isPluginLevel()==pluginLevel) {
+ continue;
+ }
+
+ // Add the label
+ String name = prop.readableName();
+ Label fieldName = new Label(name);
+ root.add(fieldName,0,row);
+
+ // Now add the field itself
+ final Class propType = prop.getType();
+ if (propType.equals(String.class)) {
+ final Pattern pattern = Pattern.compile(prop.getValidationRegex());
+
+ final TextField input = new TextField();
+ // Add field leave event to fill in the props with the result
+ input.focusedProperty().addListener(new ChangeListener<Boolean>()
{
+ @Override
+ public void changed(ObservableValue<? extends Boolean>
observableValue, Boolean oldState,
+ Boolean newState) {
+ if (newState) { // User entered input field
+ descriptionField.setText(prop.getDescription());
+ }
+ else { // User left input field
+ descriptionField.setText("");
+ setPropsValue(prop.getVariableName(),input.getText(),
propType); // TODO right place?
+ }
+ }
+ });
+ // Add validation of the input
+ input.textProperty().addListener(new ChangeListener<String>() {
+ @Override
+ public void changed(ObservableValue<? extends String>
observableValue, String s, String newText) {
+ Matcher m = pattern.matcher(newText);
+ if (!m.matches()) {
+ setErrorMessage("Input does not match " +
prop.getValidationRegex());
+ } else {
+ clearErrorMessage();
+ }
+
+ }
+ });
+ root.add(input, 1, row);
+ } else if (propType.equals(Boolean.class) || propType.equals(boolean.class))
{
+ final ChoiceBox choiceBox = new ChoiceBox();
+ choiceBox.getItems().addAll("Yes", "No");
+ choiceBox.getSelectionModel().selectLast(); // NO is default
+ choiceBox.getSelectionModel().selectedItemProperty().addListener(new
ChangeListener<String>() {
+ @Override
+ public void changed(ObservableValue<? extends String>
observableValue, String s, String newValue) {
+
setPropsValue(prop.getVariableName(),newValue.equals("Yes"),propType);
+ }
+ });
+
+ root.add(choiceBox,1,row);
+ } else if (propType.equals(ResourceCategory.class)) {
+ final ChoiceBox choiceBox = new ChoiceBox();
+ for (ResourceCategory cat : ResourceCategory.values()) {
+ choiceBox.getItems().add(cat.getLowerName());
+ }
+ choiceBox.getSelectionModel().selectLast(); // service is default
+ choiceBox.getSelectionModel().selectedItemProperty().addListener(new
ChangeListener<String>() {
+ @Override
+ public void changed(ObservableValue<? extends String>
observableValue, String s, String newValue) {
+ ResourceCategory newCategory =
ResourceCategory.valueOf(newValue.toUpperCase());
+ setPropsValue(prop.getVariableName(),newCategory,propType);
+ }
+ });
+
+ root.add(choiceBox,1,row);
+ } else if (propType.equals(File.class)) {
+ // Can not add this directly, so add a button to trigger it
+ final Text text = new Text();
+ text.setText("Pick a directory");
+ root.add(text,1,row);
+ Button pickButton = new Button("Pick");
+ pickButton.setOnAction(new EventHandler<ActionEvent>() {
+ @Override
+ public void handle(ActionEvent actionEvent) {
+ DirectoryChooser chooser = new DirectoryChooser();
+ chooser.setTitle("Pick a directory where the plugin will be
put in.");
+ File dir = chooser.showDialog(primaryStage);
+ if (dir != null) {
+ String dirName = dir.getAbsolutePath();
+ props.setFileSystemRoot(dirName);
+ clearErrorMessage();
+ text.setText(dirName);
+ } else {
+ setErrorMessage("No directory selected");
+ text.setText("Pick a directory");
+ }
+ }
+ });
+
+ root.add(pickButton,2,row);
+ }
+
+ row++;
+
+ }
+
+ return row;
+ }
+
+ private void setInfoMessage(String message) {
+ errorMessage.setText(message);
+ errorMessage.setFill(Color.DARKGREEN);
+ }
+ private void setErrorMessage(String message) {
+ errorMessage.setText(message);
+ errorMessage.setFill(Color.RED);
+ }
+
+ private void clearErrorMessage() {
+ errorMessage.setText("");
+ errorMessage.setFill(Color.WHITE);
+ }
+
+ private void setPropsValue(String variableName, Object value, Class type) {
+
+ String var = variableName.substring(0,1).toUpperCase() +
variableName.substring(1);
+ String setterName = "set"+ var;
+
+ try {
+ Method setter = Props.class.getDeclaredMethod(setterName,type);
+ setter.invoke(props,value);
+ } catch (NoSuchMethodException | IllegalAccessException |
InvocationTargetException e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ setErrorMessage(e.getMessage());
+ }
+ }
+
+}
diff --git
a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/PluginGen.java
b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/PluginGen.java
index 223a57f..64b5509 100644
--- a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/PluginGen.java
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/PluginGen.java
@@ -115,7 +115,7 @@ public class PluginGen {
* Do some post processing over the input received.
* @param props The properties just recorded from the user input
*/
- private void postprocess(Props props) {
+ protected void postprocess(Props props) {
// Set the package
String pkg = props.getPackagePrefix() + "." + props.getName();
@@ -231,7 +231,7 @@ public class PluginGen {
* Trigger the generation of the directory hierarchy.
* @param props Parameters to take into account
*/
- private void generate(Props props) {
+ protected void generate(Props props) {
log.info("Generating...");
diff --git a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Prop.java
b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Prop.java
new file mode 100644
index 0000000..73c4cd9
--- /dev/null
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Prop.java
@@ -0,0 +1,114 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.helpers.pluginGen;
+
+import java.io.File;
+
+/**
+ * All the properties that can be configured along with type, description and simple
validation rules
+ * @author Heiko W. Rupp
+ */
+public enum Prop {
+
+ PLUGIN_NAME("pluginName", String.class,"Name of the plugin",
"\\w+" , true ),
+ PLUGIN_DESCRIPTION("pluginDescription", String.class,"Description of
the plugin",".*" , true ),
+ PACKAGE("packagePrefix", String.class,"Default
Package","[a-zA-Z\\.]+",true ),
+ FILE_ROOT("fileSystemRoot", File.class,"Root directory to put the
plugin",".*",true ),
+ RHQ_VERSION("rhqVersion",String.class,"RHQ version to
use","[0-9][0-9\\.]+",true),
+
+ CATEGORY("category", ResourceCategory.class, "Category of the resource
type (platform = host level)",null),
+ TYPE_NAME("name", String.class, "Name of the resource type",
"\\w+"),
+ DESCRIPTION("description", String.class, "Description of the
type", ".*"),
+ DISCOVERY_CLASS("discoveryClass", String.class, "Discovery
class", "[A-Z][a-zA-Z0-9]*"),
+ COMPONENT_CLASS("componentClass", String.class, "Discovery
class", "[A-Z][a-zA-Z0-9]*"),
+ IS_SINGLETON("singleton",Boolean.class,"Is this type a singleton,
which means that" +
+ " there can only be one resource of that type for the given
parent?",null),
+ HAS_METRICS("hasMetrics",boolean.class,"Does this type support taking
metrics?",null),
+ HAS_OPERATIONS("hasOperations",boolean.class,"Does this type support
operations?",null),
+ HAS_EVENTS("events",boolean.class,"Does this type support
events?",null),
+ HAS_SUPPORT_FACET("supportFacet",boolean.class,"Does this type support
the support facet?",null),
+ RESOURCE_CONFIGURATION("resourceConfiguration",boolean.class,"Does
this type support " +
+ "configuring the resource?",".*"),
+ CAN_CREATE_CHILDREN("createChildren",boolean.class,"Can the type
create child resources?",null),
+ CAN_DELETE_CHILDREN("deleteChildren",boolean.class,"Can the type
delete child resources?",null),
+
+ // TODO add the remaining properties from Prop.class
+
+ ;
+
+ private String variableName;
+ private Class type;
+ private String description;
+ private boolean pluginLevel;
+ private String validationRegex;
+
+ private Prop(String variableName, Class type, String description, String
validationRegex, boolean pluginLevel) {
+ this.variableName = variableName;
+ this.type = type;
+ this.description = description;
+ this.validationRegex = validationRegex;
+ this.pluginLevel = pluginLevel;
+ }
+
+ private Prop(String variableName, Class type, String description, String
validationRegex) {
+ this.variableName = variableName;
+ this.type = type;
+ this.description = description;
+ this.validationRegex = validationRegex;
+ }
+
+ public String getVariableName() {
+ return variableName;
+ }
+
+ public Class getType() {
+ return type;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public boolean isPluginLevel() {
+ return pluginLevel;
+ }
+
+ public String getValidationRegex() {
+ return validationRegex;
+ }
+
+ public String readableName() {
+
+ String name = name();
+ name = name.replaceAll("_", " ");
+ String[] parts = name.split(" ");
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < parts.length; i++) {
+ String part = parts[i];
+ part = part.substring(0,1).toUpperCase() + part.substring(1).toLowerCase();
+ builder.append(part);
+ if (i < parts.length-1) {
+ builder.append(" ");
+ }
+ }
+ return builder.toString();
+ }
+
+}
diff --git a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
index 484d591..237f5ad 100644
--- a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
@@ -36,7 +36,7 @@ import org.rhq.helpers.pluginAnnotations.agent.Units;
public class Props {
/** What category is this ? */
- private ResourceCategory category;
+ private ResourceCategory category = ResourceCategory.SERVICE;
/** The name of this item */
private String name;
/** A description of the plugin */