Juan Hernandez has uploaded a new change for review. Change subject: restapi: Introduce RSDL metadata converter ......................................................................
restapi: Introduce RSDL metadata converter This patch introduces a RsdlMetadataConverter class that splits the giant .yaml file into many smaller files. This class isn't intended to be there for ever, but just to facilitate the creation of the patch that will actually perform the split. Once that patch is merged this class will be removed. Change-Id: I731b73d290098d410c7aeb6b73f542cd2ef08d21 Signed-off-by: Juan Hernandez <[email protected]> --- M backend/manager/modules/pom.xml M backend/manager/modules/restapi/interface/definition/pom.xml M backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/Body.java M backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/RsdlBuilder.java A backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/RsdlMetadataConverter.java 5 files changed, 235 insertions(+), 3 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/78/33778/1 diff --git a/backend/manager/modules/pom.xml b/backend/manager/modules/pom.xml index 73d590c..e0b302d 100644 --- a/backend/manager/modules/pom.xml +++ b/backend/manager/modules/pom.xml @@ -50,7 +50,7 @@ <plugin> <artifactId>maven-checkstyle-plugin</artifactId> <configuration> - <excludes>**/RsdlManager.java,**/RsdlIOManager.java</excludes> + <excludes>**/RsdlManager.java,**/RsdlIOManager.java,**/RsdlMetadataConverter.java</excludes> </configuration> </plugin> </plugins> diff --git a/backend/manager/modules/restapi/interface/definition/pom.xml b/backend/manager/modules/restapi/interface/definition/pom.xml index 83441a9..1dad6b8 100644 --- a/backend/manager/modules/restapi/interface/definition/pom.xml +++ b/backend/manager/modules/restapi/interface/definition/pom.xml @@ -159,6 +159,33 @@ </profile> <profile> + <id>convert-metadata</id> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <executions> + <execution> + <phase>validate</phase> + <goals> + <goal>java</goal> + </goals> + <configuration> + <mainClass>org.ovirt.engine.api.rsdl.RsdlMetadataConverter</mainClass> + <arguments> + <argument>${project.basedir}/src/main/metadata/all.yaml</argument> + <argument>${project.basedir}/src/main/metadata</argument> + </arguments> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + + <profile> <id>build-rsdl</id> <activation> <activeByDefault>true</activeByDefault> diff --git a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/Body.java b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/Body.java index e79f341..a354492 100644 --- a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/Body.java +++ b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/Body.java @@ -26,7 +26,7 @@ public void setParameterType(String parameterType) { this.parameterType = parameterType; } - public Boolean isRequired() { + public Boolean getRequired() { return required; } public void setRequired(Boolean required) { diff --git a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/RsdlBuilder.java b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/RsdlBuilder.java index df96597..0ae35b3 100644 --- a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/RsdlBuilder.java +++ b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/RsdlBuilder.java @@ -389,7 +389,7 @@ private void addBodyParams(DetailedLink link, Action action) { if (action.getRequest().getBody() != null) { - link.getRequest().getBody().setRequired(action.getRequest().getBody().isRequired()); + link.getRequest().getBody().setRequired(action.getRequest().getBody().getRequired()); if (action.getRequest().getBody().getSignatures() != null) { for (Signature signature : action.getRequest().getBody().getSignatures()) { ParametersSet ps = new ParametersSet(); diff --git a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/RsdlMetadataConverter.java b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/RsdlMetadataConverter.java new file mode 100644 index 0000000..4195249 --- /dev/null +++ b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/rsdl/RsdlMetadataConverter.java @@ -0,0 +1,205 @@ +/* +* Copyright (c) 2014 Red Hat, Inc. +* +* 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 org.ovirt.engine.api.rsdl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; +import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor; +import org.yaml.snakeyaml.introspector.Property; +import org.yaml.snakeyaml.nodes.NodeTuple; +import org.yaml.snakeyaml.nodes.Tag; +import org.yaml.snakeyaml.representer.Representer; + +public class RsdlMetadataConverter { + /** + * Pattern used to check if a URL segment represents a variable identifier. + */ + private static Pattern IDENTIFIER_PATTERN = Pattern.compile("^\\{.*:id\\}$"); + + /** + * Pattern used to extract the URL and the relation from an action name. + */ + private static Pattern NAME_PATTERN = Pattern.compile("^(/?)(?<url>[^|]+)\\|rel=(?<relation>.*)$"); + + public static void main(String[] args) throws Exception { + String inputPath = args[0]; + String outputPath = args[1]; + + MetaData data = loadMetaData(inputPath); + System.out.println(data); + + // Check that the output directory exists, and create it if it doesn't: + File outputDir = new File(outputPath); + if (!outputDir.isDirectory()) { + if (!outputDir.mkdirs()) { + throw new IOException( + "Output directory \"" + outputDir.getAbsolutePath() + "\" doesn't exist and it can't be created" + ); + } + } + + // Generate a file for each action: + for (Action action : data.getActions()) { + convert(action, outputDir); + } + } + + private static MetaData loadMetaData(String path) throws IOException { + try (InputStream stream = new FileInputStream(path)) { + Constructor constructor = new CustomClassLoaderConstructor(Thread.currentThread().getContextClassLoader()); + return (MetaData) new Yaml(constructor).load(stream); + } + } + + private static void convert(Action action, File outDir) throws IOException { + // The output file may be inside an not yet existing directory, so check and create it if needed: + String outPath = calculateOutputPath(action); + File outFile = new File(outDir, outPath); + File parentDir = outFile.getParentFile(); + if (!parentDir.isDirectory()) { + if (!parentDir.mkdirs()) { + throw new IOException( + "Parent directory \"" + parentDir.getAbsolutePath() + "\" for output " + + "file \"" + outFile.getAbsolutePath() + "\" doesn't exist and it can't be " + + "created" + ); + } + } + + // Write the output file: + System.out.println( + "Writing action \"" + action.getName() + "\" to file \"" + outFile.getAbsolutePath() + "\"" + ); + try (Writer out = new FileWriter(outFile)) { + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + options.setWidth(80); + Representer representer = new Representer() { + @Override + protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, + Tag customTag) { + // Don't render null values: + if (propertyValue == null) { + return null; + } + + // Don't render empty lists: + if (property.getType() == List.class) { + List listValue = (List) propertyValue; + if (listValue.isEmpty()) { + return null; + } + } + + // Don't render empty maps: + if (property.getType() == Map.class) { + Map mapValue = (Map) propertyValue; + if (mapValue.isEmpty()) { + return null; + } + } + + // Don't render empty bodies: + if (property.getType() == Body.class) { + Body bodyValue = (Body) propertyValue; + if (bodyValue.getRequired() == null && bodyValue.getParameterType() == null && + bodyValue.getSignatures().isEmpty()) { + return null; + } + } + + return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag); + } + }; + Constructor constructor = new CustomClassLoaderConstructor(Thread.currentThread().getContextClassLoader()); + Yaml yaml = new Yaml(constructor, representer, options); + yaml.dump(action, out); + } + } + + /** + * Calculates the path of the file that should contain the metadata for the given action. + */ + private static String calculateOutputPath(Action action) { + // Extract the URL and the relation from the action: + Matcher matcher = NAME_PATTERN.matcher(action.getName()); + if (!matcher.matches()) { + throw new IllegalArgumentException( + "The action name \"" + action.getName() + "\" isn't valid as it doesn't match the regular " + + "expression \"" + NAME_PATTERN + "\"" + ); + } + String url = matcher.group("url"); + String relation = matcher.group("relation"); + + // Separate the URL into segments: + String[] segments = url.split("/"); + + // Calculate the file name: + StringBuilder buffer = new StringBuilder(); + for (int i = 0; i < segments.length - 1; i++) { + String segment = segments[i]; + if (!isId(segment)) { + buffer.append(File.separator); + buffer.append(segment); + } + } + String last = segments[segments.length - 1]; + buffer.append(File.separator); + switch (relation) { + case "add": + buffer.append(last); + buffer.append(File.separator); + buffer.append(relation); + break; + case "get": + if (isId(last)) { + buffer.append(relation); + } + else { + buffer.append(last); + buffer.append(File.separator); + buffer.append("list"); + } + break; + default: + buffer.append(relation); + break; + } + buffer.append(".yaml"); + return buffer.toString(); + } + + /** + * Determines if the given URL segment represents a variable identifier. + */ + private static boolean isId(String segment) { + return IDENTIFIER_PATTERN.matcher(segment).matches(); + } +} -- To view, visit http://gerrit.ovirt.org/33778 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I731b73d290098d410c7aeb6b73f542cd2ef08d21 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Juan Hernandez <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
