diff --git a/datastructures-raml/build.gradle b/datastructures-raml/build.gradle new file mode 100644 index 0000000..81e4267 --- /dev/null +++ b/datastructures-raml/build.gradle @@ -0,0 +1,9 @@ +dependencies { + implementation 'javax.json:javax.json-api:1.1.4' + implementation 'org.apache.ws.xmlschema:xmlschema-core:2.3.0' + implementation('com.github.fge:json-schema-validator:2.2.6') { + exclude group: 'com.google.guava' + } + implementation 'org.yaml:snakeyaml:2.0' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/RamlModelBuilder.java b/datastructures-raml/src/main/java/org/xbib/raml/api/RamlModelBuilder.java new file mode 100644 index 0000000..c0bee06 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/RamlModelBuilder.java @@ -0,0 +1,256 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.net.URI; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.api.loader.ResourceLoaderFactories; +import org.xbib.raml.api.loader.ResourceLoaderFactory; +import org.xbib.raml.api.model.PermissiveURI; +import org.xbib.raml.api.model.common.ValidationResult; +import org.xbib.raml.api.model.v10.RamlFragment; +import org.xbib.raml.api.model.v10.api.DocumentationItem; +import org.xbib.raml.api.model.v10.api.Library; +import org.xbib.raml.api.model.v10.datamodel.ExampleSpec; +import org.xbib.raml.api.model.v10.datamodel.TypeDeclaration; +import org.xbib.raml.api.model.v10.methods.Trait; +import org.xbib.raml.api.model.v10.resources.ResourceType; +import org.xbib.raml.api.model.v10.security.SecurityScheme; +import org.xbib.raml.internal.impl.RamlBuilder; +import org.xbib.raml.internal.impl.commons.RamlHeader; +import org.xbib.raml.internal.impl.commons.model.Api; +import org.xbib.raml.internal.impl.commons.model.DefaultModelElement; +import org.xbib.raml.internal.impl.commons.model.RamlValidationResult; +import org.xbib.raml.internal.impl.commons.model.StringType; +import org.xbib.raml.internal.impl.commons.model.factory.TypeDeclarationModelFactory; +import org.xbib.raml.internal.impl.commons.nodes.RamlDocumentNode; +import org.xbib.raml.internal.utils.IOUtils; +import org.xbib.raml.internal.utils.RamlNodeUtils; +import org.xbib.raml.internal.utils.StreamUtils; +import org.xbib.raml.yagi.framework.model.DefaultModelBindingConfiguration; +import org.xbib.raml.yagi.framework.model.ModelBindingConfiguration; +import org.xbib.raml.yagi.framework.model.ModelProxyBuilder; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; + +/** + * Entry point class to parse top level RAML descriptors. + */ +public class RamlModelBuilder { + + public static final String MODEL_PACKAGE = "org.xbib.raml.internal.impl.commons.model"; + private final ResourceLoaderFactory resourceLoaderFactory; + private final RamlBuilder builder = new RamlBuilder(); + + public RamlModelBuilder() { + resourceLoaderFactory = ResourceLoaderFactories.defaultResourceLoaderFactory(); + // new DefaultResourceLoader(RootDirectoryFileAccessGuard.fromRootDir(Sets.newHashSet("file", "http", "https"), + // "."))); + } + + public RamlModelBuilder(ResourceLoader resourceLoaderFactory) { + this.resourceLoaderFactory = ResourceLoaderFactories.identityFactory(resourceLoaderFactory); + } + + + public RamlModelResult buildApi(String ramlLocation) { + String content = getRamlContent(ramlLocation); + if (content == null) { + return generateRamlApiResult("Raml does not exist at: " + ramlLocation); + } + return buildApi(content, ramlLocation); + } + + + public RamlModelResult buildApi(File ramlFile) { + String content = getRamlContent(ramlFile); + if (content == null) { + return generateRamlApiResult("Files does not exist or is not a regular file: " + ramlFile.getPath()); + } + return buildApi(content, ramlFile.getPath()); + } + + + public RamlModelResult buildApi(Reader reader, String ramlLocation) { + String content = getRamlContent(reader); + if (content == null) { + return generateRamlApiResult("Invalid reader provided with location: " + ramlLocation); + } + return buildApi(content, ramlLocation); + } + + + public RamlModelResult buildApi(String content, String ramlLocation) { + if (content == null) { + return buildApi(ramlLocation); + } + + if (ramlLocation.matches("^[a-z]+:.*")) { + + String actualName = PermissiveURI.create(ramlLocation).toString(); + if (ramlLocation.startsWith("file:")) { + actualName = new File(PermissiveURI.create(ramlLocation).getPath()).getParent(); + } + Node ramlNode = builder.build(content, resourceLoaderFactory.createResourceLoader(actualName), ramlLocation); + return generateRamlApiResult(ramlNode, getFragment(content)); + } else { + + Node ramlNode = builder.build(content, resourceLoaderFactory.createResourceLoader(Paths.get(ramlLocation).toAbsolutePath().getParent().toString()), ramlLocation); + return generateRamlApiResult(ramlNode, getFragment(content)); + } + } + + private RamlFragment getFragment(String content) { + try { + RamlHeader ramlHeader = RamlHeader.parse(content); + return ramlHeader.getFragment(); + } catch (RamlHeader.InvalidHeaderException e) { + // ignore, already handled by builder + } + return null; + } + + private RamlModelResult generateRamlApiResult(Node ramlNode, RamlFragment fragment) { + List validationResults = new ArrayList<>(); + List errors = RamlNodeUtils.getErrors(ramlNode); + for (ErrorNode errorNode : errors) { + validationResults.add(new RamlValidationResult(errorNode)); + } + if (validationResults.isEmpty()) { + return wrapTree(ramlNode, fragment); + } + return new RamlModelResult(validationResults); + } + + private RamlModelResult generateRamlApiResult(String errorMessage) { + List validationResults = new ArrayList<>(); + validationResults.add(new RamlValidationResult(errorMessage)); + return new RamlModelResult(validationResults); + } + + private RamlModelResult wrapTree(Node ramlNode, RamlFragment fragment) { + if (ramlNode instanceof RamlDocumentNode) { + org.xbib.raml.api.model.v10.api.Api apiV10 = ModelProxyBuilder.createModel(org.xbib.raml.api.model.v10.api.Api.class, new Api((RamlDocumentNode) ramlNode), createV10Binding()); + return new RamlModelResult(apiV10); + } + if (fragment == RamlFragment.Library) { + Library library = ModelProxyBuilder.createModel(Library.class, new DefaultModelElement(ramlNode), createV10Binding()); + return new RamlModelResult(library); + } + if (fragment == RamlFragment.DataType || fragment == RamlFragment.AnnotationTypeDeclaration) { + final org.xbib.raml.internal.impl.commons.model.type.TypeDeclaration delegateNode = new TypeDeclarationModelFactory().create(ramlNode); + final ModelBindingConfiguration v10Binding = createV10Binding(); + TypeDeclaration typeDeclaration = ModelProxyBuilder.createModel((Class) v10Binding.reverseBindingOf(delegateNode), delegateNode, v10Binding); + return new RamlModelResult(typeDeclaration); + } + if (fragment == RamlFragment.DocumentationItem) { + DocumentationItem documentationItem = ModelProxyBuilder.createModel(DocumentationItem.class, new DefaultModelElement(ramlNode), createV10Binding()); + return new RamlModelResult(documentationItem); + } + if (fragment == RamlFragment.SecurityScheme) { + SecurityScheme securityScheme = ModelProxyBuilder.createModel(SecurityScheme.class, new DefaultModelElement(ramlNode), createV10Binding()); + return new RamlModelResult(securityScheme); + } + if (fragment == RamlFragment.Trait) { + Trait trait = ModelProxyBuilder.createModel(Trait.class, new DefaultModelElement(ramlNode), createV10Binding()); + return new RamlModelResult(trait); + } + if (fragment == RamlFragment.ResourceType) { + ResourceType resourceType = ModelProxyBuilder.createModel(ResourceType.class, new DefaultModelElement(ramlNode), createV10Binding()); + return new RamlModelResult(resourceType); + } + if (fragment == RamlFragment.NamedExample) { + if (!(ramlNode instanceof KeyValueNode)) { + ramlNode = new KeyValueNodeImpl(new StringNodeImpl("__NamedExample_Fragment__"), ramlNode); + } + ExampleSpec exampleSpec = ModelProxyBuilder.createModel(ExampleSpec.class, new org.xbib.raml.internal.impl.commons.model.ExampleSpec((KeyValueNode) ramlNode), createV10Binding()); + return new RamlModelResult(exampleSpec); + } + throw new IllegalStateException("Invalid ramlNode type (" + ramlNode.getClass().getSimpleName() + ") or fragment (" + fragment + ") combination"); + } + + private ModelBindingConfiguration createV10Binding() { + final DefaultModelBindingConfiguration bindingConfiguration = new DefaultModelBindingConfiguration(); + bindingConfiguration.bindPackage(MODEL_PACKAGE); + // Bind all StringTypes to the StringType implementation they are only marker interfaces + bindingConfiguration.bind(org.xbib.raml.api.model.v10.system.types.StringType.class, StringType.class); + bindingConfiguration.bind(org.xbib.raml.api.model.v10.system.types.ValueType.class, StringType.class); + bindingConfiguration.defaultTo(DefaultModelElement.class); + bindingConfiguration.bind(TypeDeclaration.class, new TypeDeclarationModelFactory()); + bindingConfiguration.reverseBindPackage("org.xbib.raml.api.model.v10.datamodel"); + return bindingConfiguration; + } + + private String getRamlContent(File ramlFile) { + if (ramlFile == null || !ramlFile.isFile()) { + return null; + } + + ResourceLoader fileLoader = resourceLoaderFactory.createResourceLoader(ramlFile.getAbsoluteFile().getParent()); + return getRamlContent(ramlFile.getName(), fileLoader); + } + + private String getRamlContent(Reader ramlReader) { + if (ramlReader == null) { + return null; + } + try { + return IOUtils.toString(ramlReader); + } catch (IOException e) { + return null; + } finally { + IOUtils.closeQuietly(ramlReader); + } + } + + private String getRamlContent(String ramlLocation) { + + if (ramlLocation == null) { + + return null; + } + + if (ramlLocation.startsWith("file:")) { + Path p = Paths.get(URI.create(ramlLocation)).toAbsolutePath().getParent(); + return getRamlContent(ramlLocation, resourceLoaderFactory.createResourceLoader(p.toString())); + } else { + Path p = Paths.get(ramlLocation).toAbsolutePath().getParent(); + return getRamlContent(ramlLocation, resourceLoaderFactory.createResourceLoader(p.toString())); + } + } + + private String getRamlContent(String ramlLocation, ResourceLoader loader) { + if (ramlLocation == null) { + return null; + } + InputStream ramlStream = loader.fetchResource(ramlLocation); + if (ramlStream != null) { + return StreamUtils.toString(ramlStream); + } + return null; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/RamlModelResult.java b/datastructures-raml/src/main/java/org/xbib/raml/api/RamlModelResult.java new file mode 100644 index 0000000..bfe32ab --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/RamlModelResult.java @@ -0,0 +1,239 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.api.model.common.ValidationResult; +import org.xbib.raml.api.model.v10.RamlFragment; +import org.xbib.raml.api.model.v10.api.Api; +import org.xbib.raml.api.model.v10.api.DocumentationItem; +import org.xbib.raml.api.model.v10.api.Library; +import org.xbib.raml.api.model.v10.datamodel.ExampleSpec; +import org.xbib.raml.api.model.v10.datamodel.TypeDeclaration; +import org.xbib.raml.api.model.v10.methods.Trait; +import org.xbib.raml.api.model.v10.resources.ResourceType; +import org.xbib.raml.api.model.v10.security.SecurityScheme; + +/** + * Represents the result of parsing a top level RAML descriptor or fragment. + *

+ * If there are no parsing errors and the parsed RAML was a top level descriptor, + * the Api model matching the RAML version is available. + * If the parsed raml is 1.0 fragment and there are no errors, the corresponding + * fragment instance is available. + *

+ * If there are parsing errors, the list of errors is available. + */ +public class RamlModelResult { + + private List validationResults = new ArrayList<>(); + private Api apiV10; + private Library library; + private TypeDeclaration typeDeclaration; + private SecurityScheme securityScheme; + private Trait trait; + private ResourceType resourceType; + private ExampleSpec exampleSpec; + private DocumentationItem documentationItem; + + RamlModelResult(List validationResults) { + if (validationResults == null || validationResults.isEmpty()) { + throw new IllegalArgumentException("validationResults cannot be null or emtpy"); + } + this.validationResults = validationResults; + } + + RamlModelResult(Api apiV10) { + if (apiV10 == null) { + throw new IllegalArgumentException("apiV10 cannot be null"); + } + this.apiV10 = apiV10; + } + + RamlModelResult(Library library) { + if (library == null) { + throw new IllegalArgumentException("library cannot be null"); + } + this.library = library; + } + + public RamlModelResult(TypeDeclaration typeDeclaration) { + if (typeDeclaration == null) { + throw new IllegalStateException("typeDeclaration cannot be null"); + } + this.typeDeclaration = typeDeclaration; + } + + public RamlModelResult(SecurityScheme securityScheme) { + if (securityScheme == null) { + throw new IllegalStateException("securityScheme cannot be null"); + } + this.securityScheme = securityScheme; + } + + public RamlModelResult(DocumentationItem documentationItem) { + if (documentationItem == null) { + throw new IllegalStateException("documentationItem cannot be null"); + } + this.documentationItem = documentationItem; + } + + public RamlModelResult(Trait trait) { + if (trait == null) { + throw new IllegalStateException("trait cannot be null"); + } + this.trait = trait; + } + + + public RamlModelResult(ResourceType resourceType) { + if (resourceType == null) { + throw new IllegalStateException("resourceType cannot be null"); + } + this.resourceType = resourceType; + } + + + public RamlModelResult(ExampleSpec exampleSpec) { + if (exampleSpec == null) { + throw new IllegalStateException("exampleSpec cannot be null"); + } + this.exampleSpec = exampleSpec; + } + + + /** + * @return true if any parsing error occurred + */ + public boolean hasErrors() { + return !validationResults.isEmpty(); + } + + /** + * @return the list of validation results if there were parsing errors + * or an empty list if there were no parsing errors + */ + public List getValidationResults() { + return validationResults; + } + + + /** + * @return the RAML Api v1.0 parsed without errors + * or null if there were errors or the RAML version is not 1.0 or is not a top level RAML + */ + public Api getApiV10() { + return apiV10; + } + + /** + * @return the RAML Library v1.0 parsed without errors + * or null if there were errors or the RAML is not a Library fragment + */ + public Library getLibrary() { + return library; + } + + + /** + * @return the RAML Data Type v1.0 parsed without errors + * or null if there were errors or the RAML is not a Data Type fragment + */ + public TypeDeclaration getTypeDeclaration() { + return typeDeclaration; + } + + + /** + * @return the RAML Security Scheme v1.0 parsed without errors + * or null if there were errors or the RAML is not a Security Scheme fragment + */ + public SecurityScheme getSecurityScheme() { + return securityScheme; + } + + + /** + * @return the RAML Trait v1.0 parsed without errors + * or null if there were errors or the RAML is not a Trait fragment + */ + public Trait getTrait() { + return trait; + } + + + /** + * @return the RAML ResourceType v1.0 parsed without errors + * or null if there were errors or the RAML is not a ResourceType fragment + */ + public ResourceType getResourceType() { + return resourceType; + } + + + /** + * @return the RAML NamedExample v1.0 parsed without errors + * or null if there were errors or the RAML is not a NamedExample fragment + */ + public ExampleSpec getExampleSpec() { + return exampleSpec; + } + + /** + * @return the RAML DocumentationItem v1.0 parsed without errors + * or null if there were errors or the RAML is not a DocumentationItem fragment + */ + public DocumentationItem getDocumentationItem() { + return documentationItem; + } + + + /** + * @return the RAML 1.0 fragment identifier or null + * if the RAML has errors or is version 0.8 + */ + public RamlFragment getFragment() { + if (hasErrors()) { + return null; + } + if (getApiV10() != null) { + return RamlFragment.Default; + } + if (getLibrary() != null) { + return RamlFragment.Library; + } + if (getTypeDeclaration() != null) { + return RamlFragment.DataType; + } + if (getSecurityScheme() != null) { + return RamlFragment.SecurityScheme; + } + if (getTrait() != null) { + return RamlFragment.Trait; + } + if (getResourceType() != null) { + return RamlFragment.ResourceType; + } + if (getExampleSpec() != null) { + return RamlFragment.NamedExample; + } + if (getDocumentationItem() != null) { + return RamlFragment.DocumentationItem; + } + throw new IllegalStateException("Fragment not yet supported"); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/CacheResourceLoader.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/CacheResourceLoader.java new file mode 100644 index 0000000..4215807 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/CacheResourceLoader.java @@ -0,0 +1,84 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import org.xbib.raml.internal.utils.IOUtils; +import org.xbib.raml.internal.utils.Pair; + +public class CacheResourceLoader implements ResourceLoaderExtended { + + private final Map> resources = new HashMap<>(); + private final ResourceLoader resourceLoader; + + public CacheResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + @Override + public InputStream fetchResource(String resourceName) { + return fetchResource(resourceName, null); + } + + @Override + public InputStream fetchResource(String resourceName, ResourceUriCallback callback) { + try { + if (resources.containsKey(resourceName)) { + final byte[] resourceByteArray = resources.get(resourceName).getLeft(); + final URI uriCallback = resources.get(resourceName).getRight(); + if (uriCallback != null && callback != null) { + callback.onResourceFound(uriCallback); + } + return toInputStreamOrNull(resourceByteArray); + } + + InputStream resource; + URI uriCallback = null; + if (resourceLoader instanceof ResourceLoaderExtended) { + resource = ((ResourceLoaderExtended) resourceLoader).fetchResource(resourceName, callback); + uriCallback = ((ResourceLoaderExtended) resourceLoader).getUriCallBackParam(); + } else { + resource = resourceLoader.fetchResource(resourceName); + } + + // we want to cache results even if they are null + final byte[] resourceByteArray = resource == null ? null : IOUtils.toByteArray(resource); + resources.put(resourceName, Pair.of(resourceByteArray, uriCallback)); + + return toInputStreamOrNull(resourceByteArray); + + } catch (final IOException e) { + return resourceLoader.fetchResource(resourceName); + } + } + + private ByteArrayInputStream toInputStreamOrNull(final byte[] resourceByteArray) { + return resourceByteArray == null ? null : new ByteArrayInputStream(resourceByteArray); + } + + @Override + public URI getUriCallBackParam() { + if (resourceLoader != null && resourceLoader instanceof ResourceLoaderExtended) { + return ((ResourceLoaderExtended) resourceLoader).getUriCallBackParam(); + } + return null; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ClassPathResourceLoader.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ClassPathResourceLoader.java new file mode 100644 index 0000000..7e157e1 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ClassPathResourceLoader.java @@ -0,0 +1,90 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; + + +public class ClassPathResourceLoader implements ResourceLoaderExtended { + + private final String rootRamlPackage; + private URI callbackParam; + + public ClassPathResourceLoader() { + rootRamlPackage = ""; + } + + /** + * When the root raml is loaded through the classpath allows specifying + * the package where it is loaded from in order to correctly resolve + * absolute path includes and libraries + * + * @param rootRamlPackage in the classpath + */ + public ClassPathResourceLoader(String rootRamlPackage) { + if (rootRamlPackage.isBlank() || rootRamlPackage.equals("/")) { + this.rootRamlPackage = ""; + } else { + + this.rootRamlPackage = (rootRamlPackage.startsWith("/") ? rootRamlPackage.substring(1) : rootRamlPackage) + "/"; + } + } + + private URL getResource(String uselessRootPackage, String resourceName) { + String fixedResourceName = uselessRootPackage + (resourceName.startsWith("/") ? resourceName.substring(1) : resourceName); + URL url = getClass().getClassLoader().getResource(fixedResourceName); + if (url == null) { + return Thread.currentThread().getContextClassLoader().getResource(fixedResourceName); + } + + return url; + } + + @Override + public InputStream fetchResource(String resourceName, ResourceUriCallback callback) { + + try { + final URL url = getResource(rootRamlPackage, resourceName); + if (url != null) { + + this.callbackParam = url.toURI(); + if (callback != null) { + callback.onResourceFound(callbackParam); + } + + return url.openStream(); + } + return null; + } catch (IOException | URISyntaxException e) { + + return null; + } + } + + @Override + public InputStream fetchResource(String resourceName) { + return fetchResource(resourceName, null); + } + + @Override + public URI getUriCallBackParam() { + return callbackParam; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/CompositeResourceLoader.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/CompositeResourceLoader.java new file mode 100644 index 0000000..996e6f5 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/CompositeResourceLoader.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.io.InputStream; +import java.net.URI; + +public class CompositeResourceLoader implements ResourceLoaderExtended { + + private final ResourceLoader[] resourceLoaders; + private ResourceLoader callBackLoader; + + public CompositeResourceLoader(ResourceLoader... resourceLoaders) { + this.resourceLoaders = resourceLoaders; + } + + public static CompositeResourceLoader compose(ResourceLoader... resourceLoaders) { + return new CompositeResourceLoader(resourceLoaders); + } + + @Override + public InputStream fetchResource(String resourceName, ResourceUriCallback callback) { + InputStream inputStream = null; + for (ResourceLoader loader : resourceLoaders) { + if (loader instanceof ResourceLoaderExtended) { + inputStream = ((ResourceLoaderExtended) loader).fetchResource(resourceName, callback); + } else { + inputStream = loader.fetchResource(resourceName); + } + + if (inputStream != null) { + callBackLoader = loader; + break; + } + } + return inputStream; + } + + @Override + public InputStream fetchResource(String resourceName) { + return fetchResource(resourceName, null); + } + + @Override + public URI getUriCallBackParam() { + if (callBackLoader != null && callBackLoader instanceof ResourceLoaderExtended) { + return ((ResourceLoaderExtended) callBackLoader).getUriCallBackParam(); + } + return null; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/DefaultResourceLoader.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/DefaultResourceLoader.java new file mode 100644 index 0000000..1a3d933 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/DefaultResourceLoader.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.io.InputStream; +import java.net.URI; + +public class DefaultResourceLoader implements ResourceLoaderExtended { + + private final ResourceLoader resourceLoader; + + public DefaultResourceLoader() { + resourceLoader = CompositeResourceLoader.compose( + new UrlResourceLoader(), + new RamlUrlResourceLoader(), + new ClassPathResourceLoader(), + new FileResourceLoader(".")); + } + + @Override + public InputStream fetchResource(String resourceName, ResourceUriCallback callback) { + if (resourceLoader instanceof ResourceLoaderExtended) { + return ((ResourceLoaderExtended) resourceLoader).fetchResource(resourceName, callback); + } else { + return resourceLoader.fetchResource(resourceName); + } + } + + @Override + public InputStream fetchResource(String resourceName) { + return fetchResource(resourceName, null); + } + + @Override + public URI getUriCallBackParam() { + if (resourceLoader != null && resourceLoader instanceof ResourceLoaderExtended) { + return ((ResourceLoaderExtended) resourceLoader).getUriCallBackParam(); + } + return null; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/FileResourceLoader.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/FileResourceLoader.java new file mode 100644 index 0000000..bb38acb --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/FileResourceLoader.java @@ -0,0 +1,65 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; + +public class FileResourceLoader implements ResourceLoaderExtended { + + private final File parentPath; + private URI callbackParam; + + public FileResourceLoader(String path) { + this(new File(path)); + } + + public FileResourceLoader(File path) { + this.parentPath = path; + } + + @Override + public InputStream fetchResource(String resourceName, ResourceUriCallback callback) { + File includedFile = new File(resourceName); + if (!includedFile.isAbsolute()) { + includedFile = new File(parentPath, resourceName); + } + try { + if (callback != null) { + callbackParam = includedFile.toURI(); + callback.onResourceFound(callbackParam); + } + + return new FileInputStream(includedFile); + + } catch (IOException e) { + return null; + } + } + + @Override + public InputStream fetchResource(String resourceName) { + return fetchResource(resourceName, null); + } + + @Override + public URI getUriCallBackParam() { + return callbackParam; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/InputStreamProvider.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/InputStreamProvider.java new file mode 100644 index 0000000..2f33bf0 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/InputStreamProvider.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Created. There, you have it. + */ +public interface InputStreamProvider { + + InputStream apply(T object) throws IOException; +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/RamlUrlResourceLoader.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/RamlUrlResourceLoader.java new file mode 100644 index 0000000..46e4034 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/RamlUrlResourceLoader.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; + +class RamlUrlResourceLoader implements ResourceLoaderExtended { + public static final String APPLICATION_RAML = "application/raml+yaml"; + private URI callbackParam; + + + @Override + public InputStream fetchResource(String resourceName, ResourceUriCallback callback) { + try { + URL url = new URL(resourceName); + URLConnection connection = url.openConnection(); + connection.setRequestProperty("Accept", APPLICATION_RAML + ", */*"); + if (callback != null) { + callbackParam = url.toURI(); + callback.onResourceFound(callbackParam); + } + return new BufferedInputStream(connection.getInputStream()); + } catch (IOException e) { + // ignore on resource not found + } catch (URISyntaxException e) { + // Ignore + } + return null; + } + + @Override + public InputStream fetchResource(String resourceName) { + return fetchResource(resourceName, null); + } + + @Override + public URI getUriCallBackParam() { + return callbackParam; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoader.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoader.java new file mode 100644 index 0000000..56df6d6 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoader.java @@ -0,0 +1,31 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.io.InputStream; + +public interface ResourceLoader { + + /** + * Returns an input stream for reading the specified resource. + * + * @param resourceName the resource to try to fetch + * @return An input stream for reading the resource, or null + * if the resource could not be found + */ + InputStream fetchResource(String resourceName); + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoaderAware.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoaderAware.java new file mode 100644 index 0000000..a055caf --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoaderAware.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +public interface ResourceLoaderAware { + + void setResourceLoader(ResourceLoader resourceLoader); + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoaderExtended.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoaderExtended.java new file mode 100644 index 0000000..a495808 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoaderExtended.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.io.InputStream; +import java.net.URI; + +public interface ResourceLoaderExtended extends ResourceLoader { + /** + * Returns an input stream for reading the specified resource. + * + * @param resourceName the resource to try to fetch + * @return An input stream for reading the resource, or null + * if the resource could not be found + */ + InputStream fetchResource(String resourceName, ResourceUriCallback callback); + + /** + * Returns the URI used by ResourceUriCallback if exists + * + * @return An URI if callback is called in fetchResource method, or null + */ + URI getUriCallBackParam(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoaderFactories.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoaderFactories.java new file mode 100644 index 0000000..034f1d1 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoaderFactories.java @@ -0,0 +1,65 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.io.File; +import java.io.InputStream; + +/** + * Created. There, you have it. + */ +public class ResourceLoaderFactories { + + // this continously returns the same resource loader. + public static ResourceLoaderFactory identityFactory(final ResourceLoader loader) { + + return new ResourceLoaderFactory() { + @Override + public ResourceLoader createResourceLoader(String parent) { + return loader; + } + }; + } + + // this is used nowhere but in the empty positions. these loaders shouldn't open files. + public static ResourceLoaderFactory nullFactory() { + return new ResourceLoaderFactory() { + @Override + public ResourceLoader createResourceLoader(String parent) { + return new ResourceLoader() { + @Override + public InputStream fetchResource(String resourceName) { + return null; + } + }; + } + }; + } + + public static ResourceLoaderFactory defaultResourceLoaderFactory() { + + return new ResourceLoaderFactory() { + @Override + public ResourceLoader createResourceLoader(String parent) { + return CompositeResourceLoader.compose( + new DefaultResourceLoader(), + new RootRamlFileResourceLoader(new File(parent)), + new RootRamlUrlResourceLoader(parent) + ); + } + }; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoaderFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoaderFactory.java new file mode 100644 index 0000000..cf12490 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceLoaderFactory.java @@ -0,0 +1,23 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +/** + * Created. There, you have it. + */ +public interface ResourceLoaderFactory { + ResourceLoader createResourceLoader(String parent); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceUriCallback.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceUriCallback.java new file mode 100644 index 0000000..838cce5 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/ResourceUriCallback.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.net.URI; + +public interface ResourceUriCallback { + void onResourceFound(URI resourceURI); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/RootRamlFileResourceLoader.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/RootRamlFileResourceLoader.java new file mode 100644 index 0000000..c622997 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/RootRamlFileResourceLoader.java @@ -0,0 +1,62 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class RootRamlFileResourceLoader implements ResourceLoaderExtended { + + private final Logger logger = Logger.getLogger(RootRamlFileResourceLoader.class.getName()); + private final File parentPath; + private URI callbackParam; + + public RootRamlFileResourceLoader(File path) { + this.parentPath = path; + } + + @Override + public InputStream fetchResource(String resourceName, ResourceUriCallback callback) { + final File includedFile = new File(parentPath, resourceName.startsWith("/") ? resourceName.substring(1) : resourceName); + logger.log(Level.FINE, "Looking for resource " + resourceName + " on directory " + parentPath); + try { + if (callback != null) { + callbackParam = includedFile.toURI(); + callback.onResourceFound(callbackParam); + } + + return new FileInputStream(includedFile); + } catch (IOException e) { + return null; + } + } + + @Override + public InputStream fetchResource(String resourceName) { + return fetchResource(resourceName, null); + } + + @Override + public URI getUriCallBackParam() { + return callbackParam; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/RootRamlUrlResourceLoader.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/RootRamlUrlResourceLoader.java new file mode 100644 index 0000000..7a27957 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/RootRamlUrlResourceLoader.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; + +public class RootRamlUrlResourceLoader implements ResourceLoaderExtended { + public static final String APPLICATION_RAML = "application/raml+yaml"; + + private final String rootRamlUrl; + private URI callbackParam; + + public RootRamlUrlResourceLoader(String rootRamlUrl) { + this.rootRamlUrl = rootRamlUrl.endsWith("/") ? rootRamlUrl : rootRamlUrl + "/"; + } + + @Override + public InputStream fetchResource(String resourceName, ResourceUriCallback callback) { + try { + URL url = new URL(resourceName.startsWith(rootRamlUrl) ? resourceName : rootRamlUrl + resourceName); + final URLConnection connection = url.openConnection(); + connection.setRequestProperty("Accept", APPLICATION_RAML + ", */*"); + + if (callback != null) { + callbackParam = url.toURI(); + callback.onResourceFound(callbackParam); + } + + return new BufferedInputStream(connection.getInputStream()); + } catch (IOException | URISyntaxException e) { + return null; + } + } + + @Override + public InputStream fetchResource(String resourceName) { + return fetchResource(resourceName, null); + } + + @Override + public URI getUriCallBackParam() { + return callbackParam; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/loader/UrlResourceLoader.java b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/UrlResourceLoader.java new file mode 100644 index 0000000..01ee257 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/loader/UrlResourceLoader.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.loader; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; + +class UrlResourceLoader implements ResourceLoaderExtended { + private URI callbackParam; + + @Override + public InputStream fetchResource(String resourceName, ResourceUriCallback callback) { + try { + URL url = new URL(resourceName); + if (callback != null) { + callbackParam = url.toURI(); + callback.onResourceFound(url.toURI()); + } + + return new BufferedInputStream(url.openStream()); + } catch (URISyntaxException | IOException e) { + return null; + } + } + + @Override + public InputStream fetchResource(String resourceName) { + return fetchResource(resourceName, null); + } + + @Override + public URI getUriCallBackParam() { + return callbackParam; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/PermissiveURI.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/PermissiveURI.java new file mode 100644 index 0000000..3401449 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/PermissiveURI.java @@ -0,0 +1,29 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model; + +import java.net.URI; + +/** + * Created. There, you have it. + */ +public class PermissiveURI { + + public static URI create(String s) { + + return URI.create(s.replace(" ", "%20")); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/common/ValidationResult.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/common/ValidationResult.java new file mode 100644 index 0000000..81378c6 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/common/ValidationResult.java @@ -0,0 +1,23 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.common; + +public interface ValidationResult { + + String getMessage(); + + String getPath(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/RamlFragment.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/RamlFragment.java new file mode 100644 index 0000000..950789d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/RamlFragment.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10; + +public enum RamlFragment { + DocumentationItem, + DataType, + NamedExample, + ResourceType, + Trait, + AnnotationTypeDeclaration, + Library, + Overlay, + Extension, + SecurityScheme, + Default; + + + public static RamlFragment byName(String name) { + if (name.isBlank()) { + return RamlFragment.Default; + } else { + try { + return RamlFragment.valueOf(name); + } catch (IllegalArgumentException iae) { + return null; + } + } + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/Api.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/Api.java new file mode 100755 index 0000000..2ab103e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/Api.java @@ -0,0 +1,96 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.api; + +import java.util.List; +import org.xbib.raml.api.model.v10.bodies.MimeType; +import org.xbib.raml.api.model.v10.datamodel.TypeDeclaration; +import org.xbib.raml.api.model.v10.resources.Resource; +import org.xbib.raml.api.model.v10.security.SecuritySchemeRef; +import org.xbib.raml.api.model.v10.system.types.AnnotableStringType; +import org.xbib.raml.api.model.v10.system.types.FullUriTemplateString; +import org.xbib.raml.api.model.v10.system.types.MarkdownString; + + +public interface Api extends LibraryBase { + + /** + * Short plain-text label for the API + **/ + AnnotableStringType title(); + + + /** + * Longer description for the API. May be formatted using markdown. + **/ + MarkdownString description(); + + + /** + * The version of the API, e.g. 'v1' + **/ + AnnotableStringType version(); + + + /** + * A URI that's to be used as the base of all the resources' URIs. Often used as the base of the URL of each resource, containing the location of the API. Can be a template URI. + **/ + FullUriTemplateString baseUri(); + + + /** + * Named parameters used in the baseUri (template) + **/ + List baseUriParameters(); + + + /** + * The protocols supported by the API + **/ + List protocols(); + + + /** + * The default media type to use for request and response bodies (payloads), e.g. "application/json" + **/ + List mediaType(); + + + /** + * The security schemes that apply to every resource and method in the API + **/ + List securedBy(); + + + /** + * The resources of the API, identified as relative URIs that begin with a slash (/). Every property whose key begins with a slash (/), and is either at the root of the API definition or is the child property of a resource property, is a resource property, e.g.: /users, /{groupId}, etc + **/ + List resources(); + + + /** + * Additional overall documentation for the API + **/ + List documentation(); + + + /** + * Returns RAML version. "RAML10" string is returned for RAML 1.0. "RAML08" string is returned for RAML 0.8. + **/ + // --def-system-mod-- + String ramlVersion(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/DocumentationItem.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/DocumentationItem.java new file mode 100755 index 0000000..a38f6e0 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/DocumentationItem.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.api; + +import org.xbib.raml.api.model.v10.common.Annotable; +import org.xbib.raml.api.model.v10.system.types.AnnotableStringType; +import org.xbib.raml.api.model.v10.system.types.MarkdownString; + +public interface DocumentationItem extends Annotable { + + /** + * Title of documentation section + **/ + AnnotableStringType title(); + + + /** + * Content of documentation section + **/ + MarkdownString content(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/Library.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/Library.java new file mode 100755 index 0000000..82a9205 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/Library.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.api; + + +import org.xbib.raml.api.model.v10.system.types.AnnotableStringType; + +public interface Library extends LibraryBase { + + /** + * contains description of why library exist + **/ + AnnotableStringType usage(); + + + /** + * Namespace which the library is imported under + **/ + String name(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/LibraryBase.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/LibraryBase.java new file mode 100755 index 0000000..ecdcb2e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/LibraryBase.java @@ -0,0 +1,69 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.api; + +import java.util.List; +import org.xbib.raml.api.model.v10.common.Annotable; +import org.xbib.raml.api.model.v10.datamodel.TypeDeclaration; +import org.xbib.raml.api.model.v10.methods.Trait; +import org.xbib.raml.api.model.v10.resources.ResourceType; +import org.xbib.raml.api.model.v10.security.SecurityScheme; + + +public interface LibraryBase extends Annotable { + + /** + * Alias for the equivalent "types" property, for compatibility with RAML 0.8. Deprecated - API definitions should use the "types" property, as the "schemas" alias for that property name may be removed in a future RAML version. The "types" property allows for XML and JSON schemas. + **/ + List schemas(); + + + /** + * Declarations of (data) types for use within this API + **/ + List types(); + + + /** + * Declarations of traits for use within this API + **/ + List traits(); + + + /** + * Declarations of resource types for use within this API + **/ + List resourceTypes(); + + + /** + * Declarations of annotation types for use by annotations + **/ + List annotationTypes(); + + + /** + * Declarations of security schemes for use within this API. + **/ + List securitySchemes(); + + + /*** + * Importing external libraries that can be used within the API. + **/ + List uses(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/UsesDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/UsesDeclaration.java new file mode 100755 index 0000000..a6ee020 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/api/UsesDeclaration.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.api; + +import org.xbib.raml.api.model.v10.common.Annotable; + + +public interface UsesDeclaration extends Annotable { + + /** + * Name prefix (without dot) used to refer imported declarations + **/ + String key(); + + + /** + * Content of the schema + **/ + String value(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/bodies/MimeType.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/bodies/MimeType.java new file mode 100755 index 0000000..6133166 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/bodies/MimeType.java @@ -0,0 +1,24 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.bodies; + +import org.xbib.raml.api.model.v10.system.types.StringType; + + +public interface MimeType extends StringType { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/bodies/Response.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/bodies/Response.java new file mode 100755 index 0000000..4b5382c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/bodies/Response.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.bodies; + +import java.util.List; +import org.xbib.raml.api.model.v10.common.Annotable; +import org.xbib.raml.api.model.v10.datamodel.TypeDeclaration; +import org.xbib.raml.api.model.v10.system.types.MarkdownString; +import org.xbib.raml.api.model.v10.system.types.StatusCodeString; + + +public interface Response extends Annotable { + + /** + * Responses MUST be a map of one or more HTTP status codes, where each status code itself is a map that describes that status code. + **/ + StatusCodeString code(); + + + /** + * Detailed information about any response headers returned by this method + **/ + List headers(); + + + /** + * The body of the response: a body declaration + **/ + List body(); + + + /** + * A longer, human-friendly description of the response + **/ + // --def-system-mod-- + MarkdownString description(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/common/Annotable.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/common/Annotable.java new file mode 100755 index 0000000..c8be887 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/common/Annotable.java @@ -0,0 +1,29 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.common; + +import java.util.List; +import org.xbib.raml.api.model.v10.declarations.AnnotationRef; + + +public interface Annotable { + + /** + * Most of RAML model elements may have attached annotations describing additional meta data about this element + **/ + List annotations(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/AnyTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/AnyTypeDeclaration.java new file mode 100755 index 0000000..5810fa8 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/AnyTypeDeclaration.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + + +public interface AnyTypeDeclaration extends TypeDeclaration { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/ArrayTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/ArrayTypeDeclaration.java new file mode 100755 index 0000000..699388a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/ArrayTypeDeclaration.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + + +public interface ArrayTypeDeclaration extends TypeDeclaration { + + /** + * Should items in array be unique + **/ + Boolean uniqueItems(); + + + /** + * Array component type. + **/ + TypeDeclaration items(); + + + /** + * Minimum amount of items in array + **/ + Integer minItems(); + + + /** + * Maximum amount of items in array + **/ + Integer maxItems(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/BooleanTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/BooleanTypeDeclaration.java new file mode 100755 index 0000000..857a4d7 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/BooleanTypeDeclaration.java @@ -0,0 +1,24 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + + +import java.util.List; + +public interface BooleanTypeDeclaration extends TypeDeclaration { + + List enumValues(); +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/DateTimeOnlyTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/DateTimeOnlyTypeDeclaration.java new file mode 100755 index 0000000..9bf96e9 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/DateTimeOnlyTypeDeclaration.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + + +public interface DateTimeOnlyTypeDeclaration extends TypeDeclaration { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/DateTimeTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/DateTimeTypeDeclaration.java new file mode 100755 index 0000000..9a383ed --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/DateTimeTypeDeclaration.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + + +public interface DateTimeTypeDeclaration extends TypeDeclaration { + + /** + * Format used for this date time rfc3339 or rfc2616 + **/ + String format(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/DateTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/DateTypeDeclaration.java new file mode 100755 index 0000000..db8050c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/DateTypeDeclaration.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + + +public interface DateTypeDeclaration extends TypeDeclaration { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/ExampleSpec.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/ExampleSpec.java new file mode 100755 index 0000000..15fbc0f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/ExampleSpec.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + +import org.xbib.raml.api.model.v10.common.Annotable; + + +public interface ExampleSpec extends Annotable { + + /** + * String representation of example + **/ + // --def-system-mod-- + String value(); + + + /** + * Example identifier, if specified + **/ + String name(); + + + /** + * Returns object representation of example, if possible + **/ + TypeInstance structuredValue(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/ExternalTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/ExternalTypeDeclaration.java new file mode 100644 index 0000000..9ab0b93 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/ExternalTypeDeclaration.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + + +public interface ExternalTypeDeclaration extends TypeDeclaration { + + /** + * Returns schema/type content for the cases when schema is inlined + **/ + String schemaContent(); + + /** + * Returns internal fragment name when it is used + **/ + String internalFragment(); + + /** + * Returns the schema path + **/ + String schemaPath(); + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/FileTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/FileTypeDeclaration.java new file mode 100755 index 0000000..7d73048 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/FileTypeDeclaration.java @@ -0,0 +1,29 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + + +import java.util.List; + +public interface FileTypeDeclaration extends TypeDeclaration { + + Number minLength(); + + Number maxLength(); + + List fileTypes(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/IntegerTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/IntegerTypeDeclaration.java new file mode 100755 index 0000000..9dbb2d3 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/IntegerTypeDeclaration.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + + +public interface IntegerTypeDeclaration extends NumberTypeDeclaration { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/JSONTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/JSONTypeDeclaration.java new file mode 100755 index 0000000..fb3b826 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/JSONTypeDeclaration.java @@ -0,0 +1,20 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + +public interface JSONTypeDeclaration extends ExternalTypeDeclaration { + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/NullTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/NullTypeDeclaration.java new file mode 100755 index 0000000..ee52c26 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/NullTypeDeclaration.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + + +public interface NullTypeDeclaration extends TypeDeclaration { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/NumberTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/NumberTypeDeclaration.java new file mode 100755 index 0000000..081ebad --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/NumberTypeDeclaration.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + +import java.util.List; + + +public interface NumberTypeDeclaration extends TypeDeclaration { + + /** + * (Optional, applicable only for parameters of type number or integer) The minimum attribute specifies the parameter's minimum value. + **/ + Double minimum(); + + + /** + * (Optional, applicable only for parameters of type number or integer) The maximum attribute specifies the parameter's maximum value. + **/ + Double maximum(); + + + /** + * (Optional, applicable only for parameters of type string) The enum attribute provides an enumeration of the parameter's valid values. This MUST be an array. If the enum attribute is defined, API clients and servers MUST verify that a parameter's value matches a value in the enum array. If there is no matching value, the clients and servers MUST treat this as an error. + **/ + List enumValues(); + + + /** + * Value format + **/ + String format(); + + + /** + * A numeric instance is valid against "multipleOf" if the result of the division of the instance by this keyword's value is an integer. + **/ + Double multipleOf(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/ObjectTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/ObjectTypeDeclaration.java new file mode 100755 index 0000000..4b1b075 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/ObjectTypeDeclaration.java @@ -0,0 +1,53 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + +import java.util.List; + + +public interface ObjectTypeDeclaration extends TypeDeclaration { + + /** + * The properties that instances of this type may or must have. + **/ + List properties(); + + + /** + * The minimum number of properties allowed for instances of this type. + **/ + Integer minProperties(); + + + /** + * The maximum number of properties allowed for instances of this type. + **/ + Integer maxProperties(); + + Boolean additionalProperties(); + + /** + * Type property name to be used as discriminator, or boolean + **/ + String discriminator(); + + + /** + * The value of discriminator for the type. + **/ + String discriminatorValue(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/StringTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/StringTypeDeclaration.java new file mode 100755 index 0000000..864d4a2 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/StringTypeDeclaration.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + +import java.util.List; + + +public interface StringTypeDeclaration extends TypeDeclaration { + + /** + * Regular expression that this string should path + **/ + String pattern(); + + + /** + * Minimum length of the string + **/ + Integer minLength(); + + + /** + * Maximum length of the string + **/ + Integer maxLength(); + + + /** + * (Optional, applicable only for parameters of type string) The enum attribute provides an enumeration of the parameter's valid values. This MUST be an array. If the enum attribute is defined, API clients and servers MUST verify that a parameter's value matches a value in the enum array. If there is no matching value, the clients and servers MUST treat this as an error. + **/ + List enumValues(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/TimeOnlyTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/TimeOnlyTypeDeclaration.java new file mode 100755 index 0000000..de3bf0b --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/TimeOnlyTypeDeclaration.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + + +public interface TimeOnlyTypeDeclaration extends TypeDeclaration { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/TypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/TypeDeclaration.java new file mode 100755 index 0000000..cb58cbf --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/TypeDeclaration.java @@ -0,0 +1,115 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + +import java.util.List; +import org.xbib.raml.api.model.common.ValidationResult; +import org.xbib.raml.api.model.v10.common.Annotable; +import org.xbib.raml.api.model.v10.declarations.AnnotationTarget; +import org.xbib.raml.api.model.v10.system.types.AnnotableStringType; +import org.xbib.raml.api.model.v10.system.types.MarkdownString; + + +public interface TypeDeclaration extends Annotable { + + /** + * Name of the parameter + **/ + String name(); + + + /** + * The displayName attribute specifies the type display name. It is a friendly name used only for display or documentation purposes. If displayName is not specified, it defaults to the element's key (the name of the property itself). + **/ + AnnotableStringType displayName(); + + + /** + * A base type which the current type extends, or more generally a type expression. + **/ + String type(); + + + /** + * The list of inherited types + */ + List parentTypes(); + + + /** + * Provides default value for a property + **/ + String defaultValue(); + + + /** + * An example of this type instance represented as string or yaml map/sequence. This can be used, e.g., by documentation generators to generate sample values for an object of this type. Cannot be present if the examples property is present. + **/ + ExampleSpec example(); + + + /** + * An example of this type instance represented as string. This can be used, e.g., by documentation generators to generate sample values for an object of this type. Cannot be present if the example property is present. + **/ + List examples(); + + + /** + * Sets if property is optional or not + **/ + Boolean required(); + + + /** + * A longer, human-friendly description of the type + **/ + MarkdownString description(); + + + /** + * Restrictions on where annotations of this type can be applied. If this property is specified, annotations of this type may only be applied on a property corresponding to one of the target names specified as the value of this property. + **/ + List allowedTargets(); + + + /** + * Validates payload against the type/schema defined + * + * @param payload the payload to be validated + * @return the list of errors if any or an empty list if validation succeeded + */ + List validate(String payload); + + + /** + * Gets the list of user-defined facets + */ + List facets(); + + + XMLFacetInfo xml(); + + /** + * Returns a XML Schema representation of the type. + */ + String toXmlSchema(); + + /** + * Returns a JSON Schema representation of the type. + */ + String toJsonSchema(); + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/TypeInstance.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/TypeInstance.java new file mode 100755 index 0000000..7c2381f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/TypeInstance.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + +import java.util.List; + + +public interface TypeInstance { + + /** + * Array of instance properties + **/ + List properties(); + + + /** + * Whether the type is scalar + **/ + Boolean isScalar(); + + + /** + * For instances of scalar types returns scalar value + **/ + Object value(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/TypeInstanceProperty.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/TypeInstanceProperty.java new file mode 100755 index 0000000..8648ceb --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/TypeInstanceProperty.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + +import java.util.List; + + +public interface TypeInstanceProperty { + + /** + * Property name + **/ + String name(); + + + /** + * Property value + **/ + TypeInstance value(); + + + /** + * Array of values if property value is array + **/ + List values(); + + + /** + * Whether property has array as value + **/ + Boolean isArray(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/UnionTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/UnionTypeDeclaration.java new file mode 100755 index 0000000..9fac2a0 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/UnionTypeDeclaration.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + +import java.util.List; + +public interface UnionTypeDeclaration extends TypeDeclaration { + List of(); +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/XMLFacetInfo.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/XMLFacetInfo.java new file mode 100755 index 0000000..d30d515 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/XMLFacetInfo.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + +import org.xbib.raml.api.model.v10.common.Annotable; + + +public interface XMLFacetInfo extends Annotable { + + /** + * If attribute is set to true, a type instance should be serialized as an XML attribute. It can only be true for scalar types. + **/ + Boolean attribute(); + + + /** + * If wrapped is set to true, a type instance should be wrapped in its own XML element. It can not be true for scalar types and it can not be true at the same moment when attribute is true. + **/ + Boolean wrapped(); + + + /** + * Allows to override the name of the XML element or XML attribute in it's XML representation. + **/ + String name(); + + + /** + * Allows to configure the name of the XML namespace. + **/ + String namespace(); + + + /** + * Allows to configure the prefix which will be used during serialization to XML. + **/ + String prefix(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/XMLTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/XMLTypeDeclaration.java new file mode 100755 index 0000000..ceb1779 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/datamodel/XMLTypeDeclaration.java @@ -0,0 +1,20 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.datamodel; + +public interface XMLTypeDeclaration extends ExternalTypeDeclaration { + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/declarations/AnnotationRef.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/declarations/AnnotationRef.java new file mode 100755 index 0000000..0c6e071 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/declarations/AnnotationRef.java @@ -0,0 +1,29 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.declarations; + +import org.xbib.raml.api.model.v10.datamodel.TypeDeclaration; +import org.xbib.raml.api.model.v10.system.types.Reference; + + +public interface AnnotationRef extends Reference { + + /** + * Returns referenced annotation + **/ + TypeDeclaration annotation(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/declarations/AnnotationTarget.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/declarations/AnnotationTarget.java new file mode 100755 index 0000000..f61c494 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/declarations/AnnotationTarget.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.declarations; + +public enum AnnotationTarget { + API, + DocumentationItem, + Resource, + Method, + Response, + RequestBody, + ResponseBody, + TypeDeclaration, + Example, + ResourceType, + Trait, + SecurityScheme, + SecuritySchemeSettings, + AnnotationType, + Library, + Overlay, + Extension +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/Method.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/Method.java new file mode 100755 index 0000000..192fa86 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/Method.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.methods; + +import org.xbib.raml.api.model.v10.resources.Resource; + +public interface Method extends MethodBase { + + /** + * Method that can be called + **/ + String method(); + + /** + * Parent resource of the Method + * + * @return the parent resource or null if there is none + */ + Resource resource(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/MethodBase.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/MethodBase.java new file mode 100755 index 0000000..faae434 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/MethodBase.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.methods; + +import java.util.List; +import org.xbib.raml.api.model.v10.datamodel.TypeDeclaration; +import org.xbib.raml.api.model.v10.security.SecuritySchemeRef; +import org.xbib.raml.api.model.v10.system.types.AnnotableStringType; +import org.xbib.raml.api.model.v10.system.types.MarkdownString; + + +public interface MethodBase extends Operation { + + /** + * Some method verbs expect the resource to be sent as a request body. For example, to create a resource, the request must include the details of the resource to create. Resources CAN have alternate representations. For example, an API might support both JSON and XML representations. A method's body is defined in the body property as a hashmap, in which the key MUST be a valid media type. + **/ + List body(); + + + /** + * A method can override the protocols specified in the resource or at the API root, by employing this property. + **/ + List protocols(); + + + /** + * Instantiation of applyed traits + **/ + List is(); + + + /** + * securityScheme may also be applied to a resource by using the securedBy key, which is equivalent to applying the securityScheme to all methods that may be declared, explicitly or implicitly, by defining the resourceTypes or traits property for that resource. To indicate that the method may be called without applying any securityScheme, the method may be annotated with the null securityScheme. + **/ + List securedBy(); + + + MarkdownString description(); + + + AnnotableStringType displayName(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/Operation.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/Operation.java new file mode 100755 index 0000000..5a24638 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/Operation.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.methods; + +import java.util.List; +import org.xbib.raml.api.model.v10.bodies.Response; +import org.xbib.raml.api.model.v10.common.Annotable; +import org.xbib.raml.api.model.v10.datamodel.TypeDeclaration; + + +public interface Operation extends Annotable { + + /** + * An APIs resources MAY be filtered (to return a subset of results) or altered (such as transforming a response body from JSON to XML format) by the use of query strings. If the resource or its method supports a query string, the query string MUST be defined by the queryParameters property + **/ + List queryParameters(); + + + /** + * Headers that allowed at this position + **/ + List headers(); + + + /** + * Specifies the query string needed by this method. Mutually exclusive with queryParameters. + **/ + TypeDeclaration queryString(); + + + /** + * Information about the expected responses to a request + **/ + List responses(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/Trait.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/Trait.java new file mode 100755 index 0000000..10fac0f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/Trait.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.methods; + +import org.xbib.raml.api.model.v10.system.types.AnnotableStringType; + + +public interface Trait { + + // MarkdownString description(); + // + // AnnotableSimpleType displayName(); + + /** + * Name of the trait + **/ + String name(); + + /** + * Instructions on how and when the trait should be used. + **/ + AnnotableStringType usage(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/TraitRef.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/TraitRef.java new file mode 100755 index 0000000..0b0a25c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/methods/TraitRef.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.methods; + +import org.xbib.raml.api.model.v10.system.types.Reference; + + +public interface TraitRef extends Reference { + + /** + * Returns referenced trait + **/ + Trait trait(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/parameters/FileTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/parameters/FileTypeDeclaration.java new file mode 100755 index 0000000..b53bc1f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/parameters/FileTypeDeclaration.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.parameters; + +import java.util.List; +import org.xbib.raml.api.model.v10.datamodel.TypeDeclaration; +import org.xbib.raml.api.model.v10.system.types.ContentType; + + +public interface FileTypeDeclaration extends TypeDeclaration { + + /** + * It should also include a new property: fileTypes, which should be a list of valid content-type strings for the file. The file type */* should be a valid value. + **/ + List fileTypes(); + + + /** + * The minLength attribute specifies the parameter value's minimum number of bytes. + **/ + Long minLength(); + + + /** + * The maxLength attribute specifies the parameter value's maximum number of bytes. + **/ + Long maxLength(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/resources/Resource.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/resources/Resource.java new file mode 100755 index 0000000..02dc434 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/resources/Resource.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.resources; + +import java.util.List; +import org.xbib.raml.api.model.v10.system.types.AnnotableStringType; +import org.xbib.raml.api.model.v10.system.types.RelativeUriString; + + +public interface Resource extends ResourceBase { + + /** + * Relative URL of this resource from the parent resource + **/ + RelativeUriString relativeUri(); + + + /** + * The displayName attribute specifies the resource display name. It is a friendly name used only for display or documentation purposes. If displayName is not specified, it defaults to the element's key (the name of the property itself). + **/ + AnnotableStringType displayName(); + + + /** + * A nested resource is identified as any property whose name begins with a slash ("/") and is therefore treated as a relative URI. + **/ + List resources(); + + + /* + * helper methods (non-autogenerated) + */ + + String resourcePath(); + + Resource parentResource(); +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/resources/ResourceBase.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/resources/ResourceBase.java new file mode 100755 index 0000000..13e2a42 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/resources/ResourceBase.java @@ -0,0 +1,62 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.resources; + +import java.util.List; +import org.xbib.raml.api.model.v10.common.Annotable; +import org.xbib.raml.api.model.v10.datamodel.TypeDeclaration; +import org.xbib.raml.api.model.v10.methods.Method; +import org.xbib.raml.api.model.v10.methods.TraitRef; +import org.xbib.raml.api.model.v10.security.SecuritySchemeRef; +import org.xbib.raml.api.model.v10.system.types.MarkdownString; + + +public interface ResourceBase extends Annotable { + + /** + * Methods that are part of this resource type definition + **/ + List methods(); + + + /** + * A list of the traits to apply to all methods declared (implicitly or explicitly) for this resource. Individual methods may override this declaration + **/ + List is(); + + + /** + * The resource type which this resource inherits. + **/ + ResourceTypeRef type(); + + + // --def-system-mod-- + MarkdownString description(); + + + /** + * The security schemes that apply to all methods declared (implicitly or explicitly) for this resource. + **/ + List securedBy(); + + + /** + * Detailed information about any URI parameters of this resource + **/ + List uriParameters(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/resources/ResourceType.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/resources/ResourceType.java new file mode 100755 index 0000000..774398c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/resources/ResourceType.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.resources; + +import org.xbib.raml.api.model.v10.system.types.AnnotableStringType; + + +public interface ResourceType { + + /** + * The displayName attribute specifies the resource type display name. It is a friendly name used only for display or documentation purposes. If displayName is not specified, it defaults to the element's key (the name of the property itself). + **/ + // AnnotableSimpleType displayName(); + + + /** + * Name of the resource type + **/ + String name(); + + + /** + * Instructions on how and when the resource type should be used. + **/ + AnnotableStringType usage(); + + + // MarkdownString description(); +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/resources/ResourceTypeRef.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/resources/ResourceTypeRef.java new file mode 100755 index 0000000..43ebf7d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/resources/ResourceTypeRef.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.resources; + +import org.xbib.raml.api.model.v10.system.types.Reference; + + +public interface ResourceTypeRef extends Reference { + + /** + * Returns referenced resource type + **/ + ResourceType resourceType(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/security/SecurityScheme.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/security/SecurityScheme.java new file mode 100755 index 0000000..be6fc75 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/security/SecurityScheme.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.security; + +import org.xbib.raml.api.model.v10.common.Annotable; +import org.xbib.raml.api.model.v10.system.types.AnnotableStringType; +import org.xbib.raml.api.model.v10.system.types.MarkdownString; + + +public interface SecurityScheme extends Annotable { + + /** + * Name of the security scheme + **/ + String name(); + + + /** + * The securitySchemes property MUST be used to specify an API's security mechanisms, including the required settings and the authentication methods that the API supports. one authentication method is allowed if the API supports them. + **/ + String type(); + + + /** + * The description MAY be used to describe a securityScheme. + **/ + MarkdownString description(); + + + /** + * A description of the request components related to Security that are determined by the scheme: the headers, query parameters or responses. As a best practice, even for standard security schemes, API designers SHOULD describe these properties of security schemes. Including the security scheme description completes an API documentation. + **/ + SecuritySchemePart describedBy(); + + + /** + * The displayName attribute specifies the security scheme display name. It is a friendly name used only for display or documentation purposes. If displayName is not specified, it defaults to the element's key (the name of the property itself). + **/ + AnnotableStringType displayName(); + + + /** + * The settings attribute MAY be used to provide security scheme-specific information. The required attributes vary depending on the type of security scheme is being declared. It describes the minimum set of properties which any processing application MUST provide and validate if it chooses to implement the security scheme. Processing applications MAY choose to recognize other properties for things such as token lifetime, preferred cryptographic algorithms, and more. + **/ + SecuritySchemeSettings settings(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/security/SecuritySchemePart.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/security/SecuritySchemePart.java new file mode 100755 index 0000000..7341c30 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/security/SecuritySchemePart.java @@ -0,0 +1,24 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.security; + +import org.xbib.raml.api.model.v10.methods.Operation; + + +public interface SecuritySchemePart extends Operation { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/security/SecuritySchemeRef.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/security/SecuritySchemeRef.java new file mode 100755 index 0000000..93612df --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/security/SecuritySchemeRef.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.security; + +import org.xbib.raml.api.model.v10.system.types.Reference; + + +public interface SecuritySchemeRef extends Reference { + + /** + * Returns AST node of security scheme, this reference refers to, or null. + **/ + SecurityScheme securityScheme(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/security/SecuritySchemeSettings.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/security/SecuritySchemeSettings.java new file mode 100755 index 0000000..d79767c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/security/SecuritySchemeSettings.java @@ -0,0 +1,76 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.security; + +import java.util.List; +import org.xbib.raml.api.model.v10.common.Annotable; +import org.xbib.raml.api.model.v10.system.types.FixedUriString; + + +public interface SecuritySchemeSettings extends Annotable { + + /** + * The URI of the Temporary Credential Request endpoint as defined in RFC5849 Section 2.1 + * (OAuth 1) + **/ + FixedUriString requestTokenUri(); + + + /** + * The URI of the Resource Owner Authorization endpoint as defined in RFC5849 Section 2.2 + * (OAuth 1) + *

+ * The URI of the Authorization Endpoint as defined in RFC6749 Section 3.1. Required forby authorization_code and implicit grant types. + * (OAuth 2) + **/ + FixedUriString authorizationUri(); + + + /** + * The URI of the Token Request endpoint as defined in RFC5849 Section 2.3 + * (OAuth 1) + **/ + FixedUriString tokenCredentialsUri(); + + + /** + * List of the signature methods used by the server. Available methods: HMAC-SHA1, RSA-SHA1, PLAINTEXT + * (OAuth 1) + **/ + List signatures(); + + + /** + * The URI of the Token Endpoint as defined in RFC6749 Section 3.2. Not required forby implicit grant type. + * (OAuth 2) + **/ + FixedUriString accessTokenUri(); + + + /** + * A list of the Authorization grants supported by the API as defined in RFC6749 Sections 4.1, 4.2, 4.3 and 4.4, can be any of: authorization_code, password, client_credentials, implicit, or refresh_token. + * (OAuth 2) + **/ + List authorizationGrants(); + + + /** + * A list of scopes supported by the security scheme as defined in RFC6749 Section 3.3 + * (OAuth 2) + **/ + List scopes(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/AnnotableSimpleType.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/AnnotableSimpleType.java new file mode 100755 index 0000000..7690f5f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/AnnotableSimpleType.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +import org.xbib.raml.api.model.v10.common.Annotable; + +public interface AnnotableSimpleType extends Annotable { + + /** + * @return String representation of the node value + **/ + T value(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/AnnotableStringType.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/AnnotableStringType.java new file mode 100644 index 0000000..867ec8d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/AnnotableStringType.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface AnnotableStringType extends AnnotableSimpleType { + @Override + String value(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/AnyType.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/AnyType.java new file mode 100755 index 0000000..44acb93 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/AnyType.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface AnyType extends ValueType { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/BooleanType.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/BooleanType.java new file mode 100755 index 0000000..c6993c3 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/BooleanType.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface BooleanType { + + /** + * @return Boolean representation of the node value + **/ + Boolean value(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/ContentType.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/ContentType.java new file mode 100755 index 0000000..5ad9a22 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/ContentType.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface ContentType extends StringType { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/FixedUriString.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/FixedUriString.java new file mode 100755 index 0000000..01cca54 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/FixedUriString.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface FixedUriString extends AnnotableStringType { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/FullUriTemplateString.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/FullUriTemplateString.java new file mode 100755 index 0000000..75483fa --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/FullUriTemplateString.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface FullUriTemplateString extends UriTemplate, AnnotableStringType { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/MarkdownString.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/MarkdownString.java new file mode 100755 index 0000000..ccaa482 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/MarkdownString.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface MarkdownString extends AnnotableStringType { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/NumberType.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/NumberType.java new file mode 100755 index 0000000..bbbef1b --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/NumberType.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface NumberType { + + /** + * @return Number representation of the node value + **/ + Double value(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/Reference.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/Reference.java new file mode 100755 index 0000000..b91b17c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/Reference.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + +import org.xbib.raml.api.model.v10.datamodel.TypeInstance; + + +public interface Reference { + + /** + * Returns a structured object if the reference point to one. + **/ + TypeInstance structuredValue(); + + + /** + * Returns name of referenced object + **/ + String name(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/RelativeUriString.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/RelativeUriString.java new file mode 100755 index 0000000..058d8ba --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/RelativeUriString.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface RelativeUriString extends UriTemplate, StringType { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/SchemaString.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/SchemaString.java new file mode 100755 index 0000000..04aa502 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/SchemaString.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface SchemaString extends StringType { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/StatusCodeString.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/StatusCodeString.java new file mode 100755 index 0000000..ac1ae46 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/StatusCodeString.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface StatusCodeString extends StringType { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/StringType.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/StringType.java new file mode 100755 index 0000000..b7bcce1 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/StringType.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface StringType { + + /** + * @return String representation of the node value + **/ + String value(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/UriTemplate.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/UriTemplate.java new file mode 100755 index 0000000..002fd2e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/UriTemplate.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface UriTemplate { + + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/ValueType.java b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/ValueType.java new file mode 100755 index 0000000..3bb5541 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/api/model/v10/system/types/ValueType.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.api.model.v10.system.types; + + +public interface ValueType { + + /** + * @return Java representation of the node value + **/ + Object value(); + +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/RamlBuilder.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/RamlBuilder.java new file mode 100644 index 0000000..bb42c19 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/RamlBuilder.java @@ -0,0 +1,125 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import org.xbib.raml.api.loader.DefaultResourceLoader; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.api.loader.ResourceLoaderFactories; +import org.xbib.raml.internal.impl.commons.RamlHeader; +import org.xbib.raml.internal.impl.v10.Raml10Builder; +import org.xbib.raml.internal.utils.IOUtils; +import org.xbib.raml.internal.utils.StreamUtils; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.Node; + +/** + * RamlBuilder create a Node representation of your raml. + * + * @see Node + */ +public class RamlBuilder { + + public static int FIRST_PHASE = 1; + public static int GRAMMAR_PHASE = 4; + public static int LIBRARY_LINK_PHASE = 5; + + public static int ALL_PHASES = Integer.MAX_VALUE; + + private final int maxPhaseNumber; + + private String actualPath = null; + + public RamlBuilder() { + maxPhaseNumber = ALL_PHASES; + } + + public RamlBuilder(int maxPhaseNumber) { + this.maxPhaseNumber = maxPhaseNumber; + } + + public Node build(File ramlFile) { + return build(ramlFile, ResourceLoaderFactories.defaultResourceLoaderFactory().createResourceLoader(ramlFile.getAbsoluteFile().getParent())); + } + + + public Node build(File ramlFile, ResourceLoader resourceLoader) { + this.actualPath = ramlFile.getPath(); + try (InputStream inputStream = new FileInputStream(ramlFile)) { + return build(StreamUtils.reader(inputStream), resourceLoader, ramlFile.getName()); + } catch (IOException ioe) { + return ErrorNodeFactory.createInvalidInput(ioe); + } + } + + public Node build(String content) { + return build(content, ""); + } + + public Node build(String content, String resourceLocation) { + return build(content, new DefaultResourceLoader(), resourceLocation); + } + + public Node build(String content, ResourceLoader resourceLoader, String resourceLocation) { + return build(new StringReader(content), resourceLoader, resourceLocation); + } + + public Node build(Reader content, ResourceLoader resourceLoader, String resourceLocation) { + try { + resourceLoader = addRootRamlResourceLoaders(resourceLoader, resourceLocation); + + final String stringContent = IOUtils.toString(content); + + // In order to be consistent between different OS, we normalize the resource location + resourceLocation = normalizeResourceLocation(resourceLocation); + + RamlHeader ramlHeader = RamlHeader.parse(stringContent); + Node result = new Raml10Builder().build(stringContent, ramlHeader.getFragment(), resourceLoader, resourceLocation, maxPhaseNumber); + return result; + } catch (IOException ioe) { + return ErrorNodeFactory.createInvalidInput(ioe); + } catch (RamlHeader.InvalidHeaderVersionException e) { + return ErrorNodeFactory.createUnsupportedVersion(e.getMessage()); + } catch (RamlHeader.InvalidHeaderFragmentException e) { + return ErrorNodeFactory.createInvalidFragmentName(e.getMessage()); + } catch (RamlHeader.MissingHeaderException e) { + return ErrorNodeFactory.createEmptyDocument(); + } catch (RamlHeader.InvalidHeaderException e) { + return ErrorNodeFactory.createInvalidHeader(e.getMessage()); + } finally { + IOUtils.closeQuietly(content); + } + } + + private ResourceLoader addRootRamlResourceLoaders(ResourceLoader resourceLoader, String resourceLocation) { + + return resourceLoader; + } + + private String normalizeResourceLocation(String resourceLocation) { + return resourceLocation.replace("\\", "/"); + } + + public String getActualPath() { + return actualPath; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/RamlSuggester.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/RamlSuggester.java new file mode 100644 index 0000000..1fe5faf --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/RamlSuggester.java @@ -0,0 +1,425 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.api.loader.DefaultResourceLoader; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.internal.impl.commons.RamlHeader; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.EmptyErrorNode; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.DefaultSuggestion; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.ParsingContextType; +import org.xbib.raml.yagi.framework.suggester.Suggestion; +import org.xbib.raml.yagi.framework.suggester.Suggestions; + +public class RamlSuggester { + + private final ResourceLoader resourceLoader; + + public RamlSuggester(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + public RamlSuggester() { + this(new DefaultResourceLoader()); + } + + /** + * Returns the suggestions for the specified document at the given position. + * In most common cases the offset will be the cursor position. + * + * @param document The raml document + * @param offset The offset from the begging of the document + * @return The suggestions + */ + public Suggestions suggestions(String document, int offset) { + final List result = new ArrayList<>(); + final ParsingContext parsingContext = getContext(document, offset); + final int location = parsingContext.getLocation(); + final String content = parsingContext.getContent(); + final List suggestions = getSuggestions(parsingContext, document, offset, location); + if (content.isEmpty()) { + result.addAll(suggestions); + } else { + for (Suggestion suggestion : suggestions) { + if (suggestion.getValue().startsWith(content)) { + result.add(suggestion); + } + } + } + Collections.sort(result); + return new Suggestions(result, content, location); + + } + + private List getSuggestions(ParsingContext context, String document, int offset, int location) { + switch (context.getContextType()) { + case HEADER: + return getHeaderSuggestions(); + case FUNCTION_CALL: + return getFunctionCallSuggestions(); + case STRING_TEMPLATE: + return getTemplateParameterSuggestions(document, offset, location); + case LIBRARY_CALL: + case ITEM: + case VALUE: + return getSuggestionsAt(context, document, offset, location); + default: + return getSuggestionByColumn(context, document, offset, location); + + } + } + + + private List getTemplateParameterSuggestions(String document, int offset, int location) { + final Node rootNode = getRootNode(document, offset, location); + Node node = org.xbib.raml.yagi.framework.util.NodeUtils.searchNodeAt(rootNode, location); + boolean inTrait = false; + while (node != null) { + + if (node instanceof KeyValueNode) { + if (((KeyValueNode) node).getKey() instanceof StringNode) { + final String value = ((StringNode) ((KeyValueNode) node).getKey()).getValue(); + if (value.equals("traits") || value.equals("resourceTypes")) { + inTrait = value.equals("traits"); + break; + } + } + } + node = node.getParent(); + } + return inTrait ? defaultTraitParameters() : defaultResourceTypeParameters(); + } + + + private List defaultTraitParameters() { + final List suggestions = defaultResourceTypeParameters(); + suggestions.add(new DefaultSuggestion("methodName", "The name of the method", "")); + return suggestions; + } + + + private List defaultResourceTypeParameters() { + final List suggestions = new ArrayList<>(); + suggestions.add(new DefaultSuggestion("resourcePath", "The resource's full URI relative to the baseUri (if any)", "")); + suggestions.add(new DefaultSuggestion("resourcePathName", "The rightmost path fragment of the resource's relative URI, " + + "omitting any parametrize brackets (\"{\" and \"}\")", "")); + return suggestions; + } + + + private List getFunctionCallSuggestions() { + List suggestions = new ArrayList<>(); + /*final Method[] declaredMethods = Inflector.class.getDeclaredMethods(); + for (Method declaredMethod : declaredMethods) + { + if (Modifier.isStatic(declaredMethod.getModifiers()) && Modifier.isPublic(declaredMethod.getModifiers())) + { + suggestions.add(new DefaultSuggestion("!" + declaredMethod.getName(), "", declaredMethod.getName())); + } + }*/ + return suggestions; + } + + private List getSuggestionsAt(ParsingContext context, String document, int offset, int location) { + final Node root = getRootNode(document, offset, location); + Node node = org.xbib.raml.yagi.framework.util.NodeUtils.searchNodeAt(root, location); + if (node != null) { + // If it is the key of a key value pair + if (node.getParent() instanceof KeyValueNode && node.getParent().getChildren().indexOf(node) == 0) { + node = node.getParent().getParent(); + } + // Recreate path with the node at the correct indentation + final List pathToRoot = createPathToRoot(node); + // Follow the path from the root to the node and apply the rules for auto-completion. + final Rule rootRule = getRuleFor(document); + return rootRule != null ? rootRule.getSuggestions(pathToRoot, context) : Collections.emptyList(); + } else { + return Collections.emptyList(); + } + } + + private Node getRootNode(String document, int offset, int location) { + // We only run the first phase + final RamlBuilder ramlBuilder = new RamlBuilder(RamlBuilder.FIRST_PHASE); + try { + // We try the with the original document + final Node rootNode = ramlBuilder.build(document, resourceLoader, ""); + if (rootNode instanceof StringNode) { + // File still doesn't have any mapping and will not generate any suggestions so we'll force the parsing to make it a mapping + final Node rootNode2 = ramlBuilder.build(stripLastChanges(document, offset, location) + "\n\nstub: stub", resourceLoader, ""); // we add an invalid key so as to enforce the creation of + // the root node + if (rootNode2 instanceof ErrorNode) { + // Otherwise let's just try to remove the whole line starting from where we are located + return ramlBuilder.build(removeChangedLine(document, offset, location) + "\n\nstub: stub", resourceLoader, ""); + } else { + return rootNode2; + } + } else if (!(rootNode instanceof ErrorNode)) { + return rootNode; + } else if (rootNode instanceof EmptyErrorNode) { + // File is not corrupted but just empty, we should suggest initial keys for the current file + return ramlBuilder.build(document + "\n\nstub: stub", resourceLoader, ""); // we add an invalid key so as to force the creation of the root node + } else { // let's just try to remove the whole line starting from where we are located + return ramlBuilder.build(removeChangedLine(document, offset, location) + "\n\nstub: stub", resourceLoader, ""); + } + } catch (final Exception e) { + // We remove some current keywords to see if it parses + return ramlBuilder.build(stripLastChanges(document, offset, location), resourceLoader, ""); + } + } + + private String removeChangedLine(String document, int offset, int location) { + final String header = document.substring(0, location + 1); + final String footer = getFooter1(document, offset); + return header + footer; + } + + private String stripLastChanges(String document, int offset, int location) { + final String header = document.substring(0, location + 1); + final String footer = getFooter(document, offset); + return header + footer; + } + + private List getSuggestionByColumn(ParsingContext context, String document, int offset, int location) { + // // I don't care column number unless is an empty new line + int columnNumber = getColumnNumber(document, offset); + final Node root = getRootNode(document, offset, location); + Node node = org.xbib.raml.yagi.framework.util.NodeUtils.searchNodeAt(root, location); + + if (node != null) { + node = getValueNodeAtColumn(columnNumber, node); + // Recreate path with the node at the correct indentation + final List pathToRoot = createPathToRoot(node); + + // Follow the path from the root to the node and apply the rules for auto-completion. + final Rule rootRule = getRuleFor(document); + return rootRule != null ? rootRule.getSuggestions(pathToRoot, context) : Collections.emptyList(); + } else { + return Collections.emptyList(); + } + } + + private int getLineNumber(final String document, final int offset) { + int lineNumber = 0; + for (int currentIndex = 0; currentIndex <= offset; ++currentIndex) { + if (currentIndex - 1 == offset || // + currentIndex >= document.length()) // should never be possible if offset is legal + { + return lineNumber; + } + + if (document.charAt(currentIndex) == '\n') { + ++lineNumber; + } + } + + // should never reach this + return lineNumber; + } + + private List getHeaderSuggestions() { + return Arrays.asList( + new DefaultSuggestion("#%RAML 1.0", "RAML 1.0 root file header", DefaultSuggestion.RAML_1_0_HEADER), + new DefaultSuggestion("#%RAML 1.0 DocumentationItem", "An item in the collection of items that is the value of the root-level documentation property", + "RAML 1.0 Documentation Item fragment"), + new DefaultSuggestion("#%RAML 1.0 DataType", "A data type declaration where the type property may be used", "RAML 1.0 Data Type fragment"), + new DefaultSuggestion("#%RAML 1.0 NamedExample", "A property of the examples property, whose key is a name of an example and whose value describes the example", + "RAML 1.0 Named Example fragment"), + new DefaultSuggestion("#%RAML 1.0 ResourceType", "A single resource type declaration", "RAML 1.0 Resource Type fragment"), + new DefaultSuggestion("#%RAML 1.0 Trait", "A single trait declaration", "RAML 1.0 Trait fragment"), + new DefaultSuggestion("#%RAML 1.0 AnnotationTypeDeclaration", "A single annotation type declaration", "RAML 1.0 Annotation Type Declaration fragment"), + new DefaultSuggestion("#%RAML 1.0 Library", "A RAML library", "RAML 1.0 Library fragment"), + new DefaultSuggestion("#%RAML 1.0 Overlay", "An overlay file", "RAML 1.0 Overlay fragment"), + new DefaultSuggestion("#%RAML 1.0 Extension", "An extension file", "RAML 1.0 Extension fragment"), + new DefaultSuggestion("#%RAML 1.0 SecurityScheme", "A definition of a security scheme", "RAML 1.0 Security Scheme fragment")); + } + + + private ParsingContext getContext(String document, int offset) { + if (offset == -1 || getLineNumber(document, offset) == 0) { + final String content = offset < 0 || document.isEmpty() ? "" : document.substring(0, offset + 1); + return new ParsingContext(ParsingContextType.HEADER, content, offset); + } + + ParsingContext context = null; + int location = offset; + final StringBuilder content = new StringBuilder(); + while (location >= 0 && context == null) { + char character = document.charAt(location); + switch (character) { + case ':': + context = new ParsingContext(ParsingContextType.VALUE, revertAndTrim(content), location + 1); + break; + case ',': + case '[': + case '{': + case '-': + context = new ParsingContext(ParsingContextType.ITEM, revertAndTrim(content), location); + break; + case '<': + if (location > 0) { + if (document.charAt(location - 1) == '<') { + location--; + final String contextContent = revertAndTrim(content); + final String[] split = contextContent.split("\\|"); + if (split.length > 1) { + context = new ParsingContext(ParsingContextType.FUNCTION_CALL, split[split.length - 1].trim(), location); + } else if (contextContent.endsWith("|")) { + context = new ParsingContext(ParsingContextType.FUNCTION_CALL, "", location); + } else { + context = new ParsingContext(ParsingContextType.STRING_TEMPLATE, contextContent, location); + } + break; + } + } + content.append(character); + break; + case '.': + context = new ParsingContext(ParsingContextType.LIBRARY_CALL, revertAndTrim(content), location); + break; + case '\n': + context = new ParsingContext(ParsingContextType.ANY, revertAndTrim(content), location); + break; + default: + content.append(character); + } + location--; + } + + if (context == null) { + context = new ParsingContext(ParsingContextType.ANY, revertAndTrim(content), location); + } + + return context; + } + + + private String revertAndTrim(StringBuilder content) { + return content.reverse().toString().trim(); + } + + private Node getValueNodeAtColumn(int columnNumber, Node node) { + if (columnNumber == 0) { + return node.getRootNode(); + } else { + // Create the path from the selected node to the root. + final List path = createPathToRoot(node); + // Find the node with the indentation in the path + for (Node element : path) { + if (element instanceof KeyValueNode) { + if (element.getStartPosition().getColumn() < columnNumber) { + // In an object we need that it should be minor for arrays + node = ((KeyValueNode) element).getValue(); + } + } else if (element instanceof ObjectNode) { + // In an object we need that it should be equals or minor + if (element.getStartPosition().getColumn() <= columnNumber) { + node = element; + } + } + } + return node; + } + } + + + private List createPathToRoot(Node node) { + final List path = new ArrayList<>(); + Node parent = node; + while (parent != null) { + path.add(0, parent); + parent = parent.getParent(); + } + return path; + } + + + private String getFooter(String document, int offset) { + int loc = offset; + char current = document.charAt(loc); + while (loc < document.length() && current != '\n' && current != '}' && current != ']' && current != ',') { + loc++; + if (loc == document.length()) { + break; + } + current = document.charAt(loc); + } + + return loc < document.length() ? document.substring(loc) : ""; + } + + + private String getFooter1(String document, int offset) { + return getFooter(document, offset + 1); + } + + private int getColumnNumber(String document, int offset) { + final StringBuilder contextLine = getContextLine(document, offset); + int columnNumber = 0; + for (int i = 0; i < contextLine.length(); i++) { + if (Character.isWhitespace(contextLine.charAt(i))) { + columnNumber++; + } else { + break; + } + } + return columnNumber; + } + + + private StringBuilder getContextLine(String document, int offset) { + final StringBuilder contextLine = new StringBuilder(); + + if (offset < 0) // start of file detected! + { + return contextLine; + } + + int location = offset; + char character = document.charAt(location); + while (location > 0 && character != '\n') { + location--; + contextLine.append(character); + character = document.charAt(location); + + } + return contextLine.reverse(); + } + + + public Rule getRuleFor(String stringContent) { + try { + RamlHeader ramlHeader = RamlHeader.parse(stringContent); + return ramlHeader.getRule(); + } catch (RamlHeader.InvalidHeaderException e) { + // ignore, just return null + } + return null; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/RamlValidator.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/RamlValidator.java new file mode 100644 index 0000000..2635d24 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/RamlValidator.java @@ -0,0 +1,107 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl; + +import java.io.File; +import java.io.FileFilter; +import java.util.List; +import org.xbib.raml.internal.utils.RamlNodeUtils; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.Position; + +public class RamlValidator { + + private static final String USAGE = "Arguments: [-dump] file|url|dir"; + + private boolean dump; + private String ramlLocation; + + private RamlValidator(String[] args) { + parseArguments(args); + } + + private void validate() { + validate(new File(ramlLocation)); + } + + private void validate(File location) { + if (isRamlFile(location)) { + validateRaml(location); + } + + File[] files = new File[]{}; + if (location.isDirectory()) { + files = location.listFiles(new FileFilter() { + @Override + public boolean accept(File pathname) { + return pathname.isDirectory() || isRamlFile(pathname); + } + }); + } + for (File file : files) { + validate(file); + } + } + + private void validateRaml(File ramlFile) { + + final Node raml = new RamlBuilder().build(ramlFile); + List errors = RamlNodeUtils.getErrors(raml); + if (!errors.isEmpty()) { + logErrors(errors); + } + + } + + private boolean isRamlFile(File pathname) { + return pathname.isFile() && pathname.getName().endsWith(".raml"); + } + + public static void main(String[] args) { + new RamlValidator(args).validate(); + } + + private void logErrors(List errors) { + String label = errors.size() > 1 ? "errors" : "error"; + System.out.format("%d %s found:\n\n", errors.size(), label); + for (ErrorNode error : errors) { + String message = error.getErrorMessage(); + int idx = message.indexOf(". Options are"); + if (idx != -1) { + message = message.substring(0, idx); + } + Position position = error.getSource() != null ? error.getSource().getStartPosition() : error.getStartPosition(); + System.out.format("\t- %s %s\n\n", message, position); + } + } + + private void parseArguments(String[] args) { + if (args.length < 1 || args.length > 2) { + throw new IllegalArgumentException(USAGE); + } + if (args.length == 2) { + if (!"-dump".equals(args[0])) { + throw new IllegalArgumentException(USAGE); + } + this.dump = true; + this.ramlLocation = args[1]; + } else { + this.ramlLocation = args[0]; + } + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/RamlHeader.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/RamlHeader.java new file mode 100644 index 0000000..42bf2bd --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/RamlHeader.java @@ -0,0 +1,163 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons; + +import java.util.StringTokenizer; +import org.xbib.raml.api.model.v10.RamlFragment; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNodeFragment; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.internal.impl.v10.grammar.Raml10GrammarUsesAllowed; +import org.xbib.raml.internal.utils.StreamUtils; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import static org.xbib.raml.internal.impl.commons.RamlVersion.RAML_10; + +public class RamlHeader { + + public static final String RAML_HEADER_PREFIX = "#%RAML"; + + private final RamlVersion version; + private final RamlFragment fragment; + + public RamlHeader(RamlVersion version, RamlFragment fragment) { + this.version = version; + this.fragment = fragment; + } + + public RamlHeader(RamlVersion version) { + this(version, null); + } + + public static RamlHeader parse(String stringContent) throws InvalidHeaderException { + final StringTokenizer lines = new StringTokenizer(StreamUtils.trimBom(stringContent), "\n"); + if (lines.hasMoreElements()) { + final String header = lines.nextToken().trim(); + final StringTokenizer headerParts = new StringTokenizer(header); + if (headerParts.hasMoreTokens()) { + final String raml = headerParts.nextToken(); + if (RAML_HEADER_PREFIX.equals(raml)) { + if (headerParts.hasMoreTokens()) { + String stringVersion = headerParts.nextToken(); + RamlVersion version; + try { + version = RamlVersion.parse(stringVersion); + } catch (IllegalArgumentException e) { + throw new InvalidHeaderVersionException(stringVersion); + } + if (version == RAML_10) { + final String fragmentText = headerParts.hasMoreTokens() ? headerParts.nextToken() : ""; + RamlFragment fragment = RamlFragment.byName(fragmentText); + if (fragment == null) { + throw new InvalidHeaderFragmentException(fragmentText); + } + return new RamlHeader(RAML_10, fragment); + } + throw new IllegalStateException("unsupported RAML version"); + } + } + } + throw new InvalidHeaderException(header); + } else { + throw new MissingHeaderException(); + } + } + + public RamlVersion getVersion() { + return version; + } + + + public RamlFragment getFragment() { + return fragment; + } + + + public Rule getRule() { + return getFragmentRule(fragment); + } + + + public static Rule getFragmentRule(RamlFragment fragment) { + Raml10Grammar grammar = new Raml10Grammar(); + return getRule(fragment, grammar); + } + + public static Rule getFragmentUsesAllowedRule(RamlFragment fragment) { + Raml10Grammar grammar = new Raml10GrammarUsesAllowed(); + return getRule(fragment, grammar); + } + + private static Rule getRule(RamlFragment fragment, Raml10Grammar grammar) { + switch (fragment) { + case DocumentationItem: + return grammar.documentation() + .with(0, grammar.usesField()); + case DataType: + return grammar.explicitType().with(0, grammar.usesField()).then(TypeDeclarationNodeFragment.class); + case NamedExample: + return grammar.exampleFragment(); + case ResourceType: + return grammar.resourceType().with(0, grammar.usesField()); + case Trait: + return grammar.trait().with(0, grammar.usesField()); + case AnnotationTypeDeclaration: + return grammar.annotationTypeDeclaration().with(0, grammar.usesField()); + case Library: + return grammar.libraryValue(); + case Overlay: + case Extension: + return grammar.extension(); + case SecurityScheme: + return grammar.securityScheme().with(0, grammar.usesField()); + case Default: + return grammar.raml(); + default: + return null; + } + } + + @Override + public String toString() { + return RAML_HEADER_PREFIX + " " + version.value() + (fragment != null ? (" " + fragment) : ""); + } + + public static class InvalidHeaderException extends Exception { + + public InvalidHeaderException() { + } + + public InvalidHeaderException(String message) { + super(message); + } + } + + public static class InvalidHeaderFragmentException extends InvalidHeaderException { + + public InvalidHeaderFragmentException(String fragmentText) { + super(fragmentText); + } + } + + public static class InvalidHeaderVersionException extends InvalidHeaderException { + + public InvalidHeaderVersionException(String version) { + super(version); + } + } + + public static class MissingHeaderException extends InvalidHeaderException { + + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/RamlVersion.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/RamlVersion.java new file mode 100644 index 0000000..5a3cef8 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/RamlVersion.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons; + +public enum RamlVersion { + RAML_10("1.0"); + + public final String number; + + public static RamlVersion parse(String version) { + for (RamlVersion item : values()) { + if (item.number.equals(version)) { + return item; + } + } + throw new IllegalArgumentException("Invalid version " + version); + } + + RamlVersion(String number) { + this.number = number; + } + + public String value() { + return number; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/grammar/BaseRamlGrammar.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/grammar/BaseRamlGrammar.java new file mode 100644 index 0000000..cf45800 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/grammar/BaseRamlGrammar.java @@ -0,0 +1,652 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.grammar; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.function.Function; +import org.xbib.raml.internal.impl.commons.nodes.BodyNode; +import org.xbib.raml.internal.impl.commons.nodes.MethodNode; +import org.xbib.raml.internal.impl.commons.nodes.ParametrizedResourceTypeRefNode; +import org.xbib.raml.internal.impl.commons.nodes.ParametrizedSecuritySchemeRefNode; +import org.xbib.raml.internal.impl.commons.nodes.ParametrizedTraitRefNode; +import org.xbib.raml.internal.impl.commons.nodes.RamlDocumentNode; +import org.xbib.raml.internal.impl.commons.nodes.ResourceNode; +import org.xbib.raml.internal.impl.commons.nodes.ResourceTypeNode; +import org.xbib.raml.internal.impl.commons.nodes.ResourceTypeRefNode; +import org.xbib.raml.internal.impl.commons.nodes.SecuritySchemeNode; +import org.xbib.raml.internal.impl.commons.nodes.SecuritySchemeRefNode; +import org.xbib.raml.internal.impl.commons.nodes.TraitNode; +import org.xbib.raml.internal.impl.commons.nodes.TraitRefNode; +import org.xbib.raml.internal.impl.commons.rule.NodeReferenceFactory; +import org.xbib.raml.internal.impl.commons.rule.NodeReferenceRule; +import org.xbib.raml.internal.impl.commons.rule.ParametrizedNodeReferenceRule; +import org.xbib.raml.internal.impl.v10.nodes.factory.EmptyObjectNodeFactory; +import org.xbib.raml.internal.impl.v10.nodes.factory.OverlayableSimpleTypeFactory; +import org.xbib.raml.internal.impl.v10.nodes.factory.TypeExpressionReferenceFactory; +import org.xbib.raml.yagi.framework.grammar.BaseGrammar; +import org.xbib.raml.yagi.framework.grammar.ExclusiveSiblingRule; +import org.xbib.raml.yagi.framework.grammar.RuleFactory; +import org.xbib.raml.yagi.framework.grammar.RuleTraverser; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import org.xbib.raml.yagi.framework.grammar.rule.ArrayRule; +import org.xbib.raml.yagi.framework.grammar.rule.ArrayWrapperFactory; +import org.xbib.raml.yagi.framework.grammar.rule.KeyValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.NodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.ObjectRule; +import org.xbib.raml.yagi.framework.grammar.rule.RegexValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.grammar.rule.StringValueRule; +import org.xbib.raml.yagi.framework.nodes.Node; +import static org.xbib.raml.internal.impl.commons.phase.StringTemplateExpressionTransformer.TEMPLATE_PATTERN; + +public abstract class BaseRamlGrammar extends BaseGrammar { + + public static final String USES_KEY_NAME = "uses"; + public static final String RESOURCE_TYPES_KEY_NAME = "resourceTypes"; + public static final String TRAITS_KEY_NAME = "traits"; + public static final String TYPES_KEY_NAME = "types"; + public static final String SCHEMAS_KEY_NAME = "schemas"; + public static final String QUERY_PARAMETERS_KEY_NAME = "queryParameters"; + public static final String QUERY_STRING_KEY_NAME = "queryString"; + public static final String SECURITY_SCHEMES_KEY_NAME = "securitySchemes"; + public static final String MIME_TYPE_REGEX = + "([\\w\\d\\.\\-\\_\\+]+|\\*)\\/([\\w\\d\\.\\-\\_\\+]+|\\*);?([\\w\\d\\.\\-\\_\\+]+=[\\w\\d\\.\\-\\_\\+]+)?(\\s+[\\w\\d\\.\\-\\_\\+]+=[\\w\\d\\.\\-\\_\\+]+)*"; + public static final String OAUTH_1_0 = "OAuth 1.0"; + public static final String OAUTH_2_0 = "OAuth 2.0"; + + public ObjectRule raml() { + return untitledRaml().with(titleField().description("Short plain-text label for the API.")); + } + + + protected NodeReferenceRule nodeRef(String referenceKey) { + return new NodeReferenceRule(referenceKey); + } + + + public ObjectRule untitledRaml() { + return objectType() + .with(descriptionField()) + .with(schemasField()) + .with(traitsField()) + .with(resourceTypesField()) + .with(securitySchemesField()) + .with(versionField()) + .with(baseUriField()) + .with(baseUriParametersField()) + .with(protocolsField()) + .with(mediaTypeField()) + .with(securedByField().description("The security schemes that apply to every resource and method in the API.")) + .with(resourceField()) + .with(fieldWithRequiredValue(documentationKey(), documentations())) + .then(RamlDocumentNode.class); + } + + protected KeyValueRule baseUriParametersField() { + return field(baseUriParametersKey(), parameters()); + } + + protected KeyValueRule baseUriField() { + return field(baseUriKey(), new UriTemplateValidationRule(ramlScalarValue())); + } + + + protected KeyValueRule docTitleField() { + return requiredField(titleKey(), allOf(minLength(1), ramlScalarValue())); + } + + protected KeyValueRule titleField() { + return requiredField(titleKey(), titleValue()); + } + + protected Rule titleValue() { + return allOf(ramlScalarValue(), minLength(1)); + } + + protected KeyValueRule resourceField() { + return new KeyValueRule(resourceKey(), anyOf(resourceValue(), nullValue().then(new EmptyObjectNodeFactory()))).then(ResourceNode.class); + } + + + protected KeyValueRule versionField() { + return field(versionKey(), ramlScalarValue()); + } + + protected Rule ramlScalarValue() { + return scalarType(); + } + + protected KeyValueRule mediaTypeField() { + return field(mediaTypeKey(), mimeTypeRegex()); + } + + public ObjectRule resourceType() { + final ObjectRule resourceType = inNewContext(new Callable() { + + @Override + public ObjectRule call() { + return new RuleTraverser().traverse(baseResourceValue().with(field(anyResourceTypeMethod(), methodValue())), ruleParameterModifier()); + } + }); + return resourceType + .with(0, usageField()); // match anything but nested resources + } + + /** + * Returns a function that modifies a rule to support parameter + * + * @return The function that injects the parameters + */ + private Function ruleParameterModifier() { + return new Function() { + + @Override + public Boolean apply(Rule input) { + // We should change that any object now should have a parametrized key value pair + // This mean that any key can be parametrized and we don't know anything about the value + // And any value can be parametrized of any known key + if (input instanceof ObjectRule) { + ((ObjectRule) input).with(0, fieldParametrizedKey()); + } else if (input instanceof KeyValueRule keyValueRule) { + keyValueRule.setValueRule(anyOf(parametrizedValueRule(), keyValueRule.getValueRule())); + keyValueRule.cleanDefaultValue(); + } else if (input instanceof ArrayRule arrayRule) { + arrayRule.of(anyOf(parametrizedValueRule(), arrayRule.of())); + } + // We keep reference factories so that we can validate reference consistency + // and we keep overlay factories so traits/rt can be overlaid + if (!isReferenceFactory(input) && !isOverlayFactory(input) && input.getFactory() != null) { + input.cleanFactory(); + } + return true; + } + }; + } + + private boolean isOverlayFactory(Rule input) { + return input.getFactory() instanceof OverlayableSimpleTypeFactory; + } + + private boolean isReferenceFactory(Rule input) { + return input.getFactory() instanceof NodeReferenceFactory || input.getFactory() instanceof TypeExpressionReferenceFactory; + } + + public ObjectRule resourceTypeParamsResolved() { + return baseResourceValue() + .with(usageField()) + .with(field(anyResourceTypeMethod(), methodValue()) + .then(MethodNode.class)); + } + + public ObjectRule traitParamsResolved() { + return objectType() + .with(descriptionField()) + .with(field(displayNameKey(), ramlScalarValue())) + .with(queryParametersField()) + .with(headersField()) + .with(responsesField()) + .with(bodyField()) + .with(protocolsField().description("A method can override the protocols specified in the resource or at the API root, by employing this property.")) + .with(isField().description("A list of the traits to apply to this method.")) + .with(securedByField().description("The security schemes that apply to this method.")) + .with(usageField()); + + } + + // Documentation + protected Rule documentations() { + return array(documentation()); + } + + public ObjectRule documentation() { + return objectType() + .with(docTitleField().description("Title of documentation section.")) + .with(contentField().description("Content of documentation section.")); + } + + protected KeyValueRule contentField() { + return requiredField(string("content"), ramlScalarValue()); + } + + + // Security scheme + + protected Rule securitySchemes() { + return objectType() + .with( + field(scalarType(), securityScheme()) + .then(SecuritySchemeNode.class) + ); + } + + public ObjectRule securityScheme() { + return objectType() + .with(descriptionField()) + .with(requiredField( + securitySchemeTypeKey(), + anyOf( + string(OAUTH_1_0).description("The API's authentication uses OAuth 1.0 as described in RFC5849 [RFC5849]"), + string(OAUTH_2_0).description("The API's authentication uses OAuth 2.0 as described in RFC6749 [RFC6749]"), + string("Basic Authentication").description( + "The API's authentication uses Basic Authentication as described in RFC2617 [RFC2617]"), + string("Digest Authentication").description( + "The API's authentication uses Digest Authentication as described in RFC2617 [RFC2617]"), + string("Pass Through").description("Headers or Query Parameters are passed through to the API based on a defined object."), + regex("x-.+").description("The API's authentication uses an authentication method not listed above.") + ))) + .with(displayNameField()) + .with(field(string("describedBy"), securitySchemePart())) + .with(when("type", is(anyOf(string(OAUTH_1_0), string(OAUTH_2_0))).add(requiredField(string("settings"), securitySchemeSettings())))); + } + + protected ObjectRule securitySchemePart() { + return objectType() + .with(displayNameField()) + .with(descriptionField()) + .with(field(headersKey(), parameters())) + .with(queryParametersField()) + .with(responsesField()); + } + + protected ObjectRule securitySchemeSettings() { + return objectType() + .with(field(string("requestTokenUri"), ramlScalarValue())) + .with(field(string("tokenCredentialsUri"), ramlScalarValue())) + .with(field(string("accessTokenUri"), ramlScalarValue())) + .with(field(string("authorizationGrants"), anyOf(authorizationGrantsValue(), array(authorizationGrantsValue())))) + .with(field(string("scopes"), anyOf(scalarType(), array(scalarType())))); + } + + protected Rule authorizationGrantsValue() { + return scalarType(); + } + + // Traits + protected Rule traitsValue() { + return objectType() + .with( + field(scalarType(), trait()).then(TraitNode.class) + ); + } + + public ObjectRule trait() { + final ObjectRule trait = inNewContext(new Callable() { + + @Override + public ObjectRule call() { + return new RuleTraverser().traverse(methodValue(), ruleParameterModifier()); + } + }); + return trait + .with(0, usageField()); + } + + private RegexValueRule parametrizedValueRule() { + return regex(TEMPLATE_PATTERN).fullMatch(false); + } + + private KeyValueRule fieldParametrizedKey() { + return field(parametrizedValueRule(), any()); + } + + // Resource Types + protected Rule resourceTypes() { + return objectType().with(field(scalarType(), resourceType()).then(ResourceTypeNode.class)); + } + + + // Resources + protected ObjectRule resourceValue() { + return named("resourceValue", new RuleFactory() { + @Override + public ObjectRule create() { + return baseResourceValue() + .with(methodField()) + .with(resourceField()); + } + }); + } + + protected KeyValueRule methodField() { + return new KeyValueRule(anyMethod(), anyOf(methodValue(), nullValue().then(new EmptyObjectNodeFactory()))).then(MethodNode.class); + } + + protected ObjectRule baseResourceValue() { + return objectType() + .with(displayNameField()) + .with(descriptionField()) + .with(isField().description("A list of the traits to apply to all methods declared (implicitly or explicitly) for this resource. ")) + .with(resourceTypeReferenceField()) + .with(securedByField().description("The security schemes that apply to all methods declared (implicitly or explicitly) for this resource.")) + .with(field(uriParametersKey(), parameters())); + } + + // Method + protected ObjectRule methodValue() { + return objectType() + .with(descriptionField()) + .with(displayNameField()) + .with(queryParametersField()) + .with(headersField()) + .with(responsesField()) + .with(bodyField()) + .with(protocolsField().description("A method can override the protocols specified in the resource or at the API root, by employing this property.")) + .with(isField().description("A list of the traits to apply to this method.")) + .with(securedByField().description("The security schemes that apply to this method.")); + } + + protected KeyValueRule queryParametersField() { + return field(queryParametersKey(), parameters()); + } + + protected KeyValueRule responsesField() { + return field(responseKey(), responses()); + } + + protected StringValueRule responseKey() { + return string("responses") + .description("Information about the expected responses to a request"); + } + + protected StringValueRule queryStringKey() { + return string(QUERY_STRING_KEY_NAME) + .description("Specifies the query string needed by this method." + + " Mutually exclusive with queryParameters."); + } + + protected StringValueRule queryParametersKey() { + return string(QUERY_PARAMETERS_KEY_NAME) + .description("Detailed information about any query parameters needed by this method. " + + "Mutually exclusive with queryString."); + } + + + protected Rule responses() { + return objectType().with(responseField()); + } + + protected KeyValueRule responseField() { + return field(responseCodes(), response()); + } + + protected ObjectRule response() { + return objectType() + .with(displayNameField()) + .with(descriptionField()) + .with(headersField()) + .with(bodyField()); + } + + protected Rule body() { + return objectType().with(mimeTypeField()); + } + + public KeyValueRule mimeTypeField() { + return field(mimeTypeRegex(), mimeType()); + } + + public RegexValueRule mimeTypeRegex() { + return regex(MIME_TYPE_REGEX) + .suggest("application/json") + .suggest("application/xml"); + } + + protected abstract Rule mimeType(); + + protected Rule parameters() { + return objectType().with(field(scalarType(), parameter())); + } + + /** + * Describes the rule for a parameter. + */ + protected abstract Rule parameter(); + + protected ExclusiveSiblingRule exclusiveWith(String key, String... notAllowedSiblings) { + Set set = new HashSet<>(Arrays.asList(notAllowedSiblings)); + return new ExclusiveSiblingRule(key, set); + } + + protected KeyValueRule securitySchemesField() { + return field(securitySchemesKey(), securitySchemesValue()); + } + + protected abstract Rule securitySchemesValue(); + + protected StringValueRule securitySchemesKey() { + return string(SECURITY_SCHEMES_KEY_NAME).description("Declarations of security schemes for use within this API."); + } + + protected KeyValueRule schemasField() { + return field(schemasKey(), schemasValue()); + } + + protected abstract Rule schemasValue(); + + protected StringValueRule schemasKey() { + return string("schemas") + .description(schemasDescription()); + } + + + protected abstract String schemasDescription(); + + protected KeyValueRule resourceTypesField() { + return field(resourceTypesKey(), resourceTypesValue()); + } + + protected Rule resourceTypesValue() { + return anyOf(array(resourceTypes()), resourceTypes()).then(new ArrayWrapperFactory()); + } + + protected StringValueRule resourceTypesKey() { + return string(RESOURCE_TYPES_KEY_NAME).description("Declarations of resource types for use within this API."); + } + + protected KeyValueRule traitsField() { + return field(traitsKey(), traitsValue()); + } + + protected StringValueRule traitsKey() { + return string(TRAITS_KEY_NAME).description("Declarations of traits for use within this API."); + } + + protected KeyValueRule protocolsField() { + return field(protocolsKey(), protocols()); + } + + protected StringValueRule protocolsKey() { + return string("protocols").description("The protocols supported by the API."); + } + + protected KeyValueRule bodyField() { + return field(bodyKey(), + firstOf( + whenChildIs(mimeTypeField(), body()), + whenPresent("/mediaType", mimeType()))) + .then(BodyNode.class); + } + + protected StringValueRule bodyKey() { + return string("body") + .description("Some methods admit request bodies, which are described by this property."); + } + + protected KeyValueRule headersField() { + return field(headersKey(), parameters()); + } + + protected StringValueRule headersKey() { + return string("headers") + .description("Detailed information about any request headers needed by this method."); + } + + protected KeyValueRule descriptionField() { + return field(descriptionKey(), descriptionValue()); + } + + protected Rule descriptionValue() { + return ramlScalarValue(); + } + + protected KeyValueRule displayNameField() { + return field(displayNameKey(), ramlScalarValue()).defaultValue(parentKey()); + } + + protected KeyValueRule securedByField() { + Rule securitySchemeRef = anyOf(nullValue(), anyTypeReference(SECURITY_SCHEMES_KEY_NAME, SecuritySchemeRefNode.class, ParametrizedSecuritySchemeRefNode.class)); + return field(securedByKey(), anyOf(securitySchemeRef, array(securitySchemeRef)).then(new ArrayWrapperFactory())); + } + + protected KeyValueRule usageField() { + return field(string("usage"), ramlScalarValue()); + } + + protected KeyValueRule isField() { + Rule traitRef = anyTypeReference(TRAITS_KEY_NAME, TraitRefNode.class, ParametrizedTraitRefNode.class); + return field(isKey(), anyOf(traitRef, array(traitRef)).then(new ArrayWrapperFactory())); + } + + protected KeyValueRule resourceTypeReferenceField() { + return field(resourceTypeRefKey(), anyTypeReference(RESOURCE_TYPES_KEY_NAME, ResourceTypeRefNode.class, ParametrizedResourceTypeRefNode.class)); + } + + protected Rule anyTypeReference(String referenceKey, Class simpleClass, Class parametrisedClass) { + final KeyValueRule paramsRule = field(scalarType(), any()); + final KeyValueRule typeWithParams = field(scalarType(), objectType().with(paramsRule)); + final NodeFactory factory = new NodeReferenceFactory(simpleClass); + final NodeFactory parametrisedFactory = new NodeReferenceFactory(parametrisedClass); + return anyOf(nodeRef(referenceKey).then(factory), new ParametrizedNodeReferenceRule(referenceKey).with(typeWithParams).then(parametrisedFactory)); + } + + protected StringValueRule titleKey() { + return string("title"); + } + + + // Repeated keys + + protected Rule resourceKey() { + RegexValueRule rule = regex("/.*") + .label("/Resource") + .suggest("/") + .description("The resources of the API, identified as relative URIs that begin with a slash (/). " + + "Every property whose key begins with a slash (/), and is either at the root of the API definition " + + "or is the child property of a resource property, is a resource property, e.g.: /users, /{groupId}, etc"); + + return new UriTemplateValidationRule(rule); + } + + protected StringValueRule usesKey() { + return string(USES_KEY_NAME).description("Importing libraries."); + } + + + protected StringValueRule uriParametersKey() { + return string("uriParameters").description("Detailed information about any URI parameters of this resource"); + } + + protected StringValueRule securedByKey() { + return string("securedBy"); + } + + protected StringValueRule typeKey() { + return string("type") + .description("The resource type which this resource inherits."); + } + + protected StringValueRule securitySchemeTypeKey() { + return string("type") + .description("Specify the security mechanism."); + } + + protected StringValueRule resourceTypeRefKey() { + return string("type") + .description("The resource type which this resource inherits."); + } + + protected StringValueRule isKey() { + return string("is"); + } + + protected StringValueRule displayNameKey() { + return string("displayName") + .description("An alternate, human-friendly name for the method (in the resource's context)."); + } + + + protected StringValueRule descriptionKey() { + return string("description").description("A longer, human-friendly description of the API"); + } + + protected StringValueRule documentationKey() { + return string("documentation") + .description("Additional overall documentation for the API."); + } + + protected StringValueRule mediaTypeKey() { + return string("mediaType") + .description("The default media type to use for request and response bodies (payloads), e.g. \"application/json\"."); + } + + protected StringValueRule baseUriParametersKey() { + return string("baseUriParameters").description("Named parameters used in the baseUri (template)."); + } + + protected StringValueRule baseUriKey() { + return string("baseUri").description("A URI that's to be used as the base of all the resources' URIs." + + " Often used as the base of the URL of each resource, containing the location of the API. " + + "Can be a template URI."); + } + + protected StringValueRule versionKey() { + return string("version").description("The version of the API, e.g. \"v1\"."); + } + + + // Enum of values + + protected AnyOfRule anyMethod() { + return anyOf( + string("get"), + string("patch"), + string("put"), + string("post"), + string("delete"), + string("options"), + string("head")); + } + + protected AnyOfRule anyOptionalMethod() { + return anyOf(string("get?"), string("patch?"), string("put?"), string("post?"), string("delete?"), string("options?"), string("head?")); + } + + protected AnyOfRule anyResourceTypeMethod() { + return anyOf(anyMethod(), anyOptionalMethod()); + } + + protected Rule protocols() { + AnyOfRule protocols = anyOf(string("HTTP").caseSensitive(false), string("HTTPS").caseSensitive(false)); + return anyOf(protocols, array(protocols)).then(new ArrayWrapperFactory()); + } + + protected Rule responseCodes() { + return allOf(range(100, 599)); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/grammar/UriTemplateValidationRule.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/grammar/UriTemplateValidationRule.java new file mode 100644 index 0000000..6fdd70b --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/grammar/UriTemplateValidationRule.java @@ -0,0 +1,63 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.grammar; + +import java.util.List; +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.internal.utils.UriTemplateValidation; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.SYStringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class UriTemplateValidationRule extends Rule { + private final Rule rule; + + public UriTemplateValidationRule(Rule rule) { + super(); + this.rule = rule; + } + + @Override + public boolean matches(Node node) { + return rule.matches(node); + } + + + @Override + public Node apply(Node node) { + Node apply = rule.apply(node); + if (node instanceof SYStringNode) { + if (!UriTemplateValidation.isBalanced(((SYStringNode) node).getValue())) { + apply = RamlErrorNodeFactory.createInvalidUriTemplate(); + } + } + + return apply; + } + + @Override + public String getDescription() { + return rule.getDescription(); + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return rule.getSuggestions(node, context); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Annotable.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Annotable.java new file mode 100644 index 0000000..25004ab --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Annotable.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.AnnotationNode; +import org.xbib.raml.yagi.framework.model.AbstractNodeModel; +import org.xbib.raml.yagi.framework.nodes.Node; + +public abstract class Annotable extends AbstractNodeModel { + public Annotable(T node) { + super(node); + } + + public List annotations() { + List result = new ArrayList<>(); + for (Node child : getNode().getChildren()) { + if (child instanceof AnnotationNode) { + result.add(new AnnotationRef((AnnotationNode) child)); + } + } + return result; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/AnnotationRef.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/AnnotationRef.java new file mode 100644 index 0000000..5a21aa8 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/AnnotationRef.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.internal.impl.commons.model.factory.TypeDeclarationModelFactory; +import org.xbib.raml.internal.impl.commons.model.type.TypeDeclaration; +import org.xbib.raml.internal.impl.commons.nodes.AnnotationNode; +import org.xbib.raml.yagi.framework.model.AbstractNodeModel; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class AnnotationRef extends AbstractNodeModel { + public AnnotationRef(AnnotationNode node) { + super(node); + } + + public TypeDeclaration annotation() { + return new TypeDeclarationModelFactory().create(node.getAnnotationTypeNode()); + } + + public String name() { + return node.getKey().getValue(); + } + + public TypeInstance structuredValue() { + return new TypeInstance(node.getValue()); + } + + @Override + public Node getNode() { + return node; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Api.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Api.java new file mode 100644 index 0000000..8069a13 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Api.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.RamlDocumentNode; +import org.xbib.raml.internal.impl.commons.nodes.ResourceNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import static org.xbib.raml.internal.utils.RamlNodeUtils.getVersion; + +public class Api extends Annotable { + public Api(RamlDocumentNode delegateNode) { + super(delegateNode); + } + + @Override + public Node getNode() { + return node; + } + + + public List resources() { + ArrayList resultList = new ArrayList<>(); + for (Node item : node.getChildren()) { + if (item instanceof ResourceNode) { + resultList.add(new Resource((ResourceNode) item)); + } + } + return resultList; + } + + public String ramlVersion() { + return getVersion(node).value(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/BodyLike.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/BodyLike.java new file mode 100644 index 0000000..f864e70 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/BodyLike.java @@ -0,0 +1,55 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.yagi.framework.model.AbstractNodeModel; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class BodyLike extends AbstractNodeModel { + public BodyLike(KeyValueNode node) { + super(node); + } + + @Override + public Node getNode() { + return node.getValue(); + } + + public String name() { + return ((StringNode) node.getKey()).getValue(); + } + + public String schemaContent() { + String schema = NodeSelector.selectStringValue("schema", getNode()); + + // For an inline schema + if (schema == null || schema.startsWith("{") || schema.startsWith("<")) { + return schema; + } + + // For an schema reference, + Node rootRamlSchema = NodeSelector.selectFrom("/schemas/" + schema, getNode()); + if (rootRamlSchema instanceof StringNode) { + return ((StringNode) rootRamlSchema).getValue(); + } + + return null; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/DefaultModelElement.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/DefaultModelElement.java new file mode 100644 index 0000000..3465e6a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/DefaultModelElement.java @@ -0,0 +1,29 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.yagi.framework.nodes.Node; + +public class DefaultModelElement extends Annotable { + public DefaultModelElement(Node node) { + super(node); + } + + @Override + public Node getNode() { + return node; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/ExampleSpec.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/ExampleSpec.java new file mode 100644 index 0000000..f3fdd87 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/ExampleSpec.java @@ -0,0 +1,85 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.internal.utils.JSonDumper; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; + + +public class ExampleSpec extends Annotable { + public ExampleSpec(KeyValueNode node) { + super(node); + } + + public String value() { + final Node exampleValue = getExampleValue(); + + if (structuredValue().isScalar()) { + return exampleValue.toString(); + } else { + return JSonDumper.dump(exampleValue); + } + } + + public String name() { + return getName(); + } + + public TypeInstance structuredValue() { + final Node value = getExampleValue(); + // FIXME ExampleTypeNode may wrap a SimpleTypeNode + // if ((value instanceof ExampleTypeNode) && value.getSource() != null) + // { + // value = value.getSource(); + // } + return new TypeInstance(value); + } + + @Override + public Node getNode() { + return node.getValue(); + } + + + private Node getExampleValue() { + if (isExplicitExample()) { + return NodeSelector.selectFrom("value", node.getValue()); + } else { + return node.getValue(); + } + } + + private String getName() { + final Node ancestor = org.xbib.raml.yagi.framework.util.NodeUtils.getAncestor(node, 2); + if (ancestor instanceof KeyValueNode && ((KeyValueNode) ancestor).getKey().toString().equals("examples")) { + return node.getKey().toString(); + } else { + return null; + } + } + + private boolean isExplicitExample() { + if (node.getValue() instanceof ObjectNode) { + final Node value = NodeSelector.selectFrom("value", node.getValue()); + return value != null; + } + return false; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/GlobalSchema.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/GlobalSchema.java new file mode 100644 index 0000000..f764e0c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/GlobalSchema.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.yagi.framework.model.AbstractNodeModel; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +public class GlobalSchema extends AbstractNodeModel { + public GlobalSchema(KeyValueNode node) { + super(node); + } + + @Override + public Node getNode() { + return node.getValue(); + } + + public String key() { + return ((SimpleTypeNode) node.getKey()).getLiteralValue(); + } + + public StringType value() { + return new StringType((SimpleTypeNode) node.getValue()); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Library.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Library.java new file mode 100644 index 0000000..a4d5b20 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Library.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.internal.impl.v10.nodes.LibraryLinkNode; +import org.xbib.raml.internal.impl.v10.nodes.LibraryNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class Library extends Annotable { + public Library(LibraryNode node) { + super(node); + } + + @Override + public Node getNode() { + final Node value = node.getValue(); + return ((LibraryLinkNode) value).getRefNode(); + } + + public String name() { + return node.getName(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Method.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Method.java new file mode 100644 index 0000000..0b03af3 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Method.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.internal.impl.commons.nodes.MethodNode; +import org.xbib.raml.internal.impl.commons.nodes.ResourceNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class Method extends Annotable { + public Method(MethodNode node) { + super(node); + } + + @Override + public Node getNode() { + return node.getValue(); + } + + public String method() { + return node.getName(); + } + + public Resource resource() { + Node parent = node.getParent(); + if (parent != null) { + if (parent.getParent() instanceof ResourceNode) { + return new Resource((ResourceNode) parent.getParent()); + } + } + return null; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/RamlValidationResult.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/RamlValidationResult.java new file mode 100644 index 0000000..0d4544d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/RamlValidationResult.java @@ -0,0 +1,72 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Position; + +public class RamlValidationResult implements org.xbib.raml.api.model.common.ValidationResult { + + private final String message; + private String errorPath; + private Position start; + private Position end; + + public RamlValidationResult(String message) { + this.message = message; + } + + public RamlValidationResult(ErrorNode errorNode) { + this.message = errorNode.getErrorMessage(); + this.errorPath = errorNode.getPath(); + this.start = errorNode.getStartPosition(); + this.end = errorNode.getEndPosition(); + } + + @Override + public String getMessage() { + return message; + } + + @Override + public String getPath() { + return errorPath; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(message); + if (start != null) { + if (start.getLine() != Position.UNKNOWN) { + builder.append(" -- ").append(start.getPath()); + builder.append(" [line=").append(start.getLine() + 1) + .append(", col=").append(start.getColumn() + 1).append("]"); + } + } + return builder.toString(); + } + + public Position getStartPosition() { + return start; + } + + + public Position getEndPosition() { + return end; + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Reference.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Reference.java new file mode 100644 index 0000000..056e16f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Reference.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.internal.impl.commons.nodes.AbstractReferenceNode; +import org.xbib.raml.yagi.framework.model.AbstractNodeModel; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; + +public class Reference extends AbstractNodeModel { + public Reference(ReferenceNode node) { + super(node); + } + + public ReferenceNode getNode() { + return node; + } + + public TypeInstance structuredValue() { + final Node parametersNode = ((AbstractReferenceNode) getNode()).getParametersNode(); + return parametersNode != null ? new TypeInstance(parametersNode) : null; + } + + public String name() { + return getNode().getRefName(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Resource.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Resource.java new file mode 100644 index 0000000..4d05d21 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Resource.java @@ -0,0 +1,68 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.MethodNode; +import org.xbib.raml.internal.impl.commons.nodes.ResourceNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +public class Resource extends Annotable { + public Resource(ResourceNode node) { + super(node); + } + + @Override + public Node getNode() { + return node.getValue(); + } + + public StringType relativeUri() { + return new StringType((SimpleTypeNode) node.getKey()); + } + + public String resourcePath() { + return node.getResourcePath(); + } + + public List resources() { + ArrayList resultList = new ArrayList<>(); + for (Node item : node.getValue().getChildren()) { + if (item instanceof ResourceNode) { + resultList.add(new Resource((ResourceNode) item)); + } + } + return resultList; + } + + public List methods() { + ArrayList resultList = new ArrayList<>(); + for (Node item : node.getValue().getChildren()) { + if (item instanceof MethodNode) { + resultList.add(new Method((MethodNode) item)); + } + } + return resultList; + } + + public Resource parentResource() { + ResourceNode parent = node.getParentResourceNode(); + return parent != null ? new Resource(parent) : null; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/ResourceType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/ResourceType.java new file mode 100644 index 0000000..e1c637f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/ResourceType.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.internal.impl.commons.nodes.ResourceTypeNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class ResourceType extends Annotable { + public static ResourceType create(Node node) { + if (!(node instanceof ResourceTypeNode)) { + throw new IllegalArgumentException("Invalid node type: " + node.getClass().getName()); + } + return new ResourceType((ResourceTypeNode) node); + } + + public ResourceType(ResourceTypeNode node) { + super(node); + } + + @Override + public Node getNode() { + return node.getValue(); + } + + public String name() { + return node.getName(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/ResourceTypeRef.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/ResourceTypeRef.java new file mode 100644 index 0000000..12f2ae9 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/ResourceTypeRef.java @@ -0,0 +1,29 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; + +public class ResourceTypeRef extends Reference { + + public ResourceTypeRef(ReferenceNode node) { + super(node); + } + + public ResourceType resourceType() { + return ResourceType.create(getNode().getRefNode()); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Response.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Response.java new file mode 100644 index 0000000..d716372 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Response.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +public class Response extends Annotable { + public Response(KeyValueNode node) { + super(node); + } + + @Override + public Node getNode() { + return node.getValue(); + } + + public StringType code() { + return new StringType(((SimpleTypeNode) node.getKey())); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/SecurityScheme.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/SecurityScheme.java new file mode 100644 index 0000000..15aea13 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/SecurityScheme.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.internal.impl.commons.nodes.SecuritySchemeNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class SecurityScheme extends Annotable { + public SecurityScheme(SecuritySchemeNode node) { + super(node); + } + + @Override + public Node getNode() { + return node.getValue(); + } + + public String name() { + return node.getName(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/SecuritySchemeRef.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/SecuritySchemeRef.java new file mode 100644 index 0000000..ef6cb0f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/SecuritySchemeRef.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.internal.impl.commons.nodes.BaseSecuritySchemeRefNode; +import org.xbib.raml.internal.impl.commons.nodes.SecuritySchemeNode; +import org.xbib.raml.yagi.framework.model.AbstractNodeModel; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class SecuritySchemeRef extends AbstractNodeModel { + public SecuritySchemeRef(BaseSecuritySchemeRefNode node) { + super(node); + } + + @Override + public BaseSecuritySchemeRefNode getNode() { + return node; + } + + public String name() { + return node.getRefName(); + } + + public SecurityScheme securityScheme() { + if (node == null) { + return null; + } + return new SecurityScheme((SecuritySchemeNode) node.getRefNode()); + } + + public TypeInstance structuredValue() { + final Node parametersNode = getNode().getParametersNode(); + return parametersNode != null ? new TypeInstance(parametersNode) : null; + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/StringType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/StringType.java new file mode 100644 index 0000000..70ba7ff --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/StringType.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.yagi.framework.model.AbstractNodeModel; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + + +public class StringType extends AbstractNodeModel { + public StringType(SimpleTypeNode node) { + super(node); + } + + public String value() { + return node.getLiteralValue(); + } + + @Override + public Node getNode() { + return node; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Trait.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Trait.java new file mode 100644 index 0000000..ef9768f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/Trait.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.internal.impl.commons.nodes.TraitNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class Trait extends Annotable { + public Trait(TraitNode node) { + super(node); + } + + @Override + public Node getNode() { + return node.getValue(); + } + + public String name() { + return node.getName(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/TraitRef.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/TraitRef.java new file mode 100644 index 0000000..32c9770 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/TraitRef.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import org.xbib.raml.internal.impl.commons.nodes.TraitNode; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; + +public class TraitRef extends Reference { + public TraitRef(ReferenceNode node) { + super(node); + } + + public Trait trait() { + return new Trait((TraitNode) getNode().getRefNode()); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/TypeInstance.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/TypeInstance.java new file mode 100644 index 0000000..432de2c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/TypeInstance.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.yagi.framework.model.AbstractNodeModel; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +public class TypeInstance extends AbstractNodeModel { + public TypeInstance(Node node) { + super(node); + } + + public List properties() { + List result = new ArrayList<>(); + if (node instanceof ArrayNode) { + result.add(new TypeInstanceProperty((KeyValueNode) node.getParent())); + } else if (node instanceof ObjectNode) { + for (Node child : node.getChildren()) { + result.add(new TypeInstanceProperty((KeyValueNode) child)); + } + } + return result; + } + + public Boolean isScalar() { + return node instanceof SimpleTypeNode; + } + + public Object value() { + if (node instanceof SimpleTypeNode) { + return ((SimpleTypeNode) node).getValue(); + } + return null; + } + + @Override + public Node getNode() { + return node; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/TypeInstanceProperty.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/TypeInstanceProperty.java new file mode 100644 index 0000000..6ca1860 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/TypeInstanceProperty.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.yagi.framework.model.AbstractNodeModel; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +public class TypeInstanceProperty extends AbstractNodeModel { + public TypeInstanceProperty(KeyValueNode node) { + super(node); + } + + public String name() { + return ((SimpleTypeNode) node.getKey()).getLiteralValue(); + } + + public TypeInstance value() { + if (!isArray()) { + return new TypeInstance(node.getValue()); + } + return null; + } + + public List values() { + List result = new ArrayList<>(); + if (isArray()) { + for (Node child : node.getValue().getChildren()) { + result.add(new TypeInstance(child)); + } + } + return result; + } + + public Boolean isArray() { + return node.getValue() instanceof ArrayNode; + } + + @Override + public Node getNode() { + return node; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/factory/TypeDeclarationModelFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/factory/TypeDeclarationModelFactory.java new file mode 100644 index 0000000..c9384c2 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/factory/TypeDeclarationModelFactory.java @@ -0,0 +1,186 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.factory; + +import org.xbib.raml.internal.impl.commons.model.type.AnyTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.ArrayTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.BooleanTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.DateTimeOnlyTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.DateTimeTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.DateTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.FileTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.IntegerTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.JSONTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.NullTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.NumberTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.ObjectTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.StringTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.TimeOnlyTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.TypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.UnionTypeDeclaration; +import org.xbib.raml.internal.impl.commons.model.type.XMLTypeDeclaration; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.JsonSchemaExternalType; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.commons.type.XmlSchemaExternalType; +import org.xbib.raml.internal.impl.v10.type.AnyResolvedType; +import org.xbib.raml.internal.impl.v10.type.ArrayResolvedType; +import org.xbib.raml.internal.impl.v10.type.BooleanResolvedType; +import org.xbib.raml.internal.impl.v10.type.DateOnlyResolvedType; +import org.xbib.raml.internal.impl.v10.type.DateTimeOnlyResolvedType; +import org.xbib.raml.internal.impl.v10.type.DateTimeResolvedType; +import org.xbib.raml.internal.impl.v10.type.FileResolvedType; +import org.xbib.raml.internal.impl.v10.type.IntegerResolvedType; +import org.xbib.raml.internal.impl.v10.type.NullResolvedType; +import org.xbib.raml.internal.impl.v10.type.NumberResolvedType; +import org.xbib.raml.internal.impl.v10.type.ObjectResolvedType; +import org.xbib.raml.internal.impl.v10.type.StringResolvedType; +import org.xbib.raml.internal.impl.v10.type.TimeOnlyResolvedType; +import org.xbib.raml.internal.impl.v10.type.TypeVisitor; +import org.xbib.raml.internal.impl.v10.type.UnionResolvedType; +import org.xbib.raml.yagi.framework.model.NodeModelFactory; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; + +public class TypeDeclarationModelFactory implements NodeModelFactory { + + @Override + public TypeDeclaration create(Node node) { + if (node instanceof KeyValueNode keyValueNode && ((KeyValueNode) node).getValue() instanceof TypeDeclarationNode) { + final TypeDeclarationNode typeDeclarationNode = (TypeDeclarationNode) keyValueNode.getValue(); + final ResolvedType resolvedType = typeDeclarationNode.getResolvedType(); + return new NodeModelTypeFactory(keyValueNode).create(resolvedType); + } else if (node instanceof TypeDeclarationNode) { + final TypeDeclarationNode typeDeclarationNode = (TypeDeclarationNode) node; + final ResolvedType resolvedType = typeDeclarationNode.getResolvedType(); + return createTypeDeclaration(typeDeclarationNode, resolvedType); + } else { + throw new RuntimeException("Invalid node for type creation " + node.getClass()); + } + } + + public TypeDeclaration createTypeDeclaration(TypeExpressionNode node, ResolvedType resolvedType) { + KeyValueNode keyValueNode = node.findAncestorWith(KeyValueNode.class); + if (keyValueNode == null) { + keyValueNode = new KeyValueNodeImpl(new StringNodeImpl("__DataType_Fragment__"), node); + } + return new NodeModelTypeFactory(keyValueNode).create(resolvedType); + } + + @Override + public boolean polymorphic() { + return true; + } + + public TypeDeclaration create(ResolvedType type) { + return createTypeDeclaration(type.getTypeExpressionNode(), type); + } + + private static class NodeModelTypeFactory implements TypeVisitor { + private final KeyValueNode keyValueNode; + + public NodeModelTypeFactory(KeyValueNode keyValueNode) { + this.keyValueNode = keyValueNode; + } + + @Override + public TypeDeclaration visitString(StringResolvedType stringTypeDefinition) { + return new StringTypeDeclaration(keyValueNode, stringTypeDefinition); + } + + @Override + public TypeDeclaration visitObject(ObjectResolvedType objectTypeDefinition) { + return new ObjectTypeDeclaration(keyValueNode, objectTypeDefinition); + } + + @Override + public TypeDeclaration visitBoolean(BooleanResolvedType booleanTypeDefinition) { + return new BooleanTypeDeclaration(keyValueNode, booleanTypeDefinition); + } + + @Override + public TypeDeclaration visitInteger(IntegerResolvedType integerTypeDefinition) { + return new IntegerTypeDeclaration(keyValueNode, integerTypeDefinition); + } + + @Override + public TypeDeclaration visitNumber(NumberResolvedType numberTypeDefinition) { + return new NumberTypeDeclaration(keyValueNode, numberTypeDefinition); + } + + @Override + public TypeDeclaration visitDateTimeOnly(DateTimeOnlyResolvedType dateTimeOnlyTypeDefinition) { + return new DateTimeOnlyTypeDeclaration(keyValueNode, dateTimeOnlyTypeDefinition); + } + + @Override + public TypeDeclaration visitDate(DateOnlyResolvedType dateOnlyTypeDefinition) { + return new DateTypeDeclaration(keyValueNode, dateOnlyTypeDefinition); + } + + @Override + public TypeDeclaration visitDateTime(DateTimeResolvedType dateTimeTypeDefinition) { + return new DateTimeTypeDeclaration(keyValueNode, dateTimeTypeDefinition); + } + + @Override + public TypeDeclaration visitFile(FileResolvedType fileTypeDefinition) { + return new FileTypeDeclaration(keyValueNode, fileTypeDefinition); + } + + @Override + public TypeDeclaration visitNull(NullResolvedType nullTypeDefinition) { + return new NullTypeDeclaration(keyValueNode, nullTypeDefinition); + } + + @Override + public TypeDeclaration visitArray(ArrayResolvedType arrayTypeDefinition) { + return new ArrayTypeDeclaration(keyValueNode, arrayTypeDefinition); + } + + @Override + public TypeDeclaration visitUnion(UnionResolvedType unionTypeDefinition) { + return new UnionTypeDeclaration(keyValueNode, unionTypeDefinition); + } + + @Override + public TypeDeclaration visitTimeOnly(TimeOnlyResolvedType timeOnlyTypeDefinition) { + return new TimeOnlyTypeDeclaration(keyValueNode, timeOnlyTypeDefinition); + } + + @Override + public TypeDeclaration visitJson(JsonSchemaExternalType jsonTypeDefinition) { + return new JSONTypeDeclaration(keyValueNode, jsonTypeDefinition); + } + + @Override + public TypeDeclaration visitXml(XmlSchemaExternalType xmlTypeDefinition) { + return new XMLTypeDeclaration(keyValueNode, xmlTypeDefinition); + } + + @Override + public TypeDeclaration visitAny(AnyResolvedType anyResolvedType) { + return new AnyTypeDeclaration(keyValueNode, anyResolvedType); + } + + public TypeDeclaration create(ResolvedType resolvedType) { + return resolvedType.visit(this); + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/parameter/Parameter.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/parameter/Parameter.java new file mode 100644 index 0000000..61440db --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/parameter/Parameter.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.parameter; + +import org.xbib.raml.yagi.framework.model.AbstractNodeModel; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class Parameter extends AbstractNodeModel { + public Parameter(KeyValueNode node) { + super(node); + } + + @Override + public Node getNode() { + return node.getValue(); + } + + public String name() { + return ((SimpleTypeNode) node.getKey()).getLiteralValue(); + } + + public String defaultValue() { + Object defaultValue = NodeSelector.selectType("default", getNode(), null); + return defaultValue != null ? defaultValue.toString() : null; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/AnyTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/AnyTypeDeclaration.java new file mode 100755 index 0000000..7a27c6c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/AnyTypeDeclaration.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import org.xbib.raml.internal.impl.v10.type.AnyResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class AnyTypeDeclaration extends TypeDeclaration { + + public AnyTypeDeclaration(KeyValueNode node, AnyResolvedType resolvedType) { + super(node, resolvedType); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/ArrayTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/ArrayTypeDeclaration.java new file mode 100755 index 0000000..aecb583 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/ArrayTypeDeclaration.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import org.xbib.raml.internal.impl.commons.model.factory.TypeDeclarationModelFactory; +import org.xbib.raml.internal.impl.v10.type.ArrayResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +/** + * Binding implementation of {@link org.xbib.raml.api.model.v10.datamodel.ArrayTypeDeclaration} + */ +public class ArrayTypeDeclaration extends TypeDeclaration { + + public ArrayTypeDeclaration(KeyValueNode node, ArrayResolvedType resolvedType) { + super(node, resolvedType); + } + + + public Boolean uniqueItems() { + return getResolvedType().getUniqueItems(); + } + + + public TypeDeclaration items() { + return new TypeDeclarationModelFactory().create(getResolvedType().getItems()); + } + + + public Integer minItems() { + return getResolvedType().getMinItems(); + } + + + public Integer maxItems() { + return getResolvedType().getMaxItems(); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/BooleanTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/BooleanTypeDeclaration.java new file mode 100755 index 0000000..1dc95d5 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/BooleanTypeDeclaration.java @@ -0,0 +1,32 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + + +import java.util.List; +import org.xbib.raml.internal.impl.v10.type.BooleanResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class BooleanTypeDeclaration extends TypeDeclaration { + + public BooleanTypeDeclaration(KeyValueNode node, BooleanResolvedType resolvedType) { + super(node, resolvedType); + } + + public List enumValues() { + return getResolvedType().getEnums(); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/DateTimeOnlyTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/DateTimeOnlyTypeDeclaration.java new file mode 100755 index 0000000..1209133 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/DateTimeOnlyTypeDeclaration.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import org.xbib.raml.internal.impl.v10.type.DateTimeOnlyResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class DateTimeOnlyTypeDeclaration extends TypeDeclaration { + + public DateTimeOnlyTypeDeclaration(KeyValueNode node, DateTimeOnlyResolvedType resolvedType) { + super(node, resolvedType); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/DateTimeTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/DateTimeTypeDeclaration.java new file mode 100755 index 0000000..44b1431 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/DateTimeTypeDeclaration.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import org.xbib.raml.internal.impl.v10.type.DateTimeResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class DateTimeTypeDeclaration extends TypeDeclaration { + + public DateTimeTypeDeclaration(KeyValueNode node, DateTimeResolvedType dateTimeTypeDefinition) { + super(node, dateTimeTypeDefinition); + } + + public String format() { + return getResolvedType().getFormat(); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/DateTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/DateTypeDeclaration.java new file mode 100755 index 0000000..9e24c1e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/DateTypeDeclaration.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import org.xbib.raml.internal.impl.v10.type.DateOnlyResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class DateTypeDeclaration extends TypeDeclaration { + + public DateTypeDeclaration(KeyValueNode node, DateOnlyResolvedType dateOnlyTypeDefinition) { + super(node, dateOnlyTypeDefinition); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/FileTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/FileTypeDeclaration.java new file mode 100755 index 0000000..5153247 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/FileTypeDeclaration.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import java.util.List; +import org.xbib.raml.internal.impl.v10.type.FileResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class FileTypeDeclaration extends TypeDeclaration { + public FileTypeDeclaration(KeyValueNode node, FileResolvedType resolvedType) { + super(node, resolvedType); + } + + public Number minLength() { + return getResolvedType().getMinLength(); + } + + public Number maxLength() { + return getResolvedType().getMaxLength(); + } + + public List fileTypes() { + return getResolvedType().getFileTypes(); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/IntegerTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/IntegerTypeDeclaration.java new file mode 100755 index 0000000..e05fea7 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/IntegerTypeDeclaration.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + + +import org.xbib.raml.internal.impl.v10.type.IntegerResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class IntegerTypeDeclaration extends NumberTypeDeclaration { + + public IntegerTypeDeclaration(KeyValueNode node, IntegerResolvedType resolvedType) { + super(node, resolvedType); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/JSONTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/JSONTypeDeclaration.java new file mode 100755 index 0000000..73df63f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/JSONTypeDeclaration.java @@ -0,0 +1,25 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import org.xbib.raml.internal.impl.commons.type.JsonSchemaExternalType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class JSONTypeDeclaration extends TypeDeclaration { + public JSONTypeDeclaration(KeyValueNode node, JsonSchemaExternalType resolvedType) { + super(node, resolvedType); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/NullTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/NullTypeDeclaration.java new file mode 100755 index 0000000..41b19eb --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/NullTypeDeclaration.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class NullTypeDeclaration extends TypeDeclaration { + + public NullTypeDeclaration(KeyValueNode node, ResolvedType resolvedType) { + super(node, resolvedType); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/NumberTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/NumberTypeDeclaration.java new file mode 100755 index 0000000..382e448 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/NumberTypeDeclaration.java @@ -0,0 +1,53 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import java.util.List; +import org.xbib.raml.internal.impl.v10.type.NumberResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class NumberTypeDeclaration extends TypeDeclaration { + + public NumberTypeDeclaration(KeyValueNode node, NumberResolvedType resolvedType) { + super(node, resolvedType); + } + + + public Double minimum() { + final Number minimum = getResolvedType().getMinimum(); + return minimum != null ? minimum.doubleValue() : null; + } + + public Double maximum() { + final Number maximum = getResolvedType().getMaximum(); + return maximum != null ? maximum.doubleValue() : null; + } + + public List enumValues() { + return getResolvedType().getEnums(); + } + + + public String format() { + return getResolvedType().getFormat(); + } + + + public Double multipleOf() { + final Number multiple = getResolvedType().getMultiple(); + return multiple != null ? multiple.doubleValue() : null; + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/ObjectTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/ObjectTypeDeclaration.java new file mode 100755 index 0000000..9828e2e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/ObjectTypeDeclaration.java @@ -0,0 +1,68 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.xbib.raml.internal.impl.commons.model.factory.TypeDeclarationModelFactory; +import org.xbib.raml.internal.impl.v10.type.ObjectResolvedType; +import org.xbib.raml.internal.impl.v10.type.PropertyFacets; +import org.xbib.raml.internal.utils.ValueUtils; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +/** + * Implementation binding of {@link org.xbib.raml.api.model.v10.datamodel.ObjectTypeDeclaration} + */ +public class ObjectTypeDeclaration extends TypeDeclaration { + + public ObjectTypeDeclaration(KeyValueNode node, ObjectResolvedType objectTypeDefinition) { + super(node, objectTypeDefinition); + } + + + public List properties() { + final List result = new ArrayList<>(); + final Map properties = getResolvedType().getProperties(); + for (PropertyFacets propertyFacets : properties.values()) { + result.add(new TypeDeclarationModelFactory().create(propertyFacets.getValueType())); + } + return result; + } + + + public Integer minProperties() { + return getResolvedType().getMinProperties(); + } + + public Integer maxProperties() { + return getResolvedType().getMaxProperties(); + } + + public Boolean additionalProperties() { + return ValueUtils.asBoolean(getResolvedType().getAdditionalProperties(), true); + } + + + public String discriminator() { + return getResolvedType().getDiscriminator(); + } + + + public String discriminatorValue() { + return getResolvedType().getDiscriminatorValue(); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/StringTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/StringTypeDeclaration.java new file mode 100755 index 0000000..3616e31 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/StringTypeDeclaration.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import java.util.List; +import org.xbib.raml.internal.impl.v10.type.StringResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class StringTypeDeclaration extends TypeDeclaration { + + public StringTypeDeclaration(KeyValueNode node, StringResolvedType resolvedType) { + super(node, resolvedType); + } + + + public String pattern() { + return getResolvedType().getPattern(); + } + + + public List enumValues() { + return getResolvedType().getEnums(); + } + + + public Integer minLength() { + return getResolvedType().getMinLength(); + } + + + public Integer maxLength() { + return getResolvedType().getMaxLength(); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/TimeOnlyTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/TimeOnlyTypeDeclaration.java new file mode 100755 index 0000000..278303c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/TimeOnlyTypeDeclaration.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import org.xbib.raml.internal.impl.v10.type.TimeOnlyResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class TimeOnlyTypeDeclaration extends TypeDeclaration { + + public TimeOnlyTypeDeclaration(KeyValueNode node, TimeOnlyResolvedType timeOnlyTypeDefinition) { + super(node, timeOnlyTypeDefinition); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/TypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/TypeDeclaration.java new file mode 100644 index 0000000..f600399 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/TypeDeclaration.java @@ -0,0 +1,312 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import javax.json.JsonObject; +import org.apache.ws.commons.schema.XmlSchema; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.internal.impl.commons.model.Annotable; +import org.xbib.raml.internal.impl.commons.model.RamlValidationResult; +import org.xbib.raml.internal.impl.commons.model.factory.TypeDeclarationModelFactory; +import org.xbib.raml.internal.impl.commons.nodes.ExternalSchemaTypeExpressionNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.AbstractExternalType; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.commons.type.SchemaBasedResolvedType; +import org.xbib.raml.internal.impl.v10.nodes.NamedTypeExpressionNode; +import org.xbib.raml.internal.impl.v10.nodes.PropertyNode; +import org.xbib.raml.internal.impl.v10.phase.ExampleValidationPhase; +import org.xbib.raml.internal.impl.v10.type.AnyResolvedType; +import org.xbib.raml.internal.impl.v10.type.TypeToJsonSchemaVisitor; +import org.xbib.raml.internal.impl.v10.type.TypeToXmlSchemaVisitor; +import org.xbib.raml.internal.impl.v10.type.XmlFacetsCapableType; +import org.xbib.raml.internal.utils.JSonDumper; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.SYArrayNode; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.SYObjectNode; +import org.xbib.raml.yagi.framework.util.NodeUtils; +import static java.util.Collections.singletonList; +import static org.xbib.raml.internal.impl.commons.RamlVersion.RAML_10; +import static org.xbib.raml.internal.utils.RamlNodeUtils.getVersion; +import static org.xbib.raml.yagi.framework.nodes.DefaultPosition.ARTIFICIAL_NODE; +import static org.xbib.raml.yagi.framework.util.NodeSelector.selectFrom; +import static org.xbib.raml.yagi.framework.util.NodeSelector.selectType; + +public abstract class TypeDeclaration extends Annotable { + + private static final List GLOBAL_NAMED_TYPE_DECLARATION_NODE_NAMES = Arrays.asList("types", "annotationTypes", "baseUriParameters"); + private static final List LOCAL_NAMED_TYPE_DECLARATION_NODE_NAMES = Arrays.asList("headers", "queryParameters", "queryString", "uriParameters"); + + private final T resolvedType; + + public TypeDeclaration(KeyValueNode node, T resolvedType) { + super(node); + this.resolvedType = resolvedType; + } + + public T getResolvedType() { + return resolvedType; + } + + @Override + public Node getNode() { + return node.getValue(); + } + + public String name() { + if (node instanceof PropertyNode) { + return ((PropertyNode) node).getName(); + } + + String keyValue = ((StringNode) node.getKey()).getValue(); + Node parentTypeNode = node.getValue(); + if (node.getParent() instanceof TypeDeclarationNode && parentTypeNode instanceof TypeExpressionNode) { + // getting name of parent type + if (parentTypeNode instanceof ExternalSchemaTypeExpressionNode) { + return null; + } + return ((TypeExpressionNode) parentTypeNode).getTypeExpressionText(); + } + return keyValue; + } + + + public String type() { + Node typeNode = getTypeNode(); + return typeNode != null ? getTypeExpression(typeNode) : null; + } + + private String getTypeExpression(Node typeNode) { + if (typeNode instanceof TypeExpressionNode) { + return ((TypeExpressionNode) typeNode).getTypeExpressionText(); + } + if (typeNode.getSource() instanceof StringNode) { + return ((StringNode) typeNode.getSource()).getValue(); + } + return null; + } + + public List> parentTypes() { + List> result = new ArrayList<>(); + Node typeNode = getTypeNode(); + if (typeNode instanceof ArrayNode) { + List children = typeNode.getChildren(); + for (Node child : children) { + result.add(toTypeDeclaration(((NamedTypeExpressionNode) child).getRefNode())); + } + } else if (typeNode instanceof TypeExpressionNode) { + ResolvedType type = ((TypeExpressionNode) typeNode).generateDefinition(); + if (type != null) { + result.add(toTypeDeclaration(type)); + } + } + + return result; + } + + private TypeDeclaration toTypeDeclaration(ResolvedType type) { + return new TypeDeclarationModelFactory().create(type); + } + + private TypeDeclaration toTypeDeclaration(Node typeNode) { + return new TypeDeclarationModelFactory().create(typeNode); + } + + public String schemaContent() { + if (node.getValue() instanceof TypeDeclarationNode value) { + final List baseTypes = value.getBaseTypes(); + if (!baseTypes.isEmpty()) { + final ResolvedType resolvedType = baseTypes.get(0).generateDefinition(); + if (resolvedType instanceof SchemaBasedResolvedType) { + return ((SchemaBasedResolvedType) resolvedType).getSchemaValue(); + } + } + } + return null; + } + + public List validate(String payload) { + TypeDeclarationNode typeDeclarationNode; + if (getNode() instanceof TypeDeclarationNode) { + typeDeclarationNode = (TypeDeclarationNode) getNode(); + } else { + // if union or array of scalar types, TypeDeclarationNode is not generated + typeDeclarationNode = new TypeDeclarationNode(); + typeDeclarationNode.addChild(new KeyValueNodeImpl(new StringNodeImpl("type"), getResolvedType().getTypeExpressionNode())); + } + + final ResourceLoader resourceLoader = typeDeclarationNode.getStartPosition().createResourceLoader(); + final ExampleValidationPhase exampleValidationPhase = new ExampleValidationPhase(resourceLoader); + final Node validate = exampleValidationPhase.validate(typeDeclarationNode, payload); + if (NodeUtils.isErrorResult(validate)) { + ErrorNode error = validate instanceof ErrorNode ? (ErrorNode) validate : validate.findDescendantsWith(ErrorNode.class).get(0); + return singletonList(new RamlValidationResult(error)); + } else { + return Collections.emptyList(); + } + } + + public Boolean required() { + if (node instanceof PropertyNode) { + return ((PropertyNode) node).isRequired(); + } else { + // in Raml 1.0 parameters are required by default + // in Raml 0.8 parameters are optional by default except for uri parameters + if (getVersion(getNode()) == RAML_10 || isUriParameter(getNode())) { + return selectType("required", getNode(), true); + } + return selectType("required", getNode(), false); + } + } + + private boolean isUriParameter(Node node) { + Node ancestor = selectFrom("../../../../uriParameters", node); + return ancestor != null; + } + + public String defaultValue() { + Node result = selectFrom("default", getNode()); + if (result != null) { + if (result instanceof SimpleTypeNode) + return ((SimpleTypeNode) result).getValue().toString(); + if (result instanceof SYObjectNode || result instanceof SYArrayNode) + return JSonDumper.dump(result); + } + return null; + } + + public String toXmlSchema() { + if (getResolvedType() instanceof SchemaBasedResolvedType || getResolvedType() instanceof AnyResolvedType || getResolvedType() == null) { + return null; + } + final TypeToXmlSchemaVisitor typeToXmlSchemaVisitor = new TypeToXmlSchemaVisitor(); + typeToXmlSchemaVisitor.transform(rootElementName(), getResolvedType()); + final XmlSchema schema = typeToXmlSchemaVisitor.getSchema(); + final StringWriter writer = new StringWriter(); + schema.write(writer); + return writer.toString(); + } + + public String toJsonSchema() { + if (getResolvedType() instanceof SchemaBasedResolvedType || getResolvedType() instanceof AnyResolvedType || getResolvedType() == null) { + return null; + } + + final TypeToJsonSchemaVisitor typeToJsonSchemaVisitor = new TypeToJsonSchemaVisitor(); + JsonObject jsonSchema = typeToJsonSchemaVisitor.transform(this.getResolvedType()); + + return jsonSchema.toString(); + } + + public String rootElementName() { + if (resolvedType instanceof XmlFacetsCapableType) { + // an XML name facet overrides any other possibility for the root XML element + String xmlName = ((XmlFacetsCapableType) resolvedType).getXmlFacets().getName(); + if (xmlName != null) { + return xmlName; + } + } + + if (!(node instanceof PropertyNode) && !isGlobalNamedTypeDeclarationNode() && !isLocalNamedTypeDeclarationNode()) { + // type reference + final Node value = node.getValue(); + if (value.get("properties") != null || value.get("facets") != null || !(getTypeNode() instanceof NamedTypeExpressionNode)) { + // type is extending somehow supertype or inline declaration + return "root"; + } else { + // type is just referencing an existing one + return ((NamedTypeExpressionNode) getTypeNode()).getRefName(); + } + } else { + // type declaration + return name(); + } + } + + public String internalFragment() { + ResolvedType resolvedType = getResolvedType(); + if (resolvedType instanceof AbstractExternalType) { + return ((AbstractExternalType) resolvedType).getInternalFragment(); + } else { + return null; + } + } + + public String schemaPath() { + ResolvedType resolvedType = getResolvedType(); + if (resolvedType instanceof AbstractExternalType) { + if (!((AbstractExternalType) resolvedType).getSchemaPath().equalsIgnoreCase(ARTIFICIAL_NODE)) { + return ((AbstractExternalType) resolvedType).getSchemaPath(); + } + return null; + } else { + return null; + } + } + + + private Node getTypeNode() { + final Node value = node.getValue(); + final Node type = value.get("type"); + if (type != null) { + return type; + } else { + return value.get("schema"); + } + } + + /** + * True if the node is a global named type declaration as opposed to an inline/anonymous declaration. This is computed based on the parent of the current type declaration node, i.e. + * if its parent is one of the global named type declaration nodes possible. + * + * @return true if the node is a global named type declaration as opposed to an inline/anonymous declaration, false otherwise + */ + private boolean isGlobalNamedTypeDeclarationNode() { + final Node parent = node.getParent(); + final Node rootNode = NodeUtils.getContextNode(node); + return GLOBAL_NAMED_TYPE_DECLARATION_NODE_NAMES.stream() + .anyMatch(name -> parent == rootNode.get(name)); + } + + /** + * True if the node is a local named type declaration as opposed to an inline/anonymous declaration. This is computed based on the parent of the current type declaration node, i.e. + * if its parent is one of the local named type declaration nodes possible. + * + * @return true if the node is a local named type declaration as opposed to an inline/anonymous declaration, false otherwise + */ + private boolean isLocalNamedTypeDeclarationNode() { + final Node parent = node.getParent(); + // tries to get the grandparent of the current node to retrieve the same node based on the known local named declaration node names + final Node baseNode = parent.getParent().getParent(); + + return baseNode != null && + LOCAL_NAMED_TYPE_DECLARATION_NODE_NAMES.stream() + .anyMatch(name -> parent == baseNode.get(name)); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/UnionTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/UnionTypeDeclaration.java new file mode 100755 index 0000000..6d077ae --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/UnionTypeDeclaration.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.model.factory.TypeDeclarationModelFactory; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.type.UnionResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class UnionTypeDeclaration extends TypeDeclaration { + + public UnionTypeDeclaration(KeyValueNode node, UnionResolvedType unionTypeDefinition) { + super(node, unionTypeDefinition); + } + + public List of() { + final List result = new ArrayList<>(); + final UnionResolvedType resolvedType = getResolvedType(); + final List of = resolvedType.of(); + for (ResolvedType type : of) { + result.add(new TypeDeclarationModelFactory().create(type)); + } + return result; + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/XMLTypeDeclaration.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/XMLTypeDeclaration.java new file mode 100755 index 0000000..bc64e15 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/model/type/XMLTypeDeclaration.java @@ -0,0 +1,25 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.model.type; + +import org.xbib.raml.internal.impl.commons.type.XmlSchemaExternalType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; + +public class XMLTypeDeclaration extends TypeDeclaration { + public XMLTypeDeclaration(KeyValueNode node, XmlSchemaExternalType resolvedType) { + super(node, resolvedType); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AbstractReferenceNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AbstractReferenceNode.java new file mode 100644 index 0000000..0d6f82d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AbstractReferenceNode.java @@ -0,0 +1,116 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.xbib.raml.internal.impl.v10.nodes.LibraryRefNode; +import org.xbib.raml.yagi.framework.nodes.AbstractRamlNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.util.NodeUtils; + +public abstract class AbstractReferenceNode extends AbstractRamlNode implements ReferenceNode { + + private Node refNode; + private Node contextNode; + + public AbstractReferenceNode() { + } + + public AbstractReferenceNode(AbstractReferenceNode node) { + super(node); + this.refNode = node.refNode; + this.contextNode = node.contextNode; + } + + + @Override + public final Node getRefNode() { + if (refNode == null) { + refNode = resolveReference(); + } + return refNode; + } + + + public abstract Node resolveReference(); + + /** + * @return the context node closest to the reference usage + */ + private Node getRelativeNode() { + if (!getChildren().isEmpty() && getChildren().get(0) instanceof ReferenceNode) { + return ((ReferenceNode) getChildren().get(0)).getRefNode(); + } else { + return NodeUtils.getContextNode(this); + } + } + + /** + * If the contextNode is set, returns a list of two context nodes + * using the relative node as a fallback context + */ + protected List getContextNodes() { + List contextNodes = new ArrayList<>(); + contextNodes.add(getRelativeNode()); + if (contextNode != null && contextNode != contextNodes.get(0)) { + contextNodes.add(0, contextNode); + } + return contextNodes; + } + + @Override + public NodeType getType() { + return NodeType.Reference; + } + + public Map getParameters() { + Map params = new HashMap<>(); + + Node parametersNode = getParametersNode(); + if (parametersNode != null) { + for (Node node : parametersNode.getChildren()) { + KeyValueNode keyValueNode = (KeyValueNode) node; + String paramName = ((SimpleTypeNode) keyValueNode.getKey()).getLiteralValue(); + Node value = keyValueNode.getValue(); + params.put(paramName, value.copy()); + + } + } + return params; + } + + public Node getParametersNode() { + List children = getChildren(); + if (children.size() == 1 && children.get(0) instanceof KeyValueNode) { + return ((KeyValueNode) children.get(0)).getValue(); + } + if (children.size() == 2 && children.get(0) instanceof LibraryRefNode) { + return ((KeyValueNode) children.get(1)).getValue(); + } + return null; + } + + public void setContextNode(Node contextNode) { + this.contextNode = contextNode; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AnnotationNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AnnotationNode.java new file mode 100644 index 0000000..05df2bd --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AnnotationNode.java @@ -0,0 +1,108 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.api.model.v10.declarations.AnnotationTarget; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +/** + * An annotation usage + */ +public class AnnotationNode extends KeyValueNodeImpl implements OverlayableNode { + + public AnnotationNode() { + } + + public AnnotationNode(AnnotationNode node) { + super(node); + } + + public String getName() { + return getKey().getRefName(); + } + + + public AnnotationTypeNode getAnnotationTypeNode() { + AnnotationReferenceNode key = getKey(); + return (AnnotationTypeNode) key.getRefNode(); + } + + + @Override + public Node copy() { + return new AnnotationNode(this); + } + + @Override + public AnnotationReferenceNode getKey() { + AnnotationReferenceNode node = null; + if (super.getKey() instanceof AnnotationReferenceNode) { + node = (AnnotationReferenceNode) super.getKey(); + } + return node; + } + + public AnnotationTarget getTarget() { + Node parent = getParent(); + Node grampa = parent != null ? parent.getParent() : null; + if (parent instanceof RamlDocumentNode) { + return AnnotationTarget.API; + } + if (parent instanceof DocumentationItemNode) { + return AnnotationTarget.DocumentationItem; + } + if (grampa instanceof ResourceNode) { + return AnnotationTarget.Resource; + } + if (grampa instanceof MethodNode) { + return AnnotationTarget.Method; + } + if (grampa instanceof BodyNode) { + if (grampa.findAncestorWith(ResponseNode.class) != null) { + return AnnotationTarget.ResponseBody; + } + return AnnotationTarget.RequestBody; + } + if (parent instanceof TypeDeclarationNode) { + return AnnotationTarget.TypeDeclaration; + } + if (grampa instanceof ResponseNode) { + return AnnotationTarget.Response; + } + if (grampa instanceof SecuritySchemeNode) { + return AnnotationTarget.SecurityScheme; + } + if (isSecuritySchemeSettings(grampa)) { + return AnnotationTarget.SecuritySchemeSettings; + } + return null; + } + + private boolean isSecuritySchemeSettings(Node grampa) { + boolean result = false; + if (grampa instanceof KeyValueNode) { + Node key = ((KeyValueNode) grampa).getKey(); + if (key instanceof StringNode && "settings".equals(((StringNode) key).getValue())) { + result = grampa.findAncestorWith(SecuritySchemeNode.class) != null; + } + } + return result; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AnnotationReferenceNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AnnotationReferenceNode.java new file mode 100644 index 0000000..53d75d0 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AnnotationReferenceNode.java @@ -0,0 +1,78 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class AnnotationReferenceNode extends AbstractReferenceNode implements StringNode { + + public AnnotationReferenceNode() { + } + + public AnnotationReferenceNode(AnnotationReferenceNode node) { + super(node); + } + + @Override + public String getRefName() { + String value = getValue(); + int from = value.lastIndexOf(".") + 1; + if (from == 0) { + from = 1; + } + return value.substring(from, value.length() - 1); + } + + + @Override + public AnnotationTypeNode resolveReference() { + for (Node contextNode : getContextNodes()) { + final Node resolve = NodeSelector.selectFrom(Raml10Grammar.ANNOTATION_TYPES_KEY_NAME + "/*/" + getRefName() + "/..", contextNode); + if (resolve instanceof AnnotationTypeNode) { + return (AnnotationTypeNode) resolve; + } + if (resolve != null) { + return null; + } + } + return null; + } + + + @Override + public Node copy() { + return new AnnotationReferenceNode(this); + } + + @Override + public String getValue() { + return ((StringNode) getSource()).getValue(); + } + + @Override + public String getLiteralValue() { + return getValue(); + } + + @Override + public String toString() { + return getValue(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AnnotationTypeNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AnnotationTypeNode.java new file mode 100644 index 0000000..0f835f8 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AnnotationTypeNode.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.api.model.v10.declarations.AnnotationTarget; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.NamedNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class AnnotationTypeNode extends KeyValueNodeImpl implements NamedNode { + + public AnnotationTypeNode() { + } + + public AnnotationTypeNode(AnnotationTypeNode node) { + super(node); + } + + public String getName() { + final StringNode key = (StringNode) getKey(); + return key.getValue(); + } + + public TypeDeclarationNode getDeclaredType() { + return (TypeDeclarationNode) getValue(); + } + + + @Override + public Node copy() { + return new AnnotationTypeNode(this); + } + + public List getAllowedTargets() { + List targets = new ArrayList<>(); + List allowedTargets = NodeSelector.selectStringCollection("allowedTargets", getValue()); + for (String allowedTarget : allowedTargets) { + targets.add(AnnotationTarget.valueOf(allowedTarget)); + } + return targets; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AnnotationTypesNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AnnotationTypesNode.java new file mode 100644 index 0000000..b0962b9 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/AnnotationTypesNode.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; + + +public class AnnotationTypesNode extends KeyValueNodeImpl implements OverlayableNode { + + public AnnotationTypesNode() { + } + + public AnnotationTypesNode(Node keyNode, Node valueNode) { + super(keyNode, valueNode); + } + + public AnnotationTypesNode(AnnotationTypesNode node) { + super(node); + } + + + @Override + public Node copy() { + return new AnnotationTypesNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/BaseResourceTypeRefNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/BaseResourceTypeRefNode.java new file mode 100644 index 0000000..e05c09b --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/BaseResourceTypeRefNode.java @@ -0,0 +1,63 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class BaseResourceTypeRefNode extends AbstractReferenceNode { + + private final String name; + + public BaseResourceTypeRefNode(String name) { + this.name = name; + } + + public BaseResourceTypeRefNode(BaseResourceTypeRefNode node) { + super(node); + this.name = node.name; + } + + @Override + public String getRefName() { + return name; + } + + @Override + + public ResourceTypeNode resolveReference() { + for (Node contextNode : getContextNodes()) { + // We add the .. as the node selector selects the value and we want the key value pair + final Node resolve = NodeSelector.selectFrom(Raml10Grammar.RESOURCE_TYPES_KEY_NAME + "/*/" + getRefName() + "/..", contextNode); + if (resolve instanceof ResourceTypeNode) { + return (ResourceTypeNode) resolve; + } + if (resolve != null) { + return null; + } + } + return null; + } + + + @Override + public Node copy() { + return new BaseResourceTypeRefNode(this); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/BaseSecuritySchemeRefNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/BaseSecuritySchemeRefNode.java new file mode 100644 index 0000000..62b7d2d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/BaseSecuritySchemeRefNode.java @@ -0,0 +1,61 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class BaseSecuritySchemeRefNode extends AbstractReferenceNode { + private final String name; + + public BaseSecuritySchemeRefNode(String name) { + this.name = name; + } + + // copy constructor + protected BaseSecuritySchemeRefNode(BaseSecuritySchemeRefNode node) { + super(node); + this.name = node.name; + } + + @Override + public String getRefName() { + return name; + } + + @Override + public SecuritySchemeNode resolveReference() { + for (Node contextNode : getContextNodes()) { + // We add the .. as the node selector selects the value and we want the key value pair + final Node resolve = NodeSelector.selectFrom(Raml10Grammar.SECURITY_SCHEMES_KEY_NAME + "/*/" + getRefName() + "/..", contextNode); + if (resolve instanceof SecuritySchemeNode) { + return (SecuritySchemeNode) resolve; + } + if (resolve != null) { + return null; + } + } + return null; + } + + + @Override + public Node copy() { + return new BaseSecuritySchemeRefNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/BaseTraitRefNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/BaseTraitRefNode.java new file mode 100644 index 0000000..4299023 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/BaseTraitRefNode.java @@ -0,0 +1,61 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class BaseTraitRefNode extends AbstractReferenceNode { + + private final String name; + + public BaseTraitRefNode(String name) { + this.name = name; + } + + public BaseTraitRefNode(BaseTraitRefNode node) { + super(node); + this.name = node.name; + } + + @Override + public String getRefName() { + return name; + } + + @Override + public TraitNode resolveReference() { + for (Node contextNode : getContextNodes()) { + // We add the .. as the node selector selects the value and we want the key value pair + final Node resolve = NodeSelector.selectFrom(Raml10Grammar.TRAITS_KEY_NAME + "/*/" + getRefName() + "/..", contextNode); + if (resolve instanceof TraitNode) { + return (TraitNode) resolve; + } + if (resolve != null) { + return null; + } + } + return null; + } + + + @Override + public Node copy() { + return new BaseTraitRefNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/BodyNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/BodyNode.java new file mode 100644 index 0000000..3772af4 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/BodyNode.java @@ -0,0 +1,32 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; + +public class BodyNode extends KeyValueNodeImpl { + public BodyNode() { + } + + BodyNode(BodyNode node) { + super(node); + } + + @Override + public BodyNode copy() { + return new BodyNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ContextAwareNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ContextAwareNode.java new file mode 100644 index 0000000..96699f5 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ContextAwareNode.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import org.xbib.raml.yagi.framework.nodes.Node; + + +/** + * Interface used for resource types and traits parameters to allow + * the propagation of the context where the parameters were assigned + */ +public interface ContextAwareNode { + + Node getReferenceContext(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ContextAwareStringNodeImpl.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ContextAwareStringNodeImpl.java new file mode 100644 index 0000000..5c361cb --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ContextAwareStringNodeImpl.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; + + +public class ContextAwareStringNodeImpl extends StringNodeImpl implements ContextAwareNode { + + private final Node referenceContext; + + public ContextAwareStringNodeImpl(String value, Node referenceContext) { + super(value); + this.referenceContext = referenceContext; + } + + protected ContextAwareStringNodeImpl(ContextAwareStringNodeImpl node) { + super(node); + this.referenceContext = node.referenceContext; + } + + @Override + public Node getReferenceContext() { + return referenceContext; + } + + + @Override + public Node copy() { + return new ContextAwareStringNodeImpl(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/CustomFacetDefinitionNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/CustomFacetDefinitionNode.java new file mode 100644 index 0000000..7d18a51 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/CustomFacetDefinitionNode.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import org.xbib.raml.internal.impl.v10.nodes.PropertyNode; +import org.xbib.raml.internal.impl.v10.type.TypeToRuleVisitor; +import org.xbib.raml.yagi.framework.grammar.rule.KeyValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.grammar.rule.StringValueRule; + +public class CustomFacetDefinitionNode extends PropertyNode { + public CustomFacetDefinitionNode() { + } + + CustomFacetDefinitionNode(CustomFacetDefinitionNode node) { + super(node); + } + + public TypeDeclarationNode getFacetType() { + return (TypeDeclarationNode) getValue(); + } + + public String getFacetName() { + return PropertyUtils.getName(this); + } + + public boolean isRequired() { + return PropertyUtils.isRequired(this); + } + + public KeyValueRule getFacetRule() { + final TypeToRuleVisitor typeToRuleVisitor = new TypeToRuleVisitor(getStartPosition().createResourceLoader()); + final Rule value = getFacetType().getResolvedType().visit(typeToRuleVisitor); + return new KeyValueRule(new StringValueRule(getFacetName()), value); + } + + @Override + public CustomFacetDefinitionNode copy() { + return new CustomFacetDefinitionNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/DefaultRamlTypedFragment.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/DefaultRamlTypedFragment.java new file mode 100644 index 0000000..e4af5ac --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/DefaultRamlTypedFragment.java @@ -0,0 +1,72 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.api.model.v10.RamlFragment; +import org.xbib.raml.internal.impl.commons.phase.RamlTypedFragment; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.yagi.framework.nodes.AbstractObjectNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class DefaultRamlTypedFragment extends AbstractObjectNode implements RamlTypedFragment { + + private final RamlFragment fragment; + private Node libraryNode; + + public DefaultRamlTypedFragment(RamlFragment fragment) { + this.fragment = fragment; + } + + protected DefaultRamlTypedFragment(DefaultRamlTypedFragment node) { + super(node); + this.fragment = node.getFragment(); + this.libraryNode = node.getLibraryNode(); + } + + + @Override + public Node copy() { + return new DefaultRamlTypedFragment(this); + } + + + @Override + public Node getContextNode() { + return getLibraryNode() != null || getParent() == null ? this : org.xbib.raml.yagi.framework.util.NodeUtils.getContextNode(getParent()); + } + + @Override + public Node getLibraryNode() { + return libraryNode; + } + + public void resolveLibraryReference() { + if (libraryNode == null) { + libraryNode = NodeSelector.selectFrom(Raml10Grammar.USES_KEY_NAME, this); + if (libraryNode != null) { + // The parent is the key value pair + final Node parent = libraryNode.getParent(); + removeChild(parent); + } + } + } + + public RamlFragment getFragment() { + return fragment; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/DocumentationItemNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/DocumentationItemNode.java new file mode 100644 index 0000000..da5d77b --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/DocumentationItemNode.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNodeImpl; + +public class DocumentationItemNode extends ObjectNodeImpl { + + public DocumentationItemNode() { + } + + public DocumentationItemNode(DocumentationItemNode node) { + super(node); + } + + + @Override + public Node copy() { + return new DocumentationItemNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ExampleDeclarationNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ExampleDeclarationNode.java new file mode 100644 index 0000000..3fb8bbd --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ExampleDeclarationNode.java @@ -0,0 +1,74 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class ExampleDeclarationNode extends KeyValueNodeImpl implements OverlayableNode { + public ExampleDeclarationNode() { + } + + private ExampleDeclarationNode(KeyValueNodeImpl node) { + super(node); + } + + + @Override + public Node copy() { + return new ExampleDeclarationNode(this); + } + + public Node getExampleValue() { + if (isExplicitExample()) { + return NodeSelector.selectFrom("value", getValue()); + } else { + return getValue(); + } + } + + public String getName() { + final Node ancestor = org.xbib.raml.yagi.framework.util.NodeUtils.getAncestor(this, 2); + if (ancestor instanceof KeyValueNode && ((KeyValueNode) ancestor).getKey().toString().equals("examples")) { + return getKey().toString(); + } else { + return null; + } + } + + public boolean isExplicitExample() { + if (getValue() instanceof ObjectNode) { + final Node value = NodeSelector.selectFrom("value", getValue()); + return value != null; + } + return false; + } + + + public Boolean isStrict() { + if (isExplicitExample()) { + final Boolean strict = NodeSelector.selectBooleanValue("strict", getValue()); + return strict != null ? strict : true; + } else { + return true; + } + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ExamplesNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ExamplesNode.java new file mode 100644 index 0000000..8f1a002 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ExamplesNode.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; + + +public class ExamplesNode extends KeyValueNodeImpl implements OverlayableNode { + + public ExamplesNode() { + } + + public ExamplesNode(Node keyNode, Node valueNode) { + super(keyNode, valueNode); + } + + public ExamplesNode(ExamplesNode node) { + super(node); + } + + + @Override + public Node copy() { + return new ExamplesNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ExtendsNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ExtendsNode.java new file mode 100644 index 0000000..0c85256 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ExtendsNode.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; + +public class ExtendsNode extends KeyValueNodeImpl { + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ExternalSchemaTypeExpressionNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ExternalSchemaTypeExpressionNode.java new file mode 100644 index 0000000..2ff1ce5 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ExternalSchemaTypeExpressionNode.java @@ -0,0 +1,89 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.internal.impl.commons.type.JsonSchemaExternalType; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.commons.type.XmlSchemaExternalType; +import org.xbib.raml.internal.utils.SchemaGenerator; +import org.xbib.raml.yagi.framework.nodes.AbstractStringNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.SYIncludeNode; + +public class ExternalSchemaTypeExpressionNode extends AbstractStringNode implements TypeExpressionNode, SimpleTypeNode { + public ExternalSchemaTypeExpressionNode(String value) { + super(value); + } + + private ExternalSchemaTypeExpressionNode(ExternalSchemaTypeExpressionNode node) { + super(node); + } + + public String getSchemaValue() { + return getValue(); + } + + public String getSchemaPath() { + if (!getStartPosition().getIncludedResourceUri().isBlank()) { + return this.getStartPosition().getIncludedResourceUri(); + } + return this.getStartPosition().getPath(); + } + + + public String getInternalFragment() { + final Node source = org.xbib.raml.yagi.framework.util.NodeUtils.getSource(this, SYIncludeNode.class); + if (source != null) { + final String value = ((SYIncludeNode) source).getValue(); + if (value.contains("#")) { + return value.substring(value.indexOf("#") + 1); + } + } + return null; + } + + + @Override + public Node copy() { + return new ExternalSchemaTypeExpressionNode(this); + } + + public boolean isJsonSchema() { + return SchemaGenerator.isJsonSchema(getSchemaValue()); + } + + public boolean isXmlSchema() { + return SchemaGenerator.isXmlSchema(getSchemaValue()); + } + + + @Override + public ResolvedType generateDefinition() { + if (isXmlSchema()) { + return new XmlSchemaExternalType(this, getSchemaValue(), getSchemaPath(), getInternalFragment()); + } else { + return new JsonSchemaExternalType(this, getSchemaValue(), getSchemaPath(), getInternalFragment()); + } + + } + + @Override + public String getTypeExpressionText() { + return getValue(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/FacetNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/FacetNode.java new file mode 100644 index 0000000..717e441 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/FacetNode.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +public class FacetNode extends KeyValueNodeImpl { + public FacetNode() { + } + + FacetNode(FacetNode node) { + super(node); + } + + public String getName() { + if (getKey() instanceof SimpleTypeNode) { + return ((SimpleTypeNode) getKey()).getLiteralValue(); + } + throw new IllegalStateException("Invalid facet key node type: " + getKey().getClass().getSimpleName()); + } + + @Override + public FacetNode copy() { + return new FacetNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/LibraryNodeProvider.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/LibraryNodeProvider.java new file mode 100644 index 0000000..f46d139 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/LibraryNodeProvider.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import org.xbib.raml.yagi.framework.nodes.Node; + +/** + * Provides a custom way to generateDefinition the node where the libraries are defined + */ +public interface LibraryNodeProvider { + /** + * The libraries node + * + * @return The libraries node + */ + Node getLibraryNode(); + + /** + * Method invoke for this node to generateDefinition the reference + */ + void resolveLibraryReference(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/MethodNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/MethodNode.java new file mode 100644 index 0000000..ac7fe93 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/MethodNode.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +public class MethodNode extends KeyValueNodeImpl { + + public MethodNode() { + } + + public MethodNode(MethodNode node) { + super(node); + } + + public String getName() { + Node key = getKey(); + if (key instanceof StringNode) { + return ((StringNode) key).getValue(); + } else { + throw new IllegalStateException("Key must be a string but was a " + key.getClass()); + } + } + + + @Override + public Node copy() { + return new MethodNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/OverlayableNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/OverlayableNode.java new file mode 100644 index 0000000..f785492 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/OverlayableNode.java @@ -0,0 +1,23 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +/** + * Marker interface for nodes that can be overridden by an Overlay + */ +public interface OverlayableNode { + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/OverlayableObjectNodeImpl.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/OverlayableObjectNodeImpl.java new file mode 100644 index 0000000..fef8af6 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/OverlayableObjectNodeImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.AbstractObjectNode; +import org.xbib.raml.yagi.framework.nodes.AbstractRamlNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class OverlayableObjectNodeImpl extends AbstractObjectNode implements OverlayableNode { + + public OverlayableObjectNodeImpl() { + } + + public OverlayableObjectNodeImpl(AbstractRamlNode node) { + super(node); + } + + + @Override + public Node copy() { + return new OverlayableObjectNodeImpl(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/OverlayableStringNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/OverlayableStringNode.java new file mode 100644 index 0000000..c3e2ab1 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/OverlayableStringNode.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.AbstractStringNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class OverlayableStringNode extends AbstractStringNode implements OverlayableNode { + + public OverlayableStringNode(String value) { + super(value); + } + + protected OverlayableStringNode(AbstractStringNode node) { + super(node); + } + + + @Override + public Node copy() { + return new OverlayableStringNode(this); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/OverridableNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/OverridableNode.java new file mode 100644 index 0000000..03e3024 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/OverridableNode.java @@ -0,0 +1,23 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +/** + * Marker interface for scalar nodes that can be overridden by a trait or resource type + */ +public interface OverridableNode { + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ParametrizedReferenceNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ParametrizedReferenceNode.java new file mode 100644 index 0000000..b6530d2 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ParametrizedReferenceNode.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import java.util.Map; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; + +public interface ParametrizedReferenceNode extends ReferenceNode, ObjectNode { + + Map getParameters(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ParametrizedResourceTypeRefNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ParametrizedResourceTypeRefNode.java new file mode 100644 index 0000000..7c25e34 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ParametrizedResourceTypeRefNode.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.Node; + +public class ParametrizedResourceTypeRefNode extends BaseResourceTypeRefNode implements ParametrizedReferenceNode { + + public ParametrizedResourceTypeRefNode(ParametrizedResourceTypeRefNode node) { + super(node); + } + + // Used by reflection + public ParametrizedResourceTypeRefNode(String name) { + super(name); + } + + + @Override + public Node copy() { + return new ParametrizedResourceTypeRefNode(this); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ParametrizedSecuritySchemeRefNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ParametrizedSecuritySchemeRefNode.java new file mode 100644 index 0000000..1f55365 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ParametrizedSecuritySchemeRefNode.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.Node; + +public class ParametrizedSecuritySchemeRefNode extends BaseSecuritySchemeRefNode implements ParametrizedReferenceNode { + + public ParametrizedSecuritySchemeRefNode(ParametrizedSecuritySchemeRefNode node) { + super(node); + } + + // Used by reflection + public ParametrizedSecuritySchemeRefNode(String name) { + super(name); + } + + + @Override + public Node copy() { + return new ParametrizedSecuritySchemeRefNode(this); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ParametrizedTraitRefNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ParametrizedTraitRefNode.java new file mode 100644 index 0000000..7718dc0 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ParametrizedTraitRefNode.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.Node; + +public class ParametrizedTraitRefNode extends BaseTraitRefNode implements ParametrizedReferenceNode { + + public ParametrizedTraitRefNode(ParametrizedTraitRefNode node) { + super(node); + } + + // Used by reflection + public ParametrizedTraitRefNode(String name) { + super(name); + } + + + @Override + public Node copy() { + return new ParametrizedTraitRefNode(this); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/PropertyUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/PropertyUtils.java new file mode 100644 index 0000000..e1f416e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/PropertyUtils.java @@ -0,0 +1,53 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import org.xbib.raml.yagi.framework.nodes.BooleanNode; +import org.xbib.raml.yagi.framework.nodes.IntegerNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +public class PropertyUtils { + public static String getName(KeyValueNode node) { + final String keyValue = getValueAsString(node); + if (getRequiredNode(node) == null) { + // If required field is set then the ? should be ignored + return keyValue.endsWith("?") ? keyValue.substring(0, keyValue.length() - 1) : keyValue; + } else { + return keyValue; + } + } + + private static String getValueAsString(KeyValueNode node) { + final String keyValue; + if (node.getKey() instanceof IntegerNode) { + keyValue = String.valueOf(((IntegerNode) node.getKey()).getValue()); + } else { + StringNode key = (StringNode) node.getKey(); + keyValue = key.getValue(); + } + return keyValue; + } + + private static Node getRequiredNode(KeyValueNode node) { + return node.getValue().get("required"); + } + + public static boolean isRequired(KeyValueNode node) { + return getRequiredNode(node) instanceof BooleanNode ? ((BooleanNode) getRequiredNode(node)).getValue() : !getValueAsString(node).endsWith("?"); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/RamlDocumentNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/RamlDocumentNode.java new file mode 100644 index 0000000..ee56ee5 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/RamlDocumentNode.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.AbstractObjectNode; +import org.xbib.raml.yagi.framework.nodes.ContextProviderNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class RamlDocumentNode extends AbstractObjectNode implements ContextProviderNode { + public RamlDocumentNode() { + } + + protected RamlDocumentNode(RamlDocumentNode node) { + super(node); + } + + + @Override + public Node copy() { + return new RamlDocumentNode(this); + } + + + @Override + public Node getContextNode() { + return this; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/RamlVersionAnnotation.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/RamlVersionAnnotation.java new file mode 100644 index 0000000..2d14f4c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/RamlVersionAnnotation.java @@ -0,0 +1,32 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import org.xbib.raml.internal.impl.commons.RamlVersion; +import org.xbib.raml.yagi.framework.nodes.NodeAnnotation; + + +public class RamlVersionAnnotation implements NodeAnnotation { + private final RamlVersion version; + + public RamlVersionAnnotation(RamlVersion version) { + this.version = version; + } + + public RamlVersion getVersion() { + return version; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ResourceNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ResourceNode.java new file mode 100644 index 0000000..729f2ad --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ResourceNode.java @@ -0,0 +1,80 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +public class ResourceNode extends KeyValueNodeImpl { + + public ResourceNode() { + } + + public ResourceNode(ResourceNode node) { + super(node); + } + + public String getRelativeUri() { + Node key = getKey(); + if (key instanceof StringNode) { + return ((StringNode) key).getValue(); + } else { + throw new IllegalStateException("Key must be a string but was a " + key.getClass()); + } + } + + public String getResourcePath() { + String path = getRelativeUri(); + ResourceNode parent = getParentResourceNode(); + if (parent != null) { + path = parent.getResourcePath() + path; + } + return path; + } + + public ResourceNode getParentResourceNode() { + Node parent = getParent(); + if (parent != null && parent.getParent() instanceof ResourceNode) { + return (ResourceNode) parent.getParent(); + } + return null; + } + + public String getResourcePathName() { + String fullPath = getRelativeUri().substring(1); // remove leading slash + String[] path = fullPath.split("/"); + + for (int i = path.length - 1; i >= 0; i--) { + if (!path[i].contains("{")) { + return path[i]; + } + } + + ResourceNode parent = getParentResourceNode(); + if (parent == null) { + return ""; + } + return parent.getResourcePathName(); + } + + + @Override + public Node copy() { + return new ResourceNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ResourceTypeNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ResourceTypeNode.java new file mode 100644 index 0000000..7231bf3 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ResourceTypeNode.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.NamedNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +public class ResourceTypeNode extends KeyValueNodeImpl implements NamedNode { + + public ResourceTypeNode() { + } + + public ResourceTypeNode(ResourceTypeNode node) { + super(node); + } + + public String getName() { + final StringNode key = (StringNode) getKey(); + return key.getValue(); + } + + + @Override + public ResourceTypeNode copy() { + return new ResourceTypeNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ResourceTypeRefNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ResourceTypeRefNode.java new file mode 100644 index 0000000..4ae6484 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ResourceTypeRefNode.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +public class ResourceTypeRefNode extends BaseResourceTypeRefNode implements StringNode { + + public ResourceTypeRefNode(String name) { + super(name); + } + + public ResourceTypeRefNode(ResourceTypeRefNode node) { + super(node); + } + + + @Override + public Node copy() { + return new ResourceTypeRefNode(this); + } + + @Override + public String getValue() { + return getRefName(); + } + + @Override + public String getLiteralValue() { + return getValue(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ResponseNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ResponseNode.java new file mode 100644 index 0000000..a81f595 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/ResponseNode.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class ResponseNode extends KeyValueNodeImpl { + + public ResponseNode() { + } + + public ResponseNode(ResponseNode node) { + super(node); + } + + + @Override + public Node copy() { + return new ResponseNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/SecuritySchemeNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/SecuritySchemeNode.java new file mode 100644 index 0000000..8d0611e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/SecuritySchemeNode.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.NamedNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +public class SecuritySchemeNode extends KeyValueNodeImpl implements NamedNode { + + public SecuritySchemeNode() { + } + + public SecuritySchemeNode(SecuritySchemeNode node) { + super(node); + } + + public String getName() { + final StringNode key = (StringNode) getKey(); + return key.getValue(); + } + + + @Override + public Node copy() { + return new SecuritySchemeNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/SecuritySchemeRefNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/SecuritySchemeRefNode.java new file mode 100644 index 0000000..8925c79 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/SecuritySchemeRefNode.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.Node; + +public class SecuritySchemeRefNode extends BaseSecuritySchemeRefNode { + public SecuritySchemeRefNode(String name) { + super(name); + } + + // copy constructor + protected SecuritySchemeRefNode(SecuritySchemeRefNode node) { + super(node); + } + + + @Override + public Node copy() { + return new SecuritySchemeRefNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/StringTemplateNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/StringTemplateNode.java new file mode 100644 index 0000000..0d049de --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/StringTemplateNode.java @@ -0,0 +1,101 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.AbstractStringNode; +import org.xbib.raml.yagi.framework.nodes.ExecutableNode; +import org.xbib.raml.yagi.framework.nodes.ExecutionContext; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +public class StringTemplateNode extends AbstractStringNode implements ExecutableNode { + + public StringTemplateNode(String value) { + super(value); + } + + public StringTemplateNode(StringTemplateNode node) { + super(node); + } + + @Override + public void addChild(Node node) { + if (!(node instanceof StringNode)) { + throw new IllegalArgumentException("Only String nodes are valid as children"); + } + super.addChild(node); + } + + public Node execute(ExecutionContext context) { + final List executedNodes = executeNodes(context, getChildren()); + return resolveTemplate(context, executedNodes); + } + + private Node resolveTemplate(ExecutionContext context, List executedNodes) { + if (executedNodes.size() == 1 && !(executedNodes.get(0) instanceof StringNode)) { + return executedNodes.get(0); + } else { + final StringBuilder content = new StringBuilder(); + Node referenceContext = null; + for (Node executedNode : executedNodes) { + if (executedNode instanceof SimpleTypeNode) { + content.append(((SimpleTypeNode) executedNode).getLiteralValue()); + if (referenceContext == null && executedNode instanceof ContextAwareStringNodeImpl) { + // use reference context node from parameter node + referenceContext = ((ContextAwareNode) executedNode).getReferenceContext(); + } + } else { + return ErrorNodeFactory.createInvalidType(executedNode, NodeType.String); + } + } + if (referenceContext == null) { + // no context defined in parameter node, use context of current node + referenceContext = context.getContextNode(); + } + return new ContextAwareStringNodeImpl(content.toString(), referenceContext); + } + } + + private List executeNodes(ExecutionContext context, List children) { + List executedNodes = new ArrayList<>(); + for (Node child : children) { + if (child instanceof ExecutableNode) { + executedNodes.add(((ExecutableNode) child).execute(context)); + } else { + executedNodes.add(child); + } + } + return executedNodes; + } + + + @Override + public Node copy() { + return new StringTemplateNode(this); + } + + @Override + public void replaceWith(Node newNode) { + if (this != newNode) { + replaceTree(newNode); + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TemplateExpressionNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TemplateExpressionNode.java new file mode 100644 index 0000000..37e9ad9 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TemplateExpressionNode.java @@ -0,0 +1,87 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import java.util.StringTokenizer; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.AbstractStringNode; +import org.xbib.raml.yagi.framework.nodes.ExecutableNode; +import org.xbib.raml.yagi.framework.nodes.ExecutionContext; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +public class TemplateExpressionNode extends AbstractStringNode implements ExecutableNode { + public TemplateExpressionNode(String value) { + super(value); + } + + public TemplateExpressionNode(TemplateExpressionNode node) { + super(node); + } + + + public String getVariableName() { + final StringTokenizer expressionTokens = getExpressionTokens(); + return expressionTokens.hasMoreTokens() ? expressionTokens.nextToken() : null; + } + + public Node execute(ExecutionContext context) { + final StringTokenizer expressionTokens = getExpressionTokens(); + Node result = null; + if (expressionTokens.hasMoreTokens()) { + final String token = expressionTokens.nextToken().trim(); + if (context.containsVariable(token)) { + result = context.getVariable(token).copy(); + } else { + return ErrorNodeFactory.createInvalidTemplateParameterExpression(this, token); + } + } + while (expressionTokens.hasMoreTokens()) { + if (!(result instanceof SimpleTypeNode)) { + return ErrorNodeFactory.createInvalidType(result, NodeType.String); + } + final String token = expressionTokens.nextToken().trim(); + if (token.startsWith("!")) { + /*try + { + Method method = Inflector.class.getMethod(token.substring(1), String.class); + result = new StringNodeImpl(String.valueOf(method.invoke(null, ((SimpleTypeNode) result).getLiteralValue()))); + } + catch (Exception e) + { + return ErrorNodeFactory.createInvalidTemplateFunctionExpression(this, token); + }*/ + } else { + return ErrorNodeFactory.createInvalidTemplateFunctionExpression(this, token); + } + } + + return result; + + } + + private StringTokenizer getExpressionTokens() { + final String value = getValue(); + return new StringTokenizer(value, "|"); + } + + + @Override + public Node copy() { + return new TemplateExpressionNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TraitNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TraitNode.java new file mode 100644 index 0000000..1a4f9c7 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TraitNode.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.NamedNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +public class TraitNode extends KeyValueNodeImpl implements NamedNode { + + public TraitNode() { + } + + public TraitNode(TraitNode node) { + super(node); + } + + public String getName() { + final StringNode key = (StringNode) getKey(); + return key.getValue(); + } + + + @Override + public TraitNode copy() { + return new TraitNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TraitRefNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TraitRefNode.java new file mode 100644 index 0000000..85d9a3d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TraitRefNode.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +public class TraitRefNode extends BaseTraitRefNode implements StringNode { + + public TraitRefNode(String name) { + super(name); + } + + public TraitRefNode(TraitRefNode node) { + super(node); + } + + + @Override + public Node copy() { + return new TraitRefNode(this); + } + + @Override + public String getValue() { + return getRefName(); + } + + @Override + public String getLiteralValue() { + return getValue(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypeDeclarationField.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypeDeclarationField.java new file mode 100644 index 0000000..8bfb1c3 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypeDeclarationField.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.NamedNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +public class TypeDeclarationField extends KeyValueNodeImpl implements NamedNode { + public TypeDeclarationField(KeyValueNodeImpl node) { + super(node); + } + + public TypeDeclarationField() { + super(); + } + + + @Override + public Node copy() { + return new TypeDeclarationField(this); + } + + public String getName() { + return ((SimpleTypeNode) getKey()).getLiteralValue(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypeDeclarationNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypeDeclarationNode.java new file mode 100644 index 0000000..27a600c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypeDeclarationNode.java @@ -0,0 +1,171 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.type.UnionResolvedType; +import org.xbib.raml.yagi.framework.nodes.AbstractObjectNode; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +/** + * Represents a node that declares an explicit type. + * It's itself a TypeExpressionNode to allow inline inheritance of types. + */ +public class TypeDeclarationNode extends AbstractObjectNode implements TypeExpressionNode, OverlayableNode { + + private ResolvedType resolvedType; + private boolean resolvingType = false; + + public TypeDeclarationNode() { + } + + protected TypeDeclarationNode(TypeDeclarationNode node) { + super(node); + } + + + public List getBaseTypes() { + List result = new ArrayList<>(); + final Node type = getTypeValue(); + if (type instanceof ArrayNode) { + final List children = type.getChildren(); + for (Node child : children) { + result.add((TypeExpressionNode) child); + } + } else if (type != null) { + result.add((TypeExpressionNode) type); + } + return result; + } + + + public ResolvedType getResolvedType() { + // Cache it to support recursive definitions + if (resolvedType == null) { + if (resolvingType) { + this.replaceWith(RamlErrorNodeFactory.createRecurrentTypeDefinition(getTypeExpressionText())); + return null; + } else { + resolvingType = true; + resolvedType = resolveTypeDefinition(); + resolvingType = false; + } + } + return resolvedType; + } + + private ResolvedType resolveTypeDefinition() { + ResolvedType result = resolveBaseType(); + + // After result base definition we overwrite with local definitions + if (result != null) { + result = result.overwriteFacets(this); + } + return result; + } + + private ResolvedType resolveBaseType() { + final List baseTypes = getBaseTypes(); + ResolvedType result = null; + // First we inherit all base properties and merge with multiple inheritance + for (TypeExpressionNode baseType : baseTypes) { + final ResolvedType baseTypeDef = baseType.generateDefinition(); + if (result == null) { + result = baseTypeDef; + } else { + // It can inherit from union and non union and in this case the result is a union so we flip the merge order + if (baseTypeDef instanceof UnionResolvedType && !(result instanceof UnionResolvedType)) { + result = baseTypeDef.mergeFacets(result); + } else { + result = result.mergeFacets(baseTypeDef); + } + } + } + if (result != null) { + // The final resolved type should point to this node and not the the inherited one + result = result.setTypeNode(this); + } + return result; + } + + public void validateCanOverwrite() { + ResolvedType result = resolveBaseType(); + // After result base definition we overwrite with local definitions + if (result != null) { + result.validateCanOverwriteWith(this); + } + } + + public void validateState() { + final ResolvedType resolvedType = getResolvedType(); + if (resolvedType != null) { + resolvedType.validateState(); + } + } + + public List getCustomFacets() { + return findDescendantsWith(CustomFacetDefinitionNode.class); + } + + private Node getTypeValue() { + return org.xbib.raml.yagi.framework.util.NodeUtils.getType(this); + } + + + public String getTypeName() { + return getResolvedType() != null ? getResolvedType().getTypeName() : null; + } + + + @Override + public Node copy() { + return new TypeDeclarationNode(this); + } + + + @Override + public ResolvedType generateDefinition() { + return resolveTypeDefinition(); + } + + @Override + public String getTypeExpressionText() { + if (getParent() instanceof TypeDeclarationField) { + return ((SimpleTypeNode) ((TypeDeclarationField) getParent()).getKey()).getLiteralValue(); + } else if (getSource() instanceof SimpleTypeNode) { + return ((SimpleTypeNode) getSource()).getLiteralValue(); + } else { + return getResolvedType().getBuiltinTypeName(); + } + } + + public List getFacets() { + final List result = new ArrayList<>(); + + final List children = getChildren(); + for (Node child : children) { + if (child instanceof FacetNode) { + result.add((FacetNode) child); + } + } + return result; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypeDeclarationNodeFragment.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypeDeclarationNodeFragment.java new file mode 100644 index 0000000..63031a0 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypeDeclarationNodeFragment.java @@ -0,0 +1,61 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.api.model.v10.RamlFragment; +import org.xbib.raml.internal.impl.commons.phase.RamlTypedFragment; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.internal.utils.RamlNodeUtils; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.util.NodeSelector; +import org.xbib.raml.yagi.framework.util.NodeUtils; +import static org.xbib.raml.api.model.v10.RamlFragment.DataType; + + +public class TypeDeclarationNodeFragment extends TypeDeclarationNode implements RamlTypedFragment { + + private Node libraryNode; + + + @Override + public Node getContextNode() { + return getLibraryNode() != null || getParent() == null ? this : NodeUtils.getContextNode(getParent()); + } + + @Override + public Node getLibraryNode() { + if (libraryNode == null) { + libraryNode = NodeSelector.selectFrom(Raml10Grammar.USES_KEY_NAME, this); + } + return libraryNode; + } + + public void + resolveLibraryReference() { + libraryNode = NodeSelector.selectFrom(Raml10Grammar.USES_KEY_NAME, this); + if (libraryNode != null && !RamlNodeUtils.isErrorResult(libraryNode)) { + // The parent is the key value pair + final Node parent = libraryNode.getParent(); + removeChild(parent); + } + } + + @Override + public RamlFragment getFragment() { + return DataType; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypeExpressionNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypeExpressionNode.java new file mode 100644 index 0000000..2ceaa7d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypeExpressionNode.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.yagi.framework.nodes.Node; + +/** + * Represents a type expression element it can be a union type a reference to another type an array type declaration + */ +public interface TypeExpressionNode extends Node { + + /** + * Generates the definition that results of evaluating this expression + * + * @return The type definition + */ + + ResolvedType generateDefinition(); + + String getTypeExpressionText(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypesNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypesNode.java new file mode 100644 index 0000000..bb21a5d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/nodes/TypesNode.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.nodes; + + +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; + + +public class TypesNode extends KeyValueNodeImpl implements OverlayableNode { + + public TypesNode() { + } + + public TypesNode(Node keyNode, Node valueNode) { + super(keyNode, valueNode); + } + + public TypesNode(TypesNode node) { + super(node); + } + + + @Override + public Node copy() { + return new TypesNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/DuplicatedPathsTransformer.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/DuplicatedPathsTransformer.java new file mode 100644 index 0000000..feddfa7 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/DuplicatedPathsTransformer.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + +import java.util.Collection; +import java.util.HashSet; +import org.xbib.raml.internal.impl.commons.nodes.ResourceNode; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.phase.Transformer; + +public class DuplicatedPathsTransformer implements Transformer { + private final Collection paths = new HashSet(); + + @Override + public boolean matches(Node node) { + return node instanceof ResourceNode; + } + + @Override + public Node transform(Node node) { + String currentPath = ((ResourceNode) node).getResourcePath(); + if (!paths.add(currentPath)) { + return ErrorNodeFactory.createDuplicatedPathNode(currentPath); + } + + return node; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/ExtensionsMerger.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/ExtensionsMerger.java new file mode 100644 index 0000000..74b0f74 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/ExtensionsMerger.java @@ -0,0 +1,154 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + +import org.xbib.raml.internal.impl.commons.nodes.AnnotationNode; +import org.xbib.raml.internal.impl.commons.nodes.AnnotationReferenceNode; +import org.xbib.raml.internal.impl.commons.nodes.DocumentationItemNode; +import org.xbib.raml.internal.impl.commons.nodes.ExampleDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.ExtendsNode; +import org.xbib.raml.internal.impl.commons.nodes.OverlayableNode; +import org.xbib.raml.internal.impl.commons.nodes.RamlDocumentNode; +import org.xbib.raml.internal.impl.v10.nodes.LibraryLinkNode; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NullNode; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; +import static org.xbib.raml.yagi.framework.nodes.DefaultPosition.isDefaultNode; + +public class ExtensionsMerger { + + private final boolean overlay; + + public ExtensionsMerger(boolean overlay) { + this.overlay = overlay; + } + + public void merge(Node baseNode, Node copyNode) { + if (baseNode instanceof ObjectNode && copyNode instanceof ObjectNode) { + merge((ObjectNode) baseNode, (ObjectNode) copyNode); + } else if (baseNode instanceof ArrayNode && copyNode instanceof ArrayNode) { + merge((ArrayNode) baseNode, (ArrayNode) copyNode); + } else { + throw new RuntimeException(String.format("Merging not supported for nodes of type %s and %s", + baseNode.getClass().getSimpleName(), copyNode.getClass().getSimpleName())); + } + } + + private void merge(ArrayNode baseNode, ArrayNode copyNode) { + for (Node child : copyNode.getChildren()) { + baseNode.addChild(child); + } + } + + private void merge(ObjectNode baseNode, ObjectNode copyNode) { + for (Node child : copyNode.getChildren()) { + if (!(child instanceof KeyValueNode)) { + throw new RuntimeException("only expecting KeyValueNode"); + } + + Node keyNode = ((KeyValueNode) child).getKey(); + String key = keyNode.toString(); + + if (shouldIgnoreNode(child)) { + continue; + } + + Node valueNode = ((KeyValueNode) child).getValue(); + Node node = NodeSelector.selectFrom(NodeSelector.encodePath(key), baseNode); + if (node == null) { + overlayCheck(valueNode, valueNode); + baseNode.addChild(child); + } else if (valueNode instanceof NullNode) { + } else if (valueNode instanceof LibraryLinkNode) { + } else if (child instanceof AnnotationNode) { + ((KeyValueNode) node.getParent()).setValue(valueNode); + } else if (child instanceof ExampleDeclarationNode) { + ((KeyValueNode) node.getParent()).setValue(valueNode); + } else { + if (isDefaultNode(child)) { + continue; + } + if (valueNode instanceof SimpleTypeNode) { + if (overlayCheck(node, valueNode)) { + node.replaceWith(valueNode); + } + } else { + merge(node, valueNode); + } + } + } + } + + private boolean overlayCheck(Node baseNode, Node overlayNode) { + boolean check = true; + if (overlay) { + if (!isOverlayableNode(overlayNode)) { + baseNode.replaceWith(ErrorNodeFactory.createInvalidOverlayNode(overlayNode)); + check = false; + } + } + return check; + } + + private boolean isOverlayableNode(Node overlayNode) { + Node parent = overlayNode.getParent(); + if ((overlayNode instanceof OverlayableNode) || (parent instanceof OverlayableNode)) { + return true; + } + // annotations + if (parent instanceof KeyValueNode && ((KeyValueNode) parent).getKey() instanceof AnnotationReferenceNode) { + return true; + } + // libraries + if (isLibraryNode(overlayNode)) { + return true; + } + // documentation + return !overlayNode.getChildren().isEmpty() && (overlayNode.getChildren().get(0) instanceof DocumentationItemNode); + } + + private boolean isLibraryNode(Node overlayNode) { + boolean isLibrary = false; + if (overlayNode instanceof LibraryLinkNode) { + isLibrary = true; + } else if (overlayNode.getParent() instanceof KeyValueNode) { + isLibrary = isNode(overlayNode.getParent(), "uses"); + } + return isLibrary; + } + + private boolean shouldIgnoreNode(Node node) { + if (node instanceof ExtendsNode) { + return true; + } + return isNode(node, "usage"); + } + + private boolean isNode(Node node, String keyName) { + Node keyNode = ((KeyValueNode) node).getKey(); + String key = ((SimpleTypeNode) keyNode).getLiteralValue(); + return keyName.equals(key) && (node.getParent() instanceof RamlDocumentNode); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/IncludeResolver.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/IncludeResolver.java new file mode 100644 index 0000000..7b05449 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/IncludeResolver.java @@ -0,0 +1,126 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + +import java.io.InputStream; +import java.net.URI; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.api.loader.ResourceLoaderExtended; +import org.xbib.raml.api.loader.ResourceUriCallback; +import org.xbib.raml.api.model.v10.RamlFragment; +import org.xbib.raml.internal.impl.commons.RamlHeader; +import org.xbib.raml.internal.impl.commons.nodes.DefaultRamlTypedFragment; +import org.xbib.raml.internal.utils.IOUtils; +import org.xbib.raml.internal.utils.ResourcePathUtils; +import org.xbib.raml.internal.utils.StreamUtils; +import org.xbib.raml.yagi.framework.nodes.AbstractRamlNode; +import org.xbib.raml.yagi.framework.nodes.IncludeErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NullNodeImpl; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.Position; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.NodeParser; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.SYIncludeNode; +import org.xbib.raml.yagi.framework.phase.Transformer; + + +public class IncludeResolver implements Transformer, ResourceUriCallback { + + private final ResourceLoader resourceLoader; + private String includedResourceUri; + + public IncludeResolver(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + @Override + public boolean matches(Node node) { + return node instanceof SYIncludeNode; + } + + @Override + public Node transform(Node node) { + final SYIncludeNode includeNode = (SYIncludeNode) node; + final String resourcePath = ResourcePathUtils.toAbsoluteLocation(node.getStartPosition().getPath(), includeNode.getIncludePath()); + InputStream inputStream = null; + + try { + if (resourceLoader instanceof ResourceLoaderExtended) { + inputStream = ((ResourceLoaderExtended) resourceLoader).fetchResource(resourcePath, this); + } else { + inputStream = resourceLoader.fetchResource(resourcePath); + } + + if (inputStream == null) { + return new IncludeErrorNode("Include cannot be resolved: " + resourcePath); + } + Node result; + String includeContent = StreamUtils.toString(inputStream); + if (resourcePath.endsWith(".raml") || resourcePath.endsWith(".yaml") || resourcePath.endsWith(".yml")) { + try { + RamlHeader ramlHeader = RamlHeader.parse(includeContent); + final RamlFragment fragment = ramlHeader.getFragment(); + result = NodeParser.parse(resourceLoader, resourcePath, includeContent); + if (result != null && isTypedFragment(result, fragment)) { + final DefaultRamlTypedFragment newNode = new DefaultRamlTypedFragment(fragment); + result.replaceWith(newNode); + result = newNode; + } + } catch (RamlHeader.InvalidHeaderException e) { + // no valid header defined => !supportUses + result = NodeParser.parse(resourceLoader, resourcePath, includeContent); + } + + } else + // scalar value + { + result = new StringNodeImpl(includeContent); + setTempPositionWithResourceUri(result); + } + + if (result == null) { + result = new NullNodeImpl(); + } + + return result; + } finally { + IOUtils.closeQuietly(inputStream); + } + } + + private void setTempPositionWithResourceUri(Node result) { + // Position is always null, so it is generated on the fly + Position startPosition = result.getStartPosition(); + Position endPosition = result.getEndPosition(); + + startPosition.setIncludedResourceUri(includedResourceUri); + endPosition.setIncludedResourceUri(includedResourceUri); + + ((AbstractRamlNode) result).setStartPosition(startPosition); + ((AbstractRamlNode) result).setEndPosition(endPosition); + } + + private boolean isTypedFragment(Node result, RamlFragment fragment) { + return fragment != null && fragment != RamlFragment.Library && result instanceof ObjectNode; + } + + + @Override + public void onResourceFound(URI resourceURI) { + this.includedResourceUri = resourceURI.toString(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/RamlFragmentGrammarTransformer.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/RamlFragmentGrammarTransformer.java new file mode 100644 index 0000000..0411163 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/RamlFragmentGrammarTransformer.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + +import org.xbib.raml.internal.impl.commons.RamlHeader; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.phase.Transformer; +import static org.xbib.raml.internal.utils.RamlNodeUtils.isErrorResult; + +public class RamlFragmentGrammarTransformer implements Transformer { + @Override + public boolean matches(Node node) { + return node instanceof RamlTypedFragment && node.getParent() != null && !isErrorResult(node); + } + + @Override + public Node transform(Node node) { + final RamlTypedFragment ramlTypedFragmentNode = (RamlTypedFragment) node; + final Rule rule = RamlHeader.getFragmentUsesAllowedRule(ramlTypedFragmentNode.getFragment()); + return rule.apply(node); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/RamlFragmentLibraryLinkingTransformer.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/RamlFragmentLibraryLinkingTransformer.java new file mode 100644 index 0000000..adf9d8f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/RamlFragmentLibraryLinkingTransformer.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.internal.impl.v10.Raml10Builder; +import org.xbib.raml.internal.impl.v10.phase.LibraryLinkingTransformation; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.phase.TransformationPhase; +import org.xbib.raml.yagi.framework.phase.Transformer; +import static org.xbib.raml.internal.utils.PhaseUtils.applyPhases; + +public class RamlFragmentLibraryLinkingTransformer implements Transformer { + + private final Raml10Builder builder; + private final ResourceLoader resourceLoader; + + public RamlFragmentLibraryLinkingTransformer(Raml10Builder builder, ResourceLoader resourceLoader) { + this.builder = builder; + this.resourceLoader = resourceLoader; + } + + @Override + public boolean matches(Node node) { + return node instanceof RamlTypedFragment && node.getParent() != null; + } + + @Override + public Node transform(Node node) { + Node apply = applyPhases(node, new TransformationPhase(new LibraryLinkingTransformation(builder, resourceLoader))); + + // Hack!!!! + ((RamlTypedFragment) apply).resolveLibraryReference(); + + return apply; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/RamlTypedFragment.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/RamlTypedFragment.java new file mode 100644 index 0000000..15bdb68 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/RamlTypedFragment.java @@ -0,0 +1,24 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + +import org.xbib.raml.api.model.v10.RamlFragment; +import org.xbib.raml.internal.impl.commons.nodes.LibraryNodeProvider; +import org.xbib.raml.yagi.framework.nodes.ContextProviderNode; + +public interface RamlTypedFragment extends LibraryNodeProvider, ContextProviderNode { + RamlFragment getFragment(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/RemoveTopLevelSequencesTransformer.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/RemoveTopLevelSequencesTransformer.java new file mode 100644 index 0000000..915d6d1 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/RemoveTopLevelSequencesTransformer.java @@ -0,0 +1,55 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + + +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.phase.Transformer; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class RemoveTopLevelSequencesTransformer implements Transformer { + + @Override + public boolean matches(Node node) { + return node.getParent() == null; + } + + @Override + public Node transform(Node node) { + String[] paths = {"schemas", "resourceTypes", "traits", "securitySchemes"}; + for (String path : paths) { + removeSequenceForPath(node, path); + } + return node; + } + + private void removeSequenceForPath(Node node, String path) { + Node container = NodeSelector.selectFrom(path, node); + if (container instanceof ArrayNode) { + if (!container.getChildren().isEmpty()) { + Node uncle = container.getChildren().get(0); + for (int i = 1; i < container.getChildren().size(); i++) { + Node sibling = container.getChildren().get(i); + for (Node nephew : sibling.getChildren()) { + uncle.addChild(nephew); + } + } + container.replaceTree(uncle); + } + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/ResourceTypesTraitsMerger.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/ResourceTypesTraitsMerger.java new file mode 100644 index 0000000..a0395a0 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/ResourceTypesTraitsMerger.java @@ -0,0 +1,159 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import org.xbib.raml.internal.impl.commons.nodes.BodyNode; +import org.xbib.raml.internal.impl.commons.nodes.OverridableNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.internal.impl.v10.nodes.PropertyNode; +import org.xbib.raml.yagi.framework.grammar.rule.RegexValueRule; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NullNode; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; +import static org.xbib.raml.yagi.framework.nodes.DefaultPosition.isDefaultNode; + +public class ResourceTypesTraitsMerger { + + + static void merge(Node baseNode, Node copyNode) { + if (copyNode instanceof NullNode) { + // nothing to do here if copyNode is null + } else if (baseNode instanceof ObjectNode && copyNode instanceof ObjectNode) { + merge((ObjectNode) baseNode, (ObjectNode) copyNode); + } else if (baseNode instanceof ArrayNode && copyNode instanceof ArrayNode) { + merge((ArrayNode) baseNode, (ArrayNode) copyNode); + } else if ((baseNode instanceof NullNode) || (copyNode instanceof ErrorNode)) { + baseNode.replaceWith(copyNode); + } else { + throw new RuntimeException(String.format("Merging not supported for nodes of type %s and %s", + baseNode.getClass().getSimpleName(), copyNode.getClass().getSimpleName())); + } + } + + static void merge(ArrayNode baseNode, ArrayNode copyNode) { + for (Node child : copyNode.getChildren()) { + baseNode.addChild(child); + } + } + + static void merge(ObjectNode baseNode, ObjectNode copyNode) { + for (final Node child : copyNode.getChildren()) { + if (child instanceof ErrorNode) { + baseNode.addChild(child); + continue; + } + if (!(child instanceof KeyValueNode)) { + throw new RuntimeException("Only expecting KeyValueNode and got " + child.getClass()); + } + + String key = ((KeyValueNode) child).getKey().toString(); + if (shouldIgnoreKey((KeyValueNode) child)) { + continue; + } + + boolean optional = key.endsWith("?"); + if (optional) { + key = key.substring(0, key.length() - 1); + } + Node node = NodeSelector.selectFrom(NodeSelector.encodePath(key), baseNode); + Node childValue = ((KeyValueNode) child).getValue(); + + if (node == null) { + // if merging children of body node, media type is defined under baseNode and child is not a mime type node, + // child gets merge with the value of mediaType node. See #498 + RegexValueRule mimeTypeRegex = new Raml10Grammar().mimeTypeRegex(); + boolean isMimeType = mimeTypeRegex.matches(((KeyValueNode) child).getKey()); + if (baseNode.getParent() instanceof BodyNode && !isMimeType) { + if (baseNode.getChildren().size() > 0 && baseNode.getChildren().get(0) instanceof KeyValueNode mimeTypeNode) { + if (mimeTypeRegex.matches(mimeTypeNode.getKey())) { + merge(mimeTypeNode.getValue(), copyNode); + } + } + } else if (baseNode.getParent() instanceof BodyNode && baseNode instanceof TypeDeclarationNode && isMimeType) { + merge(baseNode, ((KeyValueNode) child).getValue()); + } else { + if (child instanceof PropertyNode) { + + Optional foundBasenodeChild = findPropertyNode(baseNode, (PropertyNode) child); + + if (!foundBasenodeChild.isPresent()) { + + baseNode.addChild(child); + } else { + + merge(foundBasenodeChild.get().getValue(), ((PropertyNode) child).getValue()); + } + + } else { + + baseNode.addChild(child); + } + } + } else if (childValue instanceof SimpleTypeNode) { + if (isDefaultNode(node) && !isDefaultNode(childValue)) { + node.getParent().setChild(1, childValue); + } else if (node instanceof OverridableNode) { + node.getParent().setChild(1, childValue); + } + } else { + if (node instanceof SimpleTypeNode) { + merge(baseNode, childValue); + } else { + merge(node, childValue); + } + } + } + } + + private static Optional findPropertyNode(ObjectNode baseNode, final PropertyNode child) { + return baseNode.getChildren().stream() + .filter(input -> input instanceof PropertyNode) + .map(input -> ((PropertyNode) input)) + .filter(input -> nonOptionalName(input.getName()).equals(nonOptionalName(child.getName()))) + .findFirst(); + } + + private static String nonOptionalName(String name) { + + if (name.endsWith("?")) { + return name.substring(0, name.length() - 1); + } else { + return name; + } + } + + private static boolean shouldIgnoreKey(KeyValueNode child) { + Set ignoreSet = new HashSet<>(); + ignoreSet.add("usage"); + if (!(child.getParent() instanceof TypeDeclarationNode)) { + ignoreSet.add("type"); + } + String key = child.getKey().toString(); + return ignoreSet.contains(key); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/ResourceTypesTraitsTransformer.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/ResourceTypesTraitsTransformer.java new file mode 100644 index 0000000..09bdb34 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/ResourceTypesTraitsTransformer.java @@ -0,0 +1,307 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.xbib.raml.internal.impl.commons.grammar.BaseRamlGrammar; +import org.xbib.raml.internal.impl.commons.nodes.BaseResourceTypeRefNode; +import org.xbib.raml.internal.impl.commons.nodes.BaseTraitRefNode; +import org.xbib.raml.internal.impl.commons.nodes.MethodNode; +import org.xbib.raml.internal.impl.commons.nodes.ParametrizedReferenceNode; +import org.xbib.raml.internal.impl.commons.nodes.ResourceNode; +import org.xbib.raml.internal.impl.commons.nodes.ResourceTypeNode; +import org.xbib.raml.internal.impl.commons.nodes.StringTemplateNode; +import org.xbib.raml.internal.impl.commons.nodes.TraitNode; +import org.xbib.raml.internal.impl.v10.phase.ReferenceResolverTransformer; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.ExecutionContext; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NullNode; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.SYBaseRamlNode; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.SYNullNode; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.SYObjectNode; +import org.xbib.raml.yagi.framework.phase.GrammarPhase; +import org.xbib.raml.yagi.framework.phase.Phase; +import org.xbib.raml.yagi.framework.phase.TransformationPhase; +import org.xbib.raml.yagi.framework.phase.Transformer; +import org.xbib.raml.yagi.framework.util.NodeSelector; +import org.xbib.raml.yagi.framework.util.NodeUtils; +import static org.xbib.raml.internal.impl.commons.phase.ResourceTypesTraitsMerger.merge; + +public class ResourceTypesTraitsTransformer implements Transformer { + + private final Set mergedResources = new HashSet<>(); + private final BaseRamlGrammar ramlGrammar; + + public ResourceTypesTraitsTransformer(BaseRamlGrammar ramlGrammar) { + this.ramlGrammar = ramlGrammar; + } + + @Override + public boolean matches(Node node) { + return (node instanceof BaseTraitRefNode || + node instanceof BaseResourceTypeRefNode) && + node.findAncestorWith(ResourceNode.class) != null; + } + + @Override + public Node transform(Node node) { + ResourceNode resourceNode = node.findAncestorWith(ResourceNode.class); + if (mergedResources.contains(resourceNode)) { + return node; + } + + + // apply method and resource traits if defined + checkTraits(resourceNode, resourceNode); + + // apply resource type if defined + ReferenceNode resourceTypeReference = findResourceTypeReference(resourceNode); + if (resourceTypeReference != null) { + List typeNodes = new ArrayList<>(); + typeNodes.add(resourceNode); + typeNodes.add((KeyValueNode) resourceTypeReference.getRefNode()); + findTheStuff((ResourceTypeNode) resourceTypeReference.getRefNode(), typeNodes); + + applyResourceType(resourceNode, resourceTypeReference, resourceNode, typeNodes); + } + mergedResources.add(resourceNode); + return node; + } + + private void checkTraits(KeyValueNode resourceNode, ResourceNode baseResourceNode) { + final List methodNodes = findMethodNodes(resourceNode); + final List resourceTraitRefs = findTraitReferences(resourceNode); + + for (MethodNode methodNode : methodNodes) { + final List traitRefs = findTraitReferences(methodNode); + traitRefs.addAll(resourceTraitRefs); + for (final ReferenceNode traitRef : traitRefs) { + applyTrait(methodNode, traitRef, baseResourceNode); + } + } + } + + private void applyResourceType(KeyValueNode targetNode, ReferenceNode resourceTypeReference, ResourceNode baseResourceNode, List typeNodes) { + + ResourceTypeNode refNode = (ResourceTypeNode) resourceTypeReference.getRefNode(); + if (refNode.getValue() instanceof NullNode) { + // empty resource type + return; + } + + ResourceTypeNode templateNode = refNode.copy(); + templateNode.setParent(refNode.getParent()); + + // generateDefinition parameters + Map parameters = getBuiltinResourceTypeParameters(baseResourceNode); + if (resourceTypeReference instanceof ParametrizedReferenceNode) { + parameters.putAll(((ParametrizedReferenceNode) resourceTypeReference).getParameters()); + } + resolveParameters(templateNode, parameters, NodeUtils.getContextNode(baseResourceNode)); + + // apply grammar phase to generate method nodes + GrammarPhase grammarPhase = new GrammarPhase(ramlGrammar.resourceTypeParamsResolved()); + // generateDefinition references + TransformationPhase referenceResolution = new TransformationPhase(new ReferenceResolverTransformer()); + // resolves types + + grammarPhase.apply(templateNode.getValue()); + + removeUnimplementedOptionalMethods(templateNode, typeNodes); + + boolean success = applyPhases(templateNode, referenceResolution); + + if (success) { + // apply traits + checkTraits(templateNode, baseResourceNode); + + // generateDefinition inheritance + ReferenceNode parentTypeReference = findResourceTypeReference(templateNode); + if (parentTypeReference != null) { + applyResourceType(templateNode, parentTypeReference, baseResourceNode, typeNodes); + } + } + + merge(targetNode.getValue(), templateNode.getValue()); + } + + private void findTheStuff(ResourceTypeNode templateNode, List nodes) { + + ReferenceNode parentTypeReference = findResourceTypeReference(templateNode); + if (parentTypeReference != null) { + ResourceTypeNode resourceTypeNode = (ResourceTypeNode) parentTypeReference.getRefNode(); + nodes.add(resourceTypeNode); + findTheStuff(resourceTypeNode, nodes); + } + } + + private void removeUnimplementedOptionalMethods(ResourceTypeNode templateNode, List typeNodes) { + final List unimplementedMethods = new ArrayList<>(); + for (MethodNode node : findMethodNodes(templateNode)) { + String key = node.getName(); + if (!key.endsWith("?")) + continue; + + key = key.substring(0, key.length() - 1); + + boolean found = false; + for (KeyValueNode typeNode : typeNodes) { + + if (typeNode.getKey().toString().equals(templateNode.getKey().toString())) { + break; + } + + Node methodInTemplateNode = NodeSelector.selectFrom(NodeSelector.encodePath(key), typeNode.getValue()); + if (methodInTemplateNode != null) { + found = true; + } + } + + if (!found) + unimplementedMethods.add(node); + } + + for (MethodNode unimplementedMethod : unimplementedMethods) { + templateNode.getValue().removeChild(unimplementedMethod); + } + } + + private boolean applyPhases(KeyValueNode templateNode, Phase... phases) { + List errorNodes = templateNode.findDescendantsWith(ErrorNode.class); + if (errorNodes.isEmpty()) { + for (Phase phase : phases) { + phase.apply(templateNode.getValue()); + errorNodes = templateNode.findDescendantsWith(ErrorNode.class); + if (!errorNodes.isEmpty()) { + return false; + } + } + } + return true; + + } + + private Map getBuiltinResourceTypeParameters(ResourceNode resourceNode) { + Map parameters = new HashMap<>(); + parameters.put("resourcePathName", new StringNodeImpl(resourceNode.getResourcePathName())); + parameters.put("resourcePath", new StringNodeImpl(resourceNode.getResourcePath())); + return parameters; + } + + private Map getBuiltinTraitParameters(MethodNode methodNode, ResourceNode resourceNode) { + Map parameters = getBuiltinResourceTypeParameters(resourceNode); + parameters.put("methodName", new StringNodeImpl(methodNode.getName())); + return parameters; + } + + private void applyTrait(MethodNode methodNode, ReferenceNode traitReference, ResourceNode baseResourceNode) { + TraitNode refNode = (TraitNode) traitReference.getRefNode(); + if (refNode.getValue() instanceof NullNode) { + // empty trait + return; + } + + TraitNode copy = refNode.copy(); + copy.setParent(refNode.getParent()); + + replaceNullValueWithObject(copy); + + // generateDefinition parameters + Map parameters = getBuiltinTraitParameters(methodNode, baseResourceNode); + if (traitReference instanceof ParametrizedReferenceNode) { + parameters.putAll(((ParametrizedReferenceNode) traitReference).getParameters()); + } + resolveParameters(copy, parameters, NodeUtils.getContextNode(methodNode)); + + // apply grammar phase to generate method nodes + GrammarPhase validatePhase = new GrammarPhase(ramlGrammar.traitParamsResolved()); + + // generateDefinition references + TransformationPhase referenceResolution = new TransformationPhase(new ReferenceResolverTransformer()); + // resolves types + applyPhases(copy, validatePhase, referenceResolution); + + replaceNullValueWithObject(methodNode); + merge(methodNode.getValue(), copy.getValue()); + } + + private void resolveParameters(Node parameterizedNode, Map parameters, Node referenceContext) { + ExecutionContext context = new ExecutionContext(parameters, referenceContext); + List templateNodes = parameterizedNode.findDescendantsWith(StringTemplateNode.class); + for (StringTemplateNode templateNode : templateNodes) { + Node resolvedNode = templateNode.execute(context); + templateNode.replaceTree(resolvedNode); + + } + } + + private void replaceNullValueWithObject(KeyValueNode keyValueNode) { + Node valueNode = keyValueNode.getValue(); + if (valueNode instanceof SYNullNode) { + final SYBaseRamlNode ramlNode = (SYBaseRamlNode) valueNode; + valueNode = new SYObjectNode(ramlNode); + keyValueNode.setValue(valueNode); + } + } + + private List findTraitReferences(KeyValueNode keyValueNode) { + List result = new ArrayList<>(); + Node isNode = NodeSelector.selectFrom("is", keyValueNode.getValue()); + if (isNode != null) { + List children = isNode.getChildren(); + for (Node child : children) { + result.add((ReferenceNode) child); + } + } + return result; + } + + private ReferenceNode findResourceTypeReference(KeyValueNode resourceNode) { + Node node = NodeSelector.selectFrom("type", resourceNode.getValue()); + if (node == null || node instanceof ReferenceNode) { + return (ReferenceNode) node; + } else { + ErrorNode errorNode = ErrorNodeFactory.createInvalidReferenceNode((StringNode) node); + resourceNode.getValue().replaceWith(errorNode); + return null; + } + } + + private List findMethodNodes(KeyValueNode resourceNode) { + List methodNodes = new ArrayList<>(); + for (Node node : resourceNode.getValue().getChildren()) { + if (node instanceof MethodNode) { + methodNodes.add((MethodNode) node); + } + } + return methodNodes; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/SchemaValidationTransformer.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/SchemaValidationTransformer.java new file mode 100644 index 0000000..28f147a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/SchemaValidationTransformer.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + +import com.fasterxml.jackson.core.JsonParseException; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.internal.impl.commons.nodes.ExternalSchemaTypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.JsonSchemaExternalType; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.commons.type.XmlSchemaExternalType; +import org.xbib.raml.internal.utils.SchemaGenerator; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.phase.Transformer; + +/** + * Validates that the external schemas are valid schemas. + */ +public class SchemaValidationTransformer implements Transformer { + + + private final ResourceLoader resourceLoader; + + public SchemaValidationTransformer(ResourceLoader resourceLoader) { + + this.resourceLoader = resourceLoader; + } + + @Override + public boolean matches(Node node) { + return node instanceof ExternalSchemaTypeExpressionNode; + } + + @Override + public Node transform(Node node) { + ExternalSchemaTypeExpressionNode schema = (ExternalSchemaTypeExpressionNode) node; + try { + final ResolvedType resolvedType = schema.generateDefinition(); + if (resolvedType instanceof XmlSchemaExternalType) { + SchemaGenerator.generateXmlSchema(resourceLoader, (XmlSchemaExternalType) resolvedType); + } else if (resolvedType instanceof JsonSchemaExternalType) { + SchemaGenerator.generateJsonSchema((JsonSchemaExternalType) resolvedType); + } + } catch (JsonParseException ex) { + return ErrorNodeFactory.createInvalidSchemaNode(ex.getOriginalMessage()); + } catch (Exception e) { + return ErrorNodeFactory.createInvalidSchemaNode(e.getMessage()); + } + return node; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/StringTemplateExpressionTransformer.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/StringTemplateExpressionTransformer.java new file mode 100644 index 0000000..aa16bbc --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/StringTemplateExpressionTransformer.java @@ -0,0 +1,76 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.xbib.raml.internal.impl.commons.nodes.StringTemplateNode; +import org.xbib.raml.internal.impl.commons.nodes.TemplateExpressionNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.Position; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; +import org.xbib.raml.yagi.framework.phase.Transformer; + +public class StringTemplateExpressionTransformer implements Transformer { + public static Pattern TEMPLATE_PATTERN = Pattern.compile("<<(.+?)>>"); + + @Override + public boolean matches(Node node) { + if (node instanceof StringNode) { + final String value = ((StringNode) node).getValue(); + return TEMPLATE_PATTERN.matcher(value).find(); + } + return false; + } + + @Override + public Node transform(Node node) { + if (node instanceof StringTemplateNode) { + return node; + } + final String value = ((StringNode) node).getValue(); + final StringTemplateNode stringTemplateNode = new StringTemplateNode(value); + final Matcher templateMatcher = TEMPLATE_PATTERN.matcher(value); + final Position startPosition = node.getStartPosition(); + // The previous template expression end position. + int previousEndPosition = 0; + while (templateMatcher.find()) { + final int start = templateMatcher.start(); + final int end = templateMatcher.end(); + if (start > previousEndPosition) { + final StringNodeImpl stringNode = new StringNodeImpl(value.substring(previousEndPosition, start)); + stringNode.setStartPosition(startPosition.rightShift(previousEndPosition)); + stringNode.setEndPosition(startPosition.rightShift(start)); + stringTemplateNode.addChild(stringNode); + } + final TemplateExpressionNode expressionNode = new TemplateExpressionNode(templateMatcher.group(1)); + expressionNode.setStartPosition(startPosition.rightShift(templateMatcher.start(1))); + expressionNode.setEndPosition(startPosition.rightShift(templateMatcher.end(1))); + stringTemplateNode.addChild(expressionNode); + previousEndPosition = end; + } + + if (value.length() > previousEndPosition) { + final StringNodeImpl stringNode = new StringNodeImpl(value.substring(previousEndPosition)); + stringNode.setStartPosition(startPosition.rightShift(previousEndPosition)); + stringNode.setEndPosition(startPosition.rightShift(value.length())); + stringTemplateNode.addChild(stringNode); + } + + return stringTemplateNode; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/TypeValidationPhase.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/TypeValidationPhase.java new file mode 100644 index 0000000..4dc955f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/TypeValidationPhase.java @@ -0,0 +1,63 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.phase.Phase; +import org.xbib.raml.yagi.framework.util.NodeUtils; + +public class TypeValidationPhase implements Phase { + + @Override + public Node apply(Node tree) { + final List descendantsWith = tree.findDescendantsWith(TypeDeclarationNode.class); + for (TypeDeclarationNode typeDeclarationNode : descendantsWith) { + if (!NodeUtils.isErrorResult(typeDeclarationNode)) { + if (validateInheritFromValidTypes(typeDeclarationNode)) { + typeDeclarationNode.validateCanOverwrite(); + typeDeclarationNode.validateState(); + } + } + } + return tree; + } + + private boolean validateInheritFromValidTypes(TypeDeclarationNode typeDeclarationNode) { + List baseTypes = typeDeclarationNode.getBaseTypes(); + Set extendedTypes = new HashSet<>(); + for (TypeExpressionNode baseType : baseTypes) { + ResolvedType resolvedType = baseType.generateDefinition(); + if (resolvedType != null) { + if (resolvedType.getBuiltinTypeName() != null) { + extendedTypes.add(resolvedType.getBuiltinTypeName()); + } + } + } + if (extendedTypes.size() > 1) { + typeDeclarationNode.replaceWith(ErrorNodeFactory.createCanNotInheritFromDifferentBaseTypes(extendedTypes.toArray(new String[0]))); + return false; + } + return true; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/UnusedParametersTransformer.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/UnusedParametersTransformer.java new file mode 100644 index 0000000..881943a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/phase/UnusedParametersTransformer.java @@ -0,0 +1,63 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.phase; + +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.RamlDocumentNode; +import org.xbib.raml.internal.impl.commons.nodes.ResourceNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.WarningMessageAnnotation; +import org.xbib.raml.yagi.framework.phase.Transformer; +import org.xbib.raml.yagi.framework.util.NodeSelector; +import static org.xbib.raml.internal.utils.ResourcePathUtils.getUriTemplates; + +public class UnusedParametersTransformer implements Transformer { + + @Override + public boolean matches(Node node) { + return node instanceof RamlDocumentNode || node instanceof ResourceNode; + } + + @Override + public Node transform(Node node) { + if (node instanceof RamlDocumentNode) { + Node baseUriNode = NodeSelector.selectFrom("baseUri", node); + if (baseUriNode != null) { + String value = NodeSelector.selectStringValue("value", baseUriNode); + List templates = getUriTemplates(value); + checkUriParameters("baseUriParameters", node, templates); + } + } else if (node instanceof ResourceNode) { + List templates = getUriTemplates(((ResourceNode) node).getRelativeUri()); + checkUriParameters("uriParameters", ((ResourceNode) node).getValue(), templates); + } + return node; + } + + private void checkUriParameters(String key, Node node, List templates) { + Node parametersNode = NodeSelector.selectFrom(key, node); + if (parametersNode != null) { + for (Node child : parametersNode.getChildren()) { + String parameterName = ((SimpleTypeNode) ((KeyValueNode) child).getKey()).getLiteralValue(); + if (!templates.contains(parameterName)) { + child.annotate(new WarningMessageAnnotation("Unused uri parameter '" + parameterName + "'")); + } + } + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/JsonSchemaValidationRule.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/JsonSchemaValidationRule.java new file mode 100644 index 0000000..2cfc955 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/JsonSchemaValidationRule.java @@ -0,0 +1,142 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.rule; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.fge.jsonschema.core.exceptions.ProcessingException; +import com.github.fge.jsonschema.core.report.LogLevel; +import com.github.fge.jsonschema.core.report.ProcessingMessage; +import com.github.fge.jsonschema.core.report.ProcessingReport; +import com.github.fge.jsonschema.main.JsonSchema; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.xbib.raml.internal.impl.commons.type.JsonSchemaExternalType; +import org.xbib.raml.internal.utils.JSonDumper; +import org.xbib.raml.internal.utils.SchemaGenerator; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; +import static com.github.fge.jsonschema.core.report.LogLevel.ERROR; +import static com.github.fge.jsonschema.core.report.LogLevel.WARNING; +import static org.xbib.raml.yagi.framework.nodes.jackson.JsonUtils.parseJson; + +/** + * Validates a string node content with the specified json schema + */ +public class JsonSchemaValidationRule extends Rule { + public static final String JSON_SCHEMA_FAIL_ON_WARNING_KEY = "org.xbib.raml.json_schema.fail_on_warning"; + private final boolean FAIL_ON_WARNING = Boolean.valueOf( + System.getProperty(JSON_SCHEMA_FAIL_ON_WARNING_KEY, "false")); + private JsonSchemaExternalType node; + + private JsonSchema schema; + + public JsonSchemaValidationRule(JsonSchemaExternalType schemaNode) { + try { + this.node = schemaNode; + this.schema = SchemaGenerator.generateJsonSchema(schemaNode); + } catch (Exception e) { + this.schema = null; + } + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return new ArrayList<>(); + } + + @Override + public boolean matches(Node node) { + return node instanceof StringNode; + } + + + @Override + public Node apply(Node node) { + if (schema == null) { + return ErrorNodeFactory.createInvalidJsonExampleNode("Invalid JsonSchema"); + } + try { + String value; + if (node instanceof StringNode) { + value = ((StringNode) node).getValue(); + } else { + value = JSonDumper.dump(node); + } + + if (value == null) { + return ErrorNodeFactory.createInvalidJsonExampleNode("Source example is not valid: " + node); + } + + JsonNode json = parseJson(value); + + ProcessingReport report = schema.validate(json); + Iterator iterator = report.iterator(); + List errors = new ArrayList<>(); + while (iterator.hasNext()) { + ProcessingMessage next = iterator.next(); + LogLevel logLevel = next.getLogLevel(); + + if (logLevel.equals(ERROR) || (logLevel.equals(WARNING) && FAIL_ON_WARNING)) { + errors.add(processErrorMessage(next.toString())); + } + } + + if (!errors.isEmpty()) { + return ErrorNodeFactory.createInvalidJsonExampleNode("{\n" + String.join("\n", errors) + "\n}"); + } + } catch (JsonParseException e) { + return ErrorNodeFactory.createInvalidJsonExampleNode(e.getOriginalMessage()); + } catch (IOException | ProcessingException e) { + return ErrorNodeFactory.createInvalidJsonExampleNode("Invalid json content. " + e.getMessage()); + } + return node; + } + + @Override + public String getDescription() { + return "JSON Schema validation rule"; + } + + private String processErrorMessage(String processingMessage) { + final String SCHEMA_TEXT = "schema: {\"loadingURI\":\""; + final String POINTER_TEXT = "\"pointer\":\""; + + int startOfSchema = processingMessage.indexOf(SCHEMA_TEXT); + + // If it is true then loadingUri is present in the message and we have to modify it + if (startOfSchema >= 0) { + int startOfPointer = processingMessage.indexOf(POINTER_TEXT); + String completeUri = processingMessage.substring(startOfSchema + SCHEMA_TEXT.length(), startOfPointer - 2); + + // Finding the filename: It begins after the last '/' in the uri. + // If there is no '/', we display the entire processingMessage + String reducedSchemaURI = completeUri.substring(completeUri.lastIndexOf('/') + 1); + + // Replacing the complete URI with the reduced one + return processingMessage.replace(completeUri, reducedSchemaURI); + } + + return processingMessage; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/NodeReferenceFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/NodeReferenceFactory.java new file mode 100644 index 0000000..9c108af --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/NodeReferenceFactory.java @@ -0,0 +1,155 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.rule; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.xbib.raml.internal.impl.commons.nodes.AbstractReferenceNode; +import org.xbib.raml.internal.impl.commons.nodes.AnnotationTypeNode; +import org.xbib.raml.internal.impl.commons.nodes.ContextAwareNode; +import org.xbib.raml.internal.impl.commons.nodes.ContextAwareStringNodeImpl; +import org.xbib.raml.internal.impl.commons.nodes.ResourceTypeNode; +import org.xbib.raml.internal.impl.commons.nodes.SecuritySchemeNode; +import org.xbib.raml.internal.impl.commons.nodes.TraitNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationField; +import org.xbib.raml.internal.impl.v10.nodes.LibraryNode; +import org.xbib.raml.internal.impl.v10.nodes.LibraryRefNode; +import org.xbib.raml.yagi.framework.grammar.rule.ClassNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.NodeFactory; +import org.xbib.raml.yagi.framework.nodes.AbstractRamlNode; +import org.xbib.raml.yagi.framework.nodes.NamedNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.Position; +import org.xbib.raml.yagi.framework.util.NodeSelector; +import static java.lang.System.arraycopy; + +public class NodeReferenceFactory implements NodeFactory { + + private static final Map> DECLARATION_SECTIONS; + + private static final String TYPES = "types"; + private static final String SCHEMAS = "schemas"; + private static final String RESOURCE_TYPES = "resourceTypes"; + private static final String TRAITS = "traits"; + private static final String SECURITY_SCHEMES = "securitySchemes"; + private static final String ANNOTATION_TYPES = "annotationTypes"; + + static { + DECLARATION_SECTIONS = new HashMap<>(); + DECLARATION_SECTIONS.put(TYPES, TypeDeclarationField.class); + DECLARATION_SECTIONS.put(SCHEMAS, TypeDeclarationField.class); + DECLARATION_SECTIONS.put(RESOURCE_TYPES, ResourceTypeNode.class); + DECLARATION_SECTIONS.put(TRAITS, TraitNode.class); + DECLARATION_SECTIONS.put(SECURITY_SCHEMES, SecuritySchemeNode.class); + DECLARATION_SECTIONS.put(ANNOTATION_TYPES, AnnotationTypeNode.class); + } + + private final NodeFactory defaultFactory; + + public NodeReferenceFactory(Class referenceClassNode) { + defaultFactory = new ClassNodeFactory(referenceClassNode); + } + + @Override + public Node create(Node currentNode, Object... args) { + final String value = (String) args[0]; + return parse(currentNode, value, 0); + } + + public Node parse(Node currentNode, String value, int startLocation) { + + final String[] parts = getParts(currentNode, value); + + if (parts.length > 2) { + return RamlErrorNodeFactory.createInvalidLibraryChaining(value); + } + Node result = null; + Node parent = null; + int currentShift = value.length(); + for (int i = parts.length - 1; i >= 0; i--) { + String part = parts[i]; + currentShift -= part.length(); + final Position endPosition = currentNode.getStartPosition().rightShift(startLocation + currentShift + value.length()); + final Position startPosition = currentNode.getStartPosition().rightShift(startLocation + currentShift); + if (parent == null) { + parent = defaultFactory.create(currentNode, part); + if (parent instanceof AbstractRamlNode) { + ((AbstractRamlNode) parent).setStartPosition(startPosition); + ((AbstractRamlNode) parent).setEndPosition(endPosition); + } + result = parent; + } else { + final LibraryRefNode libraryRefNode = new LibraryRefNode(part); + libraryRefNode.setStartPosition(startPosition); + libraryRefNode.setEndPosition(endPosition); + parent.addChild(libraryRefNode); + parent = libraryRefNode; + // The 1 is from the dot + currentShift -= 1; + } + if (i == 0) { + if (currentNode instanceof ContextAwareStringNodeImpl && parent instanceof AbstractReferenceNode) { + parent.setContextNode(((ContextAwareNode) currentNode).getReferenceContext()); + } + } + } + return result; + } + + private String[] getParts(Node currentNode, String value) { + if (!value.contains(".") || existsAsDeclaration(currentNode, value)) + return new String[]{value}; + + final String[] allParts = value.split("\\."); + + final Node libraryDeclarationsNode = NodeSelector.selectFrom("uses", currentNode.getRootNode()); + if (libraryDeclarationsNode != null) { + final List libraryDeclarations = libraryDeclarationsNode.findDescendantsWith(LibraryNode.class); + String libraryName = ""; + for (int i = 0; i < allParts.length - 1; i++) { + libraryName = i == 0 ? allParts[i] : libraryName + "." + allParts[i]; + for (LibraryNode libraryDeclaration : libraryDeclarations) { + if (libraryName.equalsIgnoreCase(libraryDeclaration.getName())) { + final int length = allParts.length - i; + final String[] libraryReferenceParts = new String[length]; + libraryReferenceParts[0] = libraryName; + arraycopy(allParts, i + 1, libraryReferenceParts, 1, length - 1); + return libraryReferenceParts; + } + } + } + } + + return allParts; + } + + private boolean existsAsDeclaration(Node currentNode, String value) { + for (Map.Entry> declarationSection : DECLARATION_SECTIONS.entrySet()) { + final Node node = NodeSelector.selectFrom(declarationSection.getKey(), currentNode.getRootNode()); + + if (node == null) + continue; + + final List descendants = node.findDescendantsWith(declarationSection.getValue()); + for (NamedNode descendant : descendants) { + if (descendant.getName().equalsIgnoreCase(value)) + return true; + } + } + return false; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/NodeReferenceRule.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/NodeReferenceRule.java new file mode 100644 index 0000000..7e72bbe --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/NodeReferenceRule.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.rule; + +import java.util.List; +import org.xbib.raml.internal.impl.commons.suggester.ReferenceSuggester; +import org.xbib.raml.yagi.framework.grammar.rule.StringTypeRule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class NodeReferenceRule extends StringTypeRule { + + private final ReferenceSuggester suggester; + + public NodeReferenceRule(String referenceKey) { + this.suggester = new ReferenceSuggester(referenceKey); + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return suggester.getSuggestions(node); + } + + @Override + public Node apply(Node node) { + if (node instanceof ReferenceNode) { + return node; + } else { + return super.apply(node); + } + } + + @Override + public boolean matches(Node node) { + return node instanceof SimpleTypeNode || node instanceof ReferenceNode; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/ParametrizedNodeReferenceRule.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/ParametrizedNodeReferenceRule.java new file mode 100644 index 0000000..075e744 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/ParametrizedNodeReferenceRule.java @@ -0,0 +1,78 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.ParametrizedReferenceNode; +import org.xbib.raml.internal.impl.commons.suggester.ReferenceSuggester; +import org.xbib.raml.yagi.framework.grammar.rule.ObjectRule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class ParametrizedNodeReferenceRule extends ObjectRule { + + private final ReferenceSuggester suggester; + + public ParametrizedNodeReferenceRule(String referenceKey) { + suggester = new ReferenceSuggester(referenceKey); + } + + @Override + public boolean matches(Node node) { + // It should have at least one key value pair + return (super.matches(node) && hasOneKey(node)) || node instanceof ParametrizedReferenceNode; + } + + private boolean hasOneKey(Node node) { + return !node.getChildren().isEmpty() && !node.getChildren().get(0).getChildren().isEmpty(); + } + + + @Override + public List getSuggestions(List pathToRoot, ParsingContext context) { + if (pathToRoot.size() == 1) { + return getSuggestions(pathToRoot.get(0), context); + } + return Collections.emptyList(); + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + if (hasOneKey(node)) { + final Node key = node.getChildren().get(0).getChildren().get(0); + return suggester.getSuggestions(key); + } else { + return super.getSuggestions(node, context); + } + } + + @Override + protected Node getResult(Node node) { + if (node instanceof ParametrizedReferenceNode) { + return node; + } + final String arg = node.getChildren().get(0).getChildren().get(0).toString(); + return createNodeUsingFactory(node, arg); + } + + @Override + public String getDescription() { + return "Parametrized reference call."; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/RamlErrorNodeFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/RamlErrorNodeFactory.java new file mode 100644 index 0000000..ddfa68f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/RamlErrorNodeFactory.java @@ -0,0 +1,79 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.rule; + + +import java.util.List; +import org.xbib.raml.api.model.v10.declarations.AnnotationTarget; +import org.xbib.raml.internal.impl.commons.nodes.FacetNode; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class RamlErrorNodeFactory { + + public static ErrorNode createInvalidAnnotationTarget(List allowedTargets, AnnotationTarget target) { + return new ErrorNode("Annotation not allowed at target: " + target + ". Allowed targets are: " + allowedTargets); + } + + public static ErrorNode createInvalidUriTemplate() { + return new ErrorNode("Invalid uri template syntax"); + } + + public static ErrorNode createInvalidFacetState(String type, String message) { + String prefix = "Invalid facets"; + if (type != null) { + prefix += " for type " + type; + } + return new ErrorNode(prefix + ": " + message); + } + + public static ErrorNode createInvalidRequiredFacet(String property) { + return new ErrorNode("Required property '" + property + "' cannot be made optional"); + } + + public static ErrorNode createCanNotOverrideCustomFacet(String facetName, String typeName) { + return new ErrorNode("Custom facet '" + facetName + "' cannot be set as it is already defined by " + typeName + "."); + } + + public static ErrorNode createCanNotOverrideNativeFacet(String facetName) { + return new ErrorNode("Custom facet '" + facetName + "' cannot be defined as is already defined by this type."); + } + + public static ErrorNode createCanNotOverrideProperty(String propertyName) { + return new ErrorNode("Property '" + propertyName + "' cannot be overwritten."); + } + + public static ErrorNode createPropertyCanNotBeOfSchemaType(String propertyName) { + return new ErrorNode("Property '" + propertyName + "' cannot have a schema type."); + } + + public static ErrorNode createRecurrentTypeDefinition(String typeName) { + return new ErrorNode("Recurrent type definition: " + typeName + "."); + } + + public static ErrorNode createInvalidLibraryChaining(String value) { + return new ErrorNode("Library references cannot be chained: " + value); + } + + public static ErrorNode createInvalidFacetForType(FacetNode facetNode, String typeName) { + return new ErrorNode("Facet '" + facetNode.getName() + "' cannot be applied to " + typeName); + } + + public static Node createInvalidFormatValue(String value, String format) { + return new ErrorNode(value + " is not a valid " + format + " value"); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/SchemaDeclarationRule.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/SchemaDeclarationRule.java new file mode 100644 index 0000000..f61d420 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/SchemaDeclarationRule.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.internal.utils.SchemaGenerator; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class SchemaDeclarationRule extends Rule { + @Override + public boolean matches(Node node) { + if (node instanceof StringNode) { + final String value = ((StringNode) node).getValue(); + return SchemaGenerator.isJsonSchema(value) || SchemaGenerator.isXmlSchema(value); + } else { + return false; + } + } + + + @Override + public Node apply(Node node) { + if (matches(node)) { + return createNodeUsingFactory(node, ((StringNode) node).getValue()); + } else { + return ErrorNodeFactory.createInvalidNode(node); + } + } + + @Override + public String getDescription() { + return "External schema."; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/XmlSchemaValidationRule.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/XmlSchemaValidationRule.java new file mode 100644 index 0000000..356cf29 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/rule/XmlSchemaValidationRule.java @@ -0,0 +1,139 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.rule; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.dom.DOMSource; +import javax.xml.validation.Schema; +import org.w3c.dom.Document; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.internal.impl.commons.type.XmlSchemaExternalType; +import org.xbib.raml.internal.utils.SchemaGenerator; +import org.xbib.raml.internal.utils.xml.XMLLocalConstants; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * Validates a string node content with the specified xml schema + */ +public class XmlSchemaValidationRule extends Rule { + + private Schema schema; + private String type; + + public XmlSchemaValidationRule(XmlSchemaExternalType schemaNode, ResourceLoader resourceLoader) { + try { + this.schema = SchemaGenerator.generateXmlSchema(resourceLoader, schemaNode); + this.type = schemaNode.getInternalFragment(); + } catch (SAXException e) { + this.schema = null; + } + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return new ArrayList<>(); + } + + @Override + public boolean matches(Node node) { + return node instanceof StringNode; + } + + + @Override + public Node apply(Node node) { + if (schema == null) { + return ErrorNodeFactory.createInvalidXmlExampleNode("Invalid XmlSchema"); + } + if (node instanceof SimpleTypeNode) { + return validateXmlExample(node); + } + // else We only validate xml schema against xml examples so we do nothing + return node; + } + + private Node validateXmlExample(Node node) { + String value = ((SimpleTypeNode) node).getLiteralValue(); + try { + if (this.type != null) { + final QName rootElement = getRootElement(value); + if (rootElement != null && !rootElement.getLocalPart().equals(type)) { + return ErrorNodeFactory.createInvalidXmlExampleNode("Provided object is not of type " + this.type); + } + } + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + setFeatures(factory); + + DocumentBuilder builder = factory.newDocumentBuilder(); + builder.setErrorHandler(null); + Document document = builder.parse(new InputSource(new StringReader(value))); + + schema.newValidator().validate(new DOMSource(document.getDocumentElement())); + } catch (XMLStreamException | SAXException | IOException | ParserConfigurationException e) { + return ErrorNodeFactory.createInvalidXmlExampleNode(e.getMessage()); + } + return node; + } + + private void setFeatures(DocumentBuilderFactory dbf) throws ParserConfigurationException { + String feature = null; + + // If you can't completely disable DTDs, then at least do the following: + dbf.setFeature(XMLLocalConstants.EXTERNAL_GENERAL_ENTITIES_FEATURE, XMLLocalConstants.externalEntities); + + dbf.setFeature(XMLLocalConstants.EXTERNAL_PARAMETER_ENTITIES_FEATURE, XMLLocalConstants.externalEntities); + + dbf.setFeature(XMLLocalConstants.DISALLOW_DOCTYPE_DECL_FEATURE, !XMLLocalConstants.expandEntities); + + // and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks" (see reference below) + dbf.setXIncludeAware(XMLLocalConstants.expandEntities); + dbf.setExpandEntityReferences(XMLLocalConstants.expandEntities); + dbf.setNamespaceAware(true); + } + + + public QName getRootElement(String xmlContent) throws XMLStreamException { + XMLInputFactory f = XMLInputFactory.newInstance(); + XMLStreamReader r = f.createXMLStreamReader(new StringReader(xmlContent)); + r.nextTag(); + return r.getName(); + } + + @Override + public String getDescription() { + return "Xml Schema validation Rule."; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/suggester/ReferenceSuggester.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/suggester/ReferenceSuggester.java new file mode 100644 index 0000000..34a8fab --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/suggester/ReferenceSuggester.java @@ -0,0 +1,103 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.suggester; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.DefaultSuggestion; +import org.xbib.raml.yagi.framework.suggester.Suggestion; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class ReferenceSuggester { + + private final String referenceKey; + + public ReferenceSuggester(String referenceKey) { + this.referenceKey = referenceKey; + } + + + public List getSuggestions(Node node) { + final List result = new ArrayList<>(); + Node contextNode = node.getRootNode(); + if (node instanceof StringNode) { + final String value = ((StringNode) node).getValue(); + final String[] library = value.split("\\."); + for (int i = 0; i < library.length - 1 && contextNode != null; i++) { + contextNode = NodeSelector.selectFrom(Raml10Grammar.USES_KEY_NAME + "/*/" + library[i], contextNode); + } + } + if (contextNode != null) { + final Node selectFrom = NodeSelector.selectFrom(referenceKey, contextNode); + addSuggestions(result, selectFrom); + final Node libraries = NodeSelector.selectFrom(Raml10Grammar.USES_KEY_NAME, contextNode); + addSuggestions(result, libraries); + } + return result; + } + + private void addSuggestions(List result, Node selectFrom) { + if (selectFrom != null) { + if (selectFrom instanceof ObjectNode) { + collectSuggestions(result, selectFrom); + } else if (selectFrom instanceof ArrayNode) { + final List children = selectFrom.getChildren(); + for (Node child : children) { + collectSuggestions(result, child); + } + } + } + } + + private void collectSuggestions(List result, Node selectFrom) { + final List children = selectFrom.getChildren(); + for (Node child : children) { + if (!child.getChildren().isEmpty()) { + final String value = child.getChildren().get(0).toString(); + final Node grandchild = child.getChildren().get(1); + + if (grandchild instanceof ArrayNode) // in case of a multiple inherited type + { + final List referenceNodes = grandchild.getChildren(); + for (Node referenceNode : referenceNodes) { + collectReferenceNodeSuggestions(result, value, referenceNode); + } + } else { + collectReferenceNodeSuggestions(result, value, grandchild); + } + } + } + } + + private void collectReferenceNodeSuggestions(List result, String value, Node grandchild) { + final Node description = NodeSelector.selectFrom("usage", grandchild); + String descriptionText = ""; + if (description != null) { + descriptionText = description.toString(); + } else { + final Node usage = NodeSelector.selectFrom("description", grandchild); + if (usage != null) { + descriptionText = usage.toString(); + } + } + result.add(new DefaultSuggestion(value, descriptionText, value)); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/suggester/ReferenceTypeSuggester.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/suggester/ReferenceTypeSuggester.java new file mode 100644 index 0000000..7842d66 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/suggester/ReferenceTypeSuggester.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.suggester; + +import java.util.Iterator; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.SYStringNode; +import org.xbib.raml.yagi.framework.suggester.DefaultSuggestion; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class ReferenceTypeSuggester extends ReferenceSuggester { + + public ReferenceTypeSuggester(String referenceKey) { + super(referenceKey); + } + + + public List getSuggestions(Node node) { + List result = super.getSuggestions(node); + String self = getSelfType(node); + if (!result.isEmpty()) { + Iterator suggestionIterator = result.iterator(); + while (suggestionIterator.hasNext()) { + if (suggestionIterator.next().getValue().equals(self)) { + suggestionIterator.remove(); + } + } + } + result.add(new DefaultSuggestion("object", null, "Object")); + return result; + } + + private String getSelfType(Node node) { + return ((SYStringNode) ((KeyValueNode) node.getParent().getParent().getParent()).getKey()).getValue(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/AbstractExternalType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/AbstractExternalType.java new file mode 100644 index 0000000..a165e63 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/AbstractExternalType.java @@ -0,0 +1,126 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.type; + +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.FacetNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationField; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.yagi.framework.util.NodeUtils; + +public abstract class AbstractExternalType extends BaseType implements SchemaBasedResolvedType { + + private final String schemaValue; + private final String schemaPath; + private final String internalFragment; + + public AbstractExternalType(TypeExpressionNode from, String schemaValue, String schemaPath, String internalFragment) { + super(getExternalTypeName(from), from, new ResolvedCustomFacets()); + this.schemaValue = schemaValue; + this.schemaPath = schemaPath; + this.internalFragment = internalFragment; + } + + public AbstractExternalType(AbstractExternalType externalType) { + super(externalType.getTypeName(), externalType.getTypeExpressionNode(), new ResolvedCustomFacets()); + this.schemaValue = externalType.schemaValue; + this.schemaPath = externalType.schemaPath; + this.internalFragment = externalType.internalFragment; + } + + protected abstract AbstractExternalType copy(); + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + return copy(); + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + return copy(); + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + List facetNodes = from.findDescendantsWith(FacetNode.class); + for (FacetNode facetNode : facetNodes) { + facetNode.replaceWith(RamlErrorNodeFactory.createInvalidFacetForType(facetNode, getClass().getSimpleName())); + } + } + + @Override + public void validateState() { + super.validateState(); + } + + public String getSchemaValue() { + return schemaValue; + } + + public String getSchemaPath() { + return schemaPath; + } + + public String getInternalFragment() { + return internalFragment; + } + + public static String getExternalTypeName(TypeExpressionNode node) { + TypeDeclarationField ancestor = NodeUtils.getAncestor(node, TypeDeclarationField.class); + if (ancestor != null) { + return ancestor.getName(); + } else { + return "Schema"; + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((internalFragment == null) ? 0 : internalFragment.hashCode()); + result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode()); + result = prime * result + ((schemaValue == null) ? 0 : schemaValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AbstractExternalType other = (AbstractExternalType) obj; + if (internalFragment == null) { + if (other.internalFragment != null) + return false; + } else if (!internalFragment.equals(other.internalFragment)) + return false; + if (schemaPath == null) { + if (other.schemaPath != null) + return false; + } else if (!schemaPath.equals(other.schemaPath)) + return false; + if (schemaValue == null) { + return other.schemaValue == null; + } else return schemaValue.equals(other.schemaValue); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/BaseType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/BaseType.java new file mode 100644 index 0000000..817b3af --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/BaseType.java @@ -0,0 +1,131 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.type; + +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationField; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.v10.type.UnionResolvedType; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public abstract class BaseType implements ResolvedType { + + protected ResolvedCustomFacets customFacets; + private TypeExpressionNode typeExpressionNode; + private String typeName; + + public BaseType(String typeName, TypeExpressionNode typeExpressionNode, ResolvedCustomFacets customFacets) { + this.typeExpressionNode = typeExpressionNode; + this.customFacets = customFacets; + this.typeName = typeName; + } + + public ResolvedType setTypeNode(TypeExpressionNode typeNode) { + BaseType copy = copy(); + copy.typeExpressionNode = typeNode; + return copy; + } + + protected abstract BaseType copy(); + + @Override + public ResolvedCustomFacets customFacets() { + return customFacets; + } + + protected void overwriteFacets(BaseType from, TypeDeclarationNode node) { + if (node.getParent() instanceof TypeDeclarationField) { + from.typeName = ((SimpleTypeNode) ((TypeDeclarationField) node.getParent()).getKey()).getLiteralValue(); + } else if (!isTypeReference(node)) { + from.typeName = getBuiltinTypeName(); + } + } + + private boolean isTypeReference(TypeDeclarationNode node) { + return (node.getSource() instanceof SimpleTypeNode) || isObjectWithOnlyTypeDecl(node); + } + + /** + * This method detects the pattern of + * type: + * MyType + * So that we can treat this as a reference to the node. + */ + protected boolean isObjectWithOnlyTypeDecl(final Node node) { + return node instanceof ObjectNode && NodeSelector.selectFrom("properties", node) == null; + } + + @Override + public final boolean accepts(ResolvedType valueType) { + if (valueType instanceof UnionResolvedType) { + List toAcceptOptions = ((UnionResolvedType) valueType).of(); + for (ResolvedType toAcceptOption : toAcceptOptions) { + if (!doAccept(toAcceptOption)) { + return false; + } + } + return true; + } else { + return doAccept(valueType); + } + } + + public boolean doAccept(ResolvedType resolvedType) { + // Only accepts my types + return this.getClass().equals(resolvedType.getClass()); + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + + @Override + public String getTypeName() { + return typeName; + } + + + @Override + public String getBuiltinTypeName() { + return null; + } + + @Override + public TypeExpressionNode getTypeExpressionNode() { + return typeExpressionNode; + } + + + @Override + public void validateState() { + + } + + + public static String getTypeName(TypeExpressionNode typeExpressionNode, String defaultName) { + if (typeExpressionNode.getParent() instanceof TypeDeclarationField) { + return ((SimpleTypeNode) ((TypeDeclarationField) typeExpressionNode.getParent()).getKey()).getLiteralValue(); + } else { + return defaultName; + } + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/JsonSchemaExternalType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/JsonSchemaExternalType.java new file mode 100644 index 0000000..e279ca9 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/JsonSchemaExternalType.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.type; + +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.v10.type.TypeVisitor; + +public class JsonSchemaExternalType extends AbstractExternalType { + + public JsonSchemaExternalType(TypeExpressionNode from, String schemaValue, String schemaPath, String internalFragment) { + super(from, schemaValue, schemaPath, internalFragment); + } + + public JsonSchemaExternalType(JsonSchemaExternalType externalType) { + super(externalType); + } + + protected JsonSchemaExternalType copy() { + return new JsonSchemaExternalType(this); + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitJson(this); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/ResolvedCustomFacets.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/ResolvedCustomFacets.java new file mode 100644 index 0000000..4e5f9a3 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/ResolvedCustomFacets.java @@ -0,0 +1,90 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.type; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.xbib.raml.internal.impl.commons.nodes.CustomFacetDefinitionNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; + +public class ResolvedCustomFacets { + private final Map customFacets; + private final List nativeFacets; + + public ResolvedCustomFacets(String... nativeFacets) { + this(Arrays.asList(nativeFacets), new HashMap()); + } + + public ResolvedCustomFacets(List nativeFacets, Map facets) { + this.customFacets = facets; + this.nativeFacets = nativeFacets; + } + + /** + * Checks if it can be inherited by the specified type + * + * @param from + * @return + */ + public TypeDeclarationNode validate(TypeDeclarationNode from) { + + final List customFacets = from.getCustomFacets(); + for (CustomFacetDefinitionNode customFacet : customFacets) { + if (nativeFacets.contains(customFacet.getFacetName())) { + customFacet.replaceWith(RamlErrorNodeFactory.createCanNotOverrideNativeFacet(customFacet.getFacetName())); + } else if (this.customFacets.containsKey(customFacet.getFacetName())) { + final TypeDeclarationNode parentTypeDeclaration = customFacet.findAncestorWith(TypeDeclarationNode.class); + final String typeName = parentTypeDeclaration != null ? parentTypeDeclaration.getTypeName() : ""; + customFacet.replaceWith(RamlErrorNodeFactory.createCanNotOverrideCustomFacet(customFacet.getFacetName(), typeName)); + } + } + return from; + } + + public ResolvedCustomFacets mergeWith(ResolvedCustomFacets customFacets) { + final ResolvedCustomFacets copy = copy(); + copy.customFacets.putAll(customFacets.customFacets); + return copy; + } + + public List getRules() { + List rules = new ArrayList<>(); + for (CustomFacetDefinitionNode facetDefinitionNode : customFacets.values()) { + rules.add(facetDefinitionNode.getFacetRule()); + } + return rules; + } + + public ResolvedCustomFacets copy() { + return new ResolvedCustomFacets(nativeFacets, new HashMap<>(this.customFacets)); + } + + public ResolvedCustomFacets overwriteFacets(TypeDeclarationNode from) { + final Map facets = new HashMap<>(this.customFacets); + final List customFacets = from.getCustomFacets(); + for (CustomFacetDefinitionNode customFacet : customFacets) { + facets.put(customFacet.getFacetName(), customFacet); + } + return new ResolvedCustomFacets(nativeFacets, facets); + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/ResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/ResolvedType.java new file mode 100644 index 0000000..b977141 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/ResolvedType.java @@ -0,0 +1,100 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.type; + + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.v10.type.TypeVisitor; + +/** + * Represents a resolved type in the type system. + * It describes all the facets of a type. + */ +public interface ResolvedType { + /** + * Returns a new type definition with the facets being overwritten from the specified node + * + * @param from The node from where to load the facets + * @return A new type + */ + ResolvedType overwriteFacets(TypeDeclarationNode from); + + /** + * Returns a new type definition after merging the facets of both Types + * + * @param with The type definition to merge with + * @return The new type + */ + ResolvedType mergeFacets(ResolvedType with); + + ResolvedType setTypeNode(TypeExpressionNode typeNode); + + /** + * Dispatch the implementation to the visitor method + * + * @param visitor The visitor + * @param The result type + * @return The result of the visitor execution + */ + T visit(TypeVisitor visitor); + + /** + * Returns the type name if any + * + * @return The type name + */ + String getTypeName(); + + /** + * Returns the builtin type name. + * returns null for builtin types without explicit names + * (xsd, json schema, any, unions) + * + * @return The builtin type name + */ + + String getBuiltinTypeName(); + + /** + * The type declaration node that define this type + * + * @return The node + */ + TypeExpressionNode getTypeExpressionNode(); + + /** + * Validate state consistency + */ + void validateState(); + + /** + * Validate if this type can be overwritten by the specified node + * + * @param from The node to check with + */ + void validateCanOverwriteWith(TypeDeclarationNode from); + + /** + * Returns the custom facets definitions of this type + * + * @return The custom facets definition. + */ + + ResolvedCustomFacets customFacets(); + + boolean accepts(ResolvedType valueType); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/SchemaBasedResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/SchemaBasedResolvedType.java new file mode 100644 index 0000000..d767a5f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/SchemaBasedResolvedType.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.type; + +/** + * Type descriptor for external schema based type descriptor e.g JsonSchema or XmlSchema. + */ +public interface SchemaBasedResolvedType extends ResolvedType { + /** + * The schema string content + * + * @return The schema content + */ + String getSchemaValue(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/XmlSchemaExternalType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/XmlSchemaExternalType.java new file mode 100644 index 0000000..905cef4 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/commons/type/XmlSchemaExternalType.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.commons.type; + +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.v10.type.TypeVisitor; + +public class XmlSchemaExternalType extends AbstractExternalType { + public XmlSchemaExternalType(TypeExpressionNode from, String schemaValue, String schemaPath, String internalFragment) { + super(from, schemaValue, schemaPath, internalFragment); + } + + public XmlSchemaExternalType(XmlSchemaExternalType externalType) { + super(externalType); + } + + @Override + protected XmlSchemaExternalType copy() { + return new XmlSchemaExternalType(this); + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitXml(this); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/emitter/tck/TckEmitter.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/emitter/tck/TckEmitter.java new file mode 100644 index 0000000..0c14198 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/emitter/tck/TckEmitter.java @@ -0,0 +1,239 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.emitter.tck; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.AnnotationNode; +import org.xbib.raml.internal.impl.commons.nodes.MethodNode; +import org.xbib.raml.internal.impl.commons.nodes.ResourceNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.v10.nodes.LibraryRefNode; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NullNode; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.SYObjectNode; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.nodes.MappingNode; +import org.yaml.snakeyaml.nodes.NodeTuple; +import org.yaml.snakeyaml.nodes.Tag; + +public class TckEmitter { + + private static final String INDENTATION = " "; + private static final String START_MAP = "{"; + private static final String END_MAP = "}"; + private static final String START_ARRAY = "["; + private static final String END_ARRAY = "]"; + private static final String COMMA_SEP = ",\n"; + private static final String COLON_SEP = ": "; + private static final String NEWLINE = "\n"; + + public String dump(Node raml) { + int depth = 0; + StringBuilder dump = new StringBuilder(); + dumpObject((ObjectNode) raml, dump, depth); + removeLastSeparator(dump); + return dump.toString(); + } + + private void dumpNode(Node node, StringBuilder dump, int depth) { + if (node instanceof ObjectNode) { + dumpObject((ObjectNode) node, dump, depth); + } else if (node instanceof ArrayNode) { + dumpArray((ArrayNode) node, dump, depth); + } else if (node instanceof ReferenceNode) { + dumpReference((ReferenceNode) node, dump); + } else if (node instanceof NullNode) { + dumpNullNode(dump); + } else if (node instanceof SimpleTypeNode) { + dumpString((SimpleTypeNode) node, dump); + } else if (node instanceof TypeExpressionNode) { + // ignore + } else if (node instanceof ErrorNode) { + throw new RuntimeException("Error node : " + ((ErrorNode) node).getErrorMessage()); + } else { + throw new RuntimeException("Unsupported node type: " + node.getClass().getSimpleName()); + } + } + + private void dumpReference(ReferenceNode node, StringBuilder dump) { + dump.append(sanitizeScalarValue(node.getRefName())).append(COMMA_SEP); + } + + private void dumpArray(ArrayNode arrayNode, StringBuilder dump, int depth) { + dump.append(START_ARRAY); + for (Node node : arrayNode.getChildren()) { + dumpNode(node, dump, depth + 1); + } + removeLastSeparator(dump); + dump.append(END_ARRAY).append(COMMA_SEP); + } + + private void dumpNullNode(StringBuilder dump) { + dump.append(START_MAP).append(END_MAP).append(COMMA_SEP); + } + + private void dumpString(SimpleTypeNode node, StringBuilder dump) { + dump.append(sanitizeScalarValue(node.getValue())).append(COMMA_SEP); + } + + private void dumpObject(ObjectNode objectNode, StringBuilder dump, int depth) { + List resourceNodes = new ArrayList<>(); + List methodNodes = new ArrayList<>(); + List annotationNodes = new ArrayList<>(); + + startMap(dump, depth); + + for (Node node : objectNode.getChildren()) { + if (node instanceof LibraryRefNode) { + // ignore + continue; + } + if (!(node instanceof KeyValueNode)) { + throw new RuntimeException("Expecting KeyValueNode got " + node + " on " + objectNode); + } + if (node instanceof ResourceNode) { + resourceNodes.add((ResourceNode) node); + continue; + } + if (node instanceof MethodNode) { + methodNodes.add((MethodNode) node); + continue; + } + if (node instanceof AnnotationNode) { + annotationNodes.add((AnnotationNode) node); + continue; + } + + dumpKeyValueNode(dump, depth, (KeyValueNode) node); + + } + dumpCustomArrayIfPresent(dump, depth + 1, methodNodes, "methods", "method"); + dumpCustomArrayIfPresent(dump, depth + 1, resourceNodes, "resources", "relativeUri"); + dumpAnnotationsIfPresent(dump, depth + 1, annotationNodes); + + + removeLastSeparator(dump); + dump.append(addNewline(dump)).append(indent(depth)).append(END_MAP).append(COMMA_SEP); + } + + private void dumpAnnotationsIfPresent(StringBuilder dump, int depth, List annotationNodes) { + if (!annotationNodes.isEmpty()) { + dump.append(addNewline(dump)).append(indent(depth)).append(sanitizeScalarValue("annotations")) + .append(COLON_SEP).append(START_MAP).append(NEWLINE).append(indent(depth + 1)); + + for (KeyValueNode node : annotationNodes) { + String key = node.getKey().toString(); + KeyValueNode copy = new KeyValueNodeImpl(new StringNodeImpl(key.substring(1, key.length() - 1)), node.getValue()); + dumpKeyValueNode(dump, depth, copy); + + } + removeLastSeparator(dump); + dump.append(addNewline(dump)).append(indent(depth)).append(END_MAP).append(COMMA_SEP); + } + } + + private void dumpCustomArrayIfPresent(StringBuilder dump, int depth, List keyValueNodes, String key, String innerKey) { + if (!keyValueNodes.isEmpty()) { + dump.append(addNewline(dump)).append(indent(depth)).append(sanitizeScalarValue(key)) + .append(COLON_SEP).append(START_ARRAY).append(NEWLINE).append(indent(depth + 1)); + + for (KeyValueNode node : keyValueNodes) { + Node copy = copy(node.getValue()); + copy.addChild(0, new KeyValueNodeImpl(new StringNodeImpl(innerKey), node.getKey())); + dumpObject((ObjectNode) copy, dump, depth + 1); + } + removeLastSeparator(dump); + dump.append(addNewline(dump)).append(indent(depth)).append(END_ARRAY).append(COMMA_SEP); + } + } + + private void dumpKeyValueNode(StringBuilder dump, int depth, KeyValueNode node) { + // key + String keyText = sanitizeScalarValue(node.getKey()); + dump.append(addNewline(dump)).append(indent(depth + 1)).append(keyText).append(COLON_SEP); + dumpNode(node.getValue(), dump, depth + 1); + } + + private Node copy(Node node) { + if (node instanceof NullNode) { + node = new SYObjectNode(new MappingNode(Tag.MAP, new ArrayList(), DumperOptions.FlowStyle.AUTO), + node.getStartPosition().createResourceLoader(), + node.getStartPosition().getPath()); + } else { + node = node.copy(); + } + return node; + } + + + // ******* + // helpers + // ******* + + private void startMap(StringBuilder dump, int depth) { + if (dump.toString().endsWith(COMMA_SEP)) { + dump.append(indent(depth)); + } + dump.append(START_MAP).append(NEWLINE); + } + + private void removeLastSeparator(StringBuilder dump) { + if (dump.toString().endsWith(COMMA_SEP)) { + int dumpLength = dump.length(); + dump.delete(dumpLength - COMMA_SEP.length(), dumpLength); + } + } + + private String indent(int depth) { + return INDENTATION.repeat(depth); + } + + private String addNewline(StringBuilder dump) { + return dump.toString().endsWith("\n") ? "" : "\n"; + } + + private String sanitizeScalarValue(Object value) { + if (value instanceof BigDecimal) { + return jsonEscape(((BigDecimal) value).stripTrailingZeros().toString()); + } else if (value instanceof Number || value instanceof Boolean) { + return value.toString(); + } + return jsonEscape(String.valueOf(value)); + } + + private String jsonEscape(String text) { + ObjectMapper objectMapper = new ObjectMapper(); + try { + objectMapper.disableDefaultTyping(); + return objectMapper.writeValueAsString(text); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/Raml10Builder.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/Raml10Builder.java new file mode 100644 index 0000000..b825b6b --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/Raml10Builder.java @@ -0,0 +1,220 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.api.model.v10.RamlFragment; +import org.xbib.raml.internal.impl.RamlBuilder; +import org.xbib.raml.internal.impl.commons.RamlHeader; +import org.xbib.raml.internal.impl.commons.nodes.RamlVersionAnnotation; +import org.xbib.raml.internal.impl.commons.phase.DuplicatedPathsTransformer; +import org.xbib.raml.internal.impl.commons.phase.ExtensionsMerger; +import org.xbib.raml.internal.impl.commons.phase.IncludeResolver; +import org.xbib.raml.internal.impl.commons.phase.RamlFragmentGrammarTransformer; +import org.xbib.raml.internal.impl.commons.phase.RamlFragmentLibraryLinkingTransformer; +import org.xbib.raml.internal.impl.commons.phase.ResourceTypesTraitsTransformer; +import org.xbib.raml.internal.impl.commons.phase.SchemaValidationTransformer; +import org.xbib.raml.internal.impl.commons.phase.StringTemplateExpressionTransformer; +import org.xbib.raml.internal.impl.commons.phase.TypeValidationPhase; +import org.xbib.raml.internal.impl.commons.phase.UnusedParametersTransformer; +import org.xbib.raml.internal.impl.v10.grammar.Raml10GrammarUsesAllowed; +import org.xbib.raml.internal.impl.v10.phase.AnnotationValidationPhase; +import org.xbib.raml.internal.impl.v10.phase.ExampleValidationPhase; +import org.xbib.raml.internal.impl.v10.phase.ImplicitUriParametersInjectionTransformer; +import org.xbib.raml.internal.impl.v10.phase.LibraryLinkingTransformation; +import org.xbib.raml.internal.impl.v10.phase.MediaTypeInjectionPhase; +import org.xbib.raml.internal.impl.v10.phase.ReferenceResolverTransformer; +import org.xbib.raml.internal.utils.Dumper; +import org.xbib.raml.internal.utils.RamlNodeUtils; +import org.xbib.raml.internal.utils.ResourcePathUtils; +import org.xbib.raml.internal.utils.StreamUtils; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.IncludeErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.NodeParser; +import org.xbib.raml.yagi.framework.phase.GrammarPhase; +import org.xbib.raml.yagi.framework.phase.Phase; +import org.xbib.raml.yagi.framework.phase.TransformationPhase; +import static org.xbib.raml.api.model.v10.RamlFragment.Default; +import static org.xbib.raml.api.model.v10.RamlFragment.Extension; +import static org.xbib.raml.api.model.v10.RamlFragment.Overlay; +import static org.xbib.raml.internal.impl.RamlBuilder.FIRST_PHASE; +import static org.xbib.raml.internal.impl.RamlBuilder.LIBRARY_LINK_PHASE; +import static org.xbib.raml.internal.impl.commons.RamlVersion.RAML_10; + +public class Raml10Builder { + + private final Set openedFiles = new HashSet<>(); + private final Map alreadyBuilt = new HashMap<>(); + + public Node build(String stringContent, RamlFragment fragment, ResourceLoader resourceLoader, String resourceLocation, int maxPhaseNumber) throws IOException { + return build(null, stringContent, fragment, resourceLoader, resourceLocation, maxPhaseNumber); + } + + public Node build(Node contextNode, String stringContent, RamlFragment fragment, ResourceLoader resourceLoader, String resourceLocation, int maxPhaseNumber) throws IOException { + String key = resourceLocation + stringContent.hashCode(); + if (alreadyBuilt.containsKey(key)) { + return alreadyBuilt.get(key); + } + + if (openedFiles.contains(resourceLocation)) { + + return new IncludeErrorNode("Cyclic dependency loading file: " + resourceLocation); + } + + try { + openedFiles.add(resourceLocation); + Node rootNode = NodeParser.parse(resourceLoader, resourceLocation, stringContent); + if (rootNode == null) { + return ErrorNodeFactory.createEmptyDocument(); + } + if (contextNode != null) + rootNode.setContextNode(contextNode); + boolean applyExtension = false; + if ((fragment == Extension || fragment == Overlay) && maxPhaseNumber > FIRST_PHASE) { + applyExtension = true; + maxPhaseNumber = LIBRARY_LINK_PHASE; + } + final List phases = createPhases(resourceLoader, fragment); + rootNode = runPhases(rootNode, phases, maxPhaseNumber); + if (applyExtension && !RamlNodeUtils.isErrorResult(rootNode)) { + rootNode = applyExtension(rootNode, resourceLoader, resourceLocation, fragment); + } + rootNode.annotate(new RamlVersionAnnotation(RAML_10)); + alreadyBuilt.put(key, rootNode); + return rootNode; + } finally { + openedFiles.remove(resourceLocation); + } + } + + private Node runPhases(Node rootNode, List phases, int maxPhaseNumber) { + for (int i = 0; i < phases.size(); i++) { + if (i < maxPhaseNumber) { + Phase phase = phases.get(i); + rootNode = phase.apply(rootNode); + + checkDumpPhases(i, phase, rootNode); + if (RamlNodeUtils.isErrorResult(rootNode)) { + break; + } + } + } + return rootNode; + } + + private void checkDumpPhases(int i, Phase phase, Node rootNode) { + if (Boolean.getBoolean("dump.phases")) { + System.out.println("==============================================================="); + System.out.println("After phase = " + i + " --- " + phase.getClass()); + System.out.println("---------------------------------------------------------------"); + Dumper.straightOutput(rootNode); + System.out.println("---------------------------------------------------------------"); + } + } + + private Node applyExtension(Node extensionNode, ResourceLoader resourceLoader, String resourceLocation, RamlFragment fragment) throws IOException { + StringNode baseRef = (StringNode) extensionNode.get("extends"); + String baseLocation = ResourcePathUtils.toAbsoluteLocation(resourceLocation, baseRef.getValue()); + InputStream baseStream = resourceLoader.fetchResource(baseLocation); + if (baseStream == null) { + return ErrorNodeFactory.createBaseRamlNotFound(baseRef.getValue()); + } + String baseContent = StreamUtils.toString(baseStream); + Node baseNode = new RamlBuilder().build(baseContent, resourceLoader, baseLocation); + + if (!RamlNodeUtils.isErrorResult(baseNode)) { + new ExtensionsMerger(fragment == Overlay).merge(baseNode, extensionNode); + if (!RamlNodeUtils.isErrorResult(baseNode)) { + // run all phases on merged document + List phases = createPhases(resourceLoader, Default); + baseNode = runPhases(baseNode, phases, Integer.MAX_VALUE); + } + } + return baseNode; + } + + private List createPhases(ResourceLoader resourceLoader, RamlFragment fragment) { + // The first phase expands the includes. + final TransformationPhase includePhase = new TransformationPhase(new IncludeResolver(resourceLoader), new StringTemplateExpressionTransformer()); + + final TransformationPhase ramlFragmentsValidator = new TransformationPhase(new RamlFragmentGrammarTransformer()); + + final TransformationPhase ramlFragmentsLibraryLinker = new TransformationPhase(new RamlFragmentLibraryLinkingTransformer(this, resourceLoader)); + + // Runs Schema. Applies the Raml rules and changes each node for a more specific. Annotations Library TypeSystem + final GrammarPhase grammarPhase = new GrammarPhase(RamlHeader.getFragmentRule(fragment)); + + // Detect invalid references. Library resourceTypes and Traits. This point the nodes are good enough for Editors. + + // sugar + // Normalize resources and detects duplicated ones and more than one use of url parameters. ??? + final TransformationPhase libraryLink = new TransformationPhase(new LibraryLinkingTransformation(this, resourceLoader)); + + final TransformationPhase referenceCheck = new TransformationPhase(new ReferenceResolverTransformer()); + + // Applies resourceTypes and Traits Library + final TransformationPhase resourcePhase = new TransformationPhase(new ResourceTypesTraitsTransformer(new Raml10GrammarUsesAllowed())); + + final TransformationPhase duplicatedPaths = new TransformationPhase(new DuplicatedPathsTransformer()); + + // Check unused uri parameters + final TransformationPhase checkUnusedParameters = new TransformationPhase(new UnusedParametersTransformer()); + + final TransformationPhase undefinedUriParameterInjection = new TransformationPhase(new ImplicitUriParametersInjectionTransformer()); + + // Run grammar again to re-validate tree + + final AnnotationValidationPhase annotationValidationPhase = new AnnotationValidationPhase(resourceLoader); + + final MediaTypeInjectionPhase mediaTypeInjection = new MediaTypeInjectionPhase(); + + // Schema Types example validation + final TransformationPhase schemaValidationPhase = new TransformationPhase(new SchemaValidationTransformer(resourceLoader)); + + // Checks types consistency and custom facets + final TypeValidationPhase typeValidationPhase = new TypeValidationPhase(); + + final ExampleValidationPhase exampleValidationPhase = new ExampleValidationPhase(resourceLoader); + + return Arrays.asList(includePhase, + ramlFragmentsValidator, + ramlFragmentsLibraryLinker, + grammarPhase, + libraryLink, + referenceCheck, + resourcePhase, + duplicatedPaths, + checkUnusedParameters, + undefinedUriParameterInjection, + annotationValidationPhase, + mediaTypeInjection, + grammarPhase, + schemaValidationPhase, + typeValidationPhase, + exampleValidationPhase); + + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/grammar/AuthorizationUriRequiredField.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/grammar/AuthorizationUriRequiredField.java new file mode 100644 index 0000000..f8d63f0 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/grammar/AuthorizationUriRequiredField.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.grammar; + +import org.xbib.raml.yagi.framework.grammar.rule.RequiredField; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; + + +public class AuthorizationUriRequiredField implements RequiredField { + + @Override + public boolean isRequiredField(Node parent) { + ArrayNode grants = (ArrayNode) NodeSelector.selectFrom("authorizationGrants", parent); + if (grants != null) { + for (Node grantNode : grants.getChildren()) { + String grant = ((StringNode) grantNode).getValue(); + if ("implicit".equals(grant) || "authorization_code".equals(grant)) { + return true; + } + } + } + return false; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/grammar/BuiltInScalarType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/grammar/BuiltInScalarType.java new file mode 100644 index 0000000..fda7339 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/grammar/BuiltInScalarType.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.grammar; + +public enum BuiltInScalarType { + STRING("string"), NUMBER("number"), INTEGER("integer"), BOOLEAN("boolean"), DATE_ONLY("date-only"), TIME_ONLY("time-only"), DATE_TIME_ONLY("datetime-only"), DATE_TIME("datetime"), FILE("file"); + + private final String type; + + BuiltInScalarType(String type) { + this.type = type; + } + + public static boolean isBuiltInScalarType(String type) { + for (BuiltInScalarType builtInScalarType : values()) { + if (builtInScalarType.type.equals(type)) { + return true; + } + } + return false; + } + + public String getType() { + return this.type; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/grammar/Raml10Grammar.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/grammar/Raml10Grammar.java new file mode 100644 index 0000000..57df04d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/grammar/Raml10Grammar.java @@ -0,0 +1,811 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.grammar; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.api.model.v10.declarations.AnnotationTarget; +import org.xbib.raml.internal.impl.commons.grammar.BaseRamlGrammar; +import org.xbib.raml.internal.impl.commons.nodes.AnnotationNode; +import org.xbib.raml.internal.impl.commons.nodes.AnnotationReferenceNode; +import org.xbib.raml.internal.impl.commons.nodes.AnnotationTypeNode; +import org.xbib.raml.internal.impl.commons.nodes.AnnotationTypesNode; +import org.xbib.raml.internal.impl.commons.nodes.CustomFacetDefinitionNode; +import org.xbib.raml.internal.impl.commons.nodes.DocumentationItemNode; +import org.xbib.raml.internal.impl.commons.nodes.ExampleDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.ExamplesNode; +import org.xbib.raml.internal.impl.commons.nodes.ExtendsNode; +import org.xbib.raml.internal.impl.commons.nodes.ExternalSchemaTypeExpressionNode; +import org.xbib.raml.internal.impl.commons.nodes.FacetNode; +import org.xbib.raml.internal.impl.commons.nodes.ResponseNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationField; +import org.xbib.raml.internal.impl.commons.nodes.TypesNode; +import org.xbib.raml.internal.impl.commons.rule.NodeReferenceFactory; +import org.xbib.raml.internal.impl.commons.rule.SchemaDeclarationRule; +import org.xbib.raml.internal.impl.v10.nodes.DisplayNameDefaultValue; +import org.xbib.raml.internal.impl.v10.nodes.LibraryLinkNode; +import org.xbib.raml.internal.impl.v10.nodes.LibraryNode; +import org.xbib.raml.internal.impl.v10.nodes.NativeTypeExpressionNode; +import org.xbib.raml.internal.impl.v10.nodes.PropertyNode; +import org.xbib.raml.internal.impl.v10.nodes.factory.DefaultMimeTypeDeclarationFactory; +import org.xbib.raml.internal.impl.v10.nodes.factory.InlineTypeDeclarationFactory; +import org.xbib.raml.internal.impl.v10.nodes.factory.OverlayableSimpleTypeFactory; +import org.xbib.raml.internal.impl.v10.nodes.factory.RamlScalarValueFactory; +import org.xbib.raml.internal.impl.v10.nodes.factory.TypeDeclarationNodeFactory; +import org.xbib.raml.internal.impl.v10.nodes.factory.TypeExpressionReferenceFactory; +import org.xbib.raml.internal.impl.v10.rules.TypeDefaultValue; +import org.xbib.raml.internal.impl.v10.rules.TypeExpressionReferenceRule; +import org.xbib.raml.internal.impl.v10.type.TypeId; +import org.xbib.raml.yagi.framework.grammar.RuleFactory; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import org.xbib.raml.yagi.framework.grammar.rule.ArrayWrapperFactory; +import org.xbib.raml.yagi.framework.grammar.rule.ConditionalRule; +import org.xbib.raml.yagi.framework.grammar.rule.KeyValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.ObjectRule; +import org.xbib.raml.yagi.framework.grammar.rule.RegexValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.ResourceRefRule; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.grammar.rule.StringValueRule; +import org.xbib.raml.yagi.framework.nodes.NullNodeImpl; +import static java.util.Arrays.asList; + + +public class Raml10Grammar extends BaseRamlGrammar { + + public static final String ANNOTATION_TYPES_KEY_NAME = "annotationTypes"; + public static final String DEFAULT_TYPE_RULE = "defaultTypeRule"; + public static final String PROPERTY_TYPE_RULE = "propertyTypeRule"; + public static final String TYPES_FACET_TYPE = "type"; + public static final String TYPES_FACET_SCHEMA = "schema"; + public static final String MIN_ITEMS_KEY_NAME = "minItems"; + public static final String MAX_ITEMS_KEY_NAME = "maxItems"; + public static final String UNIQUE_ITEMS_KEY_NAME = "uniqueItems"; + public static final String ITEMS_KEY_NAME = "items"; + public static final String FILE_TYPES_KEY_NAME = "fileTypes"; + public static final String MIN_LENGTH_KEY_NAME = "minLength"; + public static final String MAX_LENGTH_KEY_NAME = "maxLength"; + public static final String MINIMUM_KEY_NAME = "minimum"; + public static final String MAXIMUM_KEY_NAME = "maximum"; + public static final String FORMAT_KEY_NAME = "format"; + public static final String ENUM_KEY_NAME = "enum"; + public static final String MULTIPLE_OF_KEY_NAME = "multipleOf"; + public static final String PROPERTIES_KEY_NAME = "properties"; + public static final String MIN_PROPERTIES_KEY_NAME = "minProperties"; + public static final String MAX_PROPERTIES_KEY_NAME = "maxProperties"; + public static final String ADDITIONAL_PROPERTIES_KEY_NAME = "additionalProperties"; + public static final String DISCRIMINATOR_KEY_NAME = "discriminator"; + public static final String DISCRIMINATOR_VALUE_KEY_NAME = "discriminatorValue"; + public static final String PATTERN_KEY_NAME = "pattern"; + + public ObjectRule untitledRaml() { + return super.untitledRaml() + .with(annotationTypesField()) + .with(annotationField()) + .with(typesField()) + .with(usesField()) + .with(exclusiveKeys(TYPES_KEY_NAME, SCHEMAS_KEY_NAME)); + } + + @Override + protected ObjectRule resourceValue() { + return named("resourceValue", new RuleFactory() { + @Override + public ObjectRule create() { + return baseResourceValue() + .with(methodField()) + .with(resourceField()) + .with(annotationField()); + } + }); + + } + + @Override + protected ObjectRule methodValue() { + return super.methodValue() + .with(field(queryStringKey(), type())) + .with(exclusiveKeys(QUERY_STRING_KEY_NAME, QUERY_PARAMETERS_KEY_NAME)) + .with(annotationField()); + } + + @Override + public ObjectRule securityScheme() { + return super.securityScheme().with(annotationField()); + } + + @Override + protected ObjectRule securitySchemePart() { + return super.securitySchemePart() + .with(annotationField()) + .with(field(queryStringKey(), type())) + .with(exclusiveKeys(QUERY_STRING_KEY_NAME, QUERY_PARAMETERS_KEY_NAME)); + } + + @Override + protected ObjectRule securitySchemeSettings() { + return objectType() + .with(annotationField()) + .with( + when("../../type", + is(string(OAUTH_1_0)) + .add(requiredField(string("requestTokenUri"), ramlScalarValue())) + .add(requiredField(string("authorizationUri"), ramlScalarValue())) + .add(requiredField(string("tokenCredentialsUri"), ramlScalarValue())) + .add(field(string("signatures"), array(scalarType()))), + is(string(OAUTH_2_0)) + .add(field(string("authorizationUri"), ramlScalarValue()).requiredWhen(new AuthorizationUriRequiredField())) + .add(requiredField(string("accessTokenUri"), ramlScalarValue())) + .add(requiredField(string("authorizationGrants"), anyOf(authorizationGrantsValue(), array(authorizationGrantsValue())))) + .add(field(string("scopes"), anyOf(scalarType(), array(scalarType())))) + )); + } + + @Override + protected Rule authorizationGrantsValue() { + return anyOf(string("authorization_code"), + string("password"), + string("client_credentials"), + string("implicit"), + regex("urn:.*"), + regex("http://.*"), + regex("https://.*")); + } + + @Override + protected KeyValueRule responseField() { + return super.responseField().then(ResponseNode.class); + } + + @Override + protected ObjectRule response() { + return super.response().with(annotationField()); + } + + protected KeyValueRule typesField() { + return field(typesKey(), types()).then(TypesNode.class); + } + + protected StringValueRule typesKey() { + return string(TYPES_KEY_NAME) + .description("Declarations of (data) types for use within this API."); + } + + + // Common fields between rules + protected KeyValueRule annotationField() { + return field(annotationKey().then(new NodeReferenceFactory(AnnotationReferenceNode.class)), any()).then(AnnotationNode.class); + } + + protected RegexValueRule annotationKey() { + return regex("\\((.+)\\)") + .label("(Annotation)") + .suggest("()") + .description("Annotations to be applied to this API. " + + "Annotations are any property whose key begins with \"(\" and ends with \")\" " + + "and whose name (the part between the beginning and ending parentheses) " + + "is a declared annotation name.."); + } + + + public KeyValueRule usesField() { + return field(usesKey(), objectType().with(field(scalarType(), libraryRef()).then(LibraryNode.class))); + } + + // Extension + public ObjectRule extension() { + return untitledRaml() + .with(requiredField(extendsKey(), scalarType()).then(ExtendsNode.class)) + .with(usageField()) + .with(optionalTitleField()); + } + + protected StringValueRule extendsKey() { + return string("extends").description("The path to the base RAML document to be extended."); + } + + protected KeyValueRule optionalTitleField() { + return field(titleKey(), titleValue()); + } + + + public Rule libraryRef() { + return new ResourceRefRule().then(LibraryLinkNode.class); + } + + public ObjectRule libraryValue() { + return named("library", new RuleFactory() { + @Override + public ObjectRule create() { + return objectType() + .with(typesField()) + .with(schemasField()) + .with(resourceTypesField()) + .with(traitsField()) + .with(securitySchemesField()) + .with(annotationTypesField()) + .with(annotationField()) + .with(usesField()) + .with(usageField()); + } + }); + } + + protected KeyValueRule annotationTypesField() { + return field(annotationTypesKey(), annotationTypes()).then(AnnotationTypesNode.class); + } + + protected StringValueRule annotationTypesKey() { + return string(ANNOTATION_TYPES_KEY_NAME).description("Declarations of annotation types for use by annotations."); + } + + protected Rule annotationTypes() { + return objectType() + .with(field(scalarType(), annotationType()).then(AnnotationTypeNode.class)); + } + + private Rule annotationType() { + return anyOf(inlineType(), explicitType().with(allowedTargetsField())); + } + + private KeyValueRule allowedTargetsField() { + return field(string("allowedTargets"), anyOf(allowedTargetValues(), array(allowedTargetValues())).then(new ArrayWrapperFactory())); + } + + private Rule allowedTargetValues() { + List values = new ArrayList<>(); + for (AnnotationTarget annotationTarget : AnnotationTarget.values()) { + values.add(string(annotationTarget.name())); + } + return anyOf(values); + } + + protected Rule types() { + return objectType() + .with(field(ramlTypeKey(), type()).then(TypeDeclarationField.class)); + } + + protected Rule ramlTypeKey() { + List types = new ArrayList<>(); + for (TypeId typeId : TypeId.values()) { + types.add(string(typeId.getType())); + } + return not(anyOf(types)); + } + + protected Rule parameter() { + return anyOf(inlineType(), propertyType()); + } + + public Rule type() { + return anyOf(inlineType(), explicitType()); + } + + private AnyOfRule typeRef() { + return anyOf(inlineType(), explicitType()); + } + + protected Rule inlineType() { + return anyOf(typeExpressionReference(), array(typeExpressionReference())) + .then(new InlineTypeDeclarationFactory()); + } + + public ObjectRule explicitType() { + return baseType(TypeId.STRING, DEFAULT_TYPE_RULE); + } + + public ObjectRule annotationTypeDeclaration() { + return explicitType().with(allowedTargetsField()); + } + + private ObjectRule baseType(final TypeId defaultType, final String ruleName) { + return named(ruleName, + new RuleFactory() { + @Override + public ObjectRule create() { + return objectType() + .with(typeField(defaultType)) + .with(xmlFacetField()) + .with(displayNameField()) + .with(descriptionField()) + .with(usageField()) + .with(annotationField()) + .with(defaultField()) + .with(requiredTypeField()) + .with(facetsField()) + .with(exampleField()) + .with(examplesField()) + .with(exclusiveKeys(TYPES_FACET_TYPE, TYPES_FACET_SCHEMA)) + .with( + when(asList(TYPES_FACET_TYPE, TYPES_FACET_SCHEMA), + is(stringTypeLiteral()) + .add(patternField()) + .add(minLengthField()) + .add(maxLengthField()) + .add(enumField()), + is(booleanTypeLiteral()) + .add(enumField()), + is(dateTimeTypeLiteral()) + .add(formatField()), + is(arrayTypeLiteral()) + .add(uniqueItemsField()) + .add(itemsField()) + .add(minItemsField()) + .add(maxItemsField()), + is(integerTypeLiteral()) + .add(minimumField(integerType())) + .add(maximumField(integerType())) + .add(numberFormat()) + .add(enumField()) + .add(multipleOfField(positiveIntegerType(0L, Long.MAX_VALUE))), + is(numericTypeLiteral()) + .add(minimumField(numberType())) + .add(maximumField(numberType())) + .add(numberFormat()) + .add(enumField()) + .add(multipleOfField(positiveNumberType())), + is(fileTypeLiteral()) + .add(fileTypesField()) + .add(minLengthField()) + .add(maxLengthField()), + is(objectTypeLiteral()) + .add(propertiesField()) + .add(minPropertiesField()) + .add(maxPropertiesField()) + .add(additionalPropertiesField()) + .add(discriminatorField()) + .add(discriminatorValueField()), + // If it is an inherited type then we don't know we suggest all the properties + is(not(builtinTypes())) + .add(patternField().matchValue()) + .add(minLengthField().matchValue()) + .add(maxLengthField().matchValue()) + .add(enumField().matchValue()) + .add(formatField().matchValue()) + .add(numberFormat().matchValue()) + .add(uniqueItemsField().matchValue()) + .add(itemsField().matchValue()) + .add(minItemsField().matchValue()) + .add(maxItemsField().matchValue()) + .add(minimumField(numberType()).matchValue()) + .add(maximumField(numberType()).matchValue()) + .add(multipleOfField(positiveNumberType()).matchValue()) + .add(fileTypesField().matchValue()) + .add(propertiesField().matchValue()) + .add(minPropertiesField().matchValue()) + .add(maxPropertiesField().matchValue()) + .add(additionalPropertiesField().matchValue()) + .add(discriminatorField().matchValue()) + .add(discriminatorValueField().matchValue()) + .add(customFacetField().matchValue()) + ).defaultValue(new TypeDefaultValue(defaultType)) + ).then(new TypeDeclarationNodeFactory()); + + + } + }); + } + + private KeyValueRule customFacetField() { + return field(facetRegex(), any()).then(FacetNode.class); + } + + protected Rule builtinTypes() { + final TypeId[] values = TypeId.values(); + final List typeNames = new ArrayList<>(); + for (TypeId value : values) { + typeNames.add(string(value.getType())); + } + return anyOf(typeNames); + } + + public KeyValueRule discriminatorValueField() { + return field(string(DISCRIMINATOR_VALUE_KEY_NAME), scalarType()) + .then(FacetNode.class) + .description( + "Identifies the declaring type." + + + " Requires including a discriminator facet in the type declaration." + + + " A valid value is an actual value that might identify the type of an individual object and is unique in the hierarchy of the type." + + + " Inline type declarations are not supported."); + } + + public KeyValueRule discriminatorField() { + return field(string(DISCRIMINATOR_KEY_NAME), scalarType()) + .then(FacetNode.class) + .description( + "Determines the concrete type of an individual object at runtime when, for example, payloads contain ambiguous types due to unions or inheritance." + + + " The value must match the name of one of the declared properties of a type. " + + "Unsupported practices are inline type declarations and using discriminator with non-scalar properties."); + } + + public KeyValueRule additionalPropertiesField() { + return field(string(ADDITIONAL_PROPERTIES_KEY_NAME), booleanType()) + .then(FacetNode.class) + .description("A Boolean that indicates if an object instance has additional properties."); + } + + public KeyValueRule maxPropertiesField() { + return field(string(MAX_PROPERTIES_KEY_NAME), positiveIntegerType(1L, (long) Integer.MAX_VALUE)) + .then(FacetNode.class) + .description("The maximum number of properties allowed for instances of this type."); + } + + public KeyValueRule minPropertiesField() { + return field(string(MIN_PROPERTIES_KEY_NAME), positiveIntegerType(1L, (long) Integer.MAX_VALUE)) + .then(FacetNode.class) + .description("The minimum number of properties allowed for instances of this type."); + } + + public KeyValueRule propertiesField() { + return field(string(PROPERTIES_KEY_NAME), properties()) + .then(FacetNode.class) + .description("The properties that instances of this type can or must have."); + } + + public KeyValueRule fileTypesField() { + return field(string(FILE_TYPES_KEY_NAME), any()) + .then(FacetNode.class) + .description("A list of valid content-type strings for the file. The file type */* MUST be a valid value."); + } + + public KeyValueRule multipleOfField(Rule rule) { + return field(string(MULTIPLE_OF_KEY_NAME), rule) + .then(FacetNode.class) + .description( + "A numeric instance is valid against \"multipleOf\" if the result of dividing the instance by this keyword's value is an integer."); + } + + public KeyValueRule numberFormat() { + return field(string(FORMAT_KEY_NAME), anyOf(string("int32"), string("int64"), string("int"), string("long"), string("float"), string("double"), string("int16"), string("int8"))) + .then(FacetNode.class) + .description( + "The format of the value. The value MUST be one of the following: int32, int64, int, long, float, double, int16, int8"); + } + + public KeyValueRule maximumField(Rule rule) { + return field(string(MAXIMUM_KEY_NAME), rule) + .then(FacetNode.class) + .description("The maximum value of the parameter. Applicable only to parameters of type number or integer."); + } + + public KeyValueRule minimumField(Rule rule) { + return field(string(MINIMUM_KEY_NAME), rule) + .then(FacetNode.class) + .description("The minimum value of the parameter. Applicable only to parameters of type number or integer."); + } + + public KeyValueRule maxItemsField() { + return field(string(MAX_ITEMS_KEY_NAME), positiveIntegerType(1L, (long) Integer.MAX_VALUE)) + .then(FacetNode.class) + .description("Maximum amount of items in array. Value MUST be equal to or greater than 0."); + } + + public KeyValueRule minItemsField() { + return field(string(MIN_ITEMS_KEY_NAME), positiveIntegerType(1L, (long) Integer.MAX_VALUE)) + .then(FacetNode.class) + .description("Minimum amount of items in array. Value MUST be equal to or greater than 0."); + } + + public KeyValueRule itemsField() { + return field(string(ITEMS_KEY_NAME), typeRef()) + .then(FacetNode.class) + .description( + "Indicates the type all items in the array are inherited from. Can be a reference to an existing type or an inline type declaration."); + } + + public KeyValueRule uniqueItemsField() { + return field(string(UNIQUE_ITEMS_KEY_NAME), booleanType()) + .then(FacetNode.class) + .description("Boolean value that indicates if items in the array MUST be unique."); + } + + public KeyValueRule formatField() { + return field(string(FORMAT_KEY_NAME), anyOf(string("rfc3339"), string("rfc2616"))).then(FacetNode.class); + } + + public KeyValueRule enumField() { + return field(string(ENUM_KEY_NAME), array(scalarType())) + .then(FacetNode.class) + .description( + "Enumeration of possible values for this built-in scalar type. The value is an array containing representations of possible values, or a single value if there is only one possible value."); + } + + public KeyValueRule maxLengthField() { + return field(string(MAX_LENGTH_KEY_NAME), positiveIntegerType(1L, (long) Integer.MAX_VALUE)) + .then(FacetNode.class) + .description("Maximum length of the string. Value MUST be equal to or greater than 0."); + } + + public KeyValueRule minLengthField() { + return field(string(MIN_LENGTH_KEY_NAME), positiveIntegerType(1L, (long) Integer.MAX_VALUE)) + .then(FacetNode.class) + .description("Minimum length of the string. Value MUST be equal to or greater than 0."); + } + + public KeyValueRule patternField() { + return field(string(PATTERN_KEY_NAME), scalarType()) + .then(FacetNode.class) + .description("Regular expression that this string should match."); + } + + protected KeyValueRule examplesField() { + return field(exclusiveWith("examples", "example"), examplesValue()).then(ExamplesNode.class) + .description( + "Examples of instances of this type." + + + " This can be used, for example, by documentation generators to generate sample values for an object of this type." + + + " The \"examples\" facet MUST not be available when the \"example\" facet is already defined." + + " See section Examples for more information."); + } + + protected KeyValueRule exampleField() { + return field(exclusiveWith("example", "examples"), exampleValue()) + .then(ExampleDeclarationNode.class) + .description( + "An example of an instance of this type that can be used, for example, by documentation generators to generate sample values for an object of this type." + + + " The \"example\" facet MUST not be available when the \"examples\" facet is already defined." + + " See section Examples for more information."); + } + + protected KeyValueRule facetsField() { + return field(string("facets"), objectType() + .with(field(facetRegex(), typeRef()).then(CustomFacetDefinitionNode.class))) + .description( + "A map of additional, user-defined restrictions that will be inherited and applied by any extending subtype. See section User-defined Facets for more information."); + } + + private RegexValueRule facetRegex() { + return regex("[^\\(].*"); + } + + protected ObjectRule examplesValue() { + return objectType() + .with(field(scalarType(), exampleValue()).then(ExampleDeclarationNode.class)); + } + + private KeyValueRule typeField(TypeId defaultType) { + return field( + anyOf(typeKey(), schemaKey()), + anyOf(typeExpressionReference(), array(typeExpressionReference()), explicitType())) + .defaultValue(new TypeDefaultValue(defaultType)) + .description( + "A base type which the current type extends or just wraps." + + + " The value of a type node MUST be either a) the name of a user-defined type or b) the name of a built-in RAML data type (object, array, or one of the scalar types) or c) an inline type declaration."); + } + + private KeyValueRule requiredTypeField() { + return field(string("required"), booleanType()); + } + + private StringValueRule schemaKey() { + return string(TYPES_FACET_SCHEMA); + } + + private KeyValueRule xmlFacetField() { + return field(string("xml"), + objectType() + .with(attributeField()) + .with(wrappedField()) + .with(xmlNameField()) + .with(namespaceField()) + .with(prefixField())); + } + + private KeyValueRule xmlNameField() { + return field(string("name"), stringType()).description("Overrides the name of the XML element or XML attribute."); + } + + private KeyValueRule prefixField() { + return field(string("prefix"), stringType()).description("Configures the prefix used during serialization to XML."); + } + + private KeyValueRule namespaceField() { + return field(string("namespace"), stringType()).description("Configures the name of the XML namespace."); + } + + private KeyValueRule wrappedField() { + return field(string("wrapped"), booleanType()).description("true wraps a type instance in its own XML element. Cannot be true for scalar types or true at the same moment attribute is true."); + } + + private KeyValueRule attributeField() { + return field(string("attribute"), booleanType()).description("Serializes a type instance as an XML attribute. Can be true only for scalar types."); + } + + private KeyValueRule defaultField() { + return field(string("default"), any()); + } + + + private AnyOfRule typeExpressionReference() { + return anyOf(nullValue().then(NativeTypeExpressionNode.class), + new SchemaDeclarationRule().then(ExternalSchemaTypeExpressionNode.class), + new TypeExpressionReferenceRule().then(new TypeExpressionReferenceFactory())); + } + + @Override + protected Rule mimeType() { + return anyOf(nullValue().then(new DefaultMimeTypeDeclarationFactory()), anyOf(inlineType(), baseType(TypeId.ANY, "mimeType"))); + } + + protected Rule exampleValue() { + return anyOf(explicitExample(), any()); + } + + public Rule exampleFragment() { + return anyOf(explicitExample(true), any()); + } + + private ObjectRule explicitExample() { + return explicitExample(false); + } + + private ObjectRule explicitExample(boolean isFragment) { + ConditionalRule nestedValue = is(not(nullValue())) + .add(displayNameField()) + .add(descriptionField()) + .add(annotationField()) + .add(field(string("value"), any())) + .add(field(string("strict"), booleanType())); + if (isFragment) { + nestedValue.add(usesField()); + } + return objectType() + .with( + when("value", + nestedValue, + is(nullValue()).add(field(scalarType(), any())) + ).defaultValue(new NullNodeImpl()) + ); + } + + protected StringValueRule fileTypeLiteral() { + return string("file"); + } + + protected Rule numericTypeLiteral() { + return anyOf(numberTypeLiteral(), integerTypeLiteral()); + } + + protected Rule numberTypeLiteral() { + return string("number"); + } + + protected Rule integerTypeLiteral() { + return string("integer"); + } + + protected StringValueRule stringTypeLiteral() { + return string("string"); + } + + protected StringValueRule booleanTypeLiteral() { + return string("boolean"); + } + + private StringValueRule dateTimeTypeLiteral() { + return string("datetime"); + } + + protected AnyOfRule arrayTypeLiteral() { + return new AnyOfRule(regex(".+\\[\\]"), string("array")); + } + + protected ObjectRule properties() { + return objectType() + .with(propertyField()).named("Properties"); + } + + @Override + protected Rule parameters() { + return properties(); + } + + private KeyValueRule propertyField() { + return field(scalarType(), anyOf(inlineType(), propertyType())).then(PropertyNode.class); + } + + ObjectRule propertyType() { + return baseType(TypeId.STRING, PROPERTY_TYPE_RULE).named("PropertyTypeRule"); + } + + protected Rule objectTypeLiteral() { + return string("object"); + } + + protected KeyValueRule mediaTypeField() { + return field(mediaTypeKey(), anyOf(mimeTypeRegex(), array(mimeTypeRegex()))); + } + + protected KeyValueRule schemasField() { + return field(schemasKey(), schemasValue()).then(TypesNode.class); + } + + protected Rule schemasValue() { + return types(); + } + + + protected String schemasDescription() { + return "Alias for the equivalent \"types\" property, for compatibility " + + "with RAML 0.8. Deprecated - API definitions should use the \"types\" property, " + + "as the \"schemas\" alias for that property name may be removed in a future RAML version. " + + "The \"types\" property allows for XML and JSON schemas."; + } + + protected KeyValueRule displayNameField() { + return field(displayNameKey(), overlayableRamlScalarValue()).defaultValue(new DisplayNameDefaultValue()); + } + + protected Rule overlayableRamlScalarValue() { + return firstOf(scalarType().then(new OverlayableSimpleTypeFactory(true)), + annotatedScalarType(scalarType().then(new OverlayableSimpleTypeFactory(false)))); + } + + + protected Rule resourceTypesValue() { + return resourceTypes(); + } + + protected Rule securitySchemesValue() { + return securitySchemes(); + } + + @Override + protected Rule descriptionValue() { + return overlayableRamlScalarValue(); + } + + protected KeyValueRule docTitleField() { + return requiredField(titleKey(), + firstOf( + allOf(minLength(1), ramlScalarValue()), + annotatedScalarType(allOf(minLength(1), scalarType())) + )); + } + + @Override + protected Rule titleValue() { + return firstOf( + allOf(minLength(1), scalarType().then(new OverlayableSimpleTypeFactory(true))), + annotatedScalarType(allOf(minLength(1), scalarType().then(new OverlayableSimpleTypeFactory(false))))); + } + + @Override + public Rule ramlScalarValue() { + return firstOf(scalarType().then(new RamlScalarValueFactory()), annotatedScalarType()); + } + + protected Rule annotatedScalarType() { + return annotatedScalarType(scalarType()); + } + + protected Rule annotatedScalarType(Rule customScalarRule) { + return objectType() + .with(field(string("value"), customScalarRule)) + .with(annotationField()); + } + + public ObjectRule documentation() { + return super.documentation().with(annotationField()).then(DocumentationItemNode.class); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/grammar/Raml10GrammarUsesAllowed.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/grammar/Raml10GrammarUsesAllowed.java new file mode 100644 index 0000000..43ad4db --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/grammar/Raml10GrammarUsesAllowed.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.grammar; + +import org.xbib.raml.yagi.framework.grammar.rule.ObjectRule; + +public class Raml10GrammarUsesAllowed extends Raml10Grammar { + @Override + public ObjectRule explicitType() { + return super.explicitType().with(0, usesField()); + } + + @Override + ObjectRule propertyType() { + return super.propertyType().with(0, usesField()); + } + + @Override + public ObjectRule traitParamsResolved() { + return super.traitParamsResolved().with(usesField()); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/ArrayTypeExpressionNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/ArrayTypeExpressionNode.java new file mode 100644 index 0000000..d2e79b6 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/ArrayTypeExpressionNode.java @@ -0,0 +1,110 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes; + + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.nodes.factory.InlineTypeDeclarationFactory; +import org.xbib.raml.internal.impl.v10.type.ArrayResolvedType; +import org.xbib.raml.yagi.framework.nodes.AbstractRamlNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +public class ArrayTypeExpressionNode extends AbstractRamlNode implements TypeExpressionNode, SimpleTypeNode { + + public ArrayTypeExpressionNode() { + } + + public ArrayTypeExpressionNode(Node of) { + this.addChild(of); + } + + private ArrayTypeExpressionNode(ArrayTypeExpressionNode arrayTypeTypeNode) { + super(arrayTypeTypeNode); + } + + + @Override + public Node copy() { + return new ArrayTypeExpressionNode(this); + } + + @Override + public NodeType getType() { + return NodeType.String; + } + + + public TypeExpressionNode of() { + if (!getChildren().isEmpty() && getChildren().get(0) instanceof TypeExpressionNode) { + return (TypeExpressionNode) getChildren().get(0); + } else { + final Node typeDeclaration = getTypeDeclaration(); + if (typeDeclaration != null) { + final Node item = typeDeclaration.get("item"); + return (TypeExpressionNode) item; + } else { + return null; + } + } + } + + private Node getTypeDeclaration() { + return org.xbib.raml.yagi.framework.util.NodeUtils.getAncestor(this, 2); + } + + @Override + + public ResolvedType generateDefinition() { + final TypeExpressionNode of = of(); + if (of != null) { + final TypeDeclarationNode itemsTypeDeclarationNode = new InlineTypeDeclarationFactory().create(of.copy()); + itemsTypeDeclarationNode.setParent(this); + return new ArrayResolvedType(this, of.generateDefinition()); + } else { + return null; + } + } + + @Override + public String getTypeExpressionText() { + return getValue(); + } + + @Override + public String getValue() { + final TypeExpressionNode of = of(); + String typeExpression = of != null ? of.getTypeExpressionText() : null; + return typeExpression != null ? addParenthesesIfNeeded(typeExpression) + "[]" : null; + + } + + @Override + public String getLiteralValue() { + return getValue(); + } + + static String addParenthesesIfNeeded(String typeExpression) { + if (typeExpression.contains("|") || typeExpression.contains(",")) { + typeExpression = "(" + typeExpression + ")"; + } + return typeExpression; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/DisplayNameDefaultValue.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/DisplayNameDefaultValue.java new file mode 100644 index 0000000..c1a4f10 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/DisplayNameDefaultValue.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes; + + +import org.xbib.raml.internal.impl.commons.nodes.OverlayableStringNode; +import org.xbib.raml.yagi.framework.grammar.rule.DefaultValue; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.DefaultPosition; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNodeImpl; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; + +public class DisplayNameDefaultValue implements DefaultValue { + + + @Override + public Node getDefaultValue(Node parent) { + Node grampa = parent.getParent(); + if (grampa == null) { + // inside raml fragment file + return null; + } + if (!(grampa instanceof KeyValueNode)) { + return ErrorNodeFactory.createInvalidNode(parent); + } + final Node keyNode = ((KeyValueNode) grampa).getKey(); + final ObjectNodeImpl result = new ObjectNodeImpl(); + if (keyNode instanceof SimpleTypeNode) { + final String literalValue = ((SimpleTypeNode) keyNode).getLiteralValue(); + final OverlayableStringNode displayName = new OverlayableStringNode(literalValue); + displayName.setSource(keyNode); + displayName.setStartPosition(DefaultPosition.emptyPosition()); + displayName.setEndPosition(DefaultPosition.emptyPosition()); + result.addChild(new KeyValueNodeImpl(new StringNodeImpl("value"), displayName)); + return result; + } else { + return ErrorNodeFactory.createInvalidNode(keyNode); + } + + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/LibraryLinkNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/LibraryLinkNode.java new file mode 100644 index 0000000..f71faf0 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/LibraryLinkNode.java @@ -0,0 +1,63 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes; + + +import org.xbib.raml.yagi.framework.nodes.AbstractRamlNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; + +public class LibraryLinkNode extends AbstractRamlNode implements ReferenceNode { + private final String path; + private Node libraryReference; + + public LibraryLinkNode(String path) { + this.path = path; + } + + // For cloning + protected LibraryLinkNode(LibraryLinkNode node) { + super(node); + path = node.path; + } + + @Override + public String getRefName() { + return path; + } + + + @Override + public Node getRefNode() { + return libraryReference; + } + + public void setLibraryReference(Node libraryReference) { + this.libraryReference = libraryReference; + } + + + @Override + public Node copy() { + return new LibraryLinkNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Reference; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/LibraryNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/LibraryNode.java new file mode 100644 index 0000000..4593878 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/LibraryNode.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes; + + +import org.xbib.raml.yagi.framework.nodes.ContextProviderNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.NamedNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +public class LibraryNode extends KeyValueNodeImpl implements ContextProviderNode, NamedNode { + + public LibraryNode() { + } + + public LibraryNode(LibraryNode node) { + super(node); + } + + public String getName() { + final StringNode key = (StringNode) getKey(); + return key.getValue(); + } + + + @Override + public LibraryNode copy() { + return new LibraryNode(this); + } + + + @Override + public Node getContextNode() { + return getValue(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/LibraryRefNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/LibraryRefNode.java new file mode 100644 index 0000000..bbca611 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/LibraryRefNode.java @@ -0,0 +1,81 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes; + +import org.xbib.raml.internal.impl.commons.nodes.AbstractReferenceNode; +import org.xbib.raml.internal.impl.commons.nodes.LibraryNodeProvider; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class LibraryRefNode extends AbstractReferenceNode { + + private final String name; + + public LibraryRefNode(String name) { + this.name = name; + } + + public LibraryRefNode(LibraryRefNode node) { + super(node); + this.name = node.name; + } + + @Override + public String getRefName() { + return name; + } + + + @Override + public Node resolveReference() { + final Node node = selectLibraryLinkNode(); + if (node == null) { + return null; + } + if (node instanceof LibraryLinkNode) { + return ((LibraryLinkNode) node).getRefNode(); + } else { + return null; + } + } + + + protected Node selectLibraryLinkNode() { + // final Node relativeNode = getRelativeNode(); + for (Node contextNode : getContextNodes()) { + if (contextNode instanceof LibraryNodeProvider) { + final Node libraryNode = ((LibraryNodeProvider) contextNode).getLibraryNode(); + Node node = NodeSelector.selectFrom(name, libraryNode); + if (node != null) { + return node; + } + } else { + Node node = NodeSelector.selectFrom(Raml10Grammar.USES_KEY_NAME + "/" + name, contextNode); + if (node != null) { + return node; + } + } + } + return null; + } + + + @Override + public Node copy() { + return new LibraryRefNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/NamedTypeExpressionNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/NamedTypeExpressionNode.java new file mode 100644 index 0000000..622cd56 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/NamedTypeExpressionNode.java @@ -0,0 +1,104 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes; + + +import org.xbib.raml.internal.impl.commons.nodes.AbstractReferenceNode; +import org.xbib.raml.internal.impl.commons.nodes.RamlDocumentNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class NamedTypeExpressionNode extends AbstractReferenceNode implements TypeExpressionNode, SimpleTypeNode { + private final String name; + + public NamedTypeExpressionNode(String name) { + this.name = name; + } + + private NamedTypeExpressionNode(NamedTypeExpressionNode copy) { + super(copy); + this.name = copy.name; + } + + + @Override + public TypeDeclarationNode resolveReference() { + for (Node contextNode : getContextNodes()) { + // We add the .. as the node selector selects the value and we want the key value pair + Node node = NodeSelector.selectFrom(Raml10Grammar.TYPES_KEY_NAME + "/" + getRefName(), contextNode); + + if (node == null && contextNode != null) { + if (contextNode.getRootNode() instanceof RamlDocumentNode) { + node = NodeSelector.selectFrom(Raml10Grammar.TYPES_KEY_NAME + "/" + getRefName(), contextNode.getRootNode()); + } + } + if (node == null) { + // If is not defined in types we need to search in schemas + node = NodeSelector.selectFrom(Raml10Grammar.SCHEMAS_KEY_NAME + "/" + getRefName(), contextNode); + } + if (node instanceof TypeDeclarationNode) { + return (TypeDeclarationNode) node; + } + } + return null; + } + + @Override + public String getRefName() { + return name; + } + + + @Override + public Node copy() { + return new NamedTypeExpressionNode(this); + } + + + @Override + public ResolvedType generateDefinition() { + if (getRefNode() != null) { + return ((TypeDeclarationNode) getRefNode()).getResolvedType(); + } else { + return null; + } + } + + @Override + public String getTypeExpressionText() { + return getValue(); + } + + @Override + public String toString() { + return getRefName(); + } + + @Override + public String getValue() { + return name; + } + + @Override + public String getLiteralValue() { + return name; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/NativeTypeExpressionNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/NativeTypeExpressionNode.java new file mode 100644 index 0000000..09252ba --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/NativeTypeExpressionNode.java @@ -0,0 +1,122 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes; + + +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.type.AnyResolvedType; +import org.xbib.raml.internal.impl.v10.type.ArrayResolvedType; +import org.xbib.raml.internal.impl.v10.type.BooleanResolvedType; +import org.xbib.raml.internal.impl.v10.type.DateOnlyResolvedType; +import org.xbib.raml.internal.impl.v10.type.DateTimeOnlyResolvedType; +import org.xbib.raml.internal.impl.v10.type.DateTimeResolvedType; +import org.xbib.raml.internal.impl.v10.type.FileResolvedType; +import org.xbib.raml.internal.impl.v10.type.IntegerResolvedType; +import org.xbib.raml.internal.impl.v10.type.NullResolvedType; +import org.xbib.raml.internal.impl.v10.type.NumberResolvedType; +import org.xbib.raml.internal.impl.v10.type.ObjectResolvedType; +import org.xbib.raml.internal.impl.v10.type.StringResolvedType; +import org.xbib.raml.internal.impl.v10.type.TimeOnlyResolvedType; +import org.xbib.raml.internal.impl.v10.type.TypeId; +import org.xbib.raml.yagi.framework.nodes.AbstractStringNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +public class NativeTypeExpressionNode extends AbstractStringNode implements TypeExpressionNode, SimpleTypeNode { + + protected NativeTypeExpressionNode(NativeTypeExpressionNode node) { + super(node); + } + + public NativeTypeExpressionNode() { + super(TypeId.STRING.getType()); + } + + public NativeTypeExpressionNode(String value) { + super(value); + } + + public static boolean isNativeType(String type) { + for (TypeId builtInScalarType : TypeId.values()) { + if (builtInScalarType.getType().equals(type)) { + return true; + } + } + return false; + } + + + @Override + public Node copy() { + return new NativeTypeExpressionNode(this); + } + + public static TypeId getType(String type) { + if ("date".equals(type)) { + type = "date-only"; // bridge 0.8 and 1.0 date type + } + for (TypeId builtInScalarType : TypeId.values()) { + if (builtInScalarType.getType().equals(type)) { + return builtInScalarType; + } + } + return null; + } + + + @Override + public ResolvedType generateDefinition() { + final TypeId typeId = getType(getLiteralValue()); + if (typeId == null) { + return null; + } + switch (typeId) { + case STRING: + return new StringResolvedType(this); + case NUMBER: + return new NumberResolvedType(this); + case INTEGER: + return new IntegerResolvedType(this); + case BOOLEAN: + return new BooleanResolvedType(this); + case DATE_ONLY: + return new DateOnlyResolvedType(this); + case TIME_ONLY: + return new TimeOnlyResolvedType(this); + case DATE_TIME_ONLY: + return new DateTimeOnlyResolvedType(this); + case DATE_TIME: + return new DateTimeResolvedType(this); + case FILE: + return new FileResolvedType(this); + case OBJECT: + return new ObjectResolvedType(this); + case ARRAY: + return new ArrayResolvedType(this); + case NULL: + return new NullResolvedType(this); + case ANY: + return new AnyResolvedType(this); + } + return new AnyResolvedType(this); + } + + @Override + public String getTypeExpressionText() { + return getValue(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/OverridableNativeTypeExpressionNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/OverridableNativeTypeExpressionNode.java new file mode 100644 index 0000000..eb91944 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/OverridableNativeTypeExpressionNode.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes; + + +import org.xbib.raml.internal.impl.commons.nodes.OverridableNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class OverridableNativeTypeExpressionNode extends NativeTypeExpressionNode implements OverridableNode { + + public OverridableNativeTypeExpressionNode() { + } + + public OverridableNativeTypeExpressionNode(String value) { + super(value); + } + + protected OverridableNativeTypeExpressionNode(OverridableNativeTypeExpressionNode node) { + super(node); + } + + + @Override + public Node copy() { + return new OverridableNativeTypeExpressionNode(this); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/PropertyNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/PropertyNode.java new file mode 100644 index 0000000..5f63ee5 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/PropertyNode.java @@ -0,0 +1,61 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes; + +import org.xbib.raml.internal.impl.commons.nodes.PropertyUtils; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class PropertyNode extends KeyValueNodeImpl { + + public PropertyNode() { + } + + public PropertyNode(PropertyNode node) { + super(node); + } + + public String getName() { + return PropertyUtils.getName(this); + } + + public boolean isRequired() { + return PropertyUtils.isRequired(this); + } + + public ResolvedType getTypeDefinition() { + final Node value = getValue(); + if (value instanceof TypeDeclarationNode) { + return ((TypeDeclarationNode) value).getResolvedType(); + } else { + throw new RuntimeException("Invalid value it should always be a TypeDeclarationNode but was " + value); + } + } + + + @Override + public Node copy() { + return new PropertyNode(this); + } + + @Override + public String toString() { + return this.getName() + ":" + org.xbib.raml.yagi.framework.util.NodeUtils.getType(this.getValue()); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/UnionTypeExpressionNode.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/UnionTypeExpressionNode.java new file mode 100644 index 0000000..aa48cff --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/UnionTypeExpressionNode.java @@ -0,0 +1,114 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.type.UnionResolvedType; +import org.xbib.raml.yagi.framework.nodes.AbstractRamlNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.Position; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import static org.xbib.raml.internal.impl.v10.nodes.ArrayTypeExpressionNode.addParenthesesIfNeeded; + +public class UnionTypeExpressionNode extends AbstractRamlNode implements TypeExpressionNode, SimpleTypeNode { + + public UnionTypeExpressionNode() { + } + + private UnionTypeExpressionNode(UnionTypeExpressionNode unionTypeTypeNode) { + super(unionTypeTypeNode); + } + + + @Override + public Position getStartPosition() { + return getChildren().get(0).getStartPosition(); + } + + + @Override + public Position getEndPosition() { + return getChildren().get(getChildren().size() - 1).getEndPosition(); + } + + + @Override + public Node copy() { + return new UnionTypeExpressionNode(this); + } + + public List of() { + final List of = new ArrayList<>(); + for (Node node : getChildren()) { + if (node instanceof TypeExpressionNode) { + of.add((TypeExpressionNode) node); + } + } + return of; + } + + @Override + public NodeType getType() { + return NodeType.String; + } + + + @Override + public ResolvedType generateDefinition() { + final List of = of(); + List definitions = new ArrayList<>(); + ResolvedCustomFacets customFacets = new ResolvedCustomFacets(); + for (TypeExpressionNode typeExpressionNode : of) { + final ResolvedType resolvedType = typeExpressionNode.generateDefinition(); + if (resolvedType != null) { + definitions.add(resolvedType); + customFacets = customFacets.mergeWith(resolvedType.customFacets()); + } + } + + return new UnionResolvedType(this, definitions, customFacets); + } + + @Override + public String getTypeExpressionText() { + return getValue(); + } + + @Override + public String getValue() { + String unionOperator = " | "; + StringBuilder result = new StringBuilder(); + for (TypeExpressionNode typeExpressionNode : of()) { + String typeExpression = typeExpressionNode.getTypeExpressionText(); + if (typeExpression != null) { + result.append(addParenthesesIfNeeded(typeExpression)).append(unionOperator); + } else { + return null; + } + } + return result.delete(result.length() - unionOperator.length(), result.length()).toString(); + } + + @Override + public String getLiteralValue() { + return getValue(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/DefaultMimeTypeDeclarationFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/DefaultMimeTypeDeclarationFactory.java new file mode 100644 index 0000000..ad34471 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/DefaultMimeTypeDeclarationFactory.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes.factory; + + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.v10.nodes.OverridableNativeTypeExpressionNode; +import org.xbib.raml.internal.impl.v10.type.TypeId; +import org.xbib.raml.yagi.framework.grammar.rule.NodeFactory; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; + +public class DefaultMimeTypeDeclarationFactory implements NodeFactory { + + @Override + public Node create(Node currentNode, Object... args) { + final TypeDeclarationNode node = new TypeDeclarationNode(); + node.addChild(new KeyValueNodeImpl(new StringNodeImpl("type"), new OverridableNativeTypeExpressionNode(TypeId.ANY.getType()))); + return node; + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/EmptyObjectNodeFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/EmptyObjectNodeFactory.java new file mode 100644 index 0000000..4b7b879 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/EmptyObjectNodeFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes.factory; + + +import org.xbib.raml.yagi.framework.grammar.rule.NodeFactory; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNodeImpl; + +/** + * This factory is used for nullable object nodes that contain default values, + * in order for the grammar to generate those default fields event when the parent + * is a NullNode + */ +public class EmptyObjectNodeFactory implements NodeFactory { + + @Override + public Node create(Node currentNode, Object... args) { + return new ObjectNodeImpl(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/InlineTypeDeclarationFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/InlineTypeDeclarationFactory.java new file mode 100644 index 0000000..a19a156 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/InlineTypeDeclarationFactory.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes.factory; + + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.yagi.framework.grammar.rule.NodeFactory; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; + +public class InlineTypeDeclarationFactory implements NodeFactory { + + @Override + public TypeDeclarationNode create(Node currentNode, Object... args) { + final TypeDeclarationNode node = new TypeDeclarationNode(); + node.addChild(new KeyValueNodeImpl(new StringNodeImpl("type"), currentNode.copy())); + // We remove the children as they where already copied + currentNode.removeChildren(); + return node; + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/OverlayableSimpleTypeFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/OverlayableSimpleTypeFactory.java new file mode 100644 index 0000000..1ce00d8 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/OverlayableSimpleTypeFactory.java @@ -0,0 +1,68 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes.factory; + + +import org.xbib.raml.internal.impl.commons.nodes.OverlayableNode; +import org.xbib.raml.internal.impl.commons.nodes.OverlayableObjectNodeImpl; +import org.xbib.raml.internal.impl.commons.nodes.OverlayableStringNode; +import org.xbib.raml.internal.impl.commons.nodes.StringTemplateNode; +import org.xbib.raml.yagi.framework.grammar.rule.NodeFactory; +import org.xbib.raml.yagi.framework.nodes.AbstractObjectNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; + + +public class OverlayableSimpleTypeFactory implements NodeFactory { + + private final Boolean wrappInObject; + + public OverlayableSimpleTypeFactory(Boolean wrappInObject) { + this.wrappInObject = wrappInObject; + } + + @Override + public Node create(Node currentNode, Object... args) { + // If it is a template expression node we shouldn't apply this + if (currentNode instanceof StringTemplateNode) { + return currentNode; + } + + if (!(currentNode instanceof SimpleTypeNode)) { + throw new IllegalStateException("Factory incompatible with node of type " + currentNode.getClass().getSimpleName()); + } + if (currentNode instanceof OverlayableNode) { + return currentNode; + } + if (wrappInObject) { + AbstractObjectNode result = new OverlayableObjectNodeImpl(); + OverlayableStringNode overlayableStringNode = new OverlayableStringNode(((SimpleTypeNode) currentNode).getLiteralValue()); + overlayableStringNode.setStartPosition(currentNode.getStartPosition()); + overlayableStringNode.setEndPosition(currentNode.getEndPosition()); + KeyValueNodeImpl keyValueNode = new KeyValueNodeImpl(new StringNodeImpl("value"), overlayableStringNode); + if (currentNode.getParent() != null) { + keyValueNode.setStartPosition(currentNode.getParent().getStartPosition()); + keyValueNode.setEndPosition(currentNode.getParent().getEndPosition()); + } + result.addChild(keyValueNode); + return result; + } else { + return new OverlayableStringNode(((SimpleTypeNode) currentNode).getLiteralValue()); + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/RamlScalarValueFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/RamlScalarValueFactory.java new file mode 100644 index 0000000..0c4437d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/RamlScalarValueFactory.java @@ -0,0 +1,33 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes.factory; + + +import org.xbib.raml.yagi.framework.grammar.rule.NodeFactory; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNodeImpl; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; + +public class RamlScalarValueFactory implements NodeFactory { + + @Override + public Node create(Node currentNode, Object... args) { + final ObjectNodeImpl result = new ObjectNodeImpl(); + result.addChild(new KeyValueNodeImpl(new StringNodeImpl("value"), currentNode.copy())); + return result; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/TypeDeclarationNodeFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/TypeDeclarationNodeFactory.java new file mode 100644 index 0000000..b7388ae --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/TypeDeclarationNodeFactory.java @@ -0,0 +1,33 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes.factory; + + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNodeFragment; +import org.xbib.raml.internal.impl.commons.phase.RamlTypedFragment; +import org.xbib.raml.yagi.framework.grammar.rule.ClassNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.NodeFactory; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class TypeDeclarationNodeFactory implements NodeFactory { + @Override + public Node create(Node currentNode, Object... args) { + if (currentNode instanceof RamlTypedFragment) + return new ClassNodeFactory(TypeDeclarationNodeFragment.class).create(currentNode, args); + return new ClassNodeFactory(TypeDeclarationNode.class).create(currentNode, args); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/TypeExpressionReferenceFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/TypeExpressionReferenceFactory.java new file mode 100644 index 0000000..68bd180 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/nodes/factory/TypeExpressionReferenceFactory.java @@ -0,0 +1,196 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.nodes.factory; + +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; +import java.util.Stack; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.rule.NodeReferenceFactory; +import org.xbib.raml.internal.impl.v10.nodes.ArrayTypeExpressionNode; +import org.xbib.raml.internal.impl.v10.nodes.NamedTypeExpressionNode; +import org.xbib.raml.internal.impl.v10.nodes.NativeTypeExpressionNode; +import org.xbib.raml.internal.impl.v10.nodes.UnionTypeExpressionNode; +import org.xbib.raml.internal.impl.v10.type.TypeId; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.NodeFactory; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.Position; + +public class TypeExpressionReferenceFactory implements NodeFactory { + + + @Override + public Node create(Node currentNode, Object... args) { + String expression = ((String) args[0]).trim(); + try { + return parse(currentNode, new StringCharacterIterator(expression), 0); + } catch (TypeExpressionParsingException e) { + return ErrorNodeFactory.createInvalidTypeExpressionSyntax(e.getMessage(), expression, e.getLocation()); + } + } + + public TypeExpressionNode parse(Node currentNode, StringCharacterIterator iter, int depth) throws TypeExpressionParsingException { + // Precedence + final Stack expressionStack = new Stack<>(); + final StringBuilder simpleExpression = new StringBuilder(); + for (char c = iter.current(); c != CharacterIterator.DONE; c = iter.next()) { + switch (c) { + case '(': + iter.next(); + expressionStack.push(parse(currentNode, iter, depth + 1)); + break; + case ')': + return handleExpressionFinished(currentNode, expressionStack, iter, simpleExpression); + case '|': + handleSimpleExpression(currentNode, iter, expressionStack, simpleExpression); + if (expressionStack.isEmpty()) { + throw new TypeExpressionParsingException("Expecting a type expression before |.", iter.getIndex()); + } else { + final TypeExpressionNode pop = expressionStack.pop(); + if (expressionStack.isEmpty() || !(expressionStack.peek() instanceof UnionTypeExpressionNode)) { + expressionStack.push(new UnionTypeExpressionNode()); + } + expressionStack.peek().addChild(pop); + } + break; + case '[': + handleSimpleExpression(currentNode, iter, expressionStack, simpleExpression); + if (expressionStack.isEmpty()) { + throw new TypeExpressionParsingException("Expecting a type expression before [.", iter.getIndex()); + } else if (iter.next() != ']') { + throw new TypeExpressionParsingException("Invalid character '" + iter.current() + "' expecting ']'.", iter.getIndex()); + } else { + final TypeExpressionNode arrayType = validateNode(expressionStack.pop(), iter); + final ArrayTypeExpressionNode arrayTypeTypeNode = new ArrayTypeExpressionNode(arrayType); + arrayTypeTypeNode.setStartPosition(arrayType.getStartPosition()); + arrayTypeTypeNode.setEndPosition(arrayType.getEndPosition().rightShift(2)); // We shift 2 because is the [] of the array + expressionStack.push(arrayTypeTypeNode); + } + break; + case ' ': + case '\t': + case '\n': + // Ignore white spaces + break; + default: + simpleExpression.append(c); + } + } + if (depth > 0) { + throw new TypeExpressionParsingException("Parenthesis are not correctly balanced.", iter.getIndex()); + } + return handleExpressionFinished(currentNode, expressionStack, iter, simpleExpression); + } + + private TypeExpressionNode handleExpressionFinished(Node currentNode, Stack typeStack, StringCharacterIterator iter, StringBuilder simpleExpression) + throws TypeExpressionParsingException { + handleSimpleExpression(currentNode, iter, typeStack, simpleExpression); + TypeExpressionNode result = null; + if (typeStack.isEmpty()) { + throw new TypeExpressionParsingException("Invalid empty expression.", iter.getIndex()); + } + while (!typeStack.isEmpty()) { + final TypeExpressionNode node = typeStack.pop(); + if (result != null) { + node.addChild(result); + } + result = node; + validateNode(result, iter); + } + return result; + } + + private TypeExpressionNode validateNode(TypeExpressionNode result, StringCharacterIterator iter) throws TypeExpressionParsingException { + if (result instanceof UnionTypeExpressionNode) { + if (result.getChildren().size() < 2) { + throw new TypeExpressionParsingException("Invalid union type expression.", iter.getIndex()); + } + } else if (result instanceof ArrayTypeExpressionNode) { + if (result.getChildren().size() != 1) { + throw new TypeExpressionParsingException("Invalid array type expression.", iter.getIndex()); + } + } + return result; + } + + private void handleSimpleExpression(Node currentNode, StringCharacterIterator iter, Stack expressions, StringBuilder simpleExpression) throws TypeExpressionParsingException { + String expressionString = simpleExpression.toString(); + boolean optionalType = false; + if (expressionString.endsWith("?")) { + expressionString = expressionString.substring(0, expressionString.length() - 1); + optionalType = true; + } + + final Position startPosition = currentNode.getStartPosition().rightShift(iter.getIndex() - expressionString.length()); + final Position endPosition = currentNode.getStartPosition().rightShift(iter.getIndex()); + + // If it is a native type we should not create a reference node + if (NativeTypeExpressionNode.isNativeType(expressionString)) { + final NativeTypeExpressionNode item = new NativeTypeExpressionNode(expressionString); + item.setStartPosition(startPosition); + item.setEndPosition(endPosition); + expressions.push(item); + if (optionalType) { + handleOptionalType(expressions); + } + } else if (expressionString.length() > 0) { + final NodeReferenceFactory nodeReferenceFactory = new NodeReferenceFactory(NamedTypeExpressionNode.class); + final Node parse = nodeReferenceFactory.parse(currentNode, expressionString, iter.getIndex()); + if (parse instanceof ErrorNode) { + throw new TypeExpressionParsingException(((ErrorNode) parse).getErrorMessage(), currentNode.getStartPosition().getIndex()); + } + expressions.push((TypeExpressionNode) parse); + if (optionalType) { + handleOptionalType(expressions); + } + } + clear(simpleExpression); + + + } + + private void handleOptionalType(Stack expressions) { + final TypeExpressionNode optionalOf = expressions.pop(); + final UnionTypeExpressionNode optionalTypeExpression = new UnionTypeExpressionNode(); + optionalTypeExpression.addChild(optionalOf); + optionalTypeExpression.addChild(new NativeTypeExpressionNode(TypeId.NULL.getType())); + expressions.push(optionalTypeExpression); + } + + /** + * Clear the string builder + * + * @param simpleExpression the string builder to be cleared + */ + private void clear(StringBuilder simpleExpression) { + simpleExpression.setLength(0); + } + + private static class TypeExpressionParsingException extends Exception { + private final int location; + + public TypeExpressionParsingException(String message, int location) { + super(message); + this.location = location; + } + + public int getLocation() { + return location; + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/AnnotationValidationPhase.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/AnnotationValidationPhase.java new file mode 100644 index 0000000..ad74dfb --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/AnnotationValidationPhase.java @@ -0,0 +1,77 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.phase; + +import java.util.List; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.api.model.v10.declarations.AnnotationTarget; +import org.xbib.raml.internal.impl.commons.nodes.AnnotationNode; +import org.xbib.raml.internal.impl.commons.nodes.AnnotationTypeNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.internal.impl.v10.type.TypeToRuleVisitor; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.phase.Phase; + +public class AnnotationValidationPhase implements Phase { + + private final ResourceLoader resourceLoader; + + public AnnotationValidationPhase(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + @Override + public Node apply(Node tree) { + final List annotations = tree.findDescendantsWith(AnnotationNode.class); + for (AnnotationNode annotation : annotations) { + final String annotationName = annotation.getName(); + final AnnotationTypeNode annotationTypeNode = annotation.getAnnotationTypeNode(); + if (annotationTypeNode == null) { + annotation.replaceWith(ErrorNodeFactory.createMissingAnnotationType(annotationName)); + } else { + final Node annotationValue = annotation.getValue(); + + // check annotation target + List allowedTargets = annotationTypeNode.getAllowedTargets(); + addTargetAliases(allowedTargets); + AnnotationTarget target = annotation.getTarget(); + if (target != null && !allowedTargets.isEmpty() && !allowedTargets.contains(target)) { + annotationValue.replaceWith(RamlErrorNodeFactory.createInvalidAnnotationTarget(allowedTargets, target)); + } + + // check annotation type + final TypeDeclarationNode typeNode = annotationTypeNode.getDeclaredType(); + final Rule annotationRule = typeNode.getResolvedType().visit(new TypeToRuleVisitor(resourceLoader)); + annotationValue.replaceWith(annotationRule.apply(annotationValue)); + } + } + return tree; + } + + private void addTargetAliases(List allowedTargets) { + if (allowedTargets.contains(AnnotationTarget.TypeDeclaration)) { + if (!allowedTargets.contains(AnnotationTarget.RequestBody)) { + allowedTargets.add(AnnotationTarget.RequestBody); + } + if (!allowedTargets.contains(AnnotationTarget.ResponseBody)) { + allowedTargets.add(AnnotationTarget.ResponseBody); + } + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/ExampleValidationPhase.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/ExampleValidationPhase.java new file mode 100644 index 0000000..ba0c2f6 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/ExampleValidationPhase.java @@ -0,0 +1,266 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.phase; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.HashSet; +import java.util.List; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; +import org.apache.ws.commons.schema.XmlSchema; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.internal.impl.commons.model.factory.TypeDeclarationModelFactory; +import org.xbib.raml.internal.impl.commons.nodes.ExampleDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.type.JsonSchemaExternalType; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.commons.type.XmlSchemaExternalType; +import org.xbib.raml.internal.impl.v10.type.AnyResolvedType; +import org.xbib.raml.internal.impl.v10.type.ArrayResolvedType; +import org.xbib.raml.internal.impl.v10.type.FileResolvedType; +import org.xbib.raml.internal.impl.v10.type.ObjectResolvedType; +import org.xbib.raml.internal.impl.v10.type.StringResolvedType; +import org.xbib.raml.internal.impl.v10.type.TypeToRuleVisitor; +import org.xbib.raml.internal.impl.v10.type.TypeToXmlSchemaVisitor; +import org.xbib.raml.internal.impl.v10.type.UnionResolvedType; +import org.xbib.raml.internal.utils.xml.XMLLocalConstants; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.NullValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.NullNodeImpl; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; +import org.xbib.raml.yagi.framework.nodes.jackson.JNodeParser; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.NodeParser; +import org.xbib.raml.yagi.framework.phase.Phase; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLFilterImpl; +import org.xml.sax.helpers.XMLReaderFactory; +import static org.xbib.raml.internal.utils.xml.XMLLocalConstants.DISALLOW_DOCTYPE_DECL_FEATURE; +import static org.xbib.raml.internal.utils.xml.XMLLocalConstants.EXTERNAL_GENERAL_ENTITIES_FEATURE; +import static org.xbib.raml.internal.utils.xml.XMLLocalConstants.EXTERNAL_PARAMETER_ENTITIES_FEATURE; +import static org.xbib.raml.internal.utils.xml.XMLLocalConstants.expandEntities; +import static org.xbib.raml.internal.utils.xml.XMLLocalConstants.externalEntities; + +public class ExampleValidationPhase implements Phase { + private final ResourceLoader resourceLoader; + private static final String ERROR_MESSAGE_MAX_LENGTH = "raml.error_message_max_length"; + public static int errorMessageMaxLength = Integer.parseInt(System.getProperty(ERROR_MESSAGE_MAX_LENGTH, "10000")); + + private static final String NILLABLE_TYPES_PROP = "org.raml.nillable_types"; + public static boolean NILLABLE_TYPES = Boolean.parseBoolean(System.getProperty(NILLABLE_TYPES_PROP, "false")); + + + public ExampleValidationPhase(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + @Override + public Node apply(Node tree) { + final List descendantsWith = tree.findDescendantsWith(ExampleDeclarationNode.class); + for (ExampleDeclarationNode exampleTypeNode : descendantsWith) { + if (exampleTypeNode.isStrict()) { + final TypeDeclarationNode type = org.xbib.raml.yagi.framework.util.NodeUtils.getAncestor(exampleTypeNode, TypeDeclarationNode.class); + final Node exampleValue = exampleTypeNode.getExampleValue(); + if (type != null) { + final Node validate = validate(type, exampleValue); + if (validate != null) { + exampleValue.replaceWith(validate); + } + } + } + } + return tree; + } + + + public Node validate(TypeDeclarationNode type, String exampleValue) { + Node exampleValueNode = new StringNodeImpl(exampleValue); + + if (exampleValue == null || (exampleValue.isBlank() && !(type.getResolvedType() instanceof StringResolvedType))) { + exampleValueNode = new NullNodeImpl(); + } else if (!(type.getResolvedType() instanceof StringResolvedType) && + !(type.getResolvedType() instanceof FileResolvedType) && + !isJsonValue(exampleValue) && + !isXmlValue(exampleValue)) { + // parse as yaml except for string, file, json and xml types + exampleValueNode = NodeParser.parse(resourceLoader, "", exampleValue); + } + return validate(type, exampleValueNode); + } + + + public Node validate(TypeDeclarationNode type, Node exampleValue) { + final ResolvedType resolvedType = type.getResolvedType(); + if (resolvedType instanceof AnyResolvedType) // If accepts any no need for validation + { + return null; + } + if (exampleValue instanceof StringNode && !isExternalSchemaType(resolvedType)) { + final String value = ((StringNode) exampleValue).getValue(); + if ((mightBeAnObjectType(resolvedType)) && isXmlValue(value)) { + return validateXml(type, resolvedType, value); + } else if ((mightBeAnObjectType(resolvedType) || (resolvedType instanceof ArrayResolvedType)) && isJsonValue(value)) { + return validateJson(exampleValue, resolvedType, value); + } + } + + if (exampleValue instanceof ErrorNode) { + return exampleValue; + } + + if (exampleValue != null) { + final Rule rule = visitAppropriately(resolvedType); + return rule != null ? rule.apply(exampleValue) : null; + } + return null; + } + + private Rule visitAppropriately(ResolvedType resolvedType) { + if (NILLABLE_TYPES) { + return new AnyOfRule(resolvedType.visit(new TypeToRuleVisitor(resourceLoader, false)), new NullValueRule()); + } else { + + return resolvedType.visit(new TypeToRuleVisitor(resourceLoader, false)); + } + } + + private boolean mightBeAnObjectType(ResolvedType resolvedType) { + if (resolvedType instanceof ObjectResolvedType) { + return true; + } + + return unionMightBeAnObject(resolvedType, new HashSet()); + } + + private boolean unionMightBeAnObject(ResolvedType resolvedType, HashSet seenTypes) { + + seenTypes.add(resolvedType.getTypeName()); + if (resolvedType instanceof UnionResolvedType urt) { + for (ResolvedType type : urt.of()) { + if (!seenTypes.contains(type.getTypeName())) { + return unionMightBeAnObject(type, seenTypes); + } + } + } + + // return resolvedType instanceof ObjectResolvedType || (resolvedType instanceof ArrayResolvedType && unionMightBeAnObject(((ArrayResolvedType) resolvedType).getItems(), new + // HashSet())); + + return resolvedType instanceof ObjectResolvedType || (resolvedType instanceof ArrayResolvedType); + } + + protected Node validateJson(Node exampleValue, ResolvedType resolvedType, String value) { + final Rule rule = resolvedType.visit(new TypeToRuleVisitor(resourceLoader)); + final Node parse = JNodeParser.parse(resourceLoader, "", value); + + if (parse.getType() != NodeType.Error) { + final Node apply = rule.apply(parse); + final List errorNodeList = apply.findDescendantsWith(ErrorNode.class); + + if (apply instanceof ErrorNode) { + errorNodeList.add(0, (ErrorNode) apply); + } + + if (!errorNodeList.isEmpty()) { + String errorMessage = ""; + for (ErrorNode errorNode : errorNodeList) { + if (errorMessage.length() > errorMessageMaxLength) + break; + if (errorMessage.isEmpty()) { + errorMessage = "- " + errorNode.getErrorMessage(); + } else { + errorMessage += "\n" + "- " + errorNode.getErrorMessage(); + } + } + return ErrorNodeFactory.createInvalidJsonExampleNode(errorMessage); + } else { + return exampleValue; + } + } else { + return parse; + } + } + + + protected Node validateXml(TypeDeclarationNode type, ResolvedType resolvedType, String value) { + final TypeToXmlSchemaVisitor typeToXmlSchemaVisitor = new TypeToXmlSchemaVisitor(); + typeToXmlSchemaVisitor.transform(new TypeDeclarationModelFactory().create(type).rootElementName(), resolvedType); + final XmlSchema schema = typeToXmlSchemaVisitor.getSchema(); + final StringWriter xsd = new StringWriter(); + schema.write(xsd); + try { + final SchemaFactory factory = SchemaFactory.newInstance(XMLLocalConstants.XML_SCHEMA_VERSION); + final Schema schema1 = factory.newSchema(new StreamSource(new StringReader(xsd.toString()))); + final Validator validator = schema1.newValidator(); + + final XMLReader xmlReader = XMLReaderFactory.createXMLReader(); + + xmlReader.setFeature(DISALLOW_DOCTYPE_DECL_FEATURE, !expandEntities); + xmlReader.setFeature(EXTERNAL_GENERAL_ENTITIES_FEATURE, externalEntities); + xmlReader.setFeature(EXTERNAL_PARAMETER_ENTITIES_FEATURE, externalEntities); + + validator.validate(new SAXSource( + new NamespaceFilter(xmlReader, TypeToXmlSchemaVisitor.getTargetNamespace(resolvedType)), + new InputSource(new StringReader(value)))); + } catch (IOException | SAXException e) { + return ErrorNodeFactory.createInvalidXmlExampleNode(e.getMessage()); + } + return null; + } + + private boolean isXmlValue(String value) { + return value.trim().startsWith("<"); + } + + private boolean isJsonValue(String value) { + return value.trim().startsWith("{") || value.trim().startsWith("["); + } + + private boolean isExternalSchemaType(ResolvedType resolvedType) { + return resolvedType instanceof XmlSchemaExternalType || resolvedType instanceof JsonSchemaExternalType; + } + + + private static class NamespaceFilter extends XMLFilterImpl { + + String requiredNamespace; + + public NamespaceFilter(XMLReader parent, String requiredNamespace) { + super(parent); + this.requiredNamespace = requiredNamespace; + } + + @Override + public void startElement(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException { + if (!arg0.equals(requiredNamespace)) + arg0 = requiredNamespace; + super.startElement(arg0, arg1, arg2, arg3); + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/ImplicitUriParametersInjectionTransformer.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/ImplicitUriParametersInjectionTransformer.java new file mode 100644 index 0000000..57933b6 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/ImplicitUriParametersInjectionTransformer.java @@ -0,0 +1,79 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.phase; + +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.ResourceNode; +import org.xbib.raml.internal.impl.v10.nodes.NativeTypeExpressionNode; +import org.xbib.raml.internal.impl.v10.nodes.PropertyNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNodeImpl; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; +import org.xbib.raml.yagi.framework.phase.Transformer; +import org.xbib.raml.yagi.framework.util.NodeSelector; +import static org.xbib.raml.internal.utils.ResourcePathUtils.getUriTemplates; + +public class ImplicitUriParametersInjectionTransformer implements Transformer { + final private static String URI_PARAMETERS = "uriParameters"; + + @Override + public boolean matches(Node node) { + return node instanceof ResourceNode; + } + + @Override + public Node transform(Node node) { + ResourceNode resourceNode = (ResourceNode) node; + List templates = getUriTemplates(resourceNode.getRelativeUri()); + // version should be defined at root level + templates.remove("version"); + injectImplicitUriParameters(resourceNode.getValue(), templates); + + return node; + } + + private void injectImplicitUriParameters(Node node, List templates) { + Node parametersNode = NodeSelector.selectFrom(URI_PARAMETERS, node); + if (parametersNode != null) { + for (Node child : parametersNode.getChildren()) { + String parameterName = ((SimpleTypeNode) ((KeyValueNode) child).getKey()).getLiteralValue(); + templates.remove(parameterName.endsWith("?") ? parameterName.substring(0, parameterName.length() - 1) : parameterName); + } + if (!templates.isEmpty()) { + addUriParameters(templates, parametersNode); + } + } else if (!templates.isEmpty()) { + StringNodeImpl uriParameters = new StringNodeImpl(URI_PARAMETERS); + ObjectNodeImpl objectNode = new ObjectNodeImpl(); + + addUriParameters(templates, objectNode); + node.addChild(new KeyValueNodeImpl(uriParameters, objectNode)); + } + + } + + private void addUriParameters(List templates, Node objectNode) { + for (String uriParameter : templates) { + PropertyNode propertyNode = new PropertyNode(); + propertyNode.addChild(new StringNodeImpl(uriParameter)); + propertyNode.addChild(new NativeTypeExpressionNode("string")); + objectNode.addChild(propertyNode); + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/LibraryLinkingTransformation.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/LibraryLinkingTransformation.java new file mode 100644 index 0000000..c28f039 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/LibraryLinkingTransformation.java @@ -0,0 +1,69 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.phase; + +import java.io.IOException; +import java.io.InputStream; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.internal.impl.v10.Raml10Builder; +import org.xbib.raml.internal.impl.v10.nodes.LibraryLinkNode; +import org.xbib.raml.internal.utils.ResourcePathUtils; +import org.xbib.raml.internal.utils.StreamUtils; +import org.xbib.raml.yagi.framework.nodes.IncludeErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.phase.Transformer; +import static org.xbib.raml.api.model.v10.RamlFragment.Library; +import static org.xbib.raml.internal.impl.RamlBuilder.ALL_PHASES; + +public class LibraryLinkingTransformation implements Transformer { + + private final Raml10Builder builder; + private final ResourceLoader resourceLoader; + + public LibraryLinkingTransformation(Raml10Builder builder, ResourceLoader resourceLoader) { + this.builder = builder; + this.resourceLoader = resourceLoader; + } + + @Override + public boolean matches(Node node) { + return node instanceof LibraryLinkNode; + } + + @Override + public Node transform(Node node) { + final LibraryLinkNode linkNode = (LibraryLinkNode) node; + final String baseLocation = linkNode.getStartPosition().getPath(); + final String refName = linkNode.getRefName(); + final String absoluteLocation = ResourcePathUtils.toAbsoluteLocation(baseLocation, refName); + try { + try (InputStream inputStream = resourceLoader.fetchResource(absoluteLocation)) { + if (inputStream == null) { + return new IncludeErrorNode("Library cannot be resolved: " + absoluteLocation); + } + final String content = StreamUtils.toString(inputStream); + final Node libraryReference = builder + .build(linkNode, content, Library, resourceLoader, absoluteLocation, ALL_PHASES); + + linkNode.setLibraryReference(libraryReference); + } + } catch (IOException e) { + return new IncludeErrorNode(String.format("Library cannot be resolved: %s. (%s)", absoluteLocation, e.getMessage())); + } + + return linkNode; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/MediaTypeInjectionPhase.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/MediaTypeInjectionPhase.java new file mode 100644 index 0000000..93a6002 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/MediaTypeInjectionPhase.java @@ -0,0 +1,117 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.phase; + + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.BodyNode; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.yagi.framework.nodes.BaseNode; +import org.xbib.raml.yagi.framework.nodes.DefaultPosition; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.Position; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.phase.Phase; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class MediaTypeInjectionPhase implements Phase { + + @Override + public Node apply(Node tree) { + List defaultMediaTypes = getDefaultMediaTypes(tree); + if (!defaultMediaTypes.isEmpty()) { + List bodyNodes = tree.findDescendantsWith(BodyNode.class); + for (BodyNode bodyNode : bodyNodes) { + if (!hasExplicitMimeTypes(bodyNode)) { + injectMediaTypes(bodyNode, defaultMediaTypes); + } + } + } + return tree; + } + + private List getDefaultMediaTypes(Node tree) { + List result = new ArrayList<>(); + Node mediaTypeNode = NodeSelector.selectFrom("mediaType", tree); + if (mediaTypeNode != null) { + if (mediaTypeNode instanceof StringNode) { + result.add((StringNode) mediaTypeNode); + } else { + for (Node node : mediaTypeNode.getChildren()) { + result.add((StringNode) node); + } + } + } + return result; + } + + private void injectMediaTypes(BodyNode bodyNode, List defaultMediaTypes) { + Node injected = new MediaTypeInjectedNode(); + for (StringNode defaultMediaType : defaultMediaTypes) { + Node copy = bodyNode.getValue().copy(); + KeyValueNode keyValue = new KeyValueNodeImpl(defaultMediaType.copy(), copy); + injected.addChild(keyValue); + } + bodyNode.setValue(injected); + } + + private boolean hasExplicitMimeTypes(BodyNode bodyNode) { + List children = bodyNode.getValue().getChildren(); + if (!children.isEmpty() && !children.get(0).getChildren().isEmpty()) { + Node key = children.get(0).getChildren().get(0); + return new Raml10Grammar().mimeTypeRegex().matches(key); + } + return false; + } + + private static class MediaTypeInjectedNode extends BaseNode implements ObjectNode { + + public MediaTypeInjectedNode() { + } + + public MediaTypeInjectedNode(MediaTypeInjectedNode mediaTypeInjectedNode) { + super(mediaTypeInjectedNode); + } + + + @Override + public Position getStartPosition() { + return getParent() != null ? getParent().getStartPosition() : DefaultPosition.emptyPosition(); + } + + + @Override + public Position getEndPosition() { + return getChildren().isEmpty() ? DefaultPosition.emptyPosition() : getChildren().get(0).getEndPosition(); + } + + + @Override + public Node copy() { + return new MediaTypeInjectedNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Object; + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/ReferenceResolverTransformer.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/ReferenceResolverTransformer.java new file mode 100644 index 0000000..41fa610 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/phase/ReferenceResolverTransformer.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.phase; + +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; +import org.xbib.raml.yagi.framework.phase.Transformer; + + +public class ReferenceResolverTransformer implements Transformer { + + @Override + public boolean matches(Node node) { + return node instanceof ReferenceNode; + } + + @Override + public Node transform(Node node) { + ReferenceNode referenceNode = (ReferenceNode) node; + Node refNode = referenceNode.getRefNode(); + if (refNode == null) { + return ErrorNodeFactory.createInvalidReferenceNode(referenceNode); + } else { + return node; + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/DiscriminatorBasedRule.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/DiscriminatorBasedRule.java new file mode 100644 index 0000000..a1dfa51 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/DiscriminatorBasedRule.java @@ -0,0 +1,134 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.rules; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationField; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.v10.nodes.LibraryLinkNode; +import org.xbib.raml.internal.impl.v10.type.TypeToRuleVisitor; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class DiscriminatorBasedRule extends Rule { + private final TypeToRuleVisitor typeToRuleVisitor; + private final Node rootElement; + private final String discriminatorProperty; + private final Map typeRulesCache; + + + public DiscriminatorBasedRule(TypeToRuleVisitor typeToRuleVisitor, Node rootElement, String discriminatorProperty) { + this.typeToRuleVisitor = typeToRuleVisitor; + this.rootElement = rootElement; + this.discriminatorProperty = discriminatorProperty; + this.typeRulesCache = new HashMap<>(); + } + + @Override + public boolean matches(Node node) { + final Node discriminatorNode = node.get(discriminatorProperty); + return discriminatorNode instanceof SimpleTypeNode; + } + + + @Override + public Node apply(Node node) { + final SimpleTypeNode discriminatorValue = (SimpleTypeNode) node.get(discriminatorProperty); + if (discriminatorValue == null) { + node.replaceWith(ErrorNodeFactory.createInvalidType("discriminator not specified")); + } else { + final String literalValue = discriminatorValue.getLiteralValue(); + Rule value = findType(literalValue); + if (value != null) { + value.apply(node); + } else { + node.replaceWith(ErrorNodeFactory.createInvalidType(literalValue)); + } + } + return node; + } + + + protected Rule findType(String literalValue) { + Rule value = null; + if (!typeRulesCache.containsKey(literalValue)) { + final TypeDeclarationNode typeDeclaration = findTypeDeclaration(literalValue); + if (typeDeclaration != null) { + typeToRuleVisitor.resolveDiscrimintor(); + value = typeToRuleVisitor.generateRule(typeDeclaration.getResolvedType()); + typeRulesCache.put(literalValue, value); + } + } else { + value = typeRulesCache.get(literalValue); + } + return value; + } + + + protected TypeDeclarationNode findTypeDeclaration(String literalValue) { + final List descendantsWith = findTypeDeclarationField(rootElement); + for (TypeDeclarationField typeDeclarationField : descendantsWith) { + final Node typeDeclaration = typeDeclarationField.getValue(); + final Node discriminatorValue = typeDeclaration.get("discriminatorValue"); + String typeIdentifier; + if (discriminatorValue instanceof SimpleTypeNode) { + typeIdentifier = ((SimpleTypeNode) discriminatorValue).getLiteralValue(); + } else { + typeIdentifier = ((SimpleTypeNode) typeDeclarationField.getKey()).getLiteralValue(); + } + + if (literalValue.equals(typeIdentifier)) { + return (TypeDeclarationNode) typeDeclaration; + } + } + return null; + } + + + public List findTypeDeclarationField(Node node) { + final List result = new ArrayList<>(); + final List children = node.getChildren(); + for (Node child : children) { + if (child instanceof TypeDeclarationField) { + result.add((TypeDeclarationField) child); + } else if (child instanceof LibraryLinkNode) { + // Should search across libraries + result.addAll(findTypeDeclarationField(((LibraryLinkNode) child).getRefNode())); + } + result.addAll(findTypeDeclarationField(child)); + } + return result; + } + + @Override + public String getDescription() { + return "Dynamic rule based on '" + discriminatorProperty + "'."; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/FormatValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/FormatValueRule.java new file mode 100644 index 0000000..7070d23 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/FormatValueRule.java @@ -0,0 +1,71 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.rules; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.FloatingNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class FormatValueRule extends Rule { + private final String format; + + public FormatValueRule(String format) { + this.format = format; + } + + @Override + public boolean matches(Node node) { + if (node instanceof FloatingNode floatingNode && (format.equals("long") || format.startsWith("int"))) { + BigDecimal value = floatingNode.getValue(); + BigDecimal roundedValue = floatingNode.getValue().setScale(0, RoundingMode.DOWN); + return roundedValue.compareTo(value) == 0; + } + + return true; + } + + + @Override + public Node apply(Node node) { + if (matches(node)) { + return createNodeUsingFactory(node, ((SimpleTypeNode) node).getValue()); + } else { + return RamlErrorNodeFactory.createInvalidFormatValue( + ((SimpleTypeNode) node).getValue().toString(), + format); + } + } + + @Override + public String getDescription() { + return "Format of value"; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/TypeDefaultValue.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/TypeDefaultValue.java new file mode 100644 index 0000000..cb0a35e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/TypeDefaultValue.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.rules; + + +import org.xbib.raml.internal.impl.v10.nodes.NativeTypeExpressionNode; +import org.xbib.raml.internal.impl.v10.nodes.OverridableNativeTypeExpressionNode; +import org.xbib.raml.internal.impl.v10.type.TypeId; +import org.xbib.raml.yagi.framework.grammar.rule.DefaultValue; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class TypeDefaultValue implements DefaultValue { + private final TypeId defaultType; + + public TypeDefaultValue(TypeId defaultType) { + this.defaultType = defaultType; + } + + + @Override + public Node getDefaultValue(Node parent) { + if (parent.get("properties") != null) { + return new NativeTypeExpressionNode(TypeId.OBJECT.getType()); + } + if (parent.get("items") != null) { + return new NativeTypeExpressionNode(TypeId.ARRAY.getType()); + } + if (parent.get("fileTypes") != null) { + return new NativeTypeExpressionNode(TypeId.FILE.getType()); + } + + return new OverridableNativeTypeExpressionNode(defaultType.getType()); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/TypeExpressionReferenceRule.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/TypeExpressionReferenceRule.java new file mode 100644 index 0000000..9e4b7c9 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/TypeExpressionReferenceRule.java @@ -0,0 +1,70 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.rules; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.suggester.ReferenceSuggester; +import org.xbib.raml.internal.impl.v10.type.TypeId; +import org.xbib.raml.internal.utils.StringUtils; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.DefaultSuggestion; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class TypeExpressionReferenceRule extends Rule { + + private final ReferenceSuggester suggester; + + public TypeExpressionReferenceRule() { + this.suggester = new ReferenceSuggester("types"); + } + + @Override + public boolean matches(Node node) { + // It should be a simple type expression if is an object type then it may be a TypeExpressionNode but it should not match here + return node instanceof SimpleTypeNode; + } + + + @Override + public Node apply(Node node) { + if (node instanceof TypeExpressionNode) { + return node; + } + return createNodeUsingFactory(node, ((StringNode) node).getLiteralValue()); + } + + @Override + public String getDescription() { + return "Type reference expression."; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + final List suggestions = new ArrayList<>(suggester.getSuggestions(node)); + final TypeId[] values = TypeId.values(); + for (TypeId value : values) { + suggestions.add(new DefaultSuggestion(value.getType(), "", StringUtils.capitalize(value.getType()))); + } + return suggestions; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/TypesUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/TypesUtils.java new file mode 100644 index 0000000..e779a03 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/rules/TypesUtils.java @@ -0,0 +1,33 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.rules; + +import java.util.List; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.util.NodeUtils; + +public class TypesUtils { + + public static void validateAllWith(Rule rule, List nodes) { + for (Node facet : nodes) { + if (!NodeUtils.isErrorResult(facet)) { + final Node apply = rule.apply(facet); + facet.replaceWith(apply); + } + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/AnyResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/AnyResolvedType.java new file mode 100644 index 0000000..45dda0a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/AnyResolvedType.java @@ -0,0 +1,71 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; + +public class AnyResolvedType extends XmlFacetsCapableType { + + + public AnyResolvedType(String typeName, TypeExpressionNode declarationNode, XmlFacets xmlFacets, ResolvedCustomFacets customFacets) { + super(typeName, declarationNode, xmlFacets, customFacets); + } + + public AnyResolvedType(TypeExpressionNode declarationNode) { + super(getTypeName(declarationNode, TypeId.ANY.getType()), declarationNode, new ResolvedCustomFacets()); + } + + protected AnyResolvedType copy() { + return new AnyResolvedType(getTypeName(), getTypeExpressionNode(), getXmlFacets().copy(), customFacets.copy()); + } + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + final AnyResolvedType copy = copy(); + copy.customFacets = copy.customFacets.overwriteFacets(from); + return copy; + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + final AnyResolvedType copy = copy(); + copy.customFacets = copy.customFacets.mergeWith(with.customFacets()); + return copy; + } + + @Override + public boolean doAccept(ResolvedType valueType) { + return true; + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitAny(this); + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + customFacets.validate(from); + final AnyOfRule facetRule = new AnyOfRule().addAll(customFacets.getRules()); + TypesUtils.validateAllWith(facetRule, from.getFacets()); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/ArrayResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/ArrayResolvedType.java new file mode 100644 index 0000000..964c521 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/ArrayResolvedType.java @@ -0,0 +1,186 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.commons.type.SchemaBasedResolvedType; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.util.NodeSelector; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.ITEMS_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.MAX_ITEMS_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.MIN_ITEMS_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.UNIQUE_ITEMS_KEY_NAME; +import static org.xbib.raml.yagi.framework.util.NodeSelector.selectBooleanValue; +import static org.xbib.raml.yagi.framework.util.NodeSelector.selectIntValue; + +public class ArrayResolvedType extends XmlFacetsCapableType { + + private ResolvedType items; + private Boolean uniqueItems; + private Integer minItems; + private Integer maxItems; + + public ArrayResolvedType(String typeName, TypeExpressionNode node, XmlFacets xmlFacets, ResolvedType items, Boolean uniqueItems, Integer minItems, Integer maxItems, + ResolvedCustomFacets customFacets) { + super(typeName, node, xmlFacets, customFacets); + this.items = items; + this.uniqueItems = uniqueItems; + this.minItems = minItems; + this.maxItems = maxItems; + } + + public ArrayResolvedType(TypeExpressionNode node, ResolvedType items) { + this(node); + this.items = items; + } + + public ArrayResolvedType(TypeExpressionNode node) { + super(getTypeName(node, TypeId.ARRAY.getType()), node, new ResolvedCustomFacets(MIN_ITEMS_KEY_NAME, MAX_ITEMS_KEY_NAME, UNIQUE_ITEMS_KEY_NAME, ITEMS_KEY_NAME)); + } + + protected ArrayResolvedType copy() { + return new ArrayResolvedType(getTypeName(), getTypeExpressionNode(), getXmlFacets().copy(), items, uniqueItems, minItems, maxItems, customFacets.copy()); + } + + + public void validateCanOverwriteWith(TypeDeclarationNode from) { + customFacets.validate(from); + final Raml10Grammar grammar = new Raml10Grammar(); + final AnyOfRule facetRule = new AnyOfRule() + .add(grammar.uniqueItemsField()) + .add(grammar.itemsField()) + .add(grammar.minItemsField()) + .add(grammar.maxItemsField()) + .addAll(customFacets.getRules()); + TypesUtils.validateAllWith(facetRule, from.getFacets()); + + } + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + // Validate that is can be overwritten by + final ArrayResolvedType result = copy(); + result.customFacets = result.customFacets.overwriteFacets(from); + result.setMinItems(selectIntValue(MIN_ITEMS_KEY_NAME, from)); + result.setMaxItems(selectIntValue(MAX_ITEMS_KEY_NAME, from)); + result.setUniqueItems(selectBooleanValue(UNIQUE_ITEMS_KEY_NAME, from)); + final Node items = NodeSelector.selectFrom(ITEMS_KEY_NAME, from); + if (items != null && items instanceof TypeDeclarationNode) { + result.setItems(((TypeDeclarationNode) items).getResolvedType()); + } + overwriteFacets(result, from); + return result; + } + + @Override + public boolean doAccept(ResolvedType resolvedType) { + if (resolvedType instanceof ArrayResolvedType) { + return items.accepts(((ArrayResolvedType) resolvedType).getItems()); + } else { + return false; + } + } + + public void validateState() { + int min = minItems != null ? minItems : 0; + int max = maxItems != null ? maxItems : Integer.MAX_VALUE; + if (max < min) { + getTypeExpressionNode().replaceWith(RamlErrorNodeFactory.createInvalidFacetState(getTypeName(), "maxItems must be greater than or equal to minItems.")); + } + + if (getItems() instanceof SchemaBasedResolvedType) { + getTypeExpressionNode().replaceWith(RamlErrorNodeFactory.createInvalidFacetState(getItems().getTypeName(), "array type cannot be of an external type.")); + } + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + final ArrayResolvedType result = copy(); + if (with instanceof ArrayResolvedType) { + result.setMinItems(((ArrayResolvedType) with).getMinItems()); + result.setMaxItems(((ArrayResolvedType) with).getMaxItems()); + result.setUniqueItems(((ArrayResolvedType) with).getUniqueItems()); + result.setItems(((ArrayResolvedType) with).getItems()); + } + result.customFacets = result.customFacets.mergeWith(with.customFacets()); + return mergeFacets(result, with); + } + + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitArray(this); + } + + + public ResolvedType getItems() { + if (items == null) { + // If array is not typed (either through 'items' or an expression) then items in the array can be anything + items = new AnyResolvedType(getTypeExpressionNode()); + } + return items; + } + + private void setItems(ResolvedType items) { + if (items != null) { + this.items = items; + } + } + + public Boolean getUniqueItems() { + return uniqueItems; + } + + private void setUniqueItems(Boolean uniqueItems) { + if (uniqueItems != null) { + this.uniqueItems = uniqueItems; + } + } + + public Integer getMinItems() { + return minItems; + } + + private void setMinItems(Integer minItems) { + if (minItems != null) { + this.minItems = minItems; + } + } + + public Integer getMaxItems() { + return maxItems; + } + + private void setMaxItems(Integer maxItems) { + if (maxItems != null) { + this.maxItems = maxItems; + } + } + + + @Override + public String getBuiltinTypeName() { + return TypeId.ARRAY.getType(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/BooleanResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/BooleanResolvedType.java new file mode 100644 index 0000000..f700094 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/BooleanResolvedType.java @@ -0,0 +1,111 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.BooleanNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class BooleanResolvedType extends XmlFacetsCapableType { + + private List enums = new ArrayList<>(); + + public BooleanResolvedType(String typeName, TypeExpressionNode declarationNode, XmlFacets xmlFacets, ResolvedCustomFacets customFacets) { + super(typeName, declarationNode, xmlFacets, customFacets); + } + + public BooleanResolvedType(TypeExpressionNode from) { + super(getTypeName(from, TypeId.BOOLEAN.getType()), from, new ResolvedCustomFacets()); + } + + protected BooleanResolvedType copy() { + return new BooleanResolvedType(getTypeName(), getTypeExpressionNode(), getXmlFacets().copy(), customFacets.copy()); + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + customFacets.validate(from); + final Raml10Grammar raml10Grammar = new Raml10Grammar(); + final AnyOfRule facetRule = new AnyOfRule() + .add(raml10Grammar.enumField()) + .addAll(customFacets.getRules()); + TypesUtils.validateAllWith(facetRule, from.getFacets()); + } + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + final BooleanResolvedType copy = copy(); + copy.customFacets = copy.customFacets().overwriteFacets(from); + copy.setEnums(getEnumValues(from)); + return overwriteFacets(copy, from); + } + + + private List getEnumValues(Node typeNode) { + + Node values = typeNode.get("enum"); + List enumValues = new ArrayList<>(); + if (values != null && values instanceof ArrayNode) { + for (Node node : values.getChildren()) { + if (node instanceof BooleanNode) { + enumValues.add(((BooleanNode) node).getValue()); + } + } + } + return enumValues; + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + final BooleanResolvedType copy = copy(); + copy.customFacets = copy.customFacets().mergeWith(with.customFacets()); + if (with instanceof BooleanResolvedType) { + copy.setEnums(((BooleanResolvedType) with).getEnums()); + } + return mergeFacets(copy, with); + } + + public void setEnums(List enums) { + if (enums != null) { + this.enums = enums; + } + } + + public List getEnums() { + return enums; + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitBoolean(this); + } + + + @Override + public String getBuiltinTypeName() { + return TypeId.BOOLEAN.getType(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/DateOnlyResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/DateOnlyResolvedType.java new file mode 100644 index 0000000..7a6b022 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/DateOnlyResolvedType.java @@ -0,0 +1,70 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; + +public class DateOnlyResolvedType extends XmlFacetsCapableType { + + public DateOnlyResolvedType(String typeName, TypeExpressionNode declarationNode, XmlFacets xmlFacets, ResolvedCustomFacets customFacets) { + super(typeName, declarationNode, xmlFacets, customFacets); + } + + public DateOnlyResolvedType(TypeExpressionNode from) { + super(getTypeName(from, TypeId.DATE_ONLY.getType()), from, new ResolvedCustomFacets()); + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + customFacets.validate(from); + final AnyOfRule facetRule = new AnyOfRule().addAll(customFacets.getRules()); + TypesUtils.validateAllWith(facetRule, from.getFacets()); + } + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + final DateOnlyResolvedType copy = copy(); + copy.customFacets = copy.customFacets.overwriteFacets(from); + return overwriteFacets(copy, from); + } + + protected DateOnlyResolvedType copy() { + return new DateOnlyResolvedType(getTypeName(), getTypeExpressionNode(), getXmlFacets().copy(), customFacets.copy()); + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + final DateOnlyResolvedType copy = copy(); + copy.customFacets = copy.customFacets.mergeWith(with.customFacets()); + return mergeFacets(copy, with); + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitDate(this); + } + + + @Override + public String getBuiltinTypeName() { + return TypeId.DATE_ONLY.getType(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/DateTimeOnlyResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/DateTimeOnlyResolvedType.java new file mode 100644 index 0000000..5dfe06e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/DateTimeOnlyResolvedType.java @@ -0,0 +1,69 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; + +public class DateTimeOnlyResolvedType extends XmlFacetsCapableType { + public DateTimeOnlyResolvedType(String typeName, TypeExpressionNode declarationNode, XmlFacets xmlFacets, ResolvedCustomFacets customFacets) { + super(typeName, declarationNode, xmlFacets, customFacets); + } + + public DateTimeOnlyResolvedType(TypeExpressionNode from) { + super(getTypeName(from, TypeId.DATE_TIME_ONLY.getType()), from, new ResolvedCustomFacets()); + } + + protected DateTimeOnlyResolvedType copy() { + return new DateTimeOnlyResolvedType(getTypeName(), getTypeExpressionNode(), getXmlFacets().copy(), customFacets.copy()); + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + customFacets.validate(from); + final AnyOfRule facetRule = new AnyOfRule().addAll(customFacets.getRules()); + TypesUtils.validateAllWith(facetRule, from.getFacets()); + } + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + final DateTimeOnlyResolvedType copy = copy(); + copy.customFacets = copy.customFacets.overwriteFacets(from); + return overwriteFacets(copy, from); + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + final DateTimeOnlyResolvedType copy = copy(); + copy.customFacets = copy.customFacets.mergeWith(with.customFacets()); + return mergeFacets(copy, with); + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitDateTimeOnly(this); + } + + + @Override + public String getBuiltinTypeName() { + return TypeId.DATE_TIME_ONLY.getType(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/DateTimeResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/DateTimeResolvedType.java new file mode 100644 index 0000000..f6e6146 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/DateTimeResolvedType.java @@ -0,0 +1,94 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.FORMAT_KEY_NAME; +import static org.xbib.raml.yagi.framework.util.NodeSelector.selectStringValue; + +public class DateTimeResolvedType extends XmlFacetsCapableType { + + private String format; + + public DateTimeResolvedType(String typeName, TypeExpressionNode declarationNode, XmlFacets xmlFacets, String format, ResolvedCustomFacets customFacets) { + super(typeName, declarationNode, xmlFacets, customFacets); + this.format = format; + } + + public DateTimeResolvedType(TypeExpressionNode from) { + super(getTypeName(from, TypeId.DATE_TIME.getType()), from, new ResolvedCustomFacets(FORMAT_KEY_NAME)); + } + + protected DateTimeResolvedType copy() { + return new DateTimeResolvedType(getTypeName(), getTypeExpressionNode(), getXmlFacets().copy(), format, customFacets.copy()); + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + customFacets.validate(from); + final Raml10Grammar raml10Grammar = new Raml10Grammar(); + final AnyOfRule facetRule = new AnyOfRule() + .add(raml10Grammar.formatField()) + .addAll(customFacets.getRules()); + TypesUtils.validateAllWith(facetRule, from.getFacets()); + } + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + final DateTimeResolvedType result = copy(); + result.setFormat(selectStringValue(FORMAT_KEY_NAME, from)); + result.customFacets = customFacets.overwriteFacets(from); + return overwriteFacets(result, from); + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + final DateTimeResolvedType result = copy(); + if (with instanceof DateTimeResolvedType) { + result.setFormat(((DateTimeResolvedType) with).getFormat()); + } + result.customFacets = result.customFacets.mergeWith(with.customFacets()); + return mergeFacets(result, with); + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitDateTime(this); + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + if (format != null) { + this.format = format; + } + } + + + @Override + public String getBuiltinTypeName() { + return TypeId.DATE_TIME.getType(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/FileResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/FileResolvedType.java new file mode 100644 index 0000000..600b1f8 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/FileResolvedType.java @@ -0,0 +1,130 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.FILE_TYPES_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.FORMAT_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.MAX_LENGTH_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.MIN_LENGTH_KEY_NAME; +import static org.xbib.raml.yagi.framework.util.NodeSelector.selectIntValue; +import static org.xbib.raml.yagi.framework.util.NodeSelector.selectStringCollection; + +public class FileResolvedType extends XmlFacetsCapableType { + + private Integer minLength; + private Integer maxLength; + private List fileTypes; + + public FileResolvedType(TypeExpressionNode from) { + super(getTypeName(from, TypeId.FILE.getType()), from, new ResolvedCustomFacets(MIN_LENGTH_KEY_NAME, MAX_LENGTH_KEY_NAME, FORMAT_KEY_NAME)); + } + + public FileResolvedType(String typeName, TypeExpressionNode declarationNode, XmlFacets xmlFacets, Integer minLength, Integer maxLength, List fileTypes, ResolvedCustomFacets customFacets) { + super(typeName, declarationNode, xmlFacets, customFacets); + this.minLength = minLength; + this.maxLength = maxLength; + this.fileTypes = fileTypes; + } + + protected FileResolvedType copy() { + return new FileResolvedType(getTypeName(), getTypeExpressionNode(), getXmlFacets().copy(), minLength, maxLength, fileTypes, customFacets.copy()); + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + customFacets.validate(from); + final Raml10Grammar raml10Grammar = new Raml10Grammar(); + final AnyOfRule facetRule = new AnyOfRule() + .add(raml10Grammar.fileTypesField()) + .add(raml10Grammar.minLengthField()) + .add(raml10Grammar.maxLengthField()) + .addAll(customFacets.getRules()); + TypesUtils.validateAllWith(facetRule, from.getFacets()); + } + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + final FileResolvedType result = copy(); + result.customFacets = customFacets.overwriteFacets(from); + result.setMinLength(selectIntValue(MIN_LENGTH_KEY_NAME, from)); + result.setMaxLength(selectIntValue(MAX_LENGTH_KEY_NAME, from)); + result.setFileTypes(selectStringCollection(FILE_TYPES_KEY_NAME, from)); + return overwriteFacets(result, from); + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + final FileResolvedType result = copy(); + + if (with instanceof FileResolvedType fileTypeDefinition) { + result.setMinLength(fileTypeDefinition.getMinLength()); + result.setMaxLength(fileTypeDefinition.getMaxLength()); + result.setFileTypes(fileTypeDefinition.getFileTypes()); + } + result.customFacets = result.customFacets.mergeWith(with.customFacets()); + return mergeFacets(result, with); + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitFile(this); + } + + public Integer getMinLength() { + return minLength; + } + + public List getFileTypes() { + return fileTypes; + } + + public void setFileTypes(List fileTypes) { + if (fileTypes != null && !fileTypes.isEmpty()) { + this.fileTypes = fileTypes; + } + } + + public void setMinLength(Integer minLength) { + if (minLength != null) { + this.minLength = minLength; + } + } + + public Integer getMaxLength() { + return maxLength; + } + + public void setMaxLength(Integer maxLength) { + if (maxLength != null) { + this.maxLength = maxLength; + } + } + + + @Override + public String getBuiltinTypeName() { + return TypeId.FILE.getType(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/IntegerResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/IntegerResolvedType.java new file mode 100644 index 0000000..5d63878 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/IntegerResolvedType.java @@ -0,0 +1,116 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; + +public class IntegerResolvedType extends NumberResolvedType { + + public IntegerResolvedType(TypeExpressionNode from) { + super(from); + } + + public IntegerResolvedType(String typeName, TypeExpressionNode declarationNode, XmlFacets xmlFacets, Number minimum, Number maximum, Number multiple, String format, ResolvedCustomFacets copy) { + super(typeName, declarationNode, xmlFacets, minimum, maximum, multiple, format, copy); + } + + @Override + public NumberResolvedType copy() { + return new IntegerResolvedType(getTypeName(), getTypeExpressionNode(), getXmlFacets().copy(), getMinimum(), getMaximum(), getMultiple(), getFormat(), customFacets.copy()); + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitInteger(this); + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + customFacets.validate(from); + final Raml10Grammar raml10Grammar = new Raml10Grammar(); + final AnyOfRule facetRule = new AnyOfRule() + .add(raml10Grammar.minimumField(raml10Grammar.integerType())) + .add(raml10Grammar.maximumField(raml10Grammar.integerType())) + .add(raml10Grammar.numberFormat()) + .add(raml10Grammar.enumField()) + .add(raml10Grammar.multipleOfField(raml10Grammar.positiveIntegerType(0L, Long.MAX_VALUE))) + .addAll(customFacets.getRules()); + TypesUtils.validateAllWith(facetRule, from.getFacets()); + } + + @Override + public ErrorNode validateFacets() { + long min = getMinimum() != null ? getMinimum().longValue() : Long.MIN_VALUE; + long max = getMaximum() != null ? getMaximum().longValue() : Long.MAX_VALUE; + long mult = getMultiple() != null ? getMultiple().longValue() : 1; + + // Checking conflicts between the minimum and maximum facets + if (max < min) { + return RamlErrorNodeFactory.createInvalidFacetState( + getTypeName(), "maximum must be greater than or equal to minimum"); + } + + // It must be at least one multiple of the number between the valid range + if (getMultiple() != null && !hasValidMultiplesInRange(min, max, mult)) { + return RamlErrorNodeFactory.createInvalidFacetState( + getTypeName(), + "There must be at least one multiple of " + mult + " in the given range"); + } + + + // For each value in the list, it must be between minimum and maximum + for (Number thisEnum : getEnums()) { + long value = thisEnum.longValue(); + if (value < min || value > max) { + return RamlErrorNodeFactory.createInvalidFacetState( + getTypeName(), + "enum values must be between " + min + " and " + max); + } + + if (value % mult != 0) { + return RamlErrorNodeFactory.createInvalidFacetState( + getTypeName(), + "enum values must be multiple of " + mult); + } + } + + return null; + } + + private boolean hasValidMultiplesInRange(double min, double max, double mult) { + // Zero is multiple of every number + if (mult == 0) { + return true; + } + + double numberOfMultiplesInRange = Math.max(Math.floor(max / mult) - Math.ceil(min / mult) + 1, 0); + return numberOfMultiplesInRange > 0; + } + + + @Override + public String getBuiltinTypeName() { + return TypeId.INTEGER.getType(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/NullResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/NullResolvedType.java new file mode 100644 index 0000000..f671da5 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/NullResolvedType.java @@ -0,0 +1,71 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; + +public class NullResolvedType extends XmlFacetsCapableType { + + public NullResolvedType(String typeName, TypeExpressionNode declarationNode, XmlFacets xmlFacets, ResolvedCustomFacets customFacets) { + super(typeName, declarationNode, xmlFacets, customFacets); + } + + public NullResolvedType(TypeExpressionNode from) { + super(getTypeName(from, TypeId.NULL.getType()), from, new ResolvedCustomFacets()); + + } + + protected NullResolvedType copy() { + return new NullResolvedType(getTypeName(), getTypeExpressionNode(), getXmlFacets().copy(), customFacets.copy()); + } + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + final NullResolvedType copy = copy(); + copy.customFacets = customFacets.overwriteFacets(from); + return copy; + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + final NullResolvedType copy = copy(); + copy.customFacets = copy.customFacets.mergeWith(with.customFacets()); + return copy; + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitNull(this); + } + + + @Override + public String getBuiltinTypeName() { + return TypeId.NULL.getType(); + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + customFacets.validate(from); + final AnyOfRule facetRule = new AnyOfRule().addAll(customFacets.getRules()); + TypesUtils.validateAllWith(facetRule, from.getFacets()); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/NumberResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/NumberResolvedType.java new file mode 100644 index 0000000..54fb8af --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/NumberResolvedType.java @@ -0,0 +1,252 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; +import static java.math.BigDecimal.ONE; +import static java.math.BigDecimal.ROUND_CEILING; +import static java.math.BigDecimal.ROUND_DOWN; +import static java.math.BigDecimal.ZERO; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.FORMAT_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.MAXIMUM_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.MINIMUM_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.MULTIPLE_OF_KEY_NAME; + +public class NumberResolvedType extends XmlFacetsCapableType { + private Number minimum; + private Number maximum; + private Number multiple; + private String format; + private List enums = new ArrayList<>(); + + public NumberResolvedType(TypeExpressionNode from) { + super(getTypeName(from, TypeId.NUMBER.getType()), from, new ResolvedCustomFacets(MINIMUM_KEY_NAME, MAXIMUM_KEY_NAME, MULTIPLE_OF_KEY_NAME, FORMAT_KEY_NAME)); + } + + public NumberResolvedType(String typeName, TypeExpressionNode declarationNode, XmlFacets xmlFacets, Number minimum, Number maximum, Number multiple, String format, + ResolvedCustomFacets customFacets) { + super(typeName, declarationNode, xmlFacets, customFacets); + this.minimum = minimum; + this.maximum = maximum; + this.multiple = multiple; + this.format = format; + } + + public NumberResolvedType copy() { + return new NumberResolvedType(getTypeName(), getTypeExpressionNode(), getXmlFacets().copy(), minimum, maximum, multiple, format, customFacets.copy()); + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + customFacets.validate(from); + final Raml10Grammar raml10Grammar = new Raml10Grammar(); + final AnyOfRule facetRule = new AnyOfRule() + .add(raml10Grammar.minimumField(raml10Grammar.numberType())) + .add(raml10Grammar.maximumField(raml10Grammar.numberType())) + .add(raml10Grammar.numberFormat()) + .add(raml10Grammar.enumField()) + .add(raml10Grammar.multipleOfField(raml10Grammar.numberType())) + .addAll(customFacets.getRules()); + TypesUtils.validateAllWith(facetRule, from.getFacets()); + } + + @Override + public boolean doAccept(ResolvedType valueType) { + return valueType instanceof NumberResolvedType; + } + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + final NumberResolvedType result = copy(); + result.customFacets = customFacets.overwriteFacets(from); + result.setMinimum(NodeSelector.selectNumberValue(MINIMUM_KEY_NAME, from)); + result.setMaximum(NodeSelector.selectNumberValue(MAXIMUM_KEY_NAME, from)); + result.setMultiple(NodeSelector.selectNumberValue(MULTIPLE_OF_KEY_NAME, from)); + result.setFormat(NodeSelector.selectStringValue(FORMAT_KEY_NAME, from)); + result.setEnums(getEnumValues(from)); + return overwriteFacets(result, from); + } + + + private List getEnumValues(Node typeNode) { + + Node values = typeNode.get("enum"); + List enumValues = new ArrayList<>(); + if (values != null && values instanceof ArrayNode) { + for (Node node : values.getChildren()) { + enumValues.add((Number) ((SimpleTypeNode) node).getValue()); + } + } + return enumValues; + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + final NumberResolvedType result = copy(); + if (with instanceof NumberResolvedType numberTypeDefinition) { + result.setMinimum(numberTypeDefinition.getMinimum()); + result.setMaximum(numberTypeDefinition.getMaximum()); + result.setMultiple(numberTypeDefinition.getMultiple()); + result.setFormat(numberTypeDefinition.getFormat()); + result.setEnums(numberTypeDefinition.getEnums()); + } + result.customFacets = result.customFacets.mergeWith(with.customFacets()); + return mergeFacets(result, with); + } + + @Override + public void validateState() { + super.validateState(); + final ErrorNode errorNode = validateFacets(); + if (errorNode != null) { + getTypeExpressionNode().replaceWith(errorNode); + } + } + + public ErrorNode validateFacets() { + BigDecimal min = minimum != null ? new BigDecimal(minimum.toString()) : new BigDecimal(Integer.MIN_VALUE); + BigDecimal max = maximum != null ? new BigDecimal(maximum.toString()) : new BigDecimal(Integer.MAX_VALUE); + BigDecimal mult = multiple != null ? new BigDecimal(multiple.toString()) : null; + + // Checking conflicts between the minimum and maximum facets if both are set + if (max.compareTo(min) < 0) { + return RamlErrorNodeFactory.createInvalidFacetState( + getTypeName(), + "maximum must be greater than or equal to minimum"); + } + + // It must be at least one multiple of the number between the valid range + if (mult != null && !hasValidMultiplesInRange(min, max, mult)) { + return RamlErrorNodeFactory.createInvalidFacetState( + getTypeName(), + "There must be at least one multiple of " + mult + " in the given range"); + } + + // For each value in the list, it must be between minimum and maximum + for (Number thisEnum : enums) { + BigDecimal value = new BigDecimal(thisEnum.toString()); + + if (value.compareTo(min) < 0 || value.compareTo(max) > 0) { + return RamlErrorNodeFactory.createInvalidFacetState( + getTypeName(), + "enum values must be between " + min + " and " + max); + } + + if (mult != null && value.remainder(mult).compareTo(BigDecimal.ZERO) != 0) { + return RamlErrorNodeFactory.createInvalidFacetState( + getTypeName(), + "enum values must be multiple of " + mult); + } + } + + return null; + } + + private boolean hasValidMultiplesInRange(BigDecimal min, BigDecimal max, BigDecimal mult) { + // Zero is multiple of every number + if (mult.compareTo(BigDecimal.ZERO) == 0) { + return true; + } + + BigDecimal divideMax = max.divide(mult, 0, RoundingMode.DOWN); + BigDecimal divideMin = min.divide(mult, 0, RoundingMode.CEILING); + BigDecimal subtract = divideMax.subtract(divideMin); + BigDecimal plusOne = subtract.add(ONE); + BigDecimal max0 = plusOne.max(ZERO); + BigDecimal numberOfMultiplesInRange = max0.setScale(0, RoundingMode.DOWN); + + return numberOfMultiplesInRange.compareTo(ZERO) > 0; + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitNumber(this); + } + + public Number getMinimum() { + return minimum; + } + + + public List getEnums() { + return enums; + } + + public void setEnums(List enums) { + if (enums != null && !enums.isEmpty()) { + this.enums = enums; + } + } + + private void setMinimum(Number minimum) { + if (minimum != null) { + this.minimum = minimum; + } + } + + public Number getMaximum() { + return maximum; + } + + private void setMaximum(Number maximum) { + if (maximum != null) { + this.maximum = maximum; + } + } + + public Number getMultiple() { + return multiple; + } + + private void setMultiple(Number multiple) { + if (multiple != null) { + this.multiple = multiple; + } + } + + public String getFormat() { + return format; + } + + private void setFormat(String format) { + if (format != null) { + this.format = format; + } + } + + + @Override + public String getBuiltinTypeName() { + return TypeId.NUMBER.getType(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/ObjectResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/ObjectResolvedType.java new file mode 100644 index 0000000..220e7ab --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/ObjectResolvedType.java @@ -0,0 +1,301 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationField; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.commons.type.SchemaBasedResolvedType; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.internal.impl.v10.nodes.PropertyNode; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.ADDITIONAL_PROPERTIES_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.DISCRIMINATOR_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.DISCRIMINATOR_VALUE_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.MAX_PROPERTIES_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.MIN_PROPERTIES_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.PROPERTIES_KEY_NAME; +import static org.xbib.raml.yagi.framework.util.NodeSelector.selectBooleanValue; +import static org.xbib.raml.yagi.framework.util.NodeSelector.selectIntValue; +import static org.xbib.raml.yagi.framework.util.NodeSelector.selectStringValue; + +public class ObjectResolvedType extends XmlFacetsCapableType { + private Integer minProperties; + private Integer maxProperties; + private Boolean additionalProperties; + private String discriminator; + private String discriminatorValue; + + private Map properties = new LinkedHashMap<>(); + + public ObjectResolvedType( + String typeName, TypeExpressionNode declarationNode, + XmlFacets xmlFacets, + Integer minProperties, + Integer maxProperties, + Boolean additionalProperties, + String discriminator, + String discriminatorValue, + Map properties, + ResolvedCustomFacets customFacets) { + super(typeName, declarationNode, xmlFacets, customFacets); + this.minProperties = minProperties; + this.maxProperties = maxProperties; + this.additionalProperties = additionalProperties; + this.discriminator = discriminator; + this.discriminatorValue = discriminatorValue; + this.properties = properties; + } + + public ObjectResolvedType(TypeExpressionNode from) { + super(getTypeName(from, TypeId.OBJECT.getType()), from, + new ResolvedCustomFacets(MIN_PROPERTIES_KEY_NAME, MAX_PROPERTIES_KEY_NAME, ADDITIONAL_PROPERTIES_KEY_NAME, DISCRIMINATOR_KEY_NAME, DISCRIMINATOR_VALUE_KEY_NAME, PROPERTIES_KEY_NAME)); + } + + protected ObjectResolvedType copy() { + return new ObjectResolvedType(getTypeName(), getTypeExpressionNode(), + getXmlFacets().copy(), + minProperties, + maxProperties, + additionalProperties, + discriminator, + discriminatorValue, + new LinkedHashMap<>(properties), + customFacets.copy()); + } + + @Override + public boolean doAccept(ResolvedType valueType) { + final boolean inheritsFrom = super.doAccept(valueType); + if (inheritsFrom && (valueType instanceof ObjectResolvedType)) { + final Map properties = getProperties(); + for (PropertyFacets myProperty : properties.values()) { + final PropertyFacets matchedProperty = ((ObjectResolvedType) valueType).getProperties().get(myProperty.getName()); + if (matchedProperty != null) { + if (!myProperty.getValueType().accepts(matchedProperty.getValueType())) { + return false; + } + } else { + return false; + } + } + + } + return inheritsFrom; + } + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + final ObjectResolvedType result = copy(); + result.customFacets = customFacets.overwriteFacets(from); + result.setMinProperties(selectIntValue(MIN_PROPERTIES_KEY_NAME, from)); + result.setMaxProperties(selectIntValue(MAX_PROPERTIES_KEY_NAME, from)); + result.setAdditionalProperties(selectBooleanValue(ADDITIONAL_PROPERTIES_KEY_NAME, from)); + result.setDiscriminator(selectStringValue(DISCRIMINATOR_KEY_NAME, from)); + result.setDiscriminatorValue(selectStringValue(DISCRIMINATOR_VALUE_KEY_NAME, from)); + final Node properties = from.get(PROPERTIES_KEY_NAME); + if (properties != null) { + final List children = properties.getChildren(); + for (Node child : children) { + if (child instanceof PropertyNode property) { + final String name = property.getName(); + final PropertyFacets propertyDefinition = new PropertyFacets(property); + final Map resultProperties = result.getProperties(); + if (!resultProperties.containsKey(name)) { + resultProperties.put(name, propertyDefinition); + } else { + // If present in both merge facets of both types + resultProperties.put(name, resultProperties.get(name).overwriteFacets(propertyDefinition)); + if (propertyDefinition.getErrorNode() != null) { + child.replaceWith(propertyDefinition.getErrorNode()); + } + } + } + } + } + return overwriteFacets(result, from); + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + final ObjectResolvedType result = copy(); + if (with instanceof ObjectResolvedType) { + result.setMinProperties(((ObjectResolvedType) with).getMinProperties()); + result.setMaxProperties(((ObjectResolvedType) with).getMaxProperties()); + result.setAdditionalProperties(((ObjectResolvedType) with).getAdditionalProperties()); + result.setDiscriminator(((ObjectResolvedType) with).getDiscriminator()); + result.setDiscriminatorValue(((ObjectResolvedType) with).getDiscriminatorValue()); + final Map properties = ((ObjectResolvedType) with).getProperties(); + for (Map.Entry property : properties.entrySet()) { + if (!getProperties().containsKey(property.getKey())) { + result.getProperties().put(property.getKey(), property.getValue()); + } else { + // If present in both merge facets of both types + final PropertyFacets propertyDefinition = result.getProperties().get(property.getKey()); + result.getProperties().put(property.getKey(), propertyDefinition.mergeFacets(property.getValue())); + } + } + } + result.customFacets = result.customFacets.mergeWith(with.customFacets()); + return mergeFacets(result, with); + + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + + customFacets.validate(from); + final Raml10Grammar raml10Grammar = new Raml10Grammar(); + final AnyOfRule facetRule = new AnyOfRule() + .add(raml10Grammar.propertiesField()) + .add(raml10Grammar.minPropertiesField()) + .add(raml10Grammar.maxPropertiesField()) + .add(raml10Grammar.additionalPropertiesField()) + .addAll(customFacets.getRules()); + + if (from.getParent() instanceof TypeDeclarationField && from.getResolvedType() instanceof ObjectResolvedType) { + facetRule.add(raml10Grammar.discriminatorField()) + .add(raml10Grammar.discriminatorValueField()); + } + + TypesUtils.validateAllWith(facetRule, from.getFacets()); + final Node properties = from.get(PROPERTIES_KEY_NAME); + if (properties != null) { + final List children = properties.getChildren(); + for (Node child : children) { + if (child instanceof PropertyNode property) { + final String name = property.getName(); + if (this.properties.containsKey(name)) { + PropertyFacets myProperty = this.properties.get(name); + if (!myProperty.getValueType().accepts(property.getTypeDefinition())) { + property.replaceWith(RamlErrorNodeFactory.createCanNotOverrideProperty(name)); + } + } + } + } + } + } + + @Override + public void validateState() { + super.validateState(); + final ErrorNode errorNode = validateFacets(); + if (errorNode != null) { + getTypeExpressionNode().replaceWith(errorNode); + } + } + + public ErrorNode validateFacets() { + int min = minProperties != null ? minProperties : 0; + int max = maxProperties != null ? maxProperties : Integer.MAX_VALUE; + if (max < min) { + return RamlErrorNodeFactory.createInvalidFacetState(getTypeName(), "maxProperties must be greater than or equal to minProperties"); + } + for (PropertyFacets propertyFacets : properties.values()) { + if (propertyFacets.getValueType() instanceof SchemaBasedResolvedType) { + return RamlErrorNodeFactory.createPropertyCanNotBeOfSchemaType(propertyFacets.getName()); + } + } + + if (discriminator != null) { + if (this.properties.get(discriminator) == null) { + return RamlErrorNodeFactory.createInvalidFacetState(getTypeName(), "invalid discriminator value, property '" + discriminator + "' does not exist"); + } + } + return null; + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitObject(this); + } + + public Integer getMinProperties() { + return minProperties; + } + + public void setMinProperties(Integer minProperties) { + if (minProperties != null) { + this.minProperties = minProperties; + } + } + + public Integer getMaxProperties() { + return maxProperties; + } + + public void setMaxProperties(Integer maxProperties) { + if (maxProperties != null) { + this.maxProperties = maxProperties; + } + } + + public Boolean getAdditionalProperties() { + return additionalProperties; + } + + public void setAdditionalProperties(Boolean additionalProperties) { + if (additionalProperties != null) { + this.additionalProperties = additionalProperties; + } + } + + public String getDiscriminator() { + return discriminator; + } + + public void setDiscriminator(String discriminator) { + if (discriminator != null) { + this.discriminator = discriminator; + } + } + + public String getDiscriminatorValue() { + return discriminatorValue; + } + + public void setDiscriminatorValue(String discriminatorValue) { + if (discriminatorValue != null) { + this.discriminatorValue = discriminatorValue; + } + } + + public Map getProperties() { + return properties; + } + + public void setProperties(Map properties) { + if (properties != null && !properties.isEmpty()) { + this.properties = properties; + } + } + + + @Override + public String getBuiltinTypeName() { + return TypeId.OBJECT.getType(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/PropertyFacets.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/PropertyFacets.java new file mode 100644 index 0000000..94c6ce9 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/PropertyFacets.java @@ -0,0 +1,92 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.nodes.PropertyNode; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class PropertyFacets { + + private final String name; + private ResolvedType resolvedType; + private final boolean required; + private PropertyNode propertyNode; + private ErrorNode errorNode; + + public PropertyFacets(String name, ResolvedType resolvedType, Boolean required) { + this.name = name; + this.resolvedType = resolvedType; + this.required = required; + } + + public PropertyFacets(PropertyNode propertyNode) { + this.name = propertyNode.getName(); + this.required = propertyNode.isRequired(); + this.propertyNode = propertyNode; + } + + public String getName() { + return name; + } + + public ResolvedType getValueType() { + // Load it lazy so it support recursive definitions + if (resolvedType == null) { + resolvedType = propertyNode.getTypeDefinition(); + } + return resolvedType; + } + + public boolean isRequired() { + return required; + } + + public boolean isPatternProperty() { + return name.startsWith("/") && name.endsWith("/"); + } + + + public String getPatternRegex() { + if (isPatternProperty()) { + return name.substring(1, name.length() - 1); + } else { + return null; + } + } + + public PropertyFacets mergeFacets(PropertyFacets value) { + checkOptionalPropertyOverRequired(value); + return new PropertyFacets(name, getValueType().mergeFacets(value.getValueType()), required || value.isRequired()); + } + + public PropertyFacets overwriteFacets(PropertyFacets value) { + checkOptionalPropertyOverRequired(value); + return new PropertyFacets(name, value.getValueType(), required || value.isRequired()); + } + + private void checkOptionalPropertyOverRequired(PropertyFacets value) { + if (required && !value.isRequired()) { + value.errorNode = RamlErrorNodeFactory.createInvalidRequiredFacet(name); + } + } + + public Node getErrorNode() { + return errorNode; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/StringResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/StringResolvedType.java new file mode 100644 index 0000000..a8eb866 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/StringResolvedType.java @@ -0,0 +1,202 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.MAX_LENGTH_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.MIN_LENGTH_KEY_NAME; +import static org.xbib.raml.internal.impl.v10.grammar.Raml10Grammar.PATTERN_KEY_NAME; +import static org.xbib.raml.yagi.framework.util.NodeSelector.selectIntValue; +import static org.xbib.raml.yagi.framework.util.NodeSelector.selectStringValue; + +public class StringResolvedType extends XmlFacetsCapableType { + private static final int DEFAULT_MIN_LENGTH = 0; + private static final int DEFAULT_MAX_LENGTH = Integer.MAX_VALUE; + + private Integer minLength; + private Integer maxLength; + private String pattern; + private List enums = new ArrayList<>(); + + + public StringResolvedType(TypeExpressionNode from) { + super(getTypeName(from, TypeId.STRING.getType()), from, new ResolvedCustomFacets(MIN_LENGTH_KEY_NAME, MAX_LENGTH_KEY_NAME, PATTERN_KEY_NAME)); + } + + public StringResolvedType(String typeName, TypeExpressionNode declarationNode, XmlFacets xmlFacets, Integer minLength, Integer maxLength, String pattern, List enums, + ResolvedCustomFacets customFacets) { + super(typeName, declarationNode, xmlFacets, customFacets); + this.minLength = minLength; + this.maxLength = maxLength; + this.pattern = pattern; + this.enums = enums; + } + + protected StringResolvedType copy() { + return new StringResolvedType(getTypeName(), getTypeExpressionNode(), getXmlFacets(), minLength, maxLength, pattern, enums, customFacets.copy()); + } + + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + final StringResolvedType result = copy(); + result.customFacets = customFacets.copy().overwriteFacets(from); + result.setMinLength(selectIntValue(MIN_LENGTH_KEY_NAME, from)); + result.setMaxLength(selectIntValue(MAX_LENGTH_KEY_NAME, from)); + result.setPattern(selectStringValue(PATTERN_KEY_NAME, from)); + result.setEnums(getEnumValues(from)); + return overwriteFacets(result, from); + } + + + private List getEnumValues(Node typeNode) { + + Node values = typeNode.get("enum"); + List enumValues = new ArrayList<>(); + if (values != null && values instanceof ArrayNode) { + for (Node node : values.getChildren()) { + enumValues.add(((SimpleTypeNode) node).getLiteralValue()); + } + } + return enumValues; + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + final StringResolvedType result = copy(); + if (with instanceof StringResolvedType stringTypeDefinition) { + result.setMaxLength(stringTypeDefinition.getMaxLength()); + result.setMinLength(stringTypeDefinition.getMinLength()); + result.setPattern(stringTypeDefinition.getPattern()); + result.setEnums(stringTypeDefinition.getEnums()); + } + result.customFacets = result.customFacets.mergeWith(with.customFacets()); + return mergeFacets(result, with); + } + + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + customFacets.validate(from); + final Raml10Grammar raml10Grammar = new Raml10Grammar(); + final AnyOfRule facetRule = new AnyOfRule() + .add(raml10Grammar.patternField()) + .add(raml10Grammar.minLengthField()) + .add(raml10Grammar.maxLengthField()) + .add(raml10Grammar.enumField()) + .addAll(customFacets.getRules()); + TypesUtils.validateAllWith(facetRule, from.getFacets()); + } + + @Override + public void validateState() { + super.validateState(); + final ErrorNode errorNode = validateFacets(); + if (errorNode != null) { + getTypeExpressionNode().replaceWith(errorNode); + } + } + + private ErrorNode validateFacets() { + int minimumLength = minLength != null ? minLength : DEFAULT_MIN_LENGTH; + int maximumLength = maxLength != null ? maxLength : DEFAULT_MAX_LENGTH; + + // Validating conflicts between the length facets + if (maximumLength < minimumLength) { + return RamlErrorNodeFactory.createInvalidFacetState( + getTypeName(), + "maxLength must be greater than or equal to minLength"); + } + + // For each enum in the list, it must be between the range defined by minLength and maxLength + for (String thisEnum : enums) { + if (thisEnum.length() < minimumLength || thisEnum.length() > maximumLength) { + return RamlErrorNodeFactory.createInvalidFacetState( + getTypeName(), + "enum values must have between " + minimumLength + " and " + maximumLength + " characters"); + } + } + + return null; + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitString(this); + } + + + @Override + public String getBuiltinTypeName() { + return TypeId.STRING.getType(); + } + + private void setPattern(String pattern) { + if (pattern != null) { + this.pattern = pattern; + } + } + + private void setMinLength(Integer minLength) { + if (minLength != null) { + this.minLength = minLength; + } + } + + private void setMaxLength(Integer maxLength) { + if (maxLength != null) { + this.maxLength = maxLength; + } + } + + public List getEnums() { + return enums; + } + + public void setEnums(List enums) { + if (enums != null && !enums.isEmpty()) { + this.enums = enums; + } + } + + + public Integer getMinLength() { + return minLength; + } + + + public Integer getMaxLength() { + return maxLength; + } + + + public String getPattern() { + return pattern; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TimeOnlyResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TimeOnlyResolvedType.java new file mode 100644 index 0000000..698e70c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TimeOnlyResolvedType.java @@ -0,0 +1,72 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.v10.rules.TypesUtils; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; + +public class TimeOnlyResolvedType extends XmlFacetsCapableType { + + + public TimeOnlyResolvedType(String typeName, TypeExpressionNode declarationNode, XmlFacets xmlFacets, ResolvedCustomFacets customFacets) { + super(typeName, declarationNode, xmlFacets, customFacets); + } + + public TimeOnlyResolvedType(TypeExpressionNode from) { + super(getTypeName(from, TypeId.TIME_ONLY.getType()), from, new ResolvedCustomFacets()); + } + + protected TimeOnlyResolvedType copy() { + return new TimeOnlyResolvedType(getTypeName(), getTypeExpressionNode(), getXmlFacets().copy(), customFacets.copy()); + } + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + final TimeOnlyResolvedType copy = copy(); + copy.customFacets = customFacets.overwriteFacets(from); + return overwriteFacets(copy, from); + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + final TimeOnlyResolvedType copy = copy(); + copy.customFacets = copy.customFacets.mergeWith(with.customFacets()); + return mergeFacets(copy, with); + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitTimeOnly(this); + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + customFacets.validate(from); + final AnyOfRule facetRule = new AnyOfRule().addAll(customFacets.getRules()); + TypesUtils.validateAllWith(facetRule, from.getFacets()); + } + + + @Override + public String getBuiltinTypeName() { + return TypeId.TIME_ONLY.getType(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeId.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeId.java new file mode 100644 index 0000000..6ef62e9 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeId.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +public enum TypeId { + + STRING("string"), + ANY("any"), + NULL("nil"), + NUMBER("number"), + INTEGER("integer"), + BOOLEAN("boolean"), + DATE_ONLY("date-only"), + TIME_ONLY("time-only"), + DATE_TIME_ONLY("datetime-only"), + DATE_TIME("datetime"), + FILE("file"), + OBJECT("object"), + ARRAY("array"); // TODO this is not a valid id but + + private final String type; + + TypeId(String type) { + this.type = type; + } + + public String getType() { + return this.type; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeToJsonSchemaVisitor.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeToJsonSchemaVisitor.java new file mode 100644 index 0000000..d377912 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeToJsonSchemaVisitor.java @@ -0,0 +1,256 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.json.Json; +import javax.json.JsonArrayBuilder; +import javax.json.JsonBuilderFactory; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; +import org.xbib.raml.internal.impl.commons.type.JsonSchemaExternalType; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.commons.type.XmlSchemaExternalType; + + +public class TypeToJsonSchemaVisitor implements TypeVisitor { + + private static final String DEFINITIONS = "definitions"; + private static final String REF = "$ref"; + private static final String TYPE = "type"; + private static final String ITEMS = "items"; + private static final String FORMAT = "format"; + private static final String PROPERTIES = "properties"; + private static final String REQUIRED = "required"; + private static final String ANY_OF = "anyOf"; + + private static final String OBJECT = "object"; + private static final String NUMBER = "number"; + private static final String INTEGER = "integer"; + private static final String NULL = "null"; + private static final String DATE_TIME = "date-time"; + private static final String STRING = "string"; + private static final String BOOLEAN = "boolean"; + private static final String ARRAY = "array"; + + private static final String SCHEMA = "$schema"; + private static final String SCHEMA_VALUE = "http://json-schema.org/draft-04/schema#"; + + private final JsonObjectBuilder definitions; + private final JsonBuilderFactory factory; + private final Set definedTypes; + + + public TypeToJsonSchemaVisitor() { + this.factory = Json.createBuilderFactory(null); + this.definitions = this.factory.createObjectBuilder(); + this.definedTypes = new HashSet<>(); + } + + public JsonObject transform(final ResolvedType resolvedType) { + final JsonObjectBuilder root = resolvedType.visit(this); + root.add(DEFINITIONS, this.definitions); + root.add(SCHEMA, SCHEMA_VALUE); + return root.build(); + } + + @Override + public JsonObjectBuilder visitString(StringResolvedType stringTypeDefinition) { + if (stringTypeDefinition.getEnums().isEmpty()) { + return this.factory.createObjectBuilder().add(TYPE, STRING); + } else { + JsonArrayBuilder builder = factory.createArrayBuilder(); + for (String enumValue : stringTypeDefinition.getEnums()) { + builder.add(enumValue); + } + return this.factory.createObjectBuilder().add(TYPE, STRING).add("enum", builder); + } + } + + @Override + public JsonObjectBuilder visitObject(ObjectResolvedType objectTypeDefinition) { + final JsonObjectBuilder typeDefinitionBuilder = this.factory.createObjectBuilder(); + String typeName = getTypeName(objectTypeDefinition); + + // By default add all named types to definitions to allow fully recursive types. + if (typeName != null && !this.definedTypes.contains(typeName)) { + this.definedTypes.add(typeName); + this.definitions.add(typeName, addPropertiesToJsonObject(objectTypeDefinition, typeDefinitionBuilder)); + } + + // If the type is inline, then the object is created inline. + if (typeName == null) { + return addPropertiesToJsonObject(objectTypeDefinition, this.factory.createObjectBuilder()); + } + + return this.factory.createObjectBuilder() + .add(REF, "#/definitions/" + escapeJsonPointer(typeName)); + } + + private JsonObjectBuilder addPropertiesToJsonObject(final ObjectResolvedType objectTypeDefinition, JsonObjectBuilder objectBuilder) { + final JsonObjectBuilder propertiesBuilder = this.factory.createObjectBuilder(); + final JsonArrayBuilder requiredBuilder = this.factory.createArrayBuilder(); + + boolean fieldsRequired = false; + + for (Map.Entry entry : objectTypeDefinition.getProperties().entrySet()) { + + final String propertyName = entry.getKey(); + PropertyFacets propertyFacets = objectTypeDefinition.getProperties().get(propertyName); + + if (!propertyName.startsWith("/") || !propertyName.endsWith("/")) { + propertiesBuilder.add(propertyName, propertyFacets.getValueType().visit(this)); + if (entry.getValue().isRequired()) { + requiredBuilder.add(propertyName); + fieldsRequired = true; + } + } + } + + final JsonObjectBuilder builder = objectBuilder.add(TYPE, OBJECT).add(PROPERTIES, propertiesBuilder); + return fieldsRequired ? builder.add(REQUIRED, requiredBuilder) : builder; + } + + private String escapeJsonPointer(final String typeName) { + return typeName.replaceAll("/", "~1"); + } + + private String getTypeName(ObjectResolvedType objectTypeDefinition) { + String typeName = objectTypeDefinition.getTypeName(); + + for (TypeId typeId : TypeId.values()) { + if (typeId.getType().equals(typeName)) { + return null; + } + } + + return typeName; + } + + @Override + public JsonObjectBuilder visitBoolean(BooleanResolvedType booleanTypeDefinition) { + + if (booleanTypeDefinition.getEnums().isEmpty()) { + return this.factory.createObjectBuilder().add(TYPE, BOOLEAN); + } else { + JsonArrayBuilder builder = factory.createArrayBuilder(); + for (boolean enumValue : booleanTypeDefinition.getEnums()) { + builder.add(enumValue); + } + return this.factory.createObjectBuilder().add(TYPE, BOOLEAN).add("enum", builder); + } + } + + @Override + public JsonObjectBuilder visitInteger(IntegerResolvedType integerTypeDefinition) { + if (integerTypeDefinition.getEnums().isEmpty()) { + return this.factory.createObjectBuilder().add(TYPE, INTEGER); + } else { + JsonArrayBuilder builder = factory.createArrayBuilder(); + for (Number enumValue : integerTypeDefinition.getEnums()) { + builder.add((Long) enumValue); + } + return this.factory.createObjectBuilder().add(TYPE, INTEGER).add("enum", builder); + } + } + + @Override + public JsonObjectBuilder visitNumber(NumberResolvedType numberTypeDefinition) { + if (numberTypeDefinition.getEnums().isEmpty()) { + return this.factory.createObjectBuilder().add(TYPE, NUMBER); + } else { + JsonArrayBuilder builder = factory.createArrayBuilder(); + for (Number enumValue : numberTypeDefinition.getEnums()) { + + builder.add(new BigDecimal(enumValue.toString())); + } + return this.factory.createObjectBuilder().add(TYPE, NUMBER).add("enum", builder); + } + } + + @Override + public JsonObjectBuilder visitDateTimeOnly(DateTimeOnlyResolvedType dateTimeOnlyTypeDefinition) { + return this.factory.createObjectBuilder() + .add(TYPE, STRING) + .add(FORMAT, DATE_TIME); + } + + @Override + public JsonObjectBuilder visitDate(DateOnlyResolvedType dateOnlyTypeDefinition) { + return this.factory.createObjectBuilder() + .add(TYPE, STRING) + .add(FORMAT, DATE_TIME); + } + + @Override + public JsonObjectBuilder visitDateTime(DateTimeResolvedType dateTimeTypeDefinition) { + return this.factory.createObjectBuilder() + .add(TYPE, STRING) + .add(FORMAT, DATE_TIME); + } + + @Override + public JsonObjectBuilder visitFile(FileResolvedType fileTypeDefinition) { + return this.factory.createObjectBuilder().add(TYPE, STRING); + } + + @Override + public JsonObjectBuilder visitNull(NullResolvedType nullTypeDefinition) { + return this.factory.createObjectBuilder().add(TYPE, NULL); + } + + @Override + public JsonObjectBuilder visitArray(ArrayResolvedType arrayTypeDefinition) { + return this.factory.createObjectBuilder() + .add(TYPE, ARRAY) + .add(ITEMS, arrayTypeDefinition.getItems().visit(this)); + } + + @Override + public JsonObjectBuilder visitUnion(UnionResolvedType unionTypeDefinition) { + final JsonArrayBuilder unionArrayBuilder = this.factory.createArrayBuilder(); + + for (ResolvedType resolvedType : unionTypeDefinition.of()) { + unionArrayBuilder.add(resolvedType.visit(this)); + } + + return this.factory.createObjectBuilder().add(ANY_OF, unionArrayBuilder); + } + + @Override + public JsonObjectBuilder visitTimeOnly(TimeOnlyResolvedType timeOnlyTypeDefinition) { + return this.factory.createObjectBuilder().add(TYPE, STRING); + } + + @Override + public JsonObjectBuilder visitJson(JsonSchemaExternalType jsonTypeDefinition) { + throw new IllegalArgumentException("Unsupported type"); + } + + @Override + public JsonObjectBuilder visitXml(XmlSchemaExternalType xmlTypeDefinition) { + throw new IllegalArgumentException("Unsupported type"); + } + + @Override + public JsonObjectBuilder visitAny(AnyResolvedType anyResolvedType) { + return this.factory.createObjectBuilder(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeToRuleVisitor.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeToRuleVisitor.java new file mode 100644 index 0000000..b785d64 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeToRuleVisitor.java @@ -0,0 +1,412 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.function.Predicate; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.rule.JsonSchemaValidationRule; +import org.xbib.raml.internal.impl.commons.rule.XmlSchemaValidationRule; +import org.xbib.raml.internal.impl.commons.type.JsonSchemaExternalType; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.commons.type.XmlSchemaExternalType; +import org.xbib.raml.internal.impl.v10.rules.DiscriminatorBasedRule; +import org.xbib.raml.internal.impl.v10.rules.FormatValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.AllOfRule; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import org.xbib.raml.yagi.framework.grammar.rule.AnyValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.ArrayRule; +import org.xbib.raml.yagi.framework.grammar.rule.BooleanTypeRule; +import org.xbib.raml.yagi.framework.grammar.rule.DateValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.DivisorValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.IntegerTypeRule; +import org.xbib.raml.yagi.framework.grammar.rule.KeyValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.MaxItemsRule; +import org.xbib.raml.yagi.framework.grammar.rule.MaxLengthRule; +import org.xbib.raml.yagi.framework.grammar.rule.MaxPropertiesRule; +import org.xbib.raml.yagi.framework.grammar.rule.MaximumValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.MinItemsRule; +import org.xbib.raml.yagi.framework.grammar.rule.MinLengthRule; +import org.xbib.raml.yagi.framework.grammar.rule.MinPropertiesRule; +import org.xbib.raml.yagi.framework.grammar.rule.MinimumValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.NullValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.NumberTypeRule; +import org.xbib.raml.yagi.framework.grammar.rule.NumberValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.ObjectRule; +import org.xbib.raml.yagi.framework.grammar.rule.RangeValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.RegexValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.grammar.rule.StringTypeRule; +import org.xbib.raml.yagi.framework.grammar.rule.StringValueRule; +import org.xbib.raml.yagi.framework.util.DateType; +import static org.xbib.raml.internal.utils.BasicRuleFactory.property; +import static org.xbib.raml.internal.utils.BasicRuleFactory.regexValue; +import static org.xbib.raml.internal.utils.BasicRuleFactory.stringValue; +import static org.xbib.raml.internal.utils.ValueUtils.asBoolean; + +public class TypeToRuleVisitor implements TypeVisitor { + + private static final String CAST_STRINGS_AS_NUMBERS_PROP = "org.xbib.raml.cast_strings_as_numbers"; + public static boolean CAST_STRINGS_AS_NUMBERS = Boolean.parseBoolean(System.getProperty(CAST_STRINGS_AS_NUMBERS_PROP, "false")); + + private final ResourceLoader resourceLoader; + private final boolean useDiscriminatorsToCalculateTypes; + private boolean strictMode = false; + private final Map definitionRuleMap = new IdentityHashMap<>(); + + // Flag that should be turn on when discriminator should be resolved + private boolean resolvingDiscriminator = false; + + public TypeToRuleVisitor(ResourceLoader resourceLoader, boolean useDiscriminatorsToCalculateTypes) { + this.resourceLoader = resourceLoader; + this.useDiscriminatorsToCalculateTypes = useDiscriminatorsToCalculateTypes; + } + + public TypeToRuleVisitor(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + this.useDiscriminatorsToCalculateTypes = true; + } + + public Rule generateRule(ResolvedType items) { + if (definitionRuleMap.containsKey(items)) { + return definitionRuleMap.get(items); + } else { + return items.visit(this); + } + } + + + @Override + public Rule visitString(StringResolvedType stringTypeNode) { + final AllOfRule typeRule = new AllOfRule(new StringTypeRule()); + registerRule(stringTypeNode, typeRule); + if (!stringTypeNode.getPattern().isEmpty()) { + typeRule.and(new RegexValueRule(Pattern.compile(stringTypeNode.getPattern()))); + } + + if (stringTypeNode.getEnums() != null && !stringTypeNode.getEnums().isEmpty()) { + typeRule.and(new AnyOfRule(new ArrayList<>(getStringRules(stringTypeNode.getEnums())))); + } + + if (stringTypeNode.getMaxLength() != null) { + Integer maxLength = stringTypeNode.getMaxLength(); + typeRule.and(new MaxLengthRule(maxLength)); + } + + if (stringTypeNode.getMinLength() != null) { + Integer maxLength = stringTypeNode.getMinLength(); + typeRule.and(new MinLengthRule(maxLength)); + } + return typeRule; + } + + private List getStringRules(List enumValues) { + final List rules = new ArrayList<>(); + for (String value : enumValues) { + rules.add(stringValue(value)); + } + return rules; + } + + public void resolveDiscrimintor() { + this.resolvingDiscriminator = true; + } + + @Override + public Rule visitObject(final ObjectResolvedType objectTypeDefinition) { + if (!useDiscriminatorsToCalculateTypes) { + + final ObjectRule objectRule = new ObjectRule(strictMode); + registerRule(objectTypeDefinition, objectRule); + + final boolean isAdditionalPropertiesEnabled = asBoolean(objectTypeDefinition.getAdditionalProperties(), true); + objectRule.additionalProperties(isAdditionalPropertiesEnabled); + + final Map properties = objectTypeDefinition.getProperties(); + final Map nonPatternProperties = + getNonPatternProperties(properties).entrySet().stream() + .filter(getAllButDiscriminator(objectTypeDefinition)) + .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + addFieldsToRule(objectRule, nonPatternProperties); + + // If additional properties is set to false the pattern properties are ignored + if (isAdditionalPropertiesEnabled) { + // Additional properties should be processed after specified properties, so they will be added at the end + final Map additionalProperties = getPatternProperties(properties); + addAdditionalPropertiesToRule(objectRule, additionalProperties); + } + + if (!objectTypeDefinition.getDiscriminator().isEmpty()) { + + objectRule.with(new KeyValueRule(new StringValueRule(objectTypeDefinition.getDiscriminator()), new StringTypeRule()).required()).discriminatorName( + objectTypeDefinition.getDiscriminator()); + } + + final AllOfRule allOfRule = new AllOfRule(objectRule); + + if (objectTypeDefinition.getMaxProperties() != null) { + allOfRule.and(new MaxPropertiesRule(objectTypeDefinition.getMaxProperties())); + } + + if (objectTypeDefinition.getMinProperties() != null) { + allOfRule.and(new MinPropertiesRule(objectTypeDefinition.getMinProperties())); + } + + return allOfRule; + } + + if (!resolvingDiscriminator && objectTypeDefinition.getDiscriminator().isEmpty()) { + resolvingDiscriminator = false; + final TypeExpressionNode typeDeclarationNode = objectTypeDefinition.getTypeExpressionNode(); + return new DiscriminatorBasedRule(this, typeDeclarationNode.getRootNode(), objectTypeDefinition.getDiscriminator()); + } else { + + final ObjectRule objectRule = new ObjectRule(strictMode); + registerRule(objectTypeDefinition, objectRule); + + final boolean isAdditionalPropertiesEnabled = asBoolean(objectTypeDefinition.getAdditionalProperties(), true); + objectRule.additionalProperties(isAdditionalPropertiesEnabled); + + final Map properties = objectTypeDefinition.getProperties(); + + final Map nonPatternProperties = getNonPatternProperties(properties); + addFieldsToRule(objectRule, nonPatternProperties); + + // If additional properties is set to false the pattern properties are ignored + if (isAdditionalPropertiesEnabled) { + // Additional properties should be processed after specified properties, so they will be added at the end + final Map additionalProperties = getPatternProperties(properties); + addAdditionalPropertiesToRule(objectRule, additionalProperties); + } + + /* + * if (isNotEmpty(objectTypeDefinition.getDiscriminator())) { + * + * StringTypeRule value = new StringTypeRule(); objectRule.with(property(objectTypeDefinition.getDiscriminator(), value).); } + */ + + final AllOfRule allOfRule = new AllOfRule(objectRule); + + if (objectTypeDefinition.getMaxProperties() != null) { + allOfRule.and(new MaxPropertiesRule(objectTypeDefinition.getMaxProperties())); + } + + if (objectTypeDefinition.getMinProperties() != null) { + allOfRule.and(new MinPropertiesRule(objectTypeDefinition.getMinProperties())); + } + + return allOfRule; + } + } + + private static Predicate> getAllButDiscriminator(final ObjectResolvedType objectTypeDefinition) { + return new Predicate>() { + @Override + public boolean test(Entry input) { + if (input != null && !objectTypeDefinition.getDiscriminator().isEmpty()) { + return !input.getKey().equals(objectTypeDefinition.getDiscriminator()); + } else { + + return true; + } + } + }; + } + + private void addFieldsToRule(ObjectRule objectRule, Map properties) { + for (Entry property : properties.entrySet()) { + final PropertyFacets propertyValue = property.getValue(); + final Rule value = generateRule(propertyValue.getValueType()); + + final KeyValueRule keyValue = property(property.getKey(), value); + final Boolean required = propertyValue.isRequired(); + if (required) { + keyValue.required(); + } + objectRule.with(keyValue); + } + } + + private void addAdditionalPropertiesToRule(ObjectRule objectRule, Map properties) { + for (PropertyFacets property : properties.values()) { + final Rule value = generateRule(property.getValueType()); + final KeyValueRule keyValue = new KeyValueRule(regexValue(property.getPatternRegex()).fullMatch(false), value); + // We set to false as it should only validate the ones that matches the regex + objectRule.additionalProperties(false); + objectRule.with(keyValue); + } + } + + private Map getPatternProperties(Map properties) { + return properties.entrySet().stream().filter(isPatternProperty()).collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + } + + private Map getNonPatternProperties(Map properties) { + return properties.entrySet().stream().filter(Predicate.not(isPatternProperty())).collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + } + + private Predicate> isPatternProperty() { + return new Predicate>() { + @Override + public boolean test(Entry entry) { + return entry.getValue().isPatternProperty(); + } + }; + } + + protected void registerRule(ResolvedType objectResolvedType, Rule objectRule) { + definitionRuleMap.put(objectResolvedType, objectRule); + } + + + @Override + public Rule visitBoolean(BooleanResolvedType booleanTypeDefinition) { + return new BooleanTypeRule(); + } + + @Override + public Rule visitInteger(IntegerResolvedType integerTypeDefinition) { + return visitNumber(integerTypeDefinition, new IntegerTypeRule(CAST_STRINGS_AS_NUMBERS)); + } + + @Override + public Rule visitNumber(NumberResolvedType numberTypeDefinition) { + return visitNumber(numberTypeDefinition, new NumberTypeRule(CAST_STRINGS_AS_NUMBERS)); + } + + private Rule visitNumber(NumberResolvedType numericTypeNode, Rule numericTypeRule) { + final AllOfRule typeRule = new AllOfRule(numericTypeRule); + registerRule(numericTypeNode, typeRule); + if (numericTypeNode.getMinimum() != null && numericTypeNode.getMaximum() != null) { + if (numericTypeNode.getMinimum().getClass() == numericTypeNode.getMaximum().getClass()) { + + typeRule.and(new RangeValueRule(numericTypeNode.getMinimum(), numericTypeNode.getMaximum())); + } else { + + typeRule.and(new RangeValueRule(numericTypeNode.getMinimum().doubleValue(), numericTypeNode.getMaximum().doubleValue())); + } + } else if (numericTypeNode.getMinimum() != null) { + typeRule.and(new MinimumValueRule(numericTypeNode.getMinimum())); + } else if (numericTypeNode.getMaximum() != null) { + typeRule.and(new MaximumValueRule(numericTypeNode.getMaximum())); + } + if (numericTypeNode.getMultiple() != null) { + typeRule.and(new DivisorValueRule(numericTypeNode.getMultiple(), CAST_STRINGS_AS_NUMBERS)); + } + if (numericTypeNode.getFormat() != null) { + typeRule.and(new FormatValueRule(numericTypeNode.getFormat())); + } + + final List enums = numericTypeNode.getEnums(); + if (enums != null && !enums.isEmpty()) { + final List options = new ArrayList<>(); + for (Number anEnum : enums) { + options.add(new NumberValueRule(anEnum)); + } + typeRule.and(new AnyOfRule(options)); + } + return typeRule; + } + + @Override + public Rule visitDateTimeOnly(DateTimeOnlyResolvedType dateTimeOnlyTypeDefinition) { + return new DateValueRule(DateType.datetime_only, null); + } + + @Override + public Rule visitDate(DateOnlyResolvedType dateOnlyTypeDefinition) { + return new DateValueRule(DateType.date_only, null); + } + + @Override + public Rule visitDateTime(DateTimeResolvedType dateTimeTypeDefinition) { + return new DateValueRule(DateType.datetime, dateTimeTypeDefinition.getFormat()); + } + + @Override + public Rule visitTimeOnly(TimeOnlyResolvedType timeOnlyTypeDefinition) { + return new DateValueRule(DateType.time_only, null); + } + + @Override + public Rule visitJson(JsonSchemaExternalType jsonTypeDefinition) { + return new JsonSchemaValidationRule(jsonTypeDefinition); + } + + @Override + public Rule visitXml(XmlSchemaExternalType xmlTypeDefinition) { + return new XmlSchemaValidationRule(xmlTypeDefinition, resourceLoader); + } + + @Override + public Rule visitAny(AnyResolvedType anyResolvedType) { + return new AnyValueRule(); + } + + @Override + public Rule visitFile(FileResolvedType fileTypeDefinition) { + // TODO how do we validate files?? + return new AnyValueRule(); + } + + @Override + public Rule visitNull(NullResolvedType nullTypeDefinition) { + return new NullValueRule(); + } + + @Override + public Rule visitArray(ArrayResolvedType arrayTypeDefinition) { + final ResolvedType items = arrayTypeDefinition.getItems(); + final AllOfRule rule = new AllOfRule(new ArrayRule(generateRule(items), strictMode)); + registerRule(arrayTypeDefinition, rule); + if (arrayTypeDefinition.getMaxItems() != null) { + rule.and(new MaxItemsRule(arrayTypeDefinition.getMaxItems())); + } + + if (arrayTypeDefinition.getMinItems() != null) { + rule.and(new MinItemsRule(arrayTypeDefinition.getMinItems())); + } + + // TODO uniques how do we compare values? + + return rule; + } + + + @Override + public Rule visitUnion(UnionResolvedType unionTypeDefinition) { + final List of = unionTypeDefinition.of(); + final List rules = new ArrayList<>(); + + boolean oldStrictMode = strictMode; + strictMode = true; + for (ResolvedType resolvedType : of) { + + rules.add(generateRule(resolvedType)); + } + strictMode = oldStrictMode; + + return new AnyOfRule(rules); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeToXmlSchemaVisitor.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeToXmlSchemaVisitor.java new file mode 100644 index 0000000..1744973 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeToXmlSchemaVisitor.java @@ -0,0 +1,388 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import javax.xml.namespace.QName; +import org.apache.ws.commons.schema.XmlSchema; +import org.apache.ws.commons.schema.XmlSchemaAny; +import org.apache.ws.commons.schema.XmlSchemaAttribute; +import org.apache.ws.commons.schema.XmlSchemaChoice; +import org.apache.ws.commons.schema.XmlSchemaChoiceMember; +import org.apache.ws.commons.schema.XmlSchemaCollection; +import org.apache.ws.commons.schema.XmlSchemaComplexType; +import org.apache.ws.commons.schema.XmlSchemaContentProcessing; +import org.apache.ws.commons.schema.XmlSchemaElement; +import org.apache.ws.commons.schema.XmlSchemaEnumerationFacet; +import org.apache.ws.commons.schema.XmlSchemaForm; +import org.apache.ws.commons.schema.XmlSchemaMaxInclusiveFacet; +import org.apache.ws.commons.schema.XmlSchemaMaxLengthFacet; +import org.apache.ws.commons.schema.XmlSchemaMinInclusiveFacet; +import org.apache.ws.commons.schema.XmlSchemaMinLengthFacet; +import org.apache.ws.commons.schema.XmlSchemaPatternFacet; +import org.apache.ws.commons.schema.XmlSchemaSequence; +import org.apache.ws.commons.schema.XmlSchemaSequenceMember; +import org.apache.ws.commons.schema.XmlSchemaSimpleType; +import org.apache.ws.commons.schema.XmlSchemaSimpleTypeRestriction; +import org.apache.ws.commons.schema.XmlSchemaType; +import org.apache.ws.commons.schema.constants.Constants; +import org.xbib.raml.internal.impl.commons.type.JsonSchemaExternalType; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.commons.type.XmlSchemaExternalType; +import org.xbib.raml.internal.utils.xml.XMLChar; +import static org.xbib.raml.internal.utils.ValueUtils.asBoolean; +import static org.xbib.raml.internal.utils.ValueUtils.defaultTo; +import static org.xbib.raml.internal.utils.ValueUtils.isEmpty; + +public class TypeToXmlSchemaVisitor implements TypeVisitor { + public static final long UNBOUNDED = Long.MAX_VALUE; + private static final String DEFAULT_NAMESPACE = "http://validationnamespace.raml.org"; + private XmlSchemaCollection collection; + private XmlSchema schema; + private final Stack currentElement; + private final Map types; + + public TypeToXmlSchemaVisitor() { + this.currentElement = new Stack<>(); + this.types = new HashMap<>(); + } + + public XmlSchema getSchema() { + return schema; + } + + public XmlSchemaElement transform(String name, ResolvedType resolvedType) { + initialize(resolvedType); + return doTransform(name, resolvedType); + } + + private XmlSchemaElement doTransform(String name, ResolvedType resolvedType) { + final boolean empty = currentElement.isEmpty(); + final XmlSchemaElement schemaElement = new XmlSchemaElement(schema, empty); + schemaElement.setName(name); + currentElement.push(schemaElement); + final XmlSchemaType visit = resolvedType.visit(this); + if (visit != null) { + if (visit.getQName() != null) { + schemaElement.setSchemaTypeName(visit.getQName()); + } else { + schemaElement.setSchemaType(visit); + } + } + currentElement.pop(); + return schemaElement; + } + + public static String getTargetNamespace(ResolvedType resolvedType) { + if (resolvedType instanceof XmlFacetsCapableType && ((XmlFacetsCapableType) resolvedType).getXmlFacets().getNamespace() != null) { + return ((XmlFacetsCapableType) resolvedType).getXmlFacets().getNamespace(); + } else { + return DEFAULT_NAMESPACE; + } + } + + private void initialize(ResolvedType resolvedType) { + collection = new XmlSchemaCollection(); + + final boolean empty = currentElement.isEmpty(); + // We use namespace of this element + if (empty) { + final String target = getTargetNamespace(resolvedType); + schema = new XmlSchema(target, "raml-xsd", collection); + schema.setTargetNamespace(target); + } + schema.setElementFormDefault(XmlSchemaForm.QUALIFIED); + } + + @Override + public XmlSchemaType visitString(StringResolvedType stringTypeDefinition) { + final XmlSchemaSimpleType simpleType = new XmlSchemaSimpleType(schema, false); + final XmlSchemaSimpleTypeRestriction content = new XmlSchemaSimpleTypeRestriction(); + content.setBaseTypeName(Constants.XSD_STRING); + if (stringTypeDefinition.getMinLength() != null) { + final XmlSchemaMinLengthFacet minLength = new XmlSchemaMinLengthFacet(); + minLength.setValue(stringTypeDefinition.getMinLength()); + content.getFacets().add(minLength); + } + + if (stringTypeDefinition.getMaxLength() != null) { + final XmlSchemaMaxLengthFacet maxLength = new XmlSchemaMaxLengthFacet(); + maxLength.setValue(stringTypeDefinition.getMaxLength()); + content.getFacets().add(maxLength); + } + + final List enums = stringTypeDefinition.getEnums(); + if (!isEmpty(enums)) { + for (String anEnum : enums) { + final XmlSchemaEnumerationFacet enumValue = new XmlSchemaEnumerationFacet(); + enumValue.setValue(anEnum); + content.getFacets().add(enumValue); + } + } + + if (stringTypeDefinition.getPattern() != null) { + final XmlSchemaPatternFacet patternFacet = new XmlSchemaPatternFacet(); + patternFacet.setValue(stringTypeDefinition.getPattern()); + content.getFacets().add(patternFacet); + } + + simpleType.setContent(content); + return simpleType; + } + + @Override + public XmlSchemaType visitObject(ObjectResolvedType objectTypeDefinition) { + final String typeName = getTypeName(objectTypeDefinition); + if (typeName != null && types.containsKey(typeName)) { + // With this we support recursive structures + return types.get(typeName); + } else { + + final XmlSchemaComplexType value = new XmlSchemaComplexType(schema, typeName != null); + if (typeName != null) { + value.setName(typeName); + types.put(typeName, value); + } + final XmlSchemaSequence xmlSchemaSequence = new XmlSchemaSequence(); + final List items = xmlSchemaSequence.getItems(); + value.setParticle(xmlSchemaSequence); + final Map properties = objectTypeDefinition.getProperties(); + for (PropertyFacets propertyDefinition : properties.values()) { + + final ResolvedType valueResolvedType = propertyDefinition.getValueType(); + if (valueResolvedType instanceof XmlFacetsCapableType) { + + final XmlFacets xmlFacets = ((XmlFacetsCapableType) valueResolvedType).getXmlFacets(); + final String name = defaultTo(xmlFacets.getName(), toValidSchemaName(propertyDefinition.getName())); + if (asBoolean(xmlFacets.getAttribute(), false)) { + final XmlSchemaAttribute xmlSchemaAttribute = new XmlSchemaAttribute(schema, false); + xmlSchemaAttribute.setName(name); + final XmlSchemaType visit = valueResolvedType.visit(this); + if (visit instanceof XmlSchemaSimpleType) { + if (visit.getQName() != null) { + xmlSchemaAttribute.setSchemaTypeName(visit.getQName()); + } else { + xmlSchemaAttribute.setSchemaType((XmlSchemaSimpleType) visit); + } + } + value.getAttributes().add(xmlSchemaAttribute); + } else { + final XmlSchemaElement schemaElement = doTransform(name, valueResolvedType); + if (!propertyDefinition.isRequired()) { + // Not required + schemaElement.setMinOccurs(0); + } + items.add(schemaElement); + } + } + } + + if (asBoolean(objectTypeDefinition.getAdditionalProperties(), true)) { + final XmlSchemaAny schemaAny = new XmlSchemaAny(); + schemaAny.setMinOccurs(0); + schemaAny.setMaxOccurs(UNBOUNDED); + schemaAny.setProcessContent(XmlSchemaContentProcessing.SKIP); + items.add(schemaAny); + } + return value; + } + } + + private String getTypeName(ResolvedType resolvedType) { + String typeName = resolvedType.getTypeName(); + for (TypeId typeId : TypeId.values()) { + // return null for base types + if (typeId.getType().equals(typeName)) { + return null; + } + } + return toValidSchemaName(typeName); + } + + private String toValidSchemaName(String typeName) { + String s = typeName; + StringBuilder sb = new StringBuilder(); + if (!XMLChar.isNameStart(s.charAt(0))) { + sb.append("_"); + } + for (char c : s.toCharArray()) { + if (!XMLChar.isName(c)) { + if (c == '|') { + sb.append("or"); + } else { + sb.append("_"); + } + } else { + sb.append(c); + } + } + return sb.toString(); + } + + + @Override + public XmlSchemaType visitBoolean(BooleanResolvedType booleanTypeDefinition) { + return collection.getTypeByQName(Constants.XSD_BOOLEAN); + } + + @Override + public XmlSchemaType visitInteger(IntegerResolvedType integerTypeDefinition) { + return createNumberSchemaType(integerTypeDefinition, Constants.XSD_INTEGER); + } + + @Override + public XmlSchemaType visitNumber(NumberResolvedType numberTypeDefinition) { + return createNumberSchemaType(numberTypeDefinition, Constants.XSD_DOUBLE); + } + + + protected XmlSchemaType createNumberSchemaType(NumberResolvedType numberTypeDefinition, QName baseType) { + final XmlSchemaSimpleType simpleType = new XmlSchemaSimpleType(schema, false); + final XmlSchemaSimpleTypeRestriction content = new XmlSchemaSimpleTypeRestriction(); + content.setBaseTypeName(baseType); + if (numberTypeDefinition.getMinimum() != null) { + final XmlSchemaMinInclusiveFacet minLength = new XmlSchemaMinInclusiveFacet(); + minLength.setValue(numberTypeDefinition.getMinimum()); + content.getFacets().add(minLength); + } + + if (numberTypeDefinition.getMaximum() != null) { + final XmlSchemaMaxInclusiveFacet maxLength = new XmlSchemaMaxInclusiveFacet(); + maxLength.setValue(numberTypeDefinition.getMaximum()); + content.getFacets().add(maxLength); + } + simpleType.setContent(content); + return simpleType; + } + + @Override + public XmlSchemaType visitDateTimeOnly(DateTimeOnlyResolvedType dateTimeOnlyTypeDefinition) { + return collection.getTypeByQName(Constants.XSD_DATETIME); + } + + @Override + public XmlSchemaType visitDate(DateOnlyResolvedType dateOnlyTypeDefinition) { + return collection.getTypeByQName(Constants.XSD_DATE); + } + + @Override + public XmlSchemaType visitDateTime(DateTimeResolvedType dateTimeTypeDefinition) { + return collection.getTypeByQName(Constants.XSD_DATETIME); + } + + @Override + public XmlSchemaType visitFile(FileResolvedType fileTypeDefinition) { + return collection.getTypeByQName(Constants.XSD_BASE64); + } + + @Override + public XmlSchemaType visitNull(NullResolvedType nullTypeDefinition) { + this.currentElement.peek().setNillable(true); + return collection.getTypeByQName(Constants.XSD_ANY); + } + + @Override + public XmlSchemaType visitArray(ArrayResolvedType arrayTypeDefinition) { + final ResolvedType itemType = arrayTypeDefinition.getItems(); + final XmlSchemaType visit; + final XmlFacets xmlFacets = arrayTypeDefinition.getXmlFacets(); + + final String xmlName; + if (itemType instanceof XmlFacetsCapableType) { + xmlName = defaultTo(((XmlFacetsCapableType) itemType).getXmlFacets().getName(), getTypeName(itemType)); + } else { + xmlName = getTypeName(itemType); + } + + final String name = defaultTo(xmlName, currentElement.peek().getName()); + + if (asBoolean(xmlFacets.getWrapped(), false)) { + // This is for the inside element not the wrapped. So this one is the tag for the item type + // First uses the xml facet then the item name finally the field name or parent type name + final XmlSchemaElement transform = doTransform(name, itemType); + addArrayCardinality(arrayTypeDefinition, transform); + + final XmlSchemaComplexType value = new XmlSchemaComplexType(schema, false); + final XmlSchemaSequence xmlSchemaSequence = new XmlSchemaSequence(); + value.setParticle(xmlSchemaSequence); + xmlSchemaSequence.getItems().add(transform); + visit = value; + } else { + visit = itemType.visit(this); + + final XmlSchemaElement peek = currentElement.peek(); + addArrayCardinality(arrayTypeDefinition, peek); + } + + return visit; + } + + private void addArrayCardinality(ArrayResolvedType arrayTypeDefinition, XmlSchemaElement transform) { + if (arrayTypeDefinition.getMinItems() != null) { + transform.setMinOccurs(arrayTypeDefinition.getMinItems()); + } + + if (arrayTypeDefinition.getMaxItems() != null) { + transform.setMaxOccurs(arrayTypeDefinition.getMaxItems()); + } else { + transform.setMaxOccurs(UNBOUNDED); + } + } + + @Override + public XmlSchemaType visitUnion(UnionResolvedType unionTypeDefinition) { + // TODO we should work this better + return unionTypeDefinition.of().get(0).visit(this); + } + + @Override + public XmlSchemaType visitTimeOnly(TimeOnlyResolvedType timeOnlyTypeDefinition) { + return collection.getTypeByQName(Constants.XSD_TIME); + } + + @Override + public XmlSchemaType visitJson(JsonSchemaExternalType jsonTypeDefinition) { + return createAny(); + } + + @Override + public XmlSchemaType visitXml(XmlSchemaExternalType xmlTypeDefinition) { + return createAny(); + } + + @Override + public XmlSchemaType visitAny(AnyResolvedType anyResolvedType) { + + return createAny(); + } + + + private XmlSchemaType createAny() { + final XmlSchemaComplexType value = new XmlSchemaComplexType(schema, false); + final XmlSchemaChoice xmlSchemaSequence = new XmlSchemaChoice(); + value.setParticle(xmlSchemaSequence); + final List items = xmlSchemaSequence.getItems(); + final XmlSchemaAny schemaAny = new XmlSchemaAny(); + schemaAny.setMinOccurs(0); + schemaAny.setMaxOccurs(UNBOUNDED); + schemaAny.setProcessContent(XmlSchemaContentProcessing.SKIP); + items.add(schemaAny); + return value; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeVisitor.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeVisitor.java new file mode 100644 index 0000000..380095c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/TypeVisitor.java @@ -0,0 +1,55 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + + +import org.xbib.raml.internal.impl.commons.type.JsonSchemaExternalType; +import org.xbib.raml.internal.impl.commons.type.XmlSchemaExternalType; + +public interface TypeVisitor { + + T visitString(StringResolvedType stringTypeDefinition); + + T visitObject(ObjectResolvedType objectTypeDefinition); + + T visitBoolean(BooleanResolvedType booleanTypeDefinition); + + T visitInteger(IntegerResolvedType integerTypeDefinition); + + T visitNumber(NumberResolvedType numberTypeDefinition); + + T visitDateTimeOnly(DateTimeOnlyResolvedType dateTimeOnlyTypeDefinition); + + T visitDate(DateOnlyResolvedType dateOnlyTypeDefinition); + + T visitDateTime(DateTimeResolvedType dateTimeTypeDefinition); + + T visitFile(FileResolvedType fileTypeDefinition); + + T visitNull(NullResolvedType nullTypeDefinition); + + T visitArray(ArrayResolvedType arrayTypeDefinition); + + T visitUnion(UnionResolvedType unionTypeDefinition); + + T visitTimeOnly(TimeOnlyResolvedType timeOnlyTypeDefinition); + + T visitJson(JsonSchemaExternalType jsonTypeDefinition); + + T visitXml(XmlSchemaExternalType xmlTypeDefinition); + + T visitAny(AnyResolvedType anyResolvedType); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/UnionResolvedType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/UnionResolvedType.java new file mode 100644 index 0000000..b40bfc8 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/UnionResolvedType.java @@ -0,0 +1,141 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.rule.RamlErrorNodeFactory; +import org.xbib.raml.internal.impl.commons.type.BaseType; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.commons.type.SchemaBasedResolvedType; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import static java.util.Collections.singletonList; + +public class UnionResolvedType extends BaseType { + + private final List of; + + public UnionResolvedType(TypeExpressionNode typeNode, List of, ResolvedCustomFacets customFacets) { + this(getTypeName(typeNode, defaultName(of)), typeNode, of, customFacets); + } + + + public UnionResolvedType(String name, TypeExpressionNode typeNode, List of, ResolvedCustomFacets customFacets) { + super(name, typeNode, customFacets); + this.of = of; + } + + public List of() { + return of; + } + + static String defaultName(List of) { + StringBuilder result = new StringBuilder(); + for (ResolvedType resolvedType : of) { + if (result.length() == 0) { + result = new StringBuilder(resolvedType.getTypeName()); + } else { + result.append(" | ").append(resolvedType.getTypeName()); + } + } + return result.toString(); + } + + protected UnionResolvedType copy() { + return new UnionResolvedType(getTypeName(), getTypeExpressionNode(), new ArrayList<>(of), customFacets.copy()); + } + + @Override + public ResolvedType overwriteFacets(TypeDeclarationNode from) { + final List result = new ArrayList<>(); + for (ResolvedType resolvedType : of()) { + ResolvedType overwriteFacets = resolvedType.overwriteFacets(from); + if (overwriteFacets instanceof BaseType) { + ((BaseType) overwriteFacets).setTypeName(resolvedType.getTypeName()); + } + result.add(overwriteFacets); + } + return new UnionResolvedType(from, result, customFacets.overwriteFacets(from)); + } + + @Override + public ResolvedType mergeFacets(ResolvedType with) { + if (with instanceof UnionResolvedType) { + final List of = ((UnionResolvedType) with).of(); + return mergeWith(of); + } else { + return mergeWith(singletonList(with)); + } + } + + @Override + public boolean doAccept(ResolvedType valueType) { + for (ResolvedType resolvedType : of) { + if (resolvedType.accepts(valueType)) { + return true; + } + } + return false; + } + + @Override + public T visit(TypeVisitor visitor) { + return visitor.visitUnion(this); + } + + @Override + public void validateCanOverwriteWith(TypeDeclarationNode from) { + final Node parent = from.getParent(); + for (ResolvedType resolvedType : of) { + if (parent.findDescendantsWith(ErrorNode.class).isEmpty()) { + resolvedType.validateCanOverwriteWith(from); + } + } + } + + @Override + public void validateState() { + final Node parent = getTypeExpressionNode().getParent(); + for (ResolvedType resolvedType : of) { + if (parent.findDescendantsWith(ErrorNode.class).isEmpty()) { + resolvedType.validateState(); + } + } + + for (ResolvedType resolvedType : of) { + if (resolvedType instanceof SchemaBasedResolvedType) { + getTypeExpressionNode().replaceWith(RamlErrorNodeFactory.createInvalidFacetState(resolvedType.getTypeName(), "union type cannot be of an external type")); + } + } + } + + protected ResolvedType mergeWith(List of) { + final List combination = new ArrayList<>(); + ResolvedCustomFacets customFacets = this.customFacets.copy(); + for (ResolvedType localDefinition : of()) { + for (ResolvedType resolvedType : of) { + customFacets.mergeWith(resolvedType.customFacets()); + combination.add(localDefinition.mergeFacets(resolvedType)); + } + } + + return new UnionResolvedType(getTypeExpressionNode(), combination, customFacets); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/XmlFacets.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/XmlFacets.java new file mode 100644 index 0000000..db65ea7 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/XmlFacets.java @@ -0,0 +1,119 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class XmlFacets { + private Boolean attribute; + private Boolean wrapped; + private String name; + private String namespace; + private String prefix; + + public XmlFacets() { + } + + public XmlFacets(Boolean attribute, Boolean wrapped, String name, String namespace, String prefix) { + this.attribute = attribute; + this.wrapped = wrapped; + this.name = name; + this.namespace = namespace; + this.prefix = prefix; + } + + + public XmlFacets copy() { + return new XmlFacets(attribute, wrapped, name, namespace, prefix); + } + + + public XmlFacets overwriteFacets(TypeDeclarationNode from) { + final XmlFacets copy = copy(); + copy.setAttribute(NodeSelector.selectBooleanValue("xml/attribute", from)); + copy.setName(NodeSelector.selectStringValue("xml/name", from)); + copy.setNamespace(NodeSelector.selectStringValue("xml/namespace", from)); + copy.setPrefix(NodeSelector.selectStringValue("xml/prefix", from)); + copy.setWrapped(NodeSelector.selectBooleanValue("xml/wrapped", from)); + return copy; + } + + + public XmlFacets mergeFacets(XmlFacets with) { + final XmlFacets copy = copy(); + copy.setAttribute(with.getAttribute()); + copy.setName(with.getName()); + copy.setNamespace(with.getNamespace()); + copy.setPrefix(with.getPrefix()); + copy.setWrapped(with.getWrapped()); + return copy; + } + + // Getters and Setters + + public Boolean getAttribute() { + return attribute; + } + + public Boolean getWrapped() { + return wrapped; + } + + public String getName() { + return name; + } + + public String getNamespace() { + return namespace; + } + + public String getPrefix() { + return prefix; + } + + private void setAttribute(Boolean attribute) { + if (attribute != null) { + this.attribute = attribute; + } + } + + private void setWrapped(Boolean wrapped) { + if (wrapped != null) { + this.wrapped = wrapped; + } + } + + private void setName(String name) { + if (name != null) { + this.name = name; + } + } + + private void setNamespace(String namespace) { + if (namespace != null) { + this.namespace = namespace; + } + } + + private void setPrefix(String prefix) { + if (prefix != null) { + this.prefix = prefix; + } + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/XmlFacetsCapableType.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/XmlFacetsCapableType.java new file mode 100644 index 0000000..92ebc53 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/impl/v10/type/XmlFacetsCapableType.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.impl.v10.type; + +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.BaseType; +import org.xbib.raml.internal.impl.commons.type.ResolvedCustomFacets; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; + +public abstract class XmlFacetsCapableType extends BaseType implements ResolvedType { + private XmlFacets xmlFacets; + + public XmlFacetsCapableType(String typeName, TypeExpressionNode declarationNode, XmlFacets xmlFacets, ResolvedCustomFacets customFacets) { + super(typeName, declarationNode, customFacets); + this.xmlFacets = xmlFacets; + } + + public XmlFacetsCapableType(String typeName, TypeExpressionNode typeNode, ResolvedCustomFacets customFacets) { + super(typeName, typeNode, customFacets); + this.xmlFacets = new XmlFacets(); + } + + protected XmlFacetsCapableType overwriteFacets(XmlFacetsCapableType on, TypeDeclarationNode from) { + on.setXmlFacets(on.getXmlFacets().overwriteFacets(from)); + super.overwriteFacets(on, from); + return on; + } + + protected XmlFacetsCapableType mergeFacets(XmlFacetsCapableType on, ResolvedType with) { + if (with instanceof XmlFacetsCapableType) { + on.setXmlFacets(on.getXmlFacets().mergeFacets(((XmlFacetsCapableType) with).getXmlFacets())); + } + return on; + } + + public XmlFacets getXmlFacets() { + return xmlFacets; + } + + private void setXmlFacets(XmlFacets xmlFacets) { + this.xmlFacets = xmlFacets; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/BasicRuleFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/BasicRuleFactory.java new file mode 100644 index 0000000..5922175 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/BasicRuleFactory.java @@ -0,0 +1,48 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import java.util.regex.Pattern; +import org.xbib.raml.yagi.framework.grammar.rule.KeyValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.NullValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.RegexValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.grammar.rule.StringValueRule; + +public class BasicRuleFactory { + + public static StringValueRule stringValue(String value) { + return new StringValueRule(value); + } + + public static RegexValueRule regexValue(String value) { + return new RegexValueRule(Pattern.compile(value)); + } + + public static NullValueRule nullValue() { + return new NullValueRule(); + } + + public static KeyValueRule property(String key, Rule value) { + return new KeyValueRule(stringValue(key), value); + } + + public static KeyValueRule patternProperty(String key, Rule value) { + return new KeyValueRule(regexValue(key), value); + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/Dumper.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/Dumper.java new file mode 100644 index 0000000..6f0f0be --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/Dumper.java @@ -0,0 +1,82 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.StringWriter; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.util.NodeAppender; + +/** + * Created. There, you have it. + */ +public class Dumper { + public static String inMemoryDumper(Node raml) { + StringWriter sw = new StringWriter(); + RamlTreeNodeDumper dumper = new RamlTreeNodeDumper(sw); + dumper.dump(raml); + return sw.toString().trim(); + } + + public static void straightOutput(Node raml) { + final OutputStreamWriter writer = new OutputStreamWriter(System.out); + + RamlTreeNodeDumper dumper = new RamlTreeNodeDumper(new NodeAppender() { + @Override + public NodeAppender append(Object o) { + + try { + writer.append(o.toString()); + writer.flush(); + return this; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public NodeAppender append(String s) { + try { + writer.append(s); + writer.flush(); + return this; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public NodeAppender append(int s) { + + try { + writer.append(Integer.toString(s)); + writer.flush(); + return this; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public NodeAppender dump() { + return this; + } + }); + dumper.dump(raml); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/IOUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/IOUtils.java new file mode 100644 index 0000000..3541096 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/IOUtils.java @@ -0,0 +1,62 @@ +package org.xbib.raml.internal.utils; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.stream.Collectors; + +public class IOUtils { + + private IOUtils() { + } + + public static String toString(InputStream inputStream) throws IOException { + try (InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) { + return bufferedReader.lines() + .collect(Collectors.joining(System.lineSeparator())); + } + } + + public static String toString(Reader reader) throws IOException { + try (BufferedReader bufferedReader = new BufferedReader(reader)) { + return bufferedReader.lines() + .collect(Collectors.joining(System.lineSeparator())); + } + } + + public static byte[] toByteArray(InputStream inputStream) throws IOException { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + byte[] buffer = new byte[1024]; + int length; + while ((length = inputStream.read(buffer)) > -1) { + outputStream.write(buffer, 0, length); + } + outputStream.flush(); + return outputStream.toByteArray(); + } + } + + public static void closeQuietly(AutoCloseable autoCloseable) { + try { + autoCloseable.close(); + } catch (Exception ignored) { + //ignore exception + } + } + + public static InputStream getResourceAsStream(String name) { + return IOUtils.class.getClassLoader().getResourceAsStream(name); + } + + public static InputStream getFileAsStream(Path path) throws IOException { + return Files.newInputStream(path, StandardOpenOption.READ); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/InflectorBase.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/InflectorBase.java new file mode 100644 index 0000000..ec7702f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/InflectorBase.java @@ -0,0 +1,279 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class InflectorBase { + + private static final List singulars; + private static final List plurals; + private static final List irregulars; + private static List uncountables; + + static { + singulars = new ArrayList<>(); + plurals = new ArrayList<>(); + irregulars = new ArrayList<>(); + uncountables = new ArrayList<>(); + + addPlural("$", "s"); + addPlural("s$", "s"); + addPlural("(ax|test)is$", "$1es"); + addPlural("(octop|vir)us$", "$1i"); + addPlural("(alias|status)$", "$1es"); + addPlural("(bu)s$", "$1ses"); + addPlural("(buffal|tomat)o$", "$1oes"); + addPlural("([ti])um$", "$1a"); + addPlural("sis$", "ses"); + addPlural("(?:([^f])fe|([lr])f)$", "$1$2ves"); + addPlural("(hive)$", "$1s"); + addPlural("([^aeiouy]|qu)y$", "$1ies"); + addPlural("(x|ch|ss|sh)$", "$1es"); + addPlural("(matr|vert|ind)(?:ix|ex)$", "$1ices"); + addPlural("([m|l])ouse$", "$1ice"); + addPlural("^(ox)$", "$1en"); + addPlural("(quiz)$", "$1zes"); + + + addSingular("s$", ""); + addSingular("(n)ews$", "$1ews"); + addSingular("([ti])a$", "$1um"); + addSingular("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$", "$1sis"); + addSingular("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)sis$", "$1sis"); + addSingular("(^analy)ses$", "$1sis"); + addSingular("([^f])ves$", "$1fe"); + addSingular("(hive)s$", "$1"); + addSingular("(tive)s$", "$1"); + addSingular("([lr])ves$", "$1f"); + addSingular("([^aeiouy]|qu)ies$", "$1y"); + addSingular("(s)eries$", "$1eries"); + addSingular("(m)ovies$", "$1ovie"); + addSingular("(x|ch|ss|sh)es$", "$1"); + addSingular("([m|l])ice$", "$1ouse"); + addSingular("(bus)es$", "$1"); + addSingular("(bus)$", "$1"); + addSingular("(o)es$", "$1"); + addSingular("(shoe)s$", "$1"); + addSingular("(cris|ax|test)es$", "$1is"); + addSingular("(cris|ax|test)is$", "$1is"); + addSingular("(octop|vir)i$", "$1us"); + addSingular("(alias|status)es$", "$1"); + addSingular("(alias|status)$", "$1"); + addSingular("^(ox)en", "$1"); + addSingular("(vert|ind)ices$", "$1ex"); + addSingular("(matr)ices$", "$1ix"); + addSingular("(quiz)zes$", "$1"); + addSingular("(database)s$", "$1"); + + addIrregular("person", "people"); + addIrregular("man", "men"); + addIrregular("child", "children"); + addIrregular("sex", "sexes"); + addIrregular("move", "moves"); + addIrregular("foot", "feet"); + addIrregular("tooth", "teeth"); + + uncountables = Arrays.asList("equipment", "information", "rice", "money", "species", "series", "fish", "sheep"); + } + + private static void addPlural(String rule, String replacement) { + plurals.add(0, new String[]{rule, replacement}); + } + + private static void addSingular(String rule, String replacement) { + singulars.add(0, new String[]{rule, replacement}); + } + + private static void addIrregular(String rule, String replacement) { + irregulars.add(new String[]{rule, replacement}); + } + + + /** + * Replaces a found pattern in a word and returns a transformed word. + * + * @return Replaces a found pattern in a word and returns a transformed word. Null is pattern does not match. + */ + private static String gsub(String word, String rule, String replacement) { + Pattern pattern = Pattern.compile(rule, Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(word); + return matcher.find() ? matcher.replaceFirst(replacement) : null; + } + + public static String pluralize(String word) { + + if (uncountables.contains(word)) { + return word; + } + + for (String[] irregular : irregulars) { + if (irregular[0].equalsIgnoreCase(word)) { + return irregular[1]; + } + } + + for (String[] pair : plurals) { + String plural = gsub(word, pair[0], pair[1]); + if (plural != null) { + return plural; + } + } + + return word; + } + + + public static String singularize(String word) { + + if (uncountables.contains(word)) { + return word; + } + + for (String[] irregular : irregulars) { + if (irregular[1].equalsIgnoreCase(word)) { + return irregular[0]; + } + } + + for (String[] pair : singulars) { + String singular = gsub(word, pair[0], pair[1]); + if (singular != null) { + return singular; + } + } + + return word; + } + + /** + * Converts a camel case to underscore and then pluralizes. + *

+ * Example: "GrayDuck" is converted to "gray_ducks". + * + * @param camelCase any CamelCase phrase. + * @return pluralized version of underscored CamelCase. + */ + private static String tableize(String camelCase) { + return pluralize(underscore(camelCase)); + } + + private static String underscore(String camel) { + + List upper = new ArrayList(); + byte[] bytes = camel.getBytes(); + for (int i = 0; i < bytes.length; i++) { + byte b = bytes[i]; + if (b < 97 || b > 122) { + upper.add(i); + } + } + + StringBuffer b = new StringBuffer(camel); + for (int i = upper.size() - 1; i >= 0; i--) { + Integer index = upper.get(i); + if (index != 0) { + b.insert(index, "_"); + } + } + + return b.toString().toLowerCase(); + } + + + /** + * Generates a camel case version of a phrase from dash. + * + * @param dash dash version of a word to converted to camel case. + * @return camel case version of dash. + */ + public static String camelize(String dash) { + return camelize(dash, true); + } + + + /** + * Generates a camel case version of a phrase from dash. + * + * @param dash dash version of a word to converted to camel case. + * @param capitalizeFirstChar set to true if first character needs to be capitalized, false if not. + * @return camel case version of dash. + */ + private static String camelize(String dash, boolean capitalizeFirstChar) { + StringBuilder result = new StringBuilder(); + StringTokenizer st = new StringTokenizer(dash, "-"); + while (st.hasMoreTokens()) { + result.append(capitalize(st.nextToken())); + } + return capitalizeFirstChar ? result.toString() : result.substring(0, 1).toLowerCase() + result.substring(1); + } + + /** + * Capitalizes a word - only a first character is converted to upper case. + * + * @param word word/phrase to capitalize. + * @return same as input argument, but the first character is capitalized. + */ + public static String capitalize(String word) { + return word.substring(0, 1).toUpperCase() + word.substring(1); + } + + + private static String shortName(String className) { + return className.substring(className.lastIndexOf('.') + 1); + } + + private static String getIdName(String tableName) { + String idName = InflectorBase.singularize(tableName) + "_id"; + return idName.toLowerCase(); + } + + /** + * If a table name is made of two other table names (as is typical for many to many relationships), + * this method retrieves a name of "another" table from a join table name. + * For instance, if a source table is "payer" and the target is "player_game", then the returned value + * will be "game". + * + * @param source known table name. It may or may not exist in the target table name. + * @param target this is a potential "join" table name. + * @return a name of "another" table from a join table name. + */ + private static String getOtherName(String source, String target) { + + String other; + if (target.contains(source) && !target.equals(source)) { + + int start = target.indexOf(source); + other = start == 0 ? target.substring(source.length()) : target.substring(0, start); + } else { + return null; + } + if (other.startsWith("_")) { + other = other.replaceFirst("_", " "); + } + if (other.endsWith("_")) { + byte[] otherb = other.getBytes(); + otherb[otherb.length - 1] = ' '; + other = new String(otherb); + } + return other.trim(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/JSonDumper.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/JSonDumper.java new file mode 100644 index 0000000..43d6faf --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/JSonDumper.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +public class JSonDumper { + + public static String dump(Node node) { + return dumpNode(node); + } + + private static String dump(Node node, String start, String separator, String end) { + StringBuilder builder = new StringBuilder(); + List children = dumpChildren(node.getChildren()); + builder.append(start).append(String.join(separator, children)).append(end); + return builder.toString(); + } + + private static List dumpChildren(List children) { + List valueChildren = new ArrayList<>(); + for (Node child : children) { + valueChildren.add(dumpNode(child)); + } + return valueChildren; + } + + private static String dumpNode(Node child) { + if (child instanceof KeyValueNode keyValueNode) { + return dumpNode(keyValueNode.getKey()) + " : " + dumpNode(keyValueNode.getValue()); + } else if (child instanceof ObjectNode) { + return dump(child, "{\n", ",\n", "\n}"); + } else if (child instanceof StringNode) { + return "\"" + ((StringNode) child).getValue() + "\""; + } else if (child instanceof ArrayNode) { + return dump(child, "[\n", ",\n", "\n]"); + } else { + return child.toString(); + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/Pair.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/Pair.java new file mode 100644 index 0000000..556baf2 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/Pair.java @@ -0,0 +1,83 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import java.util.Map.Entry; + +public class Pair { + + private final L left; + private final R right; + + public Pair(L left, R right) { + super(); + this.left = left; + this.right = right; + } + + + public static Pair of(A left, B right) { + return new Pair(left, right); + } + + public static Pair fromEntry(Entry entry) { + return Pair.of(entry.getKey(), entry.getValue()); + } + + public L getLeft() { + return left; + } + + public R getRight() { + return right; + } + + + @Override + public String toString() { + return "Pair [left=" + left + ", right=" + right + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((left == null) ? 0 : left.hashCode()); + result = prime * result + ((right == null) ? 0 : right.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Pair other = (Pair) obj; + if (left == null) { + if (other.left != null) + return false; + } else if (!left.equals(other.left)) + return false; + if (right == null) { + return other.right == null; + } else return right.equals(other.right); + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/PhaseUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/PhaseUtils.java new file mode 100644 index 0000000..70f2857 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/PhaseUtils.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.phase.Phase; + +public class PhaseUtils { + + public static Node applyPhases(Node node, Phase... phases) { + Node result = node; + if (!RamlNodeUtils.isErrorResult(result)) { + for (Phase phase : phases) { + result = phase.apply(result); + if (!RamlNodeUtils.isErrorResult(result)) { + return result; + } + } + } + return result; + + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/RamlNodeUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/RamlNodeUtils.java new file mode 100644 index 0000000..3adafc0 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/RamlNodeUtils.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.internal.impl.commons.RamlVersion; +import org.xbib.raml.internal.impl.commons.nodes.RamlVersionAnnotation; +import org.xbib.raml.internal.impl.v10.nodes.LibraryLinkNode; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeAnnotation; +import org.xbib.raml.yagi.framework.util.NodeUtils; + +public class RamlNodeUtils { + public static boolean isErrorResult(Node node) { + if (NodeUtils.isErrorResult(node)) { + return true; + } else if (node != null) { + final List descendantsWith = node.findDescendantsWith(LibraryLinkNode.class); + for (LibraryLinkNode libraryLinkNode : descendantsWith) { + if (isErrorResult(libraryLinkNode.getRefNode())) { + return true; + } + } + } + return false; + } + + + public static List getErrors(Node node) { + List result = new ArrayList<>(); + if (node != null) { + if (node instanceof ErrorNode) { + result.add((ErrorNode) node); + } + + result.addAll(node.findDescendantsWith(ErrorNode.class)); + + + final List descendantsWith = node.findDescendantsWith(LibraryLinkNode.class); + for (LibraryLinkNode libraryLinkNode : descendantsWith) { + result.addAll(getErrors(libraryLinkNode.getRefNode())); + } + } + return result; + } + + public static RamlVersion getVersion(Node node) { + while (true) { + for (NodeAnnotation annotation : node.annotations()) { + if (annotation instanceof RamlVersionAnnotation) { + return ((RamlVersionAnnotation) annotation).getVersion(); + } + } + node = node.getParent(); + if (node == null) { + throw new RuntimeException("Raml Version not specified."); + } + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/RamlTreeNodeDumper.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/RamlTreeNodeDumper.java new file mode 100644 index 0000000..69512d5 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/RamlTreeNodeDumper.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import java.io.Writer; +import org.xbib.raml.internal.impl.v10.nodes.LibraryLinkNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.util.NodeAppender; +import org.xbib.raml.yagi.framework.util.TreeNodeDumper; + + +public class RamlTreeNodeDumper extends TreeNodeDumper { + + + public RamlTreeNodeDumper(NodeAppender appender) { + + super(appender); + } + + public RamlTreeNodeDumper(Writer writer) { + super(writer); + } + + protected void dumpChildren(Node node) { + super.dumpChildren(node); + + if (node instanceof LibraryLinkNode) { + final Node refNode = ((LibraryLinkNode) node).getRefNode(); + if (refNode != null) { + dump(refNode); + } + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/ResourcePathUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/ResourcePathUtils.java new file mode 100644 index 0000000..d90faeb --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/ResourcePathUtils.java @@ -0,0 +1,86 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import java.io.File; +import java.net.URI; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ResourcePathUtils { + final private static Pattern TEMPLATE_PATTERN = Pattern.compile("\\{([^}]+)\\}"); + + /** + * Returns the absolute resource location using the basePath + * basePath and relativePath must have forward slashes(/) as path separators. + * + * @param basePath The base path of the relative path + * @param relativePath the relative path + * @return The Absolute path + */ + public static String toAbsoluteLocation(String basePath, String relativePath) { + String result = relativePath; + if (!isAbsolute(relativePath)) { + // This is for file based path + int lastSlash = basePath.lastIndexOf("/"); + if (lastSlash == -1) { + // This is for URL based path + lastSlash = basePath.lastIndexOf("/"); + } + if (lastSlash != -1) { + result = basePath.substring(0, lastSlash + 1) + relativePath; + if (isUri(result)) { + URI resultUri = URI.create(result); + result = resultUri.normalize().toString(); + } else { + result = Paths.get(result).normalize().toString().replace("\\", "/"); + } + } + } + if (result.contains("#")) { + return result.split("#")[0]; + } + return result; + } + + public static boolean isUri(String includePath) { + return includePath.startsWith("http:") || includePath.startsWith("https:") || includePath.startsWith("file:"); + } + + public static boolean isAbsolute(String includePath) { + return includePath.startsWith("http:") || includePath.startsWith("https:") || includePath.startsWith("file:") || includePath.startsWith("/") || new File(includePath).isAbsolute(); + } + + /** + * Returns a List containing all the uri templates (aka uri parameters) of a resource + * + * @param value the resource to extract the parameters + * @return List containing the uri parameters + */ + public static List getUriTemplates(String value) { + List result = new ArrayList<>(); + if (value != null) { + Matcher m = TEMPLATE_PATTERN.matcher(value); + while (m.find()) { + result.add(m.group(1)); + } + } + return result; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/SchemaGenerator.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/SchemaGenerator.java new file mode 100644 index 0000000..3f0e0fc --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/SchemaGenerator.java @@ -0,0 +1,158 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.fge.jackson.JsonLoader; +import com.github.fge.jsonschema.core.exceptions.ProcessingException; +import com.github.fge.jsonschema.main.JsonSchema; +import com.github.fge.jsonschema.main.JsonSchemaFactory; +import java.io.IOException; +import java.io.StringReader; +import java.util.List; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.internal.impl.commons.nodes.ExternalSchemaTypeExpressionNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeDeclarationNode; +import org.xbib.raml.internal.impl.commons.nodes.TypeExpressionNode; +import org.xbib.raml.internal.impl.commons.type.JsonSchemaExternalType; +import org.xbib.raml.internal.impl.commons.type.ResolvedType; +import org.xbib.raml.internal.impl.commons.type.XmlSchemaExternalType; +import org.xbib.raml.internal.impl.v10.nodes.NamedTypeExpressionNode; +import org.xbib.raml.internal.utils.xml.XMLLocalConstants; +import org.xbib.raml.internal.utils.xml.XsdResourceResolver; +import org.xbib.raml.yagi.framework.util.NodeUtils; +import org.xml.sax.SAXException; + +public class SchemaGenerator { + private static final String DEFINITIONS = "/definitions/"; + + /*private static LoadingCache jsonSchemaCache = CacheBuilder.newBuilder() + .maximumSize(Integer.parseInt(System.getProperty("yagi.json_cache_size", "200"))) + .build(new CacheLoader() + { + + @Override + public JsonSchema load(JsonSchemaExternalType jsonTypeDefinition) throws IOException, + ProcessingException + { + return loadJsonSchema(jsonTypeDefinition); + } + });*/ + + public static Schema generateXmlSchema(ResourceLoader resourceLoader, XmlSchemaExternalType xmlTypeDefinition) throws SAXException { + SchemaFactory factory = SchemaFactory.newInstance(XMLLocalConstants.XML_SCHEMA_VERSION); + factory.setResourceResolver(new XsdResourceResolver(resourceLoader, xmlTypeDefinition.getSchemaPath())); + String includedResourceUri = resolveResourceUriIfIncluded(xmlTypeDefinition); + return factory.newSchema(new StreamSource(new StringReader(xmlTypeDefinition.getSchemaValue()), includedResourceUri)); + } + + private static JsonSchema loadJsonSchema(JsonSchemaExternalType jsonTypeDefinition) throws IOException, ProcessingException { + final JsonSchema result; + String includedResourceUri = resolveResourceUriIfIncluded(jsonTypeDefinition); + + JsonNode jsonSchema = JsonLoader.fromString(jsonTypeDefinition.getSchemaValue()); + JsonSchemaFactory factory = JsonSchemaFactory.byDefault(); + + if (jsonTypeDefinition.getInternalFragment() != null) { + if (includedResourceUri != null) { + result = factory.getJsonSchema(includedResourceUri + "#" + DEFINITIONS + jsonTypeDefinition.getInternalFragment()); + } else { + result = factory.getJsonSchema(jsonSchema, DEFINITIONS + jsonTypeDefinition.getInternalFragment()); + } + } else { + if (includedResourceUri != null) { + result = factory.getJsonSchema(includedResourceUri); + } else { + result = factory.getJsonSchema(jsonSchema); + } + } + return result; + } + + public static JsonSchema generateJsonSchema(JsonSchemaExternalType jsonTypeDefinition) throws IOException, ProcessingException { + try { + //return jsonSchemaCache.get(jsonTypeDefinition); + return loadJsonSchema(jsonTypeDefinition); + } catch (Exception e) { + if (e.getCause() instanceof JsonParseException) + throw (JsonParseException) e.getCause(); + else if (e.getCause() instanceof IOException) { + throw (IOException) e.getCause(); + } else + throw new ProcessingException(e.getMessage(), e.getCause()); + } + } + + + private static String resolveResourceUriIfIncluded(ResolvedType typeDefinition) { + // Getting the type holding the schema + TypeExpressionNode typeExpressionNode = typeDefinition.getTypeExpressionNode(); + + if (typeExpressionNode instanceof ExternalSchemaTypeExpressionNode schema) { + + return getIncludedResourceUri(schema); + } else { + // Inside the type declaration, we find the node containing the schema itself + List schemas = typeExpressionNode.findDescendantsWith(ExternalSchemaTypeExpressionNode.class); + if (schemas.size() > 0) { + return getIncludedResourceUri(schemas.get(0)); + } else { + // If the array is empty, then it must be a reference to a previously defined type + List refNode = typeExpressionNode.findDescendantsWith(NamedTypeExpressionNode.class); + + if (refNode.size() > 0) { + // If refNodes is not empty, then we obtain that type + typeExpressionNode = refNode.get(0).resolveReference(); + if (typeExpressionNode != null) { + schemas = typeExpressionNode.findDescendantsWith(ExternalSchemaTypeExpressionNode.class); + if (schemas.size() > 0) { + return getIncludedResourceUri(schemas.get(0)); + } + } + } + } + } + + return null; + } + + private static String getIncludedResourceUri(ExternalSchemaTypeExpressionNode schemaNode) { + final String includedResourceUri = schemaNode.getStartPosition().getIncludedResourceUri(); + + if (includedResourceUri == null) { + final TypeDeclarationNode parentTypeDeclaration = NodeUtils.getAncestor(schemaNode, TypeDeclarationNode.class); + if (parentTypeDeclaration != null) + return parentTypeDeclaration.getStartPosition().getIncludedResourceUri(); + } + + return includedResourceUri; + } + + + public static boolean isJsonSchema(String schema) { + return schema.trim().startsWith("{"); + } + + + public static boolean isXmlSchema(String schema) { + return schema.trim().startsWith("<"); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/StreamUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/StreamUtils.java new file mode 100644 index 0000000..a0994ec --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/StreamUtils.java @@ -0,0 +1,95 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +public class StreamUtils { + + private static final String RAML_PARSER_ENCODING = "raml.parser.encoding"; + + private static String getDefaultEncoding() { + return System.getProperty(RAML_PARSER_ENCODING, "UTF-8"); + } + + public static Reader reader(InputStream stream) { + try { + byte[] content = IOUtils.toByteArray(stream); + return new InputStreamReader(new ByteArrayInputStream(content), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + IOUtils.closeQuietly(stream); + } + } + + public static String toString(InputStream stream) { + try { + byte[] content = IOUtils.toByteArray(stream); + Charset encoding = StandardCharsets.UTF_8; + return new String(trimBom(content), encoding); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + IOUtils.closeQuietly(stream); + } + } + + public static String trimBom(String content) { + String trimmed = content; + trimmed = new String(trimBom(content.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8); + return trimmed; + } + + public static byte[] trimBom(byte[] content) { + int bomSize = 0; + if (content.length > 4) { + // check for UTF_32BE and UTF_32LE BOMs + if (content[0] == 0x00 && content[1] == 0x00 && content[2] == (byte) 0xFE && content[3] == (byte) 0xFF || + content[0] == (byte) 0xFF && content[1] == (byte) 0xFE && content[2] == 0x00 && content[3] == 0x00) { + bomSize = 4; + } + } + if (content.length > 3 && bomSize == 0) { + // check for UTF-8 BOM + if (content[0] == (byte) 0xEF && content[1] == (byte) 0xBB && content[2] == (byte) 0xBF) { + bomSize = 3; + } + } + if (content.length > 2 && bomSize == 0) { + // check for UTF_16BE and UTF_16LE BOMs + if (content[0] == (byte) 0xFE && content[1] == (byte) 0xFF || content[0] == (byte) 0xFF && content[1] == (byte) 0xFE) { + bomSize = 2; + } + } + + if (bomSize > 0) { + int trimmedSize = content.length - bomSize; + byte[] trimmedArray = new byte[trimmedSize]; + System.arraycopy(content, bomSize, trimmedArray, 0, trimmedSize); + return trimmedArray; + } + return content; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/StringUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/StringUtils.java new file mode 100644 index 0000000..486d5ca --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/StringUtils.java @@ -0,0 +1,8 @@ +package org.xbib.raml.internal.utils; + +public class StringUtils { + + public static String capitalize(String string) { + return string.substring(0, 1).toUpperCase() + string.substring(1); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/UriTemplateValidation.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/UriTemplateValidation.java new file mode 100644 index 0000000..0fec4b2 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/UriTemplateValidation.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import java.util.Stack; + +public class UriTemplateValidation { + private static final char OPEN_BRACE = '{'; + private static final char CLOSE_BRACE = '}'; + + public static boolean isBalanced(String value) { + Stack characterStack = new Stack(); + + for (int i = 0; i < value.length(); i++) { + if (value.charAt(i) == OPEN_BRACE) { + if (characterStack.isEmpty()) { + characterStack.push(OPEN_BRACE); + } else { + // We have found a nested brace + return false; + } + + } else if (value.charAt(i) == CLOSE_BRACE) { + if (characterStack.isEmpty()) + return false; + if (characterStack.pop() != OPEN_BRACE) + return false; + } + } + + // If the stack is empty is because all open braces has its corresponding close brace and the string is balanced + return characterStack.isEmpty(); + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/ValueUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/ValueUtils.java new file mode 100644 index 0000000..c042b96 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/ValueUtils.java @@ -0,0 +1,32 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +import java.util.List; + +public class ValueUtils { + public static boolean asBoolean(Boolean booleanValue, boolean defaultValue) { + return booleanValue == null ? defaultValue : booleanValue; + } + + public static T defaultTo(T stringValue, T defaultValue) { + return stringValue == null ? defaultValue : stringValue; + } + + public static boolean isEmpty(List collection) { + return collection == null || collection.isEmpty(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/YamlUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/YamlUtils.java new file mode 100644 index 0000000..d459413 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/YamlUtils.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils; + +public class YamlUtils { + public static boolean isYamlSignificantChar(char character) { + return character == ':' || character == '-' || character == '\n' || character == ','; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/xml/LSInputImpl.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/xml/LSInputImpl.java new file mode 100644 index 0000000..4bae930 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/xml/LSInputImpl.java @@ -0,0 +1,124 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils.xml; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.Reader; +import java.nio.charset.Charset; +import org.w3c.dom.ls.LSInput; + +public class LSInputImpl implements LSInput { + + protected Reader characterStream; + protected InputStream byteStream; + protected String stringData; + + protected String systemId; + protected String publicId; + protected String baseUri; + + protected Charset encoding; + protected boolean certifiedText; + + public LSInputImpl(String publicId, String systemId, String baseURI, ByteArrayInputStream content, Charset encoding) { + this.publicId = publicId; + this.systemId = systemId; + this.baseUri = baseURI; + this.byteStream = content; + this.encoding = encoding; + } + + @Override + public Reader getCharacterStream() { + return characterStream; + } + + @Override + public void setCharacterStream(Reader characterStream) { + this.characterStream = characterStream; + } + + @Override + public InputStream getByteStream() { + return byteStream; + } + + @Override + public void setByteStream(InputStream byteStream) { + this.byteStream = byteStream; + } + + @Override + public String getStringData() { + return stringData; + } + + @Override + public void setStringData(String stringData) { + this.stringData = stringData; + } + + @Override + public String getSystemId() { + return systemId; + } + + @Override + public void setSystemId(String systemId) { + this.systemId = systemId; + } + + @Override + public String getPublicId() { + return publicId; + } + + @Override + public void setPublicId(String publicId) { + this.publicId = publicId; + } + + @Override + public String getBaseURI() { + return baseUri; + } + + @Override + public void setBaseURI(String baseURI) { + this.baseUri = baseURI; + } + + @Override + public String getEncoding() { + return encoding.displayName(); + } + + @Override + public void setEncoding(String encoding) { + this.encoding = Charset.forName(encoding); + } + + @Override + public boolean getCertifiedText() { + return certifiedText; + } + + @Override + public void setCertifiedText(boolean certifiedText) { + this.certifiedText = certifiedText; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/xml/XMLChar.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/xml/XMLChar.java new file mode 100644 index 0000000..1e2c588 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/xml/XMLChar.java @@ -0,0 +1,632 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils.xml; + +public class XMLChar { + + // + // Constants + // + + /** + * Character flags. + */ + private static final byte[] CHARS = new byte[1 << 16]; + + /** + * Valid character mask. + */ + public static final int MASK_VALID = 0x01; + + /** + * Space character mask. + */ + public static final int MASK_SPACE = 0x02; + + /** + * Name start character mask. + */ + public static final int MASK_NAME_START = 0x04; + + /** + * Name character mask. + */ + public static final int MASK_NAME = 0x08; + + /** + * Pubid character mask. + */ + public static final int MASK_PUBID = 0x10; + + /** + * Content character mask. Special characters are those that can + * be considered the start of markup, such as '<' and '&'. + * The various newline characters are considered special as well. + * All other valid XML characters can be considered content. + *

+ * This is an optimization for the inner loop of character scanning. + */ + public static final int MASK_CONTENT = 0x20; + + /** + * NCName start character mask. + */ + public static final int MASK_NCNAME_START = 0x40; + + /** + * NCName character mask. + */ + public static final int MASK_NCNAME = 0x80; + + // + // Static initialization + // + + static { + + // + // [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | + // [#xE000-#xFFFD] | [#x10000-#x10FFFF] + // + + int[] charRange = { + 0x0009, 0x000A, 0x000D, 0x000D, 0x0020, 0xD7FF, 0xE000, 0xFFFD, + }; + + // + // [3] S ::= (#x20 | #x9 | #xD | #xA)+ + // + + int[] spaceChar = { + 0x0020, 0x0009, 0x000D, 0x000A, + }; + + // + // [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | + // CombiningChar | Extender + // + + int[] nameChar = { + 0x002D, 0x002E, // '-' and '.' + }; + + // + // [5] Name ::= (Letter | '_' | ':') (NameChar)* + // + + int[] nameStartChar = { + 0x003A, 0x005F, // ':' and '_' + }; + + // + // [13] PubidChar ::= #x20 | 0xD | 0xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] + // + + int[] pubidChar = { + 0x000A, 0x000D, 0x0020, 0x0021, 0x0023, 0x0024, 0x0025, 0x003D, + 0x005F + }; + + int[] pubidRange = { + 0x0027, 0x003B, 0x003F, 0x005A, 0x0061, 0x007A + }; + + // + // [84] Letter ::= BaseChar | Ideographic + // + + int[] letterRange = { + // BaseChar + 0x0041, 0x005A, 0x0061, 0x007A, 0x00C0, 0x00D6, 0x00D8, 0x00F6, + 0x00F8, 0x0131, 0x0134, 0x013E, 0x0141, 0x0148, 0x014A, 0x017E, + 0x0180, 0x01C3, 0x01CD, 0x01F0, 0x01F4, 0x01F5, 0x01FA, 0x0217, + 0x0250, 0x02A8, 0x02BB, 0x02C1, 0x0388, 0x038A, 0x038E, 0x03A1, + 0x03A3, 0x03CE, 0x03D0, 0x03D6, 0x03E2, 0x03F3, 0x0401, 0x040C, + 0x040E, 0x044F, 0x0451, 0x045C, 0x045E, 0x0481, 0x0490, 0x04C4, + 0x04C7, 0x04C8, 0x04CB, 0x04CC, 0x04D0, 0x04EB, 0x04EE, 0x04F5, + 0x04F8, 0x04F9, 0x0531, 0x0556, 0x0561, 0x0586, 0x05D0, 0x05EA, + 0x05F0, 0x05F2, 0x0621, 0x063A, 0x0641, 0x064A, 0x0671, 0x06B7, + 0x06BA, 0x06BE, 0x06C0, 0x06CE, 0x06D0, 0x06D3, 0x06E5, 0x06E6, + 0x0905, 0x0939, 0x0958, 0x0961, 0x0985, 0x098C, 0x098F, 0x0990, + 0x0993, 0x09A8, 0x09AA, 0x09B0, 0x09B6, 0x09B9, 0x09DC, 0x09DD, + 0x09DF, 0x09E1, 0x09F0, 0x09F1, 0x0A05, 0x0A0A, 0x0A0F, 0x0A10, + 0x0A13, 0x0A28, 0x0A2A, 0x0A30, 0x0A32, 0x0A33, 0x0A35, 0x0A36, + 0x0A38, 0x0A39, 0x0A59, 0x0A5C, 0x0A72, 0x0A74, 0x0A85, 0x0A8B, + 0x0A8F, 0x0A91, 0x0A93, 0x0AA8, 0x0AAA, 0x0AB0, 0x0AB2, 0x0AB3, + 0x0AB5, 0x0AB9, 0x0B05, 0x0B0C, 0x0B0F, 0x0B10, 0x0B13, 0x0B28, + 0x0B2A, 0x0B30, 0x0B32, 0x0B33, 0x0B36, 0x0B39, 0x0B5C, 0x0B5D, + 0x0B5F, 0x0B61, 0x0B85, 0x0B8A, 0x0B8E, 0x0B90, 0x0B92, 0x0B95, + 0x0B99, 0x0B9A, 0x0B9E, 0x0B9F, 0x0BA3, 0x0BA4, 0x0BA8, 0x0BAA, + 0x0BAE, 0x0BB5, 0x0BB7, 0x0BB9, 0x0C05, 0x0C0C, 0x0C0E, 0x0C10, + 0x0C12, 0x0C28, 0x0C2A, 0x0C33, 0x0C35, 0x0C39, 0x0C60, 0x0C61, + 0x0C85, 0x0C8C, 0x0C8E, 0x0C90, 0x0C92, 0x0CA8, 0x0CAA, 0x0CB3, + 0x0CB5, 0x0CB9, 0x0CE0, 0x0CE1, 0x0D05, 0x0D0C, 0x0D0E, 0x0D10, + 0x0D12, 0x0D28, 0x0D2A, 0x0D39, 0x0D60, 0x0D61, 0x0E01, 0x0E2E, + 0x0E32, 0x0E33, 0x0E40, 0x0E45, 0x0E81, 0x0E82, 0x0E87, 0x0E88, + 0x0E94, 0x0E97, 0x0E99, 0x0E9F, 0x0EA1, 0x0EA3, 0x0EAA, 0x0EAB, + 0x0EAD, 0x0EAE, 0x0EB2, 0x0EB3, 0x0EC0, 0x0EC4, 0x0F40, 0x0F47, + 0x0F49, 0x0F69, 0x10A0, 0x10C5, 0x10D0, 0x10F6, 0x1102, 0x1103, + 0x1105, 0x1107, 0x110B, 0x110C, 0x110E, 0x1112, 0x1154, 0x1155, + 0x115F, 0x1161, 0x116D, 0x116E, 0x1172, 0x1173, 0x11AE, 0x11AF, + 0x11B7, 0x11B8, 0x11BC, 0x11C2, 0x1E00, 0x1E9B, 0x1EA0, 0x1EF9, + 0x1F00, 0x1F15, 0x1F18, 0x1F1D, 0x1F20, 0x1F45, 0x1F48, 0x1F4D, + 0x1F50, 0x1F57, 0x1F5F, 0x1F7D, 0x1F80, 0x1FB4, 0x1FB6, 0x1FBC, + 0x1FC2, 0x1FC4, 0x1FC6, 0x1FCC, 0x1FD0, 0x1FD3, 0x1FD6, 0x1FDB, + 0x1FE0, 0x1FEC, 0x1FF2, 0x1FF4, 0x1FF6, 0x1FFC, 0x212A, 0x212B, + 0x2180, 0x2182, 0x3041, 0x3094, 0x30A1, 0x30FA, 0x3105, 0x312C, + 0xAC00, 0xD7A3, + // Ideographic + 0x3021, 0x3029, 0x4E00, 0x9FA5, + }; + int[] letterChar = { + // BaseChar + 0x0386, 0x038C, 0x03DA, 0x03DC, 0x03DE, 0x03E0, 0x0559, 0x06D5, + 0x093D, 0x09B2, 0x0A5E, 0x0A8D, 0x0ABD, 0x0AE0, 0x0B3D, 0x0B9C, + 0x0CDE, 0x0E30, 0x0E84, 0x0E8A, 0x0E8D, 0x0EA5, 0x0EA7, 0x0EB0, + 0x0EBD, 0x1100, 0x1109, 0x113C, 0x113E, 0x1140, 0x114C, 0x114E, + 0x1150, 0x1159, 0x1163, 0x1165, 0x1167, 0x1169, 0x1175, 0x119E, + 0x11A8, 0x11AB, 0x11BA, 0x11EB, 0x11F0, 0x11F9, 0x1F59, 0x1F5B, + 0x1F5D, 0x1FBE, 0x2126, 0x212E, + // Ideographic + 0x3007, + }; + + // + // [87] CombiningChar ::= ... + // + + int[] combiningCharRange = { + 0x0300, 0x0345, 0x0360, 0x0361, 0x0483, 0x0486, 0x0591, 0x05A1, + 0x05A3, 0x05B9, 0x05BB, 0x05BD, 0x05C1, 0x05C2, 0x064B, 0x0652, + 0x06D6, 0x06DC, 0x06DD, 0x06DF, 0x06E0, 0x06E4, 0x06E7, 0x06E8, + 0x06EA, 0x06ED, 0x0901, 0x0903, 0x093E, 0x094C, 0x0951, 0x0954, + 0x0962, 0x0963, 0x0981, 0x0983, 0x09C0, 0x09C4, 0x09C7, 0x09C8, + 0x09CB, 0x09CD, 0x09E2, 0x09E3, 0x0A40, 0x0A42, 0x0A47, 0x0A48, + 0x0A4B, 0x0A4D, 0x0A70, 0x0A71, 0x0A81, 0x0A83, 0x0ABE, 0x0AC5, + 0x0AC7, 0x0AC9, 0x0ACB, 0x0ACD, 0x0B01, 0x0B03, 0x0B3E, 0x0B43, + 0x0B47, 0x0B48, 0x0B4B, 0x0B4D, 0x0B56, 0x0B57, 0x0B82, 0x0B83, + 0x0BBE, 0x0BC2, 0x0BC6, 0x0BC8, 0x0BCA, 0x0BCD, 0x0C01, 0x0C03, + 0x0C3E, 0x0C44, 0x0C46, 0x0C48, 0x0C4A, 0x0C4D, 0x0C55, 0x0C56, + 0x0C82, 0x0C83, 0x0CBE, 0x0CC4, 0x0CC6, 0x0CC8, 0x0CCA, 0x0CCD, + 0x0CD5, 0x0CD6, 0x0D02, 0x0D03, 0x0D3E, 0x0D43, 0x0D46, 0x0D48, + 0x0D4A, 0x0D4D, 0x0E34, 0x0E3A, 0x0E47, 0x0E4E, 0x0EB4, 0x0EB9, + 0x0EBB, 0x0EBC, 0x0EC8, 0x0ECD, 0x0F18, 0x0F19, 0x0F71, 0x0F84, + 0x0F86, 0x0F8B, 0x0F90, 0x0F95, 0x0F99, 0x0FAD, 0x0FB1, 0x0FB7, + 0x20D0, 0x20DC, 0x302A, 0x302F, + }; + + int[] combiningCharChar = { + 0x05BF, 0x05C4, 0x0670, 0x093C, 0x094D, 0x09BC, 0x09BE, 0x09BF, + 0x09D7, 0x0A02, 0x0A3C, 0x0A3E, 0x0A3F, 0x0ABC, 0x0B3C, 0x0BD7, + 0x0D57, 0x0E31, 0x0EB1, 0x0F35, 0x0F37, 0x0F39, 0x0F3E, 0x0F3F, + 0x0F97, 0x0FB9, 0x20E1, 0x3099, 0x309A, + }; + + // + // [88] Digit ::= ... + // + + int[] digitRange = { + 0x0030, 0x0039, 0x0660, 0x0669, 0x06F0, 0x06F9, 0x0966, 0x096F, + 0x09E6, 0x09EF, 0x0A66, 0x0A6F, 0x0AE6, 0x0AEF, 0x0B66, 0x0B6F, + 0x0BE7, 0x0BEF, 0x0C66, 0x0C6F, 0x0CE6, 0x0CEF, 0x0D66, 0x0D6F, + 0x0E50, 0x0E59, 0x0ED0, 0x0ED9, 0x0F20, 0x0F29, + }; + + // + // [89] Extender ::= ... + // + + int[] extenderRange = { + 0x3031, 0x3035, 0x309D, 0x309E, 0x30FC, 0x30FE, + }; + + int[] extenderChar = { + 0x00B7, 0x02D0, 0x02D1, 0x0387, 0x0640, 0x0E46, 0x0EC6, 0x3005, + }; + + // + // SpecialChar ::= '<', '&', '\n', '\r', ']' + // + + int[] specialChar = { + '<', '&', '\n', '\r', ']', + }; + + // + // Initialize + // + + // set valid characters + for (int i = 0; i < charRange.length; i += 2) { + for (int j = charRange[i]; j <= charRange[i + 1]; j++) { + CHARS[j] |= MASK_VALID | MASK_CONTENT; + } + } + + // remove special characters + for (int i = 0; i < specialChar.length; i++) { + CHARS[specialChar[i]] = (byte) (CHARS[specialChar[i]] & ~MASK_CONTENT); + } + + // set space characters + for (int i = 0; i < spaceChar.length; i++) { + CHARS[spaceChar[i]] |= MASK_SPACE; + } + + // set name start characters + for (int i = 0; i < nameStartChar.length; i++) { + CHARS[nameStartChar[i]] |= MASK_NAME_START | MASK_NAME | + MASK_NCNAME_START | MASK_NCNAME; + } + for (int i = 0; i < letterRange.length; i += 2) { + for (int j = letterRange[i]; j <= letterRange[i + 1]; j++) { + CHARS[j] |= MASK_NAME_START | MASK_NAME | + MASK_NCNAME_START | MASK_NCNAME; + } + } + for (int i = 0; i < letterChar.length; i++) { + CHARS[letterChar[i]] |= MASK_NAME_START | MASK_NAME | + MASK_NCNAME_START | MASK_NCNAME; + } + + // set name characters + for (int i = 0; i < nameChar.length; i++) { + CHARS[nameChar[i]] |= MASK_NAME | MASK_NCNAME; + } + for (int i = 0; i < digitRange.length; i += 2) { + for (int j = digitRange[i]; j <= digitRange[i + 1]; j++) { + CHARS[j] |= MASK_NAME | MASK_NCNAME; + } + } + for (int i = 0; i < combiningCharRange.length; i += 2) { + for (int j = combiningCharRange[i]; j <= combiningCharRange[i + 1]; j++) { + CHARS[j] |= MASK_NAME | MASK_NCNAME; + } + } + for (int i = 0; i < combiningCharChar.length; i++) { + CHARS[combiningCharChar[i]] |= MASK_NAME | MASK_NCNAME; + } + for (int i = 0; i < extenderRange.length; i += 2) { + for (int j = extenderRange[i]; j <= extenderRange[i + 1]; j++) { + CHARS[j] |= MASK_NAME | MASK_NCNAME; + } + } + for (int i = 0; i < extenderChar.length; i++) { + CHARS[extenderChar[i]] |= MASK_NAME | MASK_NCNAME; + } + + // remove ':' from allowable MASK_NCNAME_START and MASK_NCNAME chars + CHARS[':'] &= ~(MASK_NCNAME_START | MASK_NCNAME); + + // set Pubid characters + for (int i = 0; i < pubidChar.length; i++) { + CHARS[pubidChar[i]] |= MASK_PUBID; + } + for (int i = 0; i < pubidRange.length; i += 2) { + for (int j = pubidRange[i]; j <= pubidRange[i + 1]; j++) { + CHARS[j] |= MASK_PUBID; + } + } + + } // () + + // + // Public static methods + // + + /** + * Returns true if the specified character is a supplemental character. + * + * @param c The character to check. + */ + public static boolean isSupplemental(int c) { + return (c >= 0x10000 && c <= 0x10FFFF); + } + + /** + * Returns true the supplemental character corresponding to the given + * surrogates. + * + * @param h The high surrogate. + * @param l The low surrogate. + */ + public static int supplemental(char h, char l) { + return (h - 0xD800) * 0x400 + (l - 0xDC00) + 0x10000; + } + + /** + * Returns the high surrogate of a supplemental character + * + * @param c The supplemental character to "split". + */ + public static char highSurrogate(int c) { + return (char) (((c - 0x00010000) >> 10) + 0xD800); + } + + /** + * Returns the low surrogate of a supplemental character + * + * @param c The supplemental character to "split". + */ + public static char lowSurrogate(int c) { + return (char) (((c - 0x00010000) & 0x3FF) + 0xDC00); + } + + /** + * Returns whether the given character is a high surrogate + * + * @param c The character to check. + */ + public static boolean isHighSurrogate(int c) { + return (0xD800 <= c && c <= 0xDBFF); + } + + /** + * Returns whether the given character is a low surrogate + * + * @param c The character to check. + */ + public static boolean isLowSurrogate(int c) { + return (0xDC00 <= c && c <= 0xDFFF); + } + + + /** + * Returns true if the specified character is valid. This method + * also checks the surrogate character range from 0x10000 to 0x10FFFF. + *

+ * If the program chooses to apply the mask directly to the + * CHARS array, then they are responsible for checking + * the surrogate character range. + * + * @param c The character to check. + */ + public static boolean isValid(int c) { + return (c < 0x10000 && (CHARS[c] & MASK_VALID) != 0) || + (0x10000 <= c && c <= 0x10FFFF); + } // isValid(int):boolean + + /** + * Returns true if the specified character is invalid. + * + * @param c The character to check. + */ + public static boolean isInvalid(int c) { + return !isValid(c); + } // isInvalid(int):boolean + + /** + * Returns true if the specified character can be considered content. + * + * @param c The character to check. + */ + public static boolean isContent(int c) { + return (c < 0x10000 && (CHARS[c] & MASK_CONTENT) != 0) || + (0x10000 <= c && c <= 0x10FFFF); + } // isContent(int):boolean + + /** + * Returns true if the specified character can be considered markup. + * Markup characters include '<', '&', and '%'. + * + * @param c The character to check. + */ + public static boolean isMarkup(int c) { + return c == '<' || c == '&' || c == '%'; + } // isMarkup(int):boolean + + /** + * Returns true if the specified character is a space character + * as defined by production [3] in the XML 1.0 specification. + * + * @param c The character to check. + */ + public static boolean isSpace(int c) { + return c <= 0x20 && (CHARS[c] & MASK_SPACE) != 0; + } // isSpace(int):boolean + + /** + * Returns true if the specified character is a valid name start + * character as defined by production [5] in the XML 1.0 + * specification. + * + * @param c The character to check. + */ + public static boolean isNameStart(int c) { + return c < 0x10000 && (CHARS[c] & MASK_NAME_START) != 0; + } // isNameStart(int):boolean + + /** + * Returns true if the specified character is a valid name + * character as defined by production [4] in the XML 1.0 + * specification. + * + * @param c The character to check. + */ + public static boolean isName(int c) { + return c < 0x10000 && (CHARS[c] & MASK_NAME) != 0; + } // isName(int):boolean + + /** + * Returns true if the specified character is a valid NCName start + * character as defined by production [4] in Namespaces in XML + * recommendation. + * + * @param c The character to check. + */ + public static boolean isNCNameStart(int c) { + return c < 0x10000 && (CHARS[c] & MASK_NCNAME_START) != 0; + } // isNCNameStart(int):boolean + + /** + * Returns true if the specified character is a valid NCName + * character as defined by production [5] in Namespaces in XML + * recommendation. + * + * @param c The character to check. + */ + public static boolean isNCName(int c) { + return c < 0x10000 && (CHARS[c] & MASK_NCNAME) != 0; + } // isNCName(int):boolean + + /** + * Returns true if the specified character is a valid Pubid + * character as defined by production [13] in the XML 1.0 + * specification. + * + * @param c The character to check. + */ + public static boolean isPubid(int c) { + return c < 0x10000 && (CHARS[c] & MASK_PUBID) != 0; + } // isPubid(int):boolean + + /* + * [5] Name ::= (Letter | '_' | ':') (NameChar)* + */ + + /** + * Check to see if a string is a valid Name according to [5] + * in the XML 1.0 Recommendation + * + * @param name string to check + * @return true if name is a valid Name + */ + public static boolean isValidName(String name) { + if (name.length() == 0) + return false; + char ch = name.charAt(0); + if (!isNameStart(ch)) + return false; + for (int i = 1; i < name.length(); i++) { + ch = name.charAt(i); + if (!isName(ch)) { + return false; + } + } + return true; + } // isValidName(String):boolean + + + /* + * from the namespace rec [4] NCName ::= (Letter | '_') (NCNameChar)* + */ + + /** + * Check to see if a string is a valid NCName according to [4] + * from the XML Namespaces 1.0 Recommendation + * + * @param name string to check + * @return true if name is a valid NCName + */ + public static boolean isValidNCName(String ncName) { + if (ncName.length() == 0) + return false; + char ch = ncName.charAt(0); + if (!isNCNameStart(ch)) + return false; + for (int i = 1; i < ncName.length(); i++) { + ch = ncName.charAt(i); + if (!isNCName(ch)) { + return false; + } + } + return true; + } // isValidNCName(String):boolean + + /* + * [7] Nmtoken ::= (NameChar)+ + */ + + /** + * Check to see if a string is a valid Nmtoken according to [7] + * in the XML 1.0 Recommendation + * + * @param nmtoken string to check + * @return true if nmtoken is a valid Nmtoken + */ + public static boolean isValidNmtoken(String nmtoken) { + if (nmtoken.length() == 0) + return false; + for (int i = 0; i < nmtoken.length(); i++) { + char ch = nmtoken.charAt(i); + if (!isName(ch)) { + return false; + } + } + return true; + } // isValidName(String):boolean + + + // encodings + + /** + * Returns true if the encoding name is a valid IANA encoding. + * This method does not verify that there is a decoder available + * for this encoding, only that the characters are valid for an + * IANA encoding name. + * + * @param ianaEncoding The IANA encoding name. + */ + public static boolean isValidIANAEncoding(String ianaEncoding) { + if (ianaEncoding != null) { + int length = ianaEncoding.length(); + if (length > 0) { + char c = ianaEncoding.charAt(0); + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { + for (int i = 1; i < length; i++) { + c = ianaEncoding.charAt(i); + if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && + (c < '0' || c > '9') && c != '.' && c != '_' && + c != '-') { + return false; + } + } + return true; + } + } + } + return false; + } // isValidIANAEncoding(String):boolean + + /** + * Returns true if the encoding name is a valid Java encoding. + * This method does not verify that there is a decoder available + * for this encoding, only that the characters are valid for an + * Java encoding name. + * + * @param javaEncoding The Java encoding name. + */ + public static boolean isValidJavaEncoding(String javaEncoding) { + if (javaEncoding != null) { + int length = javaEncoding.length(); + if (length > 0) { + for (int i = 1; i < length; i++) { + char c = javaEncoding.charAt(i); + if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && + (c < '0' || c > '9') && c != '.' && c != '_' && + c != '-') { + return false; + } + } + return true; + } + } + return false; + } // isValidIANAEncoding(String):boolean + + +} // class XMLChar diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/xml/XMLLocalConstants.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/xml/XMLLocalConstants.java new file mode 100644 index 0000000..c459a71 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/xml/XMLLocalConstants.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils.xml; + +import javax.xml.XMLConstants; + +/** + * Created. There, you have it. + */ +public class XMLLocalConstants { + public static final String EXTERNAL_ENTITIES_PROPERTY = "raml.xml.expandExternalEntities"; + public static final Boolean externalEntities = + Boolean.parseBoolean(System.getProperty(EXTERNAL_ENTITIES_PROPERTY, "false")); + public static final String EXPAND_ENTITIES_PROPERTY = "raml.xml.expandInternalEntities"; + public static final Boolean expandEntities = + Boolean.parseBoolean(System.getProperty(EXPAND_ENTITIES_PROPERTY, "false")); + public static final String EXTERNAL_GENERAL_ENTITIES_FEATURE = "http://xml.org/sax/features/external-general-entities"; + public static final String EXTERNAL_PARAMETER_ENTITIES_FEATURE = "http://xml.org/sax/features/external-parameter-entities"; + public static final String DISALLOW_DOCTYPE_DECL_FEATURE = "http://apache.org/xml/features/disallow-doctype-decl"; + + public static final String XML_SCHEMA_VERSION = System.getProperty("raml.xml.schema.version", XMLConstants.W3C_XML_SCHEMA_NS_URI); + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/xml/XsdResourceResolver.java b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/xml/XsdResourceResolver.java new file mode 100644 index 0000000..af0a756 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/internal/utils/xml/XsdResourceResolver.java @@ -0,0 +1,65 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.internal.utils.xml; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.internal.utils.IOUtils; + +public class XsdResourceResolver implements LSResourceResolver { + + private final String resourcePath; + private final ResourceLoader resourceLoader; + + public XsdResourceResolver(ResourceLoader resourceLoader, String resourcePath) { + this.resourceLoader = resourceLoader; + this.resourcePath = resourcePath; + } + + @Override + public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { + if (systemId == null || systemId.startsWith("http://") || systemId.startsWith("https://") || systemId.startsWith("file:")) { + // delegate resource resolution to xml parser + return null; + } + + if (Paths.get(systemId).normalize().isAbsolute()) { + + return null; + } + + InputStream inputStream = resourceLoader.fetchResource(systemId); + if (inputStream == null) { + // delegate resource resolution to xml parser + return null; + } + + + byte[] content; + try { + content = IOUtils.toByteArray(inputStream); + } catch (IOException e) { + throw new RuntimeException(e); + } + return new LSInputImpl(publicId, systemId, baseURI, new ByteArrayInputStream(content), StandardCharsets.UTF_8); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/BaseGrammar.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/BaseGrammar.java new file mode 100644 index 0000000..ed9fb9a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/BaseGrammar.java @@ -0,0 +1,459 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.regex.Pattern; +import org.xbib.raml.yagi.framework.grammar.rule.AllOfRule; +import org.xbib.raml.yagi.framework.grammar.rule.AnyOfRule; +import org.xbib.raml.yagi.framework.grammar.rule.AnyValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.ArrayRule; +import org.xbib.raml.yagi.framework.grammar.rule.BooleanTypeRule; +import org.xbib.raml.yagi.framework.grammar.rule.ChildBasedConditionalRule; +import org.xbib.raml.yagi.framework.grammar.rule.ConditionalRule; +import org.xbib.raml.yagi.framework.grammar.rule.ConditionalRules; +import org.xbib.raml.yagi.framework.grammar.rule.DefaultValue; +import org.xbib.raml.yagi.framework.grammar.rule.ExclusiveKeys; +import org.xbib.raml.yagi.framework.grammar.rule.FieldPresentRule; +import org.xbib.raml.yagi.framework.grammar.rule.FirstOfRule; +import org.xbib.raml.yagi.framework.grammar.rule.IntegerTypeRule; +import org.xbib.raml.yagi.framework.grammar.rule.IntegerValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.KeyValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.MinLengthRule; +import org.xbib.raml.yagi.framework.grammar.rule.NegativeRule; +import org.xbib.raml.yagi.framework.grammar.rule.NullValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.NumberTypeRule; +import org.xbib.raml.yagi.framework.grammar.rule.ObjectRule; +import org.xbib.raml.yagi.framework.grammar.rule.ParentKeyDefaultValue; +import org.xbib.raml.yagi.framework.grammar.rule.RangeValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.RegexValueRule; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.grammar.rule.ScalarTypeRule; +import org.xbib.raml.yagi.framework.grammar.rule.StringTypeRule; +import org.xbib.raml.yagi.framework.grammar.rule.StringValueRule; +import static java.util.Collections.singletonList; + +/** + * Base class for rule based grammars. + */ +public class BaseGrammar { + + private GrammarContext context; + + private String nextRuleName; + + public BaseGrammar() { + this.context = new GrammarContext(); + } + + /** + * Matches an object type + * + * @return The object rule + */ + public ObjectRule objectType() { + return register(new ObjectRule()); + } + + /** + * Register the rule in the context if a named for this rule was set. + * + * @param rule The rule to register + * @param The rule type + * @return The specified rule + */ + private T register(T rule) { + if (nextRuleName != null) { + context.registerRule(nextRuleName, rule); + nextRuleName = null; + } + return rule; + } + + /** + * Registers a rule with the specified name. If the rule is already defined then it returns it otherwise it will invoke the rule factory to create. + * + * @param name The name of the rule + * @param ruleFactory The factory of the rule + * @param The node type + * @return The rule + */ + public T named(String name, RuleFactory ruleFactory) { + if (context.hasRule(name)) { + return (T) context.getRuleByName(name); + } else { + this.nextRuleName = name; + return ruleFactory.create(); + } + } + + + /** + * Returns rule created by the callable that runs a new separate context. + * + * @param callable The callable to execute in a new context + * @param The type of rule it returns + * @return The rule + */ + public T inNewContext(Callable callable) { + final GrammarContext oldContext = this.context; + this.context = new GrammarContext(); + final T result; + try { + result = callable.call(); + } catch (Exception e) { + throw new RuntimeException(e); + } + this.context = oldContext; + return result; + } + + + /** + * Delegates to a rule if the specified condition matches the first child. + * + * @param condition The condition + * @param then the rule to be delegated + */ + public ChildBasedConditionalRule whenChildIs(Rule condition, Rule then) { + return new ChildBasedConditionalRule(condition, then); + } + + /** + * Delegates to a rule if a selector expression returns a value + * + * @param selector The selector expression + * @param then The rule to be delegated if the selector returns a value + */ + public FieldPresentRule whenPresent(String selector, Rule then) { + return new FieldPresentRule(selector, then); + } + + /** + * Matches any value + * + * @return Any value rule + */ + public AnyValueRule any() { + return new AnyValueRule(); + } + + /** + * Matches an array value + * + * @param of The type of the array + * @return The array rule + */ + public ArrayRule array(Rule of) { + return new ArrayRule(of); + } + + /** + * Matches a number that is Integer + * + * @return The rule + */ + public IntegerTypeRule integerType() { + return new IntegerTypeRule(); + } + + /** + * Matches an integer greater than zero + * + * @return The rule + */ + public IntegerTypeRule positiveIntegerType(Long minValue, Long maxValue) { + return new IntegerTypeRule(minValue, maxValue); + } + + /** + * Matches any type of number + * + * @return The rule + */ + public Rule numberType() { + return new NumberTypeRule(); + } + + /** + * Matches any number greater than zero + * + * @return The rule + */ + public Rule positiveNumberType() { + return new NumberTypeRule(0D, Double.MAX_VALUE); + } + + /** + * Matches a number that is Integer and is included in the range + * + * @return The rule + */ + public RangeValueRule range(Integer min, Integer max) { + return new RangeValueRule(min, max); + } + + /** + * Matches a number that is Integer and its value it the specified + * + * @param value The value to match + * @return The rule + */ + public IntegerValueRule integer(Integer value) { + return new IntegerValueRule(new BigInteger(value.toString())); + } + + /** + * Matches a field that the key matches the key rule and the value the value rule + * + * @param keyRule The key rule + * @param valueRule The value rule + * @return The rule + */ + public KeyValueRule field(Rule keyRule, Rule valueRule) { + return new KeyValueRule(keyRule, optional(valueRule)); + } + + /** + * Matches a field that the key is of string type and matches the specified key name and the value matches the value rule or null value + * + * @param keyName The key name + * @param valueRule The value rule + * @return The rule + */ + public KeyValueRule field(String keyName, Rule valueRule) { + return new KeyValueRule(string(keyName), optional(valueRule)); + } + + /** + * Matches a field that the key is of string type and matches the specified key name and the value matches the value rule. + * The difference with it that Null is not matched for the value. + * + * @param keyRule The key rule + * @param valueRule The value rule + * @return The rule + */ + public KeyValueRule fieldWithRequiredValue(Rule keyRule, Rule valueRule) { + return new KeyValueRule(keyRule, valueRule); + } + + /** + * Matches a field that the key is of string type and matches the specified key name and the value matches the value rule. + * The difference with it that Null is not matched for the value and also mark this field as required in the object rule. + * + * @param keyRule The key rule + * @param valueRule The value rule + * @return The rule + */ + public KeyValueRule requiredField(Rule keyRule, Rule valueRule) { + return new KeyValueRule(keyRule, valueRule).required(); + } + + /** + * Matches any scalar value e.g Number String boolean etc + * + * @return The rule + */ + public Rule scalarType() { + return new ScalarTypeRule(); + } + + /** + * Matches any String type value + * + * @return The rule + */ + public StringTypeRule stringType() { + return new StringTypeRule(); + } + + /** + * Matches any Boolean type value + * + * @return The rule + */ + public BooleanTypeRule booleanType() { + return new BooleanTypeRule(); + } + + /** + * Matches any value of type string with the specified value + * + * @param value The value to match + * @return The rule + */ + public StringValueRule string(String value) { + return new StringValueRule(value); + } + + /** + * Matches any value that is accepted by the regex pattern + * + * @param pattern The pattern + * @return The rule + */ + public RegexValueRule regex(String pattern) { + return new RegexValueRule(Pattern.compile(pattern)); + } + + /** + * Matches any value that is accepted by the regex pattern + * + * @param pattern The pattern + * @return The rule + */ + public RegexValueRule regex(Pattern pattern) { + return new RegexValueRule(pattern); + } + + /** + * Matches if any rule matches and suggests all the possibilities. + * + * @param rules The option rules + * @return The rule + */ + public AnyOfRule anyOf(Rule... rules) { + return new AnyOfRule(Arrays.asList(rules)); + } + + /** + * Matches if any rule matches and suggests all the possibilities. + * + * @param rules The option rules + * @return The rule + */ + public AnyOfRule anyOf(List rules) { + return new AnyOfRule(rules); + } + + /** + * Accepts if any rule matches and delegates the suggestion to the first one that matches. + * + * @param rules The rules + */ + public AnyOfRule firstOf(Rule... rules) { + return new FirstOfRule(Arrays.asList(rules)); + } + + /** + * Matches if the specified rule does not match + * + * @param rule The rule to be negated + * @return The rule + */ + public NegativeRule not(Rule rule) { + return new NegativeRule(rule); + } + + /** + * Matches if all the specified rules matches + * + * @param rules All the rules to match + * @return The rule + */ + public AllOfRule allOf(Rule... rules) { + return new AllOfRule(Arrays.asList(rules)); + } + + /** + * Matches if the rule matches or the value is null + * + * @param rule The rule to match + * @return The rule + */ + public AnyOfRule optional(Rule rule) { + return anyOf(rule, nullValue()); + } + + /** + * Matches a string that its length is bigger or equals to the specified + * + * @param length The length + * @return The rule + */ + public MinLengthRule minLength(int length) { + return new MinLengthRule(length); + } + + + /** + * Matches a null value. + * + * @return The rule + */ + protected NullValueRule nullValue() { + return new NullValueRule(); + } + + /** + * It will dispatch the to the conditional rule that matches the selected value. Similar to a pattern matching scenario + * + * @param expr The expression to select + * @param cases The conditional cases + * @return The rule + */ + public ConditionalRules when(String expr, ConditionalRule... cases) { + return new ConditionalRules(singletonList(expr), cases); + } + + /** + * It will dispatch the to the conditional rule that matches the selected value. Similar to a pattern matching scenario + * + * @param expr The list of expressions to try the first that is not null will be used + * @param cases The conditional cases + * @return The rule + */ + public ConditionalRules when(List expr, ConditionalRule... cases) { + return new ConditionalRules(expr, cases); + } + + /** + * Conditional rule that will accept if the rule matches + * + * @param rule The rule to be used as matching + * @return The rule + */ + public ConditionalRule is(Rule rule) { + return new ConditionalRule(rule); + } + + /** + * Returns a default value that is the parent key + * + * @return The default value + */ + public DefaultValue parentKey() { + return new ParentKeyDefaultValue(); + } + + /** + * Creates a new set of exclusive rules + * + * @param keys Each of the mutually exclusive rules + * @return The rule + */ + public ExclusiveKeys exclusiveKeys(String... keys) { + List rules = new ArrayList<>(); + for (String key : keys) { + rules.add(string(key)); + } + return new ExclusiveKeys(rules); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/ExclusiveSiblingRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/ExclusiveSiblingRule.java new file mode 100644 index 0000000..aa9ad28 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/ExclusiveSiblingRule.java @@ -0,0 +1,90 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class ExclusiveSiblingRule extends Rule { + + + private final String value; + private final Set notAllowedSiblings; + + public ExclusiveSiblingRule(String value, Set notAllowedSiblings) { + this.value = value; + this.notAllowedSiblings = notAllowedSiblings; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return new ArrayList<>(); + } + + + @Override + public boolean matches(Node node) { + return node instanceof StringNode && ((StringNode) node).getValue().equals(value); + } + + + @Override + public Node apply(Node node) { + if (!(node instanceof StringNode)) { + return ErrorNodeFactory.createInvalidType(node, NodeType.String); + } + if (!matches(node)) { + return ErrorNodeFactory.createInvalidValue(node, value); + } + if (matchesSiblings(node)) { + return ErrorNodeFactory.createInvalidSiblingsValue(node, notAllowedSiblings); + } + return createNodeUsingFactory(node, ((StringNode) node).getValue()); + } + + private boolean matchesSiblings(Node node) { + if (node.getParent() == null || node.getParent().getParent() == null) { + return false; + } + Node grandParent = node.getParent().getParent(); + for (String sibling : notAllowedSiblings) { + if (grandParent.get(sibling) != null) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return value; + } + + @Override + public String getDescription() { + return "\"" + value + "\""; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/GrammarContext.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/GrammarContext.java new file mode 100644 index 0000000..b178edc --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/GrammarContext.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar; + +import java.util.HashMap; +import java.util.Map; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; + +public class GrammarContext { + + private final Map ruleMap; + + public GrammarContext() { + this.ruleMap = new HashMap<>(); + } + + public T registerRule(String name, T rule) { + this.ruleMap.put(name, rule); + return rule; + } + + + public Rule getRuleByName(String name) { + return ruleMap.get(name); + } + + public boolean hasRule(String name) { + return ruleMap.containsKey(name); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/RuleFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/RuleFactory.java new file mode 100644 index 0000000..d0b055e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/RuleFactory.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar; + +import org.xbib.raml.yagi.framework.grammar.rule.Rule; + +public interface RuleFactory { + T create(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/RuleTraverser.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/RuleTraverser.java new file mode 100644 index 0000000..26a3dab --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/RuleTraverser.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Function; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; + +public class RuleTraverser { + + private final Set visitedRules = new HashSet<>(); + + public T traverse(T rule, Function callable) { + visitedRules.add(rule); + final Boolean apply = callable.apply(rule); + if (apply != null && apply) { + for (Rule child : rule.getChildren()) { + if (!visitedRules.contains(child)) { + traverse(child, callable); + } + } + } + + return rule; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AbstractTypeRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AbstractTypeRule.java new file mode 100644 index 0000000..0be6536 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AbstractTypeRule.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +public abstract class AbstractTypeRule extends Rule { + + + @Override + public Node apply(Node node) { + if (matches(node)) { + if (node instanceof SimpleTypeNode) { + return createNodeUsingFactory(node, ((SimpleTypeNode) node).getValue()); + } else { + return createNodeUsingFactory(node); + } + } else { + return ErrorNodeFactory.createInvalidType(node, getType()); + } + } + + + abstract NodeType getType(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AllOfRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AllOfRule.java new file mode 100644 index 0000000..be0a57d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AllOfRule.java @@ -0,0 +1,128 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; +import static org.xbib.raml.yagi.framework.util.NodeUtils.isErrorResult; + +public class AllOfRule extends Rule { + + private final List rules; + + public AllOfRule(Rule... rules) { + this(Arrays.asList(rules)); + } + + public AllOfRule(List rules) { + this.rules = new ArrayList<>(rules); + } + + @Override + + public List getSuggestions(Node node, ParsingContext context) { + final List result = new ArrayList<>(); + for (Rule rule : rules) { + result.addAll(rule.getSuggestions(node, context)); + } + return result; + } + + public AllOfRule and(Rule rule) { + this.rules.add(rule); + return this; + } + + + public Rule getMatchingRule(Node node) { + if (this.matches(node)) { + return this; + } + return null; + } + + @Override + public List getChildren() { + return rules; + } + + @Override + public boolean matches(Node node) { + for (Rule rule : rules) { + if (!rule.matches(node)) { + return false; + } + } + return true; + } + + @Override + public Node apply(Node node) { + for (Rule rule : rules) { + if (!rule.matches(node)) { + return rule.apply(node); + } + } + + for (Rule rule : rules) { + node = rule.apply(node); + if (isErrorResult(node)) + return node; + } + return createNodeUsingFactory(node); + } + + @Override + public String getDescription() { + final StringBuilder desc = new StringBuilder(); + desc.append("All of :"); + int i = 0; + for (Rule rule : rules) { + if (i > 0) { + desc.append(","); + } + desc.append(rule.getDescription()); + i++; + } + return desc.toString(); + } + + @Override + public List getSuggestions(List pathToRoot, ParsingContext context) { + if (!pathToRoot.isEmpty()) { + final Node peek = pathToRoot.get(0); + final Rule innerRule = getMatchingRule(peek); + if (innerRule != null) { + final List suggestions = innerRule.getSuggestions(pathToRoot.subList(1, pathToRoot.size()), context); + if (suggestions.isEmpty()) { + return getSuggestions(peek, context); + } else { + return suggestions; + } + } else { + return getSuggestions(peek, context); + } + + } else { + return Collections.emptyList(); + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AlwaysRequiredField.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AlwaysRequiredField.java new file mode 100644 index 0000000..3337529 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AlwaysRequiredField.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + + +import org.xbib.raml.yagi.framework.nodes.Node; + +public class AlwaysRequiredField implements RequiredField { + + private static final AlwaysRequiredField instance = new AlwaysRequiredField(); + + private AlwaysRequiredField() { + } + + @Override + public boolean isRequiredField(Node parent) { + return true; + } + + public static RequiredField getInstance() { + return instance; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AnyOfRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AnyOfRule.java new file mode 100644 index 0000000..d256afa --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AnyOfRule.java @@ -0,0 +1,138 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +/** + * Accepts if any rule matches and suggests all the possibilities. + */ +public class AnyOfRule extends Rule { + + protected List rules; + + + public AnyOfRule(List rules) { + this.rules = new ArrayList<>(rules); + } + + public AnyOfRule(Rule... rules) { + this(Arrays.asList(rules)); + } + + public List getRules() { + return rules; + } + + @Override + + public List getSuggestions(Node node, ParsingContext context) { + final List result = new ArrayList<>(); + for (Rule rule : rules) { + result.addAll(rule.getSuggestions(node, context)); + } + return result; + } + + public AnyOfRule add(Rule rule) { + this.rules.add(rule); + return this; + } + + + public Rule getMatchingRule(Node node) { + for (Rule rule : rules) { + if (rule.matches(node)) { + return rule; + } + } + return null; + } + + @Override + public List getChildren() { + return rules; + } + + @Override + public boolean matches(Node node) { + for (Rule rule : rules) { + if (rule.matches(node)) { + return true; + } + } + return false; + } + + @Override + public Node apply(Node node) { + for (Rule rule : rules) { + if (rule.matches(node)) { + final Node appliedNode = rule.apply(node); + return createNodeUsingFactory(appliedNode); + } + } + + return ErrorNodeFactory.createInvalidNode(node); + } + + @Override + public String getDescription() { + final StringBuilder desc = new StringBuilder(); + desc.append("Any of :"); + int i = 0; + for (Rule rule : rules) { + if (i > 0) { + desc.append(","); + } + desc.append(rule.getDescription()); + i++; + } + return desc.toString(); + } + + @Override + public List getSuggestions(List pathToRoot, ParsingContext context) { + if (!pathToRoot.isEmpty()) { + final Node peek = pathToRoot.get(0); + final Rule innerRule = getMatchingRule(peek); + if (innerRule != null) { + final List suggestions = innerRule.getSuggestions(pathToRoot, context); + if (suggestions.isEmpty()) { + return getSuggestions(peek, context); + } else { + return suggestions; + } + } else { + return getSuggestions(peek, context); + } + + } else { + return Collections.emptyList(); + } + } + + public AnyOfRule addAll(List rules) { + this.rules.addAll(rules); + return this; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AnyValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AnyValueRule.java new file mode 100644 index 0000000..e4f1e37 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/AnyValueRule.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class AnyValueRule extends Rule { + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + + @Override + public boolean matches(Node node) { + return true; + } + + @Override + public Node apply(Node node) { + return createNodeUsingFactory(node); + } + + @Override + public String getDescription() { + return "any"; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ArrayRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ArrayRule.java new file mode 100644 index 0000000..2dfbf28 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ArrayRule.java @@ -0,0 +1,129 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.NullNodeImpl; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.ParsingContextType; +import org.xbib.raml.yagi.framework.suggester.Suggestion; +import org.xbib.raml.yagi.framework.util.NodeUtils; + +public class ArrayRule extends Rule { + + private Rule of; + private boolean strict = false; + + public ArrayRule(Rule of) { + this.of = of; + } + + public ArrayRule(Rule of, boolean strict) { + this.of = of; + this.strict = strict; + } + + public Rule of() { + return of; + } + + public void of(Rule of) { + this.of = of; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + // Array does not have any children then we need to create a dummy one and inject into the tree + final NullNodeImpl nullNode = new NullNodeImpl(); + node.addChild(nullNode); + final List suggestions = of.getSuggestions(nullNode, context); + final List result = new ArrayList<>(); + for (Suggestion suggestion : suggestions) { + if (node instanceof ArrayNode && !((ArrayNode) node).isJsonStyle()) { + result.add(suggestion); + } else if (context.getContextType() == ParsingContextType.VALUE) { + final String prefix = "\n" + NodeUtils.computeColumnForChild(node.getParent()); + result.add(suggestion.withValue("- " + suggestion.getValue()).withPrefix(prefix)); + } else { + result.add(suggestion.withValue("- " + suggestion.getValue())); + } + } + return result; + } + + @Override + public List getSuggestions(List pathToRoot, ParsingContext context) { + if (pathToRoot.isEmpty()) { + return Collections.emptyList(); + } else { + final Node mappingNode = pathToRoot.get(0); + if (pathToRoot.size() == 1) { + return getSuggestions(mappingNode, context); + } + return of.getSuggestions(pathToRoot.subList(1, pathToRoot.size()), context); + } + } + + + @Override + public List getChildren() { + return Collections.singletonList(of); + } + + @Override + public boolean matches(Node node) { + boolean matches = node instanceof ArrayNode; + if (matches && strict) { + for (Node child : node.getChildren()) { + if (!of.matches(child)) { + return false; + } + } + } + return matches; + } + + @Override + public Node apply(Node node) { + if (!matches(node)) { + return ErrorNodeFactory.createInvalidType(node, NodeType.Array); + } else { + Node result = createNodeUsingFactory(node); + final List children = node.getChildren(); + for (Node child : children) { + if (of.matches(child)) { + final Node transform = of.apply(child); + child.replaceWith(transform); + } else { + child.replaceWith(ErrorNodeFactory.createInvalidArrayElement(child)); + } + } + return result; + } + } + + @Override + public String getDescription() { + return "Array[" + of.getDescription() + "]"; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ArrayWrapperFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ArrayWrapperFactory.java new file mode 100644 index 0000000..081bfe5 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ArrayWrapperFactory.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + + +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class ArrayWrapperFactory implements NodeFactory { + @Override + public Node create(Node matchNode, Object... args) { + if (matchNode instanceof ArrayNode) { + return matchNode; + } + return new ArrayWrapperNode(matchNode.copy()); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ArrayWrapperNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ArrayWrapperNode.java new file mode 100644 index 0000000..2a2dde6 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ArrayWrapperNode.java @@ -0,0 +1,98 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.BaseNode; +import org.xbib.raml.yagi.framework.nodes.DefaultPosition; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.Position; + +public class ArrayWrapperNode extends BaseNode implements ArrayNode { + + private Node wrapped; + + public ArrayWrapperNode(Node child) { + this.wrapped = child; + this.wrapped.setParent(this); + } + + + @Override + public boolean isJsonStyle() { + return false; + } + + @Override + public void addChild(Node node) { + // This is a wrapper so we add the child nodes to the wrapper valued + wrapped.addChild(node); + } + + @Override + public void setChild(int idx, Node newNode) { + if (newNode instanceof ErrorNode) { + wrapped = newNode; + } else { + wrapped.setChild(idx, newNode); + } + } + + @Override + public void addChild(int idx, Node newNode) { + // This is a wrapper so we add the child nodes to the wrapper valued + wrapped.addChild(idx, newNode); + } + + @Override + public void removeChild(Node node) { + // This is a wrapper so we add the child nodes to the wrapper valued + wrapped.removeChild(node); + } + + + @Override + public List getChildren() { + return Collections.singletonList(wrapped); + } + + + @Override + public Position getStartPosition() { + return DefaultPosition.emptyPosition(); + } + + + @Override + public Position getEndPosition() { + return DefaultPosition.emptyPosition(); + } + + + @Override + public Node copy() { + return new ArrayWrapperNode(wrapped); + } + + @Override + public NodeType getType() { + return NodeType.Array; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/BooleanTypeRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/BooleanTypeRule.java new file mode 100644 index 0000000..88260af --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/BooleanTypeRule.java @@ -0,0 +1,70 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Arrays; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.BooleanNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.DefaultSuggestion; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class BooleanTypeRule extends AbstractTypeRule { + public static final String STRICT_BOOLEANS = "org.raml.strict_booleans"; + + private final static String TRUE = "true"; + private final static String FALSE = "false"; + + private final boolean strictBoolean; + + public BooleanTypeRule() { + this.strictBoolean = Boolean.parseBoolean(System.getProperty(STRICT_BOOLEANS, "false")); + } + + BooleanTypeRule(boolean strictBoolean) { + this.strictBoolean = strictBoolean; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Arrays.asList(new DefaultSuggestion("true", "Boolean true", "true"), new DefaultSuggestion("false", "Boolean false", "false")); + } + + @Override + public boolean matches(Node node) { + if (!strictBoolean && (node instanceof StringNode)) { + String value = ((StringNode) node).getValue(); + return TRUE.equals(value) || FALSE.equals(value); + } + return node instanceof BooleanNode; + } + + + @Override + public String getDescription() { + return "Boolean"; + } + + + @Override + NodeType getType() { + return NodeType.Boolean; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ChildBasedConditionalRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ChildBasedConditionalRule.java new file mode 100644 index 0000000..acfdfda --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ChildBasedConditionalRule.java @@ -0,0 +1,74 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +/** + * Delegates to a rule if the specified condition matches the first child. + */ +public class ChildBasedConditionalRule extends Rule { + + private final Rule discriminator; + private final Rule delegate; + + public ChildBasedConditionalRule(Rule condition, Rule delegate) { + this.discriminator = condition; + this.delegate = delegate; + } + + @Override + public List getSuggestions(List pathToRoot, ParsingContext context) { + if (discriminator.matches(pathToRoot.get(0))) { + return delegate.getSuggestions(pathToRoot, context); + } else { + return Collections.emptyList(); + } + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return delegate.getSuggestions(node, context); + } + + @Override + public List getChildren() { + return Collections.singletonList(delegate); + } + + @Override + public boolean matches(Node node) { + List children = node.getChildren(); + boolean matches = delegate.matches(node); + return matches && (children.isEmpty() || discriminator.matches(children.get(0))); + } + + @Override + public Node apply(Node node) { + return delegate.apply(node); + } + + @Override + public String getDescription() { + return delegate.getDescription(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ClassNodeFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ClassNodeFactory.java new file mode 100644 index 0000000..0df0953 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ClassNodeFactory.java @@ -0,0 +1,53 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class ClassNodeFactory implements NodeFactory { + + private final Class clazz; + + public ClassNodeFactory(Class clazz) { + this.clazz = clazz; + } + + @Override + public Node create(Node currentNode, Object... args) { + try { + if (args != null) { + Class[] types = new Class[args.length]; + for (int i = 0; i < args.length; i++) { + Object arg = args[i]; + types[i] = arg.getClass(); + } + try { + final Constructor constructor = clazz.getConstructor(types); + return clazz.cast(constructor.newInstance(args)); + } catch (NoSuchMethodException ignored) { + // If no constructor with the arguments try default constructor + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + return clazz.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ConditionalRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ConditionalRule.java new file mode 100644 index 0000000..4fce4ec --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ConditionalRule.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class ConditionalRule { + private final Rule condition; + private final List rules; + + public ConditionalRule(Rule condition) { + this.condition = condition; + this.rules = new ArrayList<>(); + } + + public boolean matches(Node node) { + return condition.matches(node); + } + + public ConditionalRule add(KeyValueRule rule) { + rules.add(rule); + return this; + } + + + public List getRules() { + return rules; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ConditionalRules.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ConditionalRules.java new file mode 100644 index 0000000..f3b738c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ConditionalRules.java @@ -0,0 +1,95 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class ConditionalRules { + + private final List selectorExpression; + private final List options; + private DefaultValue defaultValue; + + /** + * Creates a rule that depends on another rule on your grammar + * + * @param selectorExpression expression to obtain the node that will be used for the pattern matching + * @param cases Conditional cases + */ + public ConditionalRules(List selectorExpression, ConditionalRule... cases) { + this.selectorExpression = selectorExpression; + this.options = Arrays.asList(cases); + } + + + public List getRulesNode(Node node) { + Node from = selectValue(node); + if (from == null && defaultValue != null) { + from = defaultValue.getDefaultValue(node); + } + + if (from != null) { + for (ConditionalRule option : options) { + if (option.matches(from)) { + return option.getRules(); + } + } + } + + return Collections.emptyList(); + } + + public List getChildren() { + final ArrayList result = new ArrayList<>(); + for (ConditionalRule option : options) { + result.addAll(new ArrayList<>(option.getRules())); + } + return result; + } + + + private Node selectValue(Node node) { + + for (String expr : selectorExpression) { + Node from = NodeSelector.selectFrom(expr, node); + if (from != null) { + return from; + } + } + return null; + } + + public ConditionalRules defaultValue(DefaultValue defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + /** + * This method lets you use a value node to match the when clause when there is no other rule that matches. + * + * @param defaultValue value node. + */ + public ConditionalRules defaultValue(Node defaultValue) { + this.defaultValue = new LiteralDefaultValue(defaultValue); + return this; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/DateValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/DateValueRule.java new file mode 100644 index 0000000..2d568db --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/DateValueRule.java @@ -0,0 +1,72 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; +import org.xbib.raml.yagi.framework.util.DateType; +import org.xbib.raml.yagi.framework.util.DateUtils; + +public class DateValueRule extends Rule { + + private final DateType dateType; + private String rfc = "rfc3339"; + private final DateUtils dateUtils = DateUtils.createFromProperties(); + + public DateValueRule(DateType dateType, String rfc) { + this.dateType = dateType; + if (rfc != null) { + this.rfc = rfc; + } + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + @Override + public boolean matches(Node node) { + return node instanceof StringNode && dateUtils.isValidDate(((StringNode) node).getValue(), this.dateType, this.rfc); + } + + @Override + public Node apply(Node node) { + if (matches(node)) { + if (dateUtils.isValidDate(((StringNode) node).getValue(), this.dateType, this.rfc)) { + return node; + } else { + return ErrorNodeFactory.createInvalidDateValue((StringNode) node, this.dateType.name(), this.rfc); + } + } else { + if (node instanceof StringNode) { + return ErrorNodeFactory.createInvalidDateValue((StringNode) node, this.dateType.name(), this.rfc); + } + return ErrorNodeFactory.createInvalidNode(node); + } + } + + @Override + public String getDescription() { + return "Multiple of value"; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/DefaultValue.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/DefaultValue.java new file mode 100644 index 0000000..066c253 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/DefaultValue.java @@ -0,0 +1,33 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import org.xbib.raml.yagi.framework.nodes.Node; + +/** + * Generates a default value when needed. + */ +public interface DefaultValue { + + /** + * Generates a default value node based on the parent context. + * + * @param parent The parent node of the default value. + * @return The default value node or null when it cannot be generated in a fragment file + */ + + Node getDefaultValue(Node parent); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/DivisorValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/DivisorValueRule.java new file mode 100644 index 0000000..920692a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/DivisorValueRule.java @@ -0,0 +1,97 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.FloatingNode; +import org.xbib.raml.yagi.framework.nodes.IntegerNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; +import static java.math.BigDecimal.ZERO; + +public class DivisorValueRule extends Rule { + + private final boolean castStringsAsNumbers; + private final Number divisorValue; + + public DivisorValueRule(Number divisorValue) { + this.divisorValue = divisorValue; + this.castStringsAsNumbers = false; + } + + public DivisorValueRule(Number multiple, boolean castStringsAsNumbers) { + + this.divisorValue = multiple; + this.castStringsAsNumbers = castStringsAsNumbers; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + @Override + public boolean matches(Node node) { + final BigDecimal divisor = new BigDecimal(divisorValue.toString()); + BigDecimal value = null; + if (node instanceof StringNode && castStringsAsNumbers) { + String intString = ((StringNode) node).getValue(); + try { + value = new BigDecimal(intString); + } catch (NumberFormatException e) { + return false; + } + } + if (node instanceof IntegerNode) { + value = new BigDecimal(((IntegerNode) node).getValue()); + } else if (node instanceof FloatingNode) { + value = ((FloatingNode) node).getValue(); + } + + if (value != null) { + if (divisor.compareTo(ZERO) == 0 && value.compareTo(ZERO) == 0) { + return true; + } + return !(divisor.compareTo(ZERO) == 0) && (value.remainder(divisor).compareTo(ZERO) == 0); + } + + return false; + } + + @Override + public Node apply(Node node) { + if (matches(node)) { + return createNodeUsingFactory(node, ((SimpleTypeNode) node).getValue()); + } else { + if ((node instanceof IntegerNode && divisorValue.intValue() == 0) || + node instanceof FloatingNode && divisorValue.floatValue() == 0f) { + return ErrorNodeFactory.createInvalidDivisorValue(); + } + return ErrorNodeFactory.createInvalidMultipleOfValue(divisorValue); + } + } + + @Override + public String getDescription() { + return "Multiple of value"; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ErrorNodeFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ErrorNodeFactory.java new file mode 100644 index 0000000..4990cfe --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ErrorNodeFactory.java @@ -0,0 +1,232 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.io.IOException; +import java.util.Collection; +import java.util.Set; +import org.xbib.raml.yagi.framework.nodes.EmptyErrorNode; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.nodes.snakeyaml.LimitsException; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public class ErrorNodeFactory { + + public static ErrorNode createCanNotInheritFromDifferentBaseTypes(String... baseTypes) { + return new ErrorNode("Can not inherit from different base types '" + String.join(" , ", baseTypes)); + } + + public static ErrorNode createUnexpectedKey(Node key, Collection options) { + return new ErrorNode("Unexpected key '" + key + "'. Options are : " + String.join(" or ", options)); + } + + public static ErrorNode createInvalidArrayElement(Node child) { + return new ErrorNode("Invalid array element " + child + "."); + } + + public static ErrorNode createInvalidNode(Node child) { + return new ErrorNode("Invalid element " + child + getKeyFieldMessage(child) + "."); + } + + public static ErrorNode createInvalidRootElement(Node rootNode, String expected) { + return new ErrorNode("Invalid root node " + rootNode + ". Expected : " + expected + "."); + } + + public static ErrorNode createInvalidTemplateFunctionExpression(Node node, String token) { + return new ErrorNode("Invalid template function expression " + token); + } + + public static ErrorNode createInvalidTemplateParameterExpression(Node node, String token) { + return new ErrorNode("Cannot resolve parameter " + token); + } + + public static Node createRequiredValueNotFound(Node node, Rule keyRule) { + final ErrorNode errorNode = new ErrorNode("Missing required field " + keyRule.getDescription()); + errorNode.setSource(node); + return errorNode; + } + + public static Node createInvalidType(Node node, NodeType type) { + return new ErrorNode("Invalid type " + node.getType() + ", expected " + type + getFieldMessageIfPresent(node)); + } + + private static String getFieldMessageIfPresent(Node node) { + return node.getParent() != null ? " for " + node.getParent().getChildren().get(0).toString() : ""; + } + + private static String getKeyFieldMessage(Node node) { + return node.getParent() != null && (node.getParent() instanceof KeyValueNode) ? " for " + ((KeyValueNode) node.getParent()).getKey().toString() : ""; + } + + public static Node createInvalidFragmentName(String fragmentText) { + return new ErrorNode("Invalid fragment name '" + fragmentText + "'"); + } + + public static EmptyErrorNode createEmptyDocument() { + return new EmptyErrorNode(); + } + + public static Node createUnsupportedVersion(String version) { + return new ErrorNode("Unsupported version " + version); + } + + public static Node createInvalidHeader(String header) { + return new ErrorNode("Invalid header declaration " + header); + } + + public static Node createInvalidInput(IOException ioe) { + return new ErrorNode("Error while reading the input. Reason " + ioe.getMessage()); + } + + public static Node createInvalidMaxLength(int maxLength, Node node) { + return createInvalidLength(maxLength, node, "max"); + } + + public static Node createInvalidMaxItems(int maxItems) { + return new ErrorNode("Expected max items " + maxItems); + } + + public static Node createInvalidMinItems(int minItems) { + return new ErrorNode("Expected min items " + minItems); + } + + public static Node createInvalidMaxProperties(int maxProperties) { + return new ErrorNode("Expected max properties " + maxProperties); + } + + public static Node createInvalidMinProperties(int minProperties) { + return new ErrorNode("Expected min properties " + minProperties); + } + + public static Node createInvalidMinLength(int minLength, Node node) { + return createInvalidLength(minLength, node, "min"); + } + + private static Node createInvalidLength(int length, Node node, String minOrMax) { + if (node.getParent() == null) + return new ErrorNode("Expected " + minOrMax + " length " + length + " for value \"" + node + "\""); + Node field = node.getParent().getChildren().get(0); + return new ErrorNode("Expected " + minOrMax + " length " + length + " for field \"" + field.toString() + "\", but got \"" + node + "\""); + } + + public static Node createInvalidMinimumValue(Number minimumValue) { + return new ErrorNode("Expected minimum value " + minimumValue); + } + + public static Node createInvalidDivisorValue() { + return new ErrorNode("Can not divide by 0"); + } + + public static Node createInvalidMultipleOfValue(Number multipleOfValue) { + return new ErrorNode("Expected a multiple of " + multipleOfValue); + } + + public static Node createInvalidMaximumValue(Number maximumValue) { + return new ErrorNode("Expected maximum value " + maximumValue); + } + + public static Node createInvalidRangeValue(Node node, Number minimumValue, Number maximumValue) { + if (node.getParent() != null && node.getParent().getChildren().get(0) != node) { + return new ErrorNode("Invalid number " + node + " for " + node.getParent().getChildren().get(0).toString() + " expected number between " + minimumValue + " and " + maximumValue); + } + return new ErrorNode("Invalid number " + node + " expected number between " + minimumValue + " and " + maximumValue); + } + + public static Node createMissingField(String selector) { + return new ErrorNode("Missing field " + selector); + } + + public static Node createMissingAnnotationType(String type) { + return new ErrorNode("Missing Annotation Type '" + type + "'"); + } + + public static Node createInvalidValue(Node node, String expected) { + return new ErrorNode("Invalid value '" + node + "'. Expected " + expected + getFieldMessageIfPresent(node)); + } + + public static Node createInvalidSiblingsValue(Node node, Set siblings) { + return new ErrorNode("Invalid node '" + node + "'. Node not expected when one of " + siblings + " is present."); + } + + public static Node createInvalidJsonExampleNode(String error) { + return new ErrorNode("Error validating JSON. Error: " + error); + } + + public static Node createInvalidXmlExampleNode(String error) { + return new ErrorNode("Error validating XML. Error: " + error); + } + + public static Node createInvalidSchemaNode(String error) { + return new ErrorNode("Error validating Schema. Error: " + error); + } + + public static ErrorNode createInvalidType(String typeName) { + return new ErrorNode("Invalid type name: " + typeName); + } + + public static ErrorNode createInvalidNumberOfProperties(String comparator, Integer expected, Integer actual) { + return new ErrorNode("Expected " + comparator + " number of properties to be: " + expected + " but was: " + actual); + } + + public static ErrorNode createInvalidDateValue(StringNode dateValue, String dateFormat, String rfc) { + return new ErrorNode("Provided value " + dateValue.getValue() + " is not compliant with the format " + dateFormat + " provided in " + rfc + getFieldMessageIfPresent(dateValue)); + } + + public static ErrorNode createInvalidReferenceNode(ReferenceNode refNode) { + return new ErrorNode("Invalid reference '" + refNode.getRefName() + "'"); + } + + public static ErrorNode createInvalidReferenceNode(StringNode refNode) { + return new ErrorNode("Invalid reference '" + refNode + "'"); + } + + public static ErrorNode createDuplicatedPathNode(String path) { + return new ErrorNode("The path " + path + " was already defined."); + } + + public static ErrorNode createInvalidTypeExpressionSyntax(String message, String expression, int location) { + return new ErrorNode("Invalid type expression syntax: \"" + expression + "\". Caused by : " + message + " at character : " + location); + } + + public static ErrorNode createInvalidOverlayNode(Node overlayNode) { + String label = NodeSelector.selectStringValue("../[0]", overlayNode); + if ("value".equals(label)) { + String parentKey = NodeSelector.selectStringValue("../../../[0]", overlayNode); + if (parentKey != null) { + label = parentKey + "." + label; + } + } + return new ErrorNode("Invalid overlay node. Cannot override node: " + label); + } + + public static Node createBaseRamlNotFound(String location) { + return new ErrorNode("Base RAML not found: " + location); + } + + public static ErrorNode createExclusiveKeys(String firstRule, String secondRule) { + return new ErrorNode(firstRule + " and " + secondRule + " are mutually exclusive."); + } + + public static ErrorNode limitsExceptionThrown(LimitsException e) { + + return new ErrorNode(e.getMessage() + ", with node at " + e.getStartMark()); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ExclusiveKeys.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ExclusiveKeys.java new file mode 100644 index 0000000..43050c8 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ExclusiveKeys.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Arrays; +import java.util.List; + +public class ExclusiveKeys { + protected List keys; + + public ExclusiveKeys(List keys) { + if (keys.isEmpty()) { + throw new IllegalArgumentException("rules cannot be empty"); + } + this.keys = keys; + } + + public ExclusiveKeys(Rule... fields) { + this(Arrays.asList(fields)); + } + + public List getAllRules() { + return keys; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/FieldPresentRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/FieldPresentRule.java new file mode 100644 index 0000000..f02a19a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/FieldPresentRule.java @@ -0,0 +1,71 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +/** + * Delegates to a rule if a selector expression returns a value + */ +public class FieldPresentRule extends Rule { + + private final String selector; + + private final Rule delegate; + + public FieldPresentRule(String selector, Rule then) { + this.selector = selector; + this.delegate = then; + } + + @Override + public List getSuggestions(List pathToRoot, ParsingContext context) { + return delegate.getSuggestions(pathToRoot, context); + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return delegate.getSuggestions(node, context); + } + + @Override + public boolean matches(Node node) { + return isPresent(node) && delegate.matches(node); + } + + private boolean isPresent(Node node) { + return NodeSelector.selectFrom(selector, node) != null; + } + + @Override + public Node apply(Node node) { + if (isPresent(node)) { + return delegate.apply(node); + } else { + return ErrorNodeFactory.createMissingField(selector); + } + } + + @Override + public String getDescription() { + return delegate.getDescription(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/FirstOfRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/FirstOfRule.java new file mode 100644 index 0000000..490dc90 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/FirstOfRule.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +/** + * Accepts if any rule matches and delegates the suggestion to the first one that matches. + */ +public class FirstOfRule extends AnyOfRule { + + public FirstOfRule(List rules) { + super(rules); + } + + @Override + + public List getSuggestions(Node node, ParsingContext context) { + for (Rule rule : rules) { + if (rule.matches(node)) { + return rule.getSuggestions(node, context); + } + } + return rules.get(0).getSuggestions(node, context); + } + + @Override + public Node apply(Node node) { + Node apply = super.apply(node); + if (apply instanceof ErrorNode) { + apply = rules.get(0).apply(node); + } + return apply; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/IntegerTypeRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/IntegerTypeRule.java new file mode 100644 index 0000000..63b32dc --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/IntegerTypeRule.java @@ -0,0 +1,102 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.FloatingNode; +import org.xbib.raml.yagi.framework.nodes.IntegerNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class IntegerTypeRule extends AbstractTypeRule { + + private final boolean castStringsAsNumbers; + + private Long lowerBound; + + private Long upperBound; + + public IntegerTypeRule(Long lowerBound, Long upperBound) { + this.lowerBound = lowerBound; + this.upperBound = upperBound; + this.castStringsAsNumbers = false; + } + + public IntegerTypeRule() { + this(null, null); + } + + public IntegerTypeRule(boolean castStringsAsNumbers) { + + this.castStringsAsNumbers = castStringsAsNumbers; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + + @Override + public boolean matches(Node node) { + if (node instanceof StringNode && castStringsAsNumbers) { + String intString = ((StringNode) node).getValue(); + try { + long longValue = Long.parseLong(intString); + return isInRange(longValue); + } catch (NumberFormatException e) { + return false; + } + } + + if (node instanceof IntegerNode) { + return isInRange(((IntegerNode) node).getValue()); + } else if (node instanceof FloatingNode) { + try { + long value = ((FloatingNode) node).getValue().longValue(); + if (((FloatingNode) node).getValue().compareTo(new BigDecimal(value)) != 0) { + return false; + } + + return isInRange(value); + } catch (NumberFormatException e) { + return false; + } + } + return false; + } + + private boolean isInRange(Long value) { + return lowerBound == null || upperBound == null || (lowerBound >= value && value <= upperBound); + } + + @Override + public String getDescription() { + return "Integer"; + } + + + @Override + NodeType getType() { + return NodeType.Integer; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/IntegerValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/IntegerValueRule.java new file mode 100644 index 0000000..9c370ee --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/IntegerValueRule.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.math.BigInteger; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.IntegerNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class IntegerValueRule extends Rule { + + private final BigInteger number; + + public IntegerValueRule(BigInteger number) { + this.number = number; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + + @Override + public boolean matches(Node node) { + if (node instanceof IntegerNode) { + return ((IntegerNode) node).getValue().equals(number.intValue()); + } else { + return false; + } + } + + @Override + public Node apply(Node node) { + if (!matches(node)) { + return ErrorNodeFactory.createInvalidValue(node, String.valueOf(number)); + } else { + return createNodeUsingFactory(node); + } + + } + + @Override + public String getDescription() { + return number.toString(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/KeyValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/KeyValueRule.java new file mode 100644 index 0000000..a9d490f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/KeyValueRule.java @@ -0,0 +1,207 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.DefaultPosition; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.StringNodeImpl; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class KeyValueRule extends Rule { + + private Rule keyRule; + private Rule valueRule; + private String description; + + private RequiredField requiredField; + private DefaultValue defaultValue; + private boolean matchValue = false; + + public KeyValueRule(Rule keyRule, Rule valueRule) { + this.keyRule = keyRule; + this.valueRule = valueRule; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return getValueRule().getSuggestions(node, context); + } + + + public List getKeySuggestions(Node node, ParsingContext context) { + final List suggestions = getKeyRule().getSuggestions(node, context); + final List result = new ArrayList<>(); + for (Suggestion suggestion : suggestions) { + Suggestion keySuggest = suggestion; + if (description != null) { + keySuggest = suggestion.withDescription(description); + } + keySuggest = keySuggest.withValue(suggestion.getValue() + ": "); + result.add(keySuggest); + } + return result; + } + + @Override + public List getSuggestions(List pathToRoot, ParsingContext context) { + if (!pathToRoot.isEmpty()) { + return valueRule.getSuggestions(pathToRoot.subList(1, pathToRoot.size()), context); + } else { + return super.getSuggestions(pathToRoot, context); + } + } + + @Override + public List getChildren() { + return Arrays.asList(getKeyRule(), getValueRule()); + } + + public KeyValueRule description(String description) { + this.description = description; + return this; + } + + + @Override + public boolean matches(Node node) { + if (node instanceof KeyValueNode keyValueNode) { + final boolean matches = getKeyRule().matches(keyValueNode.getKey()); + return matches && (!matchValue || getValueRule().matches(keyValueNode.getValue())); + } else { + return false; + } + } + + /** + * Marks this rule to accept only when it matches they key and also the value + * + * @return This rule with this new behaviour + */ + public KeyValueRule matchValue() { + matchValue = true; + return this; + } + + public boolean repeated() { + return !(getKeyRule() instanceof StringValueRule); + } + + public Rule getKeyRule() { + return keyRule; + } + + public Rule getValueRule() { + return valueRule; + } + + public void setValueRule(Rule valueRule) { + this.valueRule = valueRule; + } + + public void setKeyRule(Rule keyRule) { + this.keyRule = keyRule; + } + + public KeyValueRule then(Class clazz) { + super.then(clazz); + return this; + } + + @Override + public Node apply(Node node) { + if (!(node instanceof KeyValueNode keyValueNode)) { + return ErrorNodeFactory.createInvalidType(node, NodeType.KeyValue); + } else if (!getKeyRule().matches(((KeyValueNode) node).getKey())) { + return getKeyRule().apply(node); + } + final Node key = keyValueNode.getKey(); + key.replaceWith(getKeyRule().apply(key)); + final Node value = keyValueNode.getValue(); + value.replaceWith(getValueRule().apply(value)); + return createNodeUsingFactory(keyValueNode); + } + + @Override + public String getDescription() { + return getKeyRule().getDescription() + ": " + getValueRule().getDescription(); + } + + + public KeyValueRule required() { + this.requiredField = AlwaysRequiredField.getInstance(); + return this; + } + + + public KeyValueRule requiredWhen(RequiredField requiredField) { + this.requiredField = requiredField; + return this; + } + + public boolean isRequired(Node parent) { + return requiredField != null && requiredField.isRequiredField(parent); + } + + public KeyValueRule cleanDefaultValue() { + this.defaultValue = null; + return this; + } + + + public KeyValueRule defaultValue(DefaultValue defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + public void applyDefault(Node parent) { + if (defaultValue == null) { + return; + } + + StringValueRule keyRule = getStringKeyRule(getKeyRule()); + Node valueNode = this.defaultValue.getDefaultValue(parent); + if (valueNode == null) { + // default not applicable in fragment file + return; + } + Node keyNode = new StringNodeImpl(keyRule.getValue()); + KeyValueNodeImpl newNode = new KeyValueNodeImpl(keyNode, valueNode); + newNode.setEndPosition(DefaultPosition.emptyPosition()); + newNode.setStartPosition(DefaultPosition.emptyPosition()); + parent.addChild(newNode); + } + + private StringValueRule getStringKeyRule(Rule keyRule) { + + if (keyRule instanceof AnyOfRule) { + keyRule = getStringKeyRule(((AnyOfRule) keyRule).getRules().get(0)); + } + + if (!(keyRule instanceof StringValueRule)) { + throw new RuntimeException("Key rule " + keyRule.getClass().getSimpleName() + " does not support default values"); + } + return (StringValueRule) keyRule; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/LiteralDefaultValue.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/LiteralDefaultValue.java new file mode 100644 index 0000000..f6d8387 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/LiteralDefaultValue.java @@ -0,0 +1,33 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + + +import org.xbib.raml.yagi.framework.nodes.Node; + +public class LiteralDefaultValue implements DefaultValue { + private final Node value; + + public LiteralDefaultValue(Node value) { + this.value = value; + } + + + @Override + public Node getDefaultValue(Node parent) { + return value; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MaxItemsRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MaxItemsRule.java new file mode 100644 index 0000000..a412f5d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MaxItemsRule.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class MaxItemsRule extends Rule { + private final int maxItems; + + public MaxItemsRule(int maxItems) { + this.maxItems = maxItems; + } + + @Override + public boolean matches(Node node) { + return node.getChildren().size() <= maxItems; + } + + + @Override + public Node apply(Node node) { + if (matches(node)) { + return createNodeUsingFactory(node); + } else { + return ErrorNodeFactory.createInvalidMaxItems(maxItems); + } + } + + @Override + public String getDescription() { + return "Max amount of items " + maxItems; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MaxLengthRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MaxLengthRule.java new file mode 100644 index 0000000..daa6376 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MaxLengthRule.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class MaxLengthRule extends Rule { + private final int maxLength; + + public MaxLengthRule(int maxLength) { + this.maxLength = maxLength; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + @Override + public boolean matches(Node node) { + if (node instanceof SimpleTypeNode) { + return ((SimpleTypeNode) node).getLiteralValue().length() <= maxLength; + } + return false; + } + + @Override + public Node apply(Node node) { + if (!matches(node)) { + return ErrorNodeFactory.createInvalidMaxLength(maxLength, node); + } + return createNodeUsingFactory(node, ((SimpleTypeNode) node).getLiteralValue()); + } + + + @Override + public String getDescription() { + return "Max length"; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MaxPropertiesRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MaxPropertiesRule.java new file mode 100644 index 0000000..6281aa4 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MaxPropertiesRule.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class MaxPropertiesRule extends Rule { + private final int maxProperties; + + public MaxPropertiesRule(int maxProperties) { + this.maxProperties = maxProperties; + } + + @Override + public boolean matches(Node node) { + return node.getChildren().size() <= maxProperties; + } + + + @Override + public Node apply(Node node) { + if (matches(node)) { + return createNodeUsingFactory(node); + } else { + return ErrorNodeFactory.createInvalidMaxProperties(maxProperties); + } + } + + @Override + public String getDescription() { + return "Max amount of properties " + maxProperties; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MaximumValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MaximumValueRule.java new file mode 100644 index 0000000..3481427 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MaximumValueRule.java @@ -0,0 +1,70 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.FloatingNode; +import org.xbib.raml.yagi.framework.nodes.IntegerNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class MaximumValueRule extends Rule { + + private final Number maximumValue; + + public MaximumValueRule(Number maximumValue) { + this.maximumValue = maximumValue; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + @Override + public boolean matches(Node node) { + BigDecimal value = null; + if (node instanceof StringNode) { + value = new BigDecimal(((StringNode) node).getValue()); + } else if (node instanceof IntegerNode) { + value = BigDecimal.valueOf(((IntegerNode) node).getValue()); + } else if (node instanceof FloatingNode) { + value = ((FloatingNode) node).getValue(); + } + return value != null && value.compareTo(BigDecimal.valueOf(maximumValue.doubleValue())) <= 0; + } + + @Override + public Node apply(Node node) { + if (matches(node)) { + return createNodeUsingFactory(node, ((SimpleTypeNode) node).getValue()); + } else { + return ErrorNodeFactory.createInvalidMaximumValue(maximumValue); + } + } + + + @Override + public String getDescription() { + return "Maximum value"; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MinItemsRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MinItemsRule.java new file mode 100644 index 0000000..70a4ac4 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MinItemsRule.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class MinItemsRule extends Rule { + private final int minItems; + + public MinItemsRule(int minItems) { + this.minItems = minItems; + } + + @Override + public boolean matches(Node node) { + return (node instanceof ArrayNode) && node.getChildren().size() >= minItems; + } + + + @Override + public Node apply(Node node) { + if (matches(node)) { + return createNodeUsingFactory(node); + } else { + return ErrorNodeFactory.createInvalidMinItems(minItems); + } + } + + @Override + public String getDescription() { + return "Min amount of items " + minItems; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MinLengthRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MinLengthRule.java new file mode 100644 index 0000000..8ac5dcd --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MinLengthRule.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class MinLengthRule extends Rule { + private final int minLength; + + public MinLengthRule(int minLength) { + this.minLength = minLength; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + @Override + public boolean matches(Node node) { + if (node instanceof SimpleTypeNode) { + return ((SimpleTypeNode) node).getLiteralValue().length() >= minLength; + } + return false; + } + + @Override + public Node apply(Node node) { + if (!matches(node)) { + return ErrorNodeFactory.createInvalidMinLength(minLength, node); + } + return createNodeUsingFactory(node, ((SimpleTypeNode) node).getLiteralValue()); + } + + @Override + public String getDescription() { + return "Min length"; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MinPropertiesRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MinPropertiesRule.java new file mode 100644 index 0000000..77060fb --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MinPropertiesRule.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class MinPropertiesRule extends Rule { + private final int minProperties; + + public MinPropertiesRule(int minProperties) { + this.minProperties = minProperties; + } + + @Override + public boolean matches(Node node) { + return node.getChildren().size() >= minProperties; + } + + + @Override + public Node apply(Node node) { + if (matches(node)) { + return createNodeUsingFactory(node); + } else { + return ErrorNodeFactory.createInvalidMinProperties(minProperties); + } + } + + @Override + public String getDescription() { + return "Min amount of properties " + minProperties; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MinimumValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MinimumValueRule.java new file mode 100644 index 0000000..4a844b2 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/MinimumValueRule.java @@ -0,0 +1,69 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.FloatingNode; +import org.xbib.raml.yagi.framework.nodes.IntegerNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class MinimumValueRule extends Rule { + + private final Number minimumValue; + + public MinimumValueRule(Number minimumValue) { + this.minimumValue = minimumValue; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + @Override + public boolean matches(Node node) { + BigDecimal value = null; + if (node instanceof StringNode) { + value = new BigDecimal(((StringNode) node).getValue()); + } else if (node instanceof IntegerNode) { + value = BigDecimal.valueOf(((IntegerNode) node).getValue()); + } else if (node instanceof FloatingNode) { + value = ((FloatingNode) node).getValue(); + } + return value != null && value.compareTo(BigDecimal.valueOf(minimumValue.doubleValue())) >= 0; + } + + @Override + public Node apply(Node node) { + if (matches(node)) { + return createNodeUsingFactory(node, ((SimpleTypeNode) node).getValue()); + } else { + return ErrorNodeFactory.createInvalidMinimumValue(minimumValue); + } + } + + @Override + public String getDescription() { + return "Minimum value"; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NegativeRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NegativeRule.java new file mode 100644 index 0000000..10c7bf8 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NegativeRule.java @@ -0,0 +1,67 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class NegativeRule extends Rule { + + private final Rule rule; + + + public NegativeRule(Rule rule) { + this.rule = rule; + } + + @Override + + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + + @Override + public boolean matches(Node node) { + return !rule.matches(node); + } + + @Override + public Node apply(Node node) { + final Node result; + if (this.matches(node)) { + result = createNodeUsingFactory(node); + } else { + result = ErrorNodeFactory.createInvalidNode(node); + } + return result; + } + + @Override + public String getDescription() { + String desc = "Not :" + + rule.getDescription(); + return desc; + } + + @Override + public List getSuggestions(List pathToRoot, ParsingContext context) { + return Collections.emptyList(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NodeFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NodeFactory.java new file mode 100644 index 0000000..b1fb215 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NodeFactory.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import org.xbib.raml.yagi.framework.nodes.Node; + +public interface NodeFactory { + Node create(Node currentNode, Object... args); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NullValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NullValueRule.java new file mode 100644 index 0000000..523d1d5 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NullValueRule.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NullNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class NullValueRule extends Rule { + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + + @Override + public boolean matches(Node node) { + return node instanceof NullNode; + } + + @Override + public Node apply(Node node) { + if (!matches(node)) { + return ErrorNodeFactory.createInvalidValue(node, ""); + } + return createNodeUsingFactory(node); + } + + @Override + public String getDescription() { + return "null"; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NumberTypeRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NumberTypeRule.java new file mode 100644 index 0000000..bf67252 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NumberTypeRule.java @@ -0,0 +1,91 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.FloatingNode; +import org.xbib.raml.yagi.framework.nodes.IntegerNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class NumberTypeRule extends AbstractTypeRule { + private final boolean castStringsAsNumbers; + + private Double lowerBound; + + private Double upperBound; + + public NumberTypeRule(Double lowerBound, Double upperBound) { + this.lowerBound = lowerBound; + this.upperBound = upperBound; + this.castStringsAsNumbers = false; + } + + public NumberTypeRule() { + this(null, null); + } + + public NumberTypeRule(boolean castStringsAsNumbers) { + + this.castStringsAsNumbers = castStringsAsNumbers; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + + @Override + public boolean matches(Node node) { + if (node instanceof StringNode && castStringsAsNumbers) { + String intString = ((StringNode) node).getValue(); + try { + double doubleValue = Double.parseDouble(intString); + return contains(doubleValue); + } catch (NumberFormatException e) { + return false; + } + } + if (node instanceof FloatingNode) { + return contains(((FloatingNode) node).getValue().doubleValue()); + } + if (node instanceof IntegerNode) { + return contains(((IntegerNode) node).getValue().doubleValue()); + } + return false; + } + + @Override + public String getDescription() { + return "Number"; + } + + + @Override + NodeType getType() { + return NodeType.Float; + } + + private boolean contains(Double d) { + return lowerBound == null || upperBound == null || lowerBound <= d && d <= upperBound; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NumberValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NumberValueRule.java new file mode 100644 index 0000000..c65cb36 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/NumberValueRule.java @@ -0,0 +1,68 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.FloatingNode; +import org.xbib.raml.yagi.framework.nodes.IntegerNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class NumberValueRule extends AbstractTypeRule { + private final Number value; + + public NumberValueRule(Number value) { + this.value = value; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + @Override + public boolean matches(Node node) { + if (node instanceof FloatingNode) { + return ((FloatingNode) node).getValue().doubleValue() == value.doubleValue(); + } else if (node instanceof IntegerNode) { + return ((IntegerNode) node).getValue() == value.intValue(); + } + if (node instanceof StringNode) { + try { + return Double.parseDouble(((StringNode) node).getValue()) == value.doubleValue(); + } catch (NumberFormatException ex) { + return false; + } + } + return false; + } + + @Override + public String getDescription() { + return "Number"; + } + + + @Override + NodeType getType() { + return NodeType.Float; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ObjectRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ObjectRule.java new file mode 100644 index 0000000..bcd114d --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ObjectRule.java @@ -0,0 +1,396 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.NullNode; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.ParsingContextType; +import org.xbib.raml.yagi.framework.suggester.Suggestion; +import org.xbib.raml.yagi.framework.util.NodeUtils; + +public class ObjectRule extends Rule { + + private final List fields; + + private ConditionalRules conditionalRules; + private ExclusiveKeys exclusiveKeys; + private boolean strict = false; + private boolean allowsAdditionalProperties = false; + private String discriminatorName; + + + public ObjectRule() { + this.fields = new ArrayList<>(); + } + + @Override + public List getChildren() { + final ArrayList children = new ArrayList<>(); + children.addAll(fields); + if (conditionalRules != null) { + children.addAll(conditionalRules.getChildren()); + } + return children; + } + + public ObjectRule(boolean strict) { + this(); + this.strict = strict; + } + + public ObjectRule named(String ruleName) { + super.named(ruleName); + return this; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + List result = new ArrayList<>(); + // In cases where the node we are trying to suggest is a null node just return the known fields else try guessing the conditional ones + final List fieldRules = node instanceof NullNode ? fields : getAllFieldRules(node); + for (KeyValueRule rule : fieldRules) { + if (rule.repeated() || findMatchingNode(rule, node.getChildren()) == null) { + if (context.getContextType() == ParsingContextType.VALUE) { + final List keySuggestions = rule.getKeySuggestions(node, context); + final Node editing = NodeUtils.searchNodeAt(NodeUtils.traverseToRoot(node), context.getLocation()); + final String prefix = "\n" + NodeUtils.computeColumnForChild(editing instanceof NullNode ? editing.getParent() : editing); + for (Suggestion keySuggestion : keySuggestions) { + result.add(keySuggestion.withPrefix(prefix)); + } + } else { + // We return the suggestions of the key + result.addAll(rule.getKeySuggestions(node, context)); + } + } + } + return result; + } + + + private Node findMatchingNode(KeyValueRule rule, List children) { + for (Node child : children) { + if (rule.matches(child) && matchesKey(child, rule) && matchesValue(child, rule)) { + return child; + } + } + + return null; + } + + @Override + public boolean matches(Node node) { + boolean isObjectNode = node instanceof ObjectNode; + if (!strict) { + return isObjectNode; + } else { + return isObjectNode && allChildrenMatch(node); + } + } + + private boolean allChildrenMatch(Node node) { + List children = node.getChildren(); + final List allFieldRules = getAllFieldRules(node); + + Set unmatchedChildren = new HashSet<>(children); + + for (KeyValueRule rule : allFieldRules) { + // If the key is required, but it does not match any rule + if (rule.isRequired(node) && !unmatchedChildren.remove(findMatchingNode(rule, children))) { + return false; + } + } + + // All children that are not required and additional properties will be in unmatchedChildren + for (Node child : unmatchedChildren) { + // If it matches the key, but does not match the rule + if (childMatchesAnyKey(child, allFieldRules) && !childMatchesAnyRule(child, allFieldRules)) { + return false; + } + } + + return true; + } + + private boolean childMatchesAnyKey(Node child, List allFieldRules) { + for (KeyValueRule rule : allFieldRules) { + if (matchesKey(child, rule)) { + return true; + } + } + + return false; + } + + private boolean childMatchesAnyRule(Node child, List allFieldRules) { + for (KeyValueRule rule : allFieldRules) { + if (rule.matches(child) && matchesKey(child, rule) && matchesValue(child, rule)) { + return true; + } + } + + return false; + } + + private boolean matchesKey(Node child, KeyValueRule rule) { + return rule.getKeyRule().matches(child.getChildren().get(0)); + } + + private boolean matchesValue(Node child, KeyValueRule rule) { + return rule.getValueRule().matches(child.getChildren().get(1)); + } + + + @Override + public Node apply(Node node) { + if (!matches(node)) { + return ErrorNodeFactory.createInvalidType(node, NodeType.Object); + } else { + + final List children = node.getChildren(); + final List allFieldRules = getAllFieldRules(node); + final List nonMatchingRules = new ArrayList<>(allFieldRules); + + for (Node child : children) { + final Rule matchingRule = findMatchingRule(allFieldRules, child); + if (matchingRule != null) { + nonMatchingRules.remove(matchingRule); + final Node newChild = matchingRule.apply(child); + child.replaceWith(newChild); + } else { + if (!allowsAdditionalProperties) { + final Collection options = allFieldRules.stream() + .map(rule -> rule.getKeyRule().getDescription()).toList(); + child.replaceWith(ErrorNodeFactory.createUnexpectedKey(((KeyValueNode) child).getKey(), new TreeSet<>(options))); + } + } + } + + for (KeyValueRule rule : nonMatchingRules) { + if (discriminatorName == null) { + + if (rule.isRequired(node)) { + node.addChild(ErrorNodeFactory.createRequiredValueNotFound(node, rule.getKeyRule())); + } else { + + rule.applyDefault(node); + } + } else { + + if (rule.isRequired(node)) { + if (rule.getKeyRule() instanceof StringValueRule && ((StringValueRule) rule.getKeyRule()).getValue().equals(discriminatorName)) { + + node.replaceWith(ErrorNodeFactory.createInvalidType("discriminator not specified")); + } else { + + node.addChild(ErrorNodeFactory.createRequiredValueNotFound(node, rule.getKeyRule())); + } + } else { + rule.applyDefault(node); + } + } + } + + validateKeysUnique(node); + validateExclusiveKeys(node); + return getResult(node); + } + } + + private void validateKeysUnique(final Node node) { + final List children = node.getChildren(); + + final Set gotcha = new HashSet<>(); + for (final Node child : children) { + if (child instanceof KeyValueNode) { + final String key = ((KeyValueNode) child).getKey().toString(); + if (gotcha.contains(key)) { + child.replaceWith(new ErrorNode("Duplicated key '" + key + "'")); + } else { + gotcha.add(key); + } + } + } + } + + private void validateExclusiveKeys(final Node node) { + if (exclusiveKeys != null) { + boolean hasMatchedRule = false; + List children = node.getChildren(); + List keys = exclusiveKeys.getAllRules(); + + for (Node child : children) { + for (Rule rule : keys) { + if (child instanceof KeyValueNode) { + Node key = ((KeyValueNodeImpl) child).getKey(); + + if (rule.matches(key)) { + if (!hasMatchedRule) { + hasMatchedRule = true; + } else { + final String firstRule = keys.get(0).getDescription(); + final String secondRule = keys.get(1).getDescription(); + child.replaceWith(ErrorNodeFactory.createExclusiveKeys(firstRule, secondRule)); + break; + } + } + } + } + } + } + } + + protected Node getResult(Node node) { + return createNodeUsingFactory(node); + } + + private List getAllFieldRules(Node node) { + if (conditionalRules != null) { + // We first add the local rules and then conditional rules + final ArrayList rules = new ArrayList<>(fields); + final List rulesNode = conditionalRules.getRulesNode(node); + rules.addAll(rulesNode); + return rules; + } else { + return fields; + } + } + + + private Rule findMatchingRule(List rootRule, Node node) { + for (Rule rule : rootRule) { + if (rule.matches(node)) { + return rule; + } + } + return null; + } + + @Override + public ObjectRule then(Class clazz) { + super.then(clazz); + return this; + } + + @Override + public ObjectRule then(NodeFactory factory) { + super.then(factory); + return this; + } + + /** + * Adds a field to this object rule + * + * @param field The field defined to this object + * @return this + */ + public ObjectRule with(KeyValueRule field) { + this.fields.add(field); + return this; + } + + /** + * Adds all a field to this object rule + * + * @param fields The fields defined to this object + * @return this + */ + public ObjectRule withAll(KeyValueRule... fields) { + if (fields != null) { + this.fields.addAll(Arrays.asList(fields)); + } + return this; + } + + /** + * Adds a field to this object rule at a given order + * + * @param field The field defined to this object + * @param index the index + * @return this + */ + public ObjectRule with(int index, KeyValueRule field) { + this.fields.add(index, field); + return this; + } + + public ObjectRule discriminatorName(String name) { + this.discriminatorName = name; + return this; + } + + @Override + public List getSuggestions(List pathToRoot, ParsingContext context) { + if (pathToRoot.isEmpty()) { + return Collections.emptyList(); + } else { + final Node mappingNode = pathToRoot.get(0); + if (pathToRoot.size() == 1) { + return getSuggestions(mappingNode, context); + } + final Node node = pathToRoot.get(1); + final Rule matchingRule = findMatchingRule(getAllFieldRules(mappingNode), node); + return matchingRule == null ? Collections.emptyList() : matchingRule.getSuggestions(pathToRoot.subList(1, pathToRoot.size()), context); + } + } + + @Override + public String getDescription() { + return "Mapping"; + } + + public void additionalProperties(boolean allowsAdditionalProperties) { + this.allowsAdditionalProperties = allowsAdditionalProperties; + } + + /** + * Defines conditional fields based on a condition. + * This fields are only valid if the specified condition is + * + * @param conditional The conditional fields + * @return this + */ + public ObjectRule with(ConditionalRules conditional) { + this.conditionalRules = conditional; + return this; + } + + /** + * Defines the mutually exclusive fields + * + * @param exclusive The exclusive rules + * @return this + */ + public ObjectRule with(ExclusiveKeys exclusive) { + this.exclusiveKeys = exclusive; + return this; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ParentKeyDefaultValue.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ParentKeyDefaultValue.java new file mode 100644 index 0000000..f2386b1 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ParentKeyDefaultValue.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + + +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class ParentKeyDefaultValue implements DefaultValue { + + + @Override + public Node getDefaultValue(Node parent) { + Node grampa = parent.getParent(); + if (grampa == null) { + // inside raml fragment file + return null; + } + if (!(grampa instanceof KeyValueNode)) { + return ErrorNodeFactory.createInvalidNode(parent); + } + Node keyNode = ((KeyValueNode) grampa).getKey(); + return keyNode.copy(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/RangeValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/RangeValueRule.java new file mode 100644 index 0000000..585ca26 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/RangeValueRule.java @@ -0,0 +1,113 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.FloatingNode; +import org.xbib.raml.yagi.framework.nodes.IntegerNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class RangeValueRule extends Rule { + + private final Number lowerBound; + + private final Number upperBound; + + public RangeValueRule(Number lowerBound, Number upperBound) { + this.lowerBound = lowerBound; + this.upperBound = upperBound; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + @Override + public boolean matches(Node node) { + if (node instanceof IntegerNode || node instanceof FloatingNode) { + return true; + } else if (node instanceof SimpleTypeNode) { + try { + Long.parseLong(((SimpleTypeNode) node).getLiteralValue()); + return true; + } catch (NumberFormatException parseLongException) { + try { + Double.parseDouble(((SimpleTypeNode) node).getLiteralValue()); + return true; + } catch (NumberFormatException parseDoubleException) { + return false; + } + } + } else { + return false; + } + } + + @Override + public Node apply(Node node) { + if (validate(node)) { + return createNodeUsingFactory(node, ((SimpleTypeNode) node).getValue()); + } else { + return ErrorNodeFactory.createInvalidRangeValue(node, lowerBound, upperBound); + } + } + + private boolean validate(Node node) { + if (node instanceof IntegerNode) { + Long value = ((IntegerNode) node).getValue(); + return containsLong(value); + } else if (node instanceof FloatingNode) { + BigDecimal value = ((FloatingNode) node).getValue(); + return containsDouble(value.doubleValue()); + } else if (node instanceof SimpleTypeNode) { + try { + long parseLong = Long.parseLong(((StringNode) node).getValue()); + return containsLong(parseLong); + } catch (NumberFormatException parseLongException) { + try { + double parseDouble = Double.parseDouble(((StringNode) node).getValue()); + return containsDouble(parseDouble); + } catch (NumberFormatException parseDoubleException) { + return false; + } + + } + } else { + return false; + } + } + + @Override + public String getDescription() { + return "Maximum value"; + } + + private boolean containsLong(Long l) { + return lowerBound == null || upperBound == null || (lowerBound.longValue() <= l && l <= upperBound.longValue()); + } + + private boolean containsDouble(Double d) { + return lowerBound == null || upperBound == null || (lowerBound.doubleValue() <= d && d <= upperBound.doubleValue()); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/RegexValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/RegexValueRule.java new file mode 100644 index 0000000..e237fc1 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/RegexValueRule.java @@ -0,0 +1,116 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.suggester.DefaultSuggestion; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class RegexValueRule extends Rule { + + private final Pattern value; + private String description; + private final List suggestions = new ArrayList<>(); + private String label; + private boolean fullMatch = true; + + public RegexValueRule(Pattern value) { + this.value = value; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + if (suggestions.isEmpty()) { + return Collections.emptyList(); + } else { + List result = new ArrayList<>(); + for (String suggestion : suggestions) { + String label = this.label; + if (label.isBlank()) { + label = suggestion; + } + result.add(new DefaultSuggestion(suggestion, description, label)); + } + return result; + } + } + + + @Override + public boolean matches(Node node) { + return node instanceof SimpleTypeNode && (fullMatch ? getMatcher((SimpleTypeNode) node).matches() : getMatcher((SimpleTypeNode) node).find()); + } + + private Matcher getMatcher(SimpleTypeNode node) { + return value.matcher(node.getLiteralValue()); + } + + public RegexValueRule label(String value) { + this.label = value; + return this; + } + + public RegexValueRule suggest(String value) { + this.suggestions.add(value); + return this; + } + + public RegexValueRule description(String description) { + this.description = description; + return this; + } + + public RegexValueRule fullMatch(boolean fullMatch) { + this.fullMatch = fullMatch; + return this; + } + + @Override + public Node apply(Node node) { + if (!matches(node)) { + return ErrorNodeFactory.createInvalidValue(node, String.valueOf(value)); + } + final Matcher matcher = getMatcher((SimpleTypeNode) node); + final int i = matcher.groupCount(); + final List groups = new ArrayList<>(); + if (i > 0) { + if (fullMatch) { + matcher.matches(); + } else { + matcher.find(); + } + } + for (int j = 1; j <= i; j++) { + final String group = matcher.group(j); + groups.add(group); + } + return createNodeUsingFactory(node, groups.toArray(new String[groups.size()])); + } + + @Override + public String getDescription() { + return "/" + value.pattern() + "/"; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/RequiredField.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/RequiredField.java new file mode 100644 index 0000000..1c65381 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/RequiredField.java @@ -0,0 +1,29 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import org.xbib.raml.yagi.framework.nodes.Node; + +public interface RequiredField { + + /** + * Evaluates if a missing field is required. + * + * @param parent + * @return true if the field is required + */ + boolean isRequiredField(Node parent); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ResourceRefRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ResourceRefRule.java new file mode 100644 index 0000000..0d24d47 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ResourceRefRule.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + + +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; + +public class ResourceRefRule extends StringTypeRule { + + @Override + public Node apply(Node node) { + if (node instanceof ReferenceNode) { + return node; + } else { + return super.apply(node); + } + } + + @Override + public boolean matches(Node node) { + return super.matches(node) || node instanceof ReferenceNode; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/Rule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/Rule.java new file mode 100644 index 0000000..0bd5277 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/Rule.java @@ -0,0 +1,160 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.grammar.BaseGrammar; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public abstract class Rule { + + private NodeFactory factory; + private String ruleName = getClass().getSimpleName(); + + protected Rule() { + if (Boolean.getBoolean("yagi.rule.debug")) { + final StackTraceElement[] stackTrace = new Throwable().getStackTrace(); + for (StackTraceElement stackTraceElement : stackTrace) { + final String className = stackTraceElement.getClassName(); + if (className.contains("Grammar") && !className.endsWith(BaseGrammar.class.getSimpleName())) { + ruleName = stackTraceElement.getMethodName(); + break; + } + } + } + } + + public List getChildren() { + return Collections.emptyList(); + } + + public Rule named(String ruleName) { + this.ruleName = ruleName; + return this; + } + + public String ruleName() { + return ruleName; + } + + @Override + public String toString() { + return ruleName; + } + + /** + * Check if the current rule matches the specified node + * + * @param node The node to check with + * @return True if it matches otherwise false + */ + public abstract boolean matches(Node node); + + /** + * Applies the rule to the node using the following criteria + * - if rule does not match returns an ErrorNode and stops processing + * - if rule matches, applies rules to children + * - if rule contains a NodeFactory, returns the result of it + * - else returns node + *

+ * Only structure rules ({@link ObjectRule}, {@link ArrayRule}, {@link KeyValueRule}) replace child nodes. + * + * @param node The current node + * @return the result of the factory or the current node + */ + + public abstract Node apply(Node node); + + /** + * Returns a description of this rule + * + * @return the description + */ + public abstract String getDescription(); + + + public NodeFactory getFactory() { + return factory; + } + + + protected Node createNodeUsingFactory(Node currentNode, Object... args) { + if (getFactory() != null) { + Node newNode = getFactory().create(currentNode, args); + if (!newNode.getClass().isAssignableFrom(currentNode.getClass())) { + return newNode; + } + } + return currentNode; + } + + /** + * Sets the clazz of the node that is going to be created to replaced the matched node of this rule. + * This is only applied if the rule matches + * + * @param clazz The class of the node + * @return this + */ + public Rule then(Class clazz) { + this.factory = new ClassNodeFactory(clazz); + return this; + } + + /** + * Sets the factory of the node that is going to be created to replaced the matched node of this rule. + * This is only applied if the rule matches + * + * @param factory The class of the node + * @return this + */ + public Rule then(NodeFactory factory) { + this.factory = factory; + return this; + } + + public Rule cleanFactory() { + this.factory = null; + return this; + } + + /** + * Returns the list of suggestions after navigating through the path + * + * @param pathToRoot The path of nodes to get of the node from where we want the suggestions + * @param context The parse context + * @return The list of suggestions + */ + public List getSuggestions(List pathToRoot, ParsingContext context) { + if (!pathToRoot.isEmpty()) { + return getSuggestions(pathToRoot.get(0), context); + } else { + return Collections.emptyList(); + } + } + + /** + * Returns the suggestions of this specific rule + * + * @param node The node + * @param context The parse context + * @return The list of suggestions for the specified rule + */ + + public abstract List getSuggestions(Node node, ParsingContext context); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ScalarTypeRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ScalarTypeRule.java new file mode 100644 index 0000000..fa974fa --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/ScalarTypeRule.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class ScalarTypeRule extends AbstractTypeRule { + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + @Override + public boolean matches(Node node) { + return node instanceof SimpleTypeNode; + } + + @Override + public String getDescription() { + return "String"; + } + + + @Override + NodeType getType() { + return NodeType.String; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/StringTypeRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/StringTypeRule.java new file mode 100644 index 0000000..4767001 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/StringTypeRule.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class StringTypeRule extends AbstractTypeRule { + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.emptyList(); + } + + @Override + public boolean matches(Node node) { + return node instanceof StringNode; + } + + @Override + public String getDescription() { + return "String"; + } + + + @Override + NodeType getType() { + return NodeType.String; + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/StringValueRule.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/StringValueRule.java new file mode 100644 index 0000000..51a6531 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/grammar/rule/StringValueRule.java @@ -0,0 +1,89 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.grammar.rule; + +import java.util.Collections; +import java.util.List; +import org.xbib.raml.internal.utils.StringUtils; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.xbib.raml.yagi.framework.suggester.DefaultSuggestion; +import org.xbib.raml.yagi.framework.suggester.ParsingContext; +import org.xbib.raml.yagi.framework.suggester.Suggestion; + +public class StringValueRule extends Rule { + + private final String value; + private String description; + private boolean caseSensitive = true; + + public StringValueRule(String value) { + this.value = value; + } + + + @Override + public List getSuggestions(Node node, ParsingContext context) { + return Collections.singletonList(new DefaultSuggestion(value, description, StringUtils.capitalize(value))); + } + + + @Override + public boolean matches(Node node) { + return node instanceof StringNode && + ((caseSensitive) ? + ((StringNode) node).getValue().equals(value) : + ((StringNode) node).getValue().equalsIgnoreCase(value)); + } + + public StringValueRule description(String description) { + this.description = description; + return this; + } + + public StringValueRule caseSensitive(boolean caseSensitive) { + this.caseSensitive = caseSensitive; + return this; + } + + + @Override + public Node apply(Node node) { + if (!(node instanceof StringNode)) { + return ErrorNodeFactory.createInvalidType(node, NodeType.String); + } + if (!matches(node)) { + return ErrorNodeFactory.createInvalidValue(node, value); + } + return createNodeUsingFactory(node, ((StringNode) node).getValue()); + + } + + @Override + public String toString() { + return value; + } + + @Override + public String getDescription() { + return "\"" + value + "\""; + } + + public String getValue() { + return value; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/AbstractNodeModel.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/AbstractNodeModel.java new file mode 100644 index 0000000..e64c983 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/AbstractNodeModel.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + +import java.util.Objects; +import org.xbib.raml.yagi.framework.nodes.Node; + +public abstract class AbstractNodeModel implements NodeModel { + protected final T node; + + public AbstractNodeModel(T node) { + Objects.requireNonNull(node); + this.node = node; + } + + @Override + public int hashCode() { + return node.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof NodeModel nodeModel)) { + return false; + } + return getNode().equals(nodeModel.getNode()); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ClassNodeModelFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ClassNodeModelFactory.java new file mode 100644 index 0000000..2105705 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ClassNodeModelFactory.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +/** + * Class based factory + */ +public class ClassNodeModelFactory implements NodeModelFactory { + private final Class aClass; + + + public ClassNodeModelFactory(Class aClass) { + this.aClass = aClass; + } + + @Override + public NodeModel create(Node node) { + + Constructor nodeConstructor = findNodeConstructor(aClass); + try { + if (KeyValueNode.class.isAssignableFrom(nodeConstructor.getParameterTypes()[0])) { + // If constructor expects a key value pair we try the current node or the parent. + if (node instanceof KeyValueNode) { + return (NodeModel) nodeConstructor.newInstance(node); + } else { + return (NodeModel) nodeConstructor.newInstance(node.findAncestorWith(KeyValueNode.class)); + } + } else { + return (NodeModel) nodeConstructor.newInstance(node); + } + } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean polymorphic() { + return false; + } + + + private static Constructor findNodeConstructor(Class aClass) { + Constructor[] constructors = aClass.getConstructors(); + for (Constructor constructor : constructors) { + if (constructor.getParameterTypes().length == 1) { + if (Node.class.isAssignableFrom(constructor.getParameterTypes()[0])) { + return constructor; + } + } + } + throw new RuntimeException("No constructor with a single Node type was found for " + aClass.getName()); + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/DefaultModelBindingConfiguration.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/DefaultModelBindingConfiguration.java new file mode 100644 index 0000000..b666484 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/DefaultModelBindingConfiguration.java @@ -0,0 +1,93 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + + +public class DefaultModelBindingConfiguration implements ModelBindingConfiguration { + + private final List bindings; + private final List reverseBinding; + private NodeModelFactory defaultBinding; + + public DefaultModelBindingConfiguration() { + this.bindings = new ArrayList<>(); + this.reverseBinding = new ArrayList<>(); + this.defaultBinding = new ClassNodeModelFactory(DefaultNodeBaseModel.class); + } + + + @Override + public NodeModelFactory bindingOf(Class className) { + for (ModelBinding binding : bindings) { + final NodeModelFactory result = binding.binding(className); + if (result != null) { + return result; + } + } + if (defaultBinding != null) { + return defaultBinding; + } else { + throw new RuntimeException("No binding found for " + className); + } + } + + + @Override + public Class reverseBindingOf(NodeModel model) { + for (ModelReverseBinding modelReverseBinding : reverseBinding) { + final Class aClass = modelReverseBinding.reverseBindingOf(model); + if (aClass != null) { + return aClass; + } + } + throw new RuntimeException("No reverse bind found for " + model.getClass()); + } + + public DefaultModelBindingConfiguration bindPackage(String basePackageName) { + this.bindings.add(new PackageModelBinding(basePackageName)); + return this; + } + + public DefaultModelBindingConfiguration bindSimpleName(Class modelClass, String... names) { + this.bindings.add(new SimpleClassNameBinding(new HashSet<>(Arrays.asList(names)), modelClass)); + return this; + } + + public DefaultModelBindingConfiguration bind(Class anInterface, Class model) { + this.bindings.add(new SimpleBinding(anInterface, new ClassNodeModelFactory(model))); + return this; + } + + public DefaultModelBindingConfiguration bind(Class clazz, NodeModelFactory factory) { + this.bindings.add(new SimpleBinding(clazz, factory)); + return this; + } + + public DefaultModelBindingConfiguration defaultTo(Class defaultClass) { + this.defaultBinding = new ClassNodeModelFactory(defaultClass); + return this; + } + + public DefaultModelBindingConfiguration reverseBindPackage(String basePackage) { + this.reverseBinding.add(new PackageReverseBinding(basePackage)); + return this; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/DefaultNodeBaseModel.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/DefaultNodeBaseModel.java new file mode 100644 index 0000000..bd4002e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/DefaultNodeBaseModel.java @@ -0,0 +1,32 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + +import org.xbib.raml.yagi.framework.nodes.Node; + +/** + * Default Model implementation + */ +public class DefaultNodeBaseModel extends AbstractNodeModel { + public DefaultNodeBaseModel(Node node) { + super(node); + } + + @Override + public Node getNode() { + return node; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelBinding.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelBinding.java new file mode 100644 index 0000000..bd5ad15 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelBinding.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + + +public interface ModelBinding { + + NodeModelFactory binding(Class clazz); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelBindingConfiguration.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelBindingConfiguration.java new file mode 100644 index 0000000..c832d28 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelBindingConfiguration.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + +/** + * Handles the binding between the model interface and NodeBaseModel implementation + */ +public interface ModelBindingConfiguration { + /** + * Returns a class that implements NodeBaseModel + * + * @param className The className + * @return The factory of the implementation + */ + + NodeModelFactory bindingOf(Class className); + + /** + * Returns the reverse binding of a model in a polymorphic scenario. + * Returns the interface class that binds to this implementation + * {@link NodeModelFactory#polymorphic()} + * + * @param model The implementation model + * @return The interface class + */ + + Class reverseBindingOf(NodeModel model); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelProxyBuilder.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelProxyBuilder.java new file mode 100644 index 0000000..b036baa --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelProxyBuilder.java @@ -0,0 +1,166 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Proxy; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.util.NodeSelector; +import org.xbib.raml.yagi.framework.util.NodeUtils; + +public class ModelProxyBuilder { + + public static T createModel(Class apiInterface, NodeModel delegateNode, ModelBindingConfiguration bindingConfiguration) { + return (T) Proxy.newProxyInstance(apiInterface.getClassLoader(), + new Class[]{apiInterface, NodeModel.class}, + new SimpleProxy(delegateNode, bindingConfiguration)); + } + + private static class SimpleProxy implements InvocationHandler { + private final NodeModel delegate; + private final ModelBindingConfiguration bindingConfiguration; + + public SimpleProxy(NodeModel delegate, ModelBindingConfiguration bindingConfiguration) { + this.bindingConfiguration = bindingConfiguration; + if (delegate == null) { + throw new IllegalArgumentException("delegate cannot be null"); + } + this.delegate = delegate; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + final Type genericReturnType = method.getGenericReturnType(); + final Method delegateMethod = findMatchingMethod(method); + try { + if (delegateMethod == null) { + return fromNodeKey(method, genericReturnType); + } else { + return fromMethod(args, genericReturnType, delegateMethod); + } + } catch (Exception e) { + throw new RuntimeException("Internal error while trying to call " + method.toGenericString(), e); + } + } + + protected Object fromNodeKey(Method method, Type genericReturnType) { + final String propertyName = method.getName(); + if (delegate != null && method.getParameterTypes().length == 0) { + return resolveValue(genericReturnType, NodeSelector.selectFrom(propertyName, delegate.getNode())); + } else { + throw new RuntimeException("Can not resolve method : " + method.getDeclaringClass().getName() + " from " + method.toGenericString() + " on " + delegate.getClass().getName()); + } + } + + protected Object fromMethod(Object[] args, Type genericReturnType, Method delegateMethod) throws IllegalAccessException, InvocationTargetException { + final Object invoke = delegateMethod.invoke(delegate, args); + return resolveValue(genericReturnType, invoke); + } + + + private Object resolveValue(Type genericReturnType, Object invoke) { + Class returnType = ModelUtils.toClass(genericReturnType); + if (invoke == null || ModelUtils.isPrimitiveOrWrapperOrString(returnType) || ModelUtils.isObject(returnType)) { + return invoke; + } else if (List.class.isAssignableFrom(returnType)) { + final List returnList = new ArrayList<>(); + final List result = (List) invoke; + final Type itemClass = ((ParameterizedType) genericReturnType).getActualTypeArguments()[0]; + if (ModelUtils.isPrimitiveOrWrapperOrString(ModelUtils.toClass(itemClass))) { + return result; + } + for (Object item : result) { + returnList.add(resolveValue(itemClass, item)); + } + return returnList; + } else if (returnType.isAssignableFrom(invoke.getClass())) { + // No need for proxy the object is already an instance of the expected value + return invoke; + } else { + NodeModelFactory nodeModelFactory = bindingConfiguration.bindingOf(returnType); + Class proxyInterface = nodeModelFactory.polymorphic() ? bindingConfiguration.reverseBindingOf((NodeModel) invoke) : returnType; + return createModel(proxyInterface, (NodeModel) invoke, bindingConfiguration); + } + } + + protected Object resolveValue(Type returnType, Node node) { + final SimpleValueTransformer[] values = SimpleValueTransformer.values(); + final Class returnClass = ModelUtils.toClass(returnType); + for (SimpleValueTransformer value : values) { + if (value.accepts(returnClass)) { + return value.adaptTo(node, returnClass); + } + } + + // If it is not a simple type then it can be a list or an pojo + if (List.class.isAssignableFrom(returnClass) && returnType instanceof ParameterizedType) { + final Type itemClass = ((ParameterizedType) returnType).getActualTypeArguments()[0]; + final List returnList = new ArrayList<>(); + if (NodeUtils.isNull(node)) { + return returnList; + } else if (node instanceof ArrayNode || node instanceof ObjectNode) { + final List children = node.getChildren(); + for (Node child : children) { + returnList.add(resolveValue(itemClass, child)); + } + } else { + returnList.add(resolveValue(itemClass, node)); + } + return returnList; + } else if (NodeUtils.isNull(node)) { + return null; + } else if (returnClass.equals(Object.class)) { + if (node instanceof SimpleTypeNode) { + return ((SimpleTypeNode) node).getValue(); + } else { + // TODO: Here we should map it to map or list of maps + return null; + } + } else { + final NodeModelFactory nodeModelFactory = bindingConfiguration.bindingOf(returnClass); + final NodeModel nodeModel = nodeModelFactory.create(node); + final Class proxyInterface; + if (nodeModelFactory.polymorphic()) { + proxyInterface = bindingConfiguration.reverseBindingOf(nodeModel); + } else { + proxyInterface = returnClass; + } + + return createModel(proxyInterface, nodeModel, bindingConfiguration); + } + } + + + private Method findMatchingMethod(Method method) { + try { + return delegate.getClass().getMethod(method.getName(), method.getParameterTypes()); + } catch (NoSuchMethodException e) { + return null; + } + } + + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelReverseBinding.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelReverseBinding.java new file mode 100644 index 0000000..9856d1a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelReverseBinding.java @@ -0,0 +1,20 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + +public interface ModelReverseBinding { + Class reverseBindingOf(NodeModel model); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelUtils.java new file mode 100644 index 0000000..3fdeb76 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/ModelUtils.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.HashSet; +import java.util.Set; + +public class ModelUtils { + + private static final Set> WRAPPERS_PLUS_STRING = new HashSet>(); + + static { + WRAPPERS_PLUS_STRING.add(Boolean.class); + WRAPPERS_PLUS_STRING.add(Character.class); + WRAPPERS_PLUS_STRING.add(Byte.class); + WRAPPERS_PLUS_STRING.add(Short.class); + WRAPPERS_PLUS_STRING.add(Integer.class); + WRAPPERS_PLUS_STRING.add(Long.class); + WRAPPERS_PLUS_STRING.add(Float.class); + WRAPPERS_PLUS_STRING.add(Double.class); + WRAPPERS_PLUS_STRING.add(BigInteger.class); + WRAPPERS_PLUS_STRING.add(BigDecimal.class); + WRAPPERS_PLUS_STRING.add(String.class); + } + + public static boolean isPrimitiveOrWrapperOrString(Class type) { + return type.isPrimitive() || WRAPPERS_PLUS_STRING.contains(type); + } + + + public static boolean isObject(Class type) { + return Object.class.equals(type); + } + + public static Class toClass(Type type) { + if (type instanceof Class) { + return (Class) type; + } else if (type instanceof ParameterizedType) { + return toClass(((ParameterizedType) type).getRawType()); + } else if (type instanceof WildcardType) { + return toClass(((WildcardType) type).getUpperBounds()[0]); + } else { + return Object.class; + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/NodeModel.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/NodeModel.java new file mode 100644 index 0000000..9ec9d16 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/NodeModel.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + +import org.xbib.raml.yagi.framework.nodes.Node; + +/** + * Interface used by the model proxy builder + */ +public interface NodeModel { + /** + * The node this model is represented by + * + * @return The node + */ + Node getNode(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/NodeModelFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/NodeModelFactory.java new file mode 100644 index 0000000..a1da3c7 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/NodeModelFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + +import org.xbib.raml.yagi.framework.nodes.Node; + +/** + * Create a Node based model based on a Node + */ +public interface NodeModelFactory { + /** + * The model to create + * + * @param node The node + * @return The model + */ + NodeModel create(Node node); + + /** + * True if this factory create polymorphic implementations + * + * @return If the model is polymorphic + */ + boolean polymorphic(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/PackageModelBinding.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/PackageModelBinding.java new file mode 100644 index 0000000..fe2b8ba --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/PackageModelBinding.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + + +public class PackageModelBinding implements ModelBinding { + private final String packageName; + + public PackageModelBinding(String packageName) { + this.packageName = packageName; + } + + + @Override + public NodeModelFactory binding(Class clazz) { + final String simpleName = clazz.getSimpleName(); + try { + final Class aClass = Class.forName(packageName + "." + simpleName); + return new ClassNodeModelFactory((Class) aClass); + } catch (ClassNotFoundException e) { + // No binding available + return null; + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/PackageReverseBinding.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/PackageReverseBinding.java new file mode 100644 index 0000000..40f00d6 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/PackageReverseBinding.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + +public class PackageReverseBinding implements ModelReverseBinding { + private final String basePackage; + + public PackageReverseBinding(String basePackage) { + this.basePackage = basePackage; + } + + @Override + public Class reverseBindingOf(NodeModel model) { + try { + return Class.forName(basePackage + "." + model.getClass().getSimpleName()); + } catch (ClassNotFoundException e) { + return null; + } + + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/SimpleBinding.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/SimpleBinding.java new file mode 100644 index 0000000..6116f77 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/SimpleBinding.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + + +public class SimpleBinding implements ModelBinding { + + + private final Class anInterface; + private final NodeModelFactory factory; + + public SimpleBinding(Class anInterface, NodeModelFactory factory) { + this.anInterface = anInterface; + this.factory = factory; + } + + + @Override + public NodeModelFactory binding(Class clazz) { + if (anInterface.isAssignableFrom(clazz)) { + return factory; + } + return null; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/SimpleClassNameBinding.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/SimpleClassNameBinding.java new file mode 100644 index 0000000..e6cc80f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/SimpleClassNameBinding.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + +import java.util.Set; + + +public class SimpleClassNameBinding implements ModelBinding { + + private final Set simpleNames; + private final Class model; + + public SimpleClassNameBinding(Set simpleNames, Class model) { + this.simpleNames = simpleNames; + this.model = model; + } + + + @Override + public NodeModelFactory binding(Class clazz) { + if (simpleNames.contains(clazz.getSimpleName())) { + return new ClassNodeModelFactory(model); + } + return null; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/SimpleValueTransformer.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/SimpleValueTransformer.java new file mode 100644 index 0000000..8e6fab6 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/model/SimpleValueTransformer.java @@ -0,0 +1,135 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.model; + + +import org.xbib.raml.yagi.framework.nodes.BooleanNode; +import org.xbib.raml.yagi.framework.nodes.IntegerNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.util.NodeUtils; + +public enum SimpleValueTransformer { + + STRING { + @Override + public boolean accepts(Class type) { + return String.class.isAssignableFrom(type); + } + + @Override + public String adaptTo(Node valueNode, Class returnType) { + if (NodeUtils.isNull(valueNode)) { + return null; + } + if (valueNode instanceof SimpleTypeNode) { + return ((SimpleTypeNode) valueNode).getLiteralValue(); + } else { + throw new RuntimeException("Invalid node type " + valueNode.getType() + " expecting a simple type."); + } + + } + }, + BOOLEAN { + @Override + public boolean accepts(Class type) { + return Boolean.class.isAssignableFrom(type) || Boolean.TYPE.equals(type); + } + + @Override + public Boolean adaptTo(Node valueNode, Class returnType) { + if (NodeUtils.isNull(valueNode)) { + return null; + } + if (valueNode instanceof BooleanNode) { + return ((BooleanNode) valueNode).getValue(); + } + if (valueNode instanceof SimpleTypeNode) { + return Boolean.parseBoolean(((SimpleTypeNode) valueNode).getLiteralValue()); + } else { + throw new RuntimeException("Invalid node type " + valueNode.getType() + " expecting a simple type."); + } + + } + }, + INT { + @Override + public boolean accepts(Class type) { + return Integer.class.isAssignableFrom(type) || Integer.TYPE.equals(type) || + Long.class.isAssignableFrom(type) || Long.TYPE.equals(type); + } + + @Override + public Long adaptTo(Node valueNode, Class returnType) { + if (NodeUtils.isNull(valueNode)) { + return null; + } + if (valueNode instanceof IntegerNode) { + return ((IntegerNode) valueNode).getValue(); + } + if (valueNode instanceof SimpleTypeNode) { + return Long.parseLong(((SimpleTypeNode) valueNode).getLiteralValue()); + } else { + throw new RuntimeException("Invalid node type " + valueNode.getType() + " expecting a simple type."); + } + + } + }, + FLOAT { + @Override + public boolean accepts(Class type) { + return Float.class.isAssignableFrom(type) || Float.TYPE.equals(type); + } + + @Override + public Float adaptTo(Node valueNode, Class returnType) { + if (NodeUtils.isNull(valueNode)) { + return null; + } + if (valueNode instanceof SimpleTypeNode) { + return Float.parseFloat(((SimpleTypeNode) valueNode).getLiteralValue()); + } else { + throw new RuntimeException("Invalid node type " + valueNode.getType() + " expecting a simple type."); + } + + } + }, + + ENUM { + @Override + public boolean accepts(Class type) { + return type.isEnum(); + } + + @Override + public Object adaptTo(Node valueNode, Class returnType) { + if (NodeUtils.isNull(valueNode)) { + return null; + } + if (valueNode instanceof SimpleTypeNode) { + final String literalValue = ((SimpleTypeNode) valueNode).getLiteralValue(); + return Enum.valueOf((Class) returnType, literalValue); + } else { + throw new RuntimeException("Invalid node type " + valueNode.getType() + " expecting a simple type."); + } + + } + }; + + public abstract Object adaptTo(Node valueNode, Class returnType); + + public abstract boolean accepts(Class type); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/AbstractObjectNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/AbstractObjectNode.java new file mode 100644 index 0000000..6440e4a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/AbstractObjectNode.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public abstract class AbstractObjectNode extends AbstractRamlNode implements ObjectNode { + protected AbstractObjectNode(AbstractRamlNode node) { + super(node); + } + + public AbstractObjectNode() { + } + + @Override + public NodeType getType() { + return NodeType.Object; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/AbstractPosition.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/AbstractPosition.java new file mode 100644 index 0000000..a926c41 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/AbstractPosition.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + + +import org.xbib.raml.api.loader.ResourceLoaderFactory; + +public abstract class AbstractPosition implements Position { + + private final ResourceLoaderFactory resourceLoaderFactory; + + public AbstractPosition(ResourceLoaderFactory resourceLoaderFactory) { + this.resourceLoaderFactory = resourceLoaderFactory; + } + + + @Override + public Position rightShift(int offset) { + return new DefaultPosition(getIndex() + offset, getLine(), getColumn() + offset, getPath(), resourceLoaderFactory); + } + + + @Override + public Position leftShift(int offset) { + return new DefaultPosition(getIndex() - offset, getLine(), getColumn() - offset, getPath(), resourceLoaderFactory); + } + + @Override + public String toString() { + return String.format("[line=%d, col=%d]", getLine() + 1, getColumn() + 1); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/AbstractRamlNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/AbstractRamlNode.java new file mode 100644 index 0000000..eace03f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/AbstractRamlNode.java @@ -0,0 +1,84 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + + +public abstract class AbstractRamlNode extends BaseNode { + + public AbstractRamlNode() { + } + + public AbstractRamlNode(AbstractRamlNode node) { + super(node); + this.startPosition = node.startPosition; + this.endPosition = node.endPosition; + } + + + private Position endPosition; + + + private Position startPosition; + + public void setEndPosition(Position endPosition) { + this.endPosition = endPosition; + } + + public void setStartPosition(Position startPosition) { + this.startPosition = startPosition; + } + + @Override + public void setSource(Node source) { + super.setSource(source); + updatePosition(source); + } + + private void updatePosition(Node source) { + // Gets the position of the source node + Position sourceStartPosition = source.getStartPosition(); + Position sourceEndPosition = source.getEndPosition(); + + // If it is a SYIncludeNode, the current node holds the URI of the resource loaded, + // we must not replace the current node's position with the source's one without saving the URI + if (source instanceof IncludeNode) { + // Propagate resourceURI already calculated by the include resolver + // and stored in an artificial node + String resourceURI = null; + if (startPosition != null) { + resourceURI = startPosition.getIncludedResourceUri(); + } + + sourceStartPosition.setIncludedResourceUri(resourceURI); + sourceEndPosition.setIncludedResourceUri(resourceURI); + } + + this.endPosition = sourceEndPosition; + this.startPosition = sourceStartPosition; + } + + + @Override + public Position getEndPosition() { + return endPosition != null ? endPosition : DefaultPosition.emptyPosition(); + } + + + @Override + public Position getStartPosition() { + return startPosition != null ? startPosition : DefaultPosition.emptyPosition(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/AbstractStringNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/AbstractStringNode.java new file mode 100644 index 0000000..f6acb34 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/AbstractStringNode.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public abstract class AbstractStringNode extends AbstractRamlNode implements StringNode { + protected String value; + + public AbstractStringNode(String value) { + this.value = value; + } + + protected AbstractStringNode(AbstractStringNode node) { + super(node); + this.value = node.value; + } + + @Override + public String getValue() { + return value; + } + + @Override + public String getLiteralValue() { + return value; + } + + @Override + public NodeType getType() { + return NodeType.String; + } + + @Override + public String toString() { + return value; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ArrayNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ArrayNode.java new file mode 100644 index 0000000..8817c7b --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ArrayNode.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public interface ArrayNode extends Node { + /** + * Return true if the array was persisted with the json style [ "item"] + * + * @return True if it was written like ["item"] and false if it was written like: - item + */ + boolean isJsonStyle(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/BaseNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/BaseNode.java new file mode 100644 index 0000000..ab2fedd --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/BaseNode.java @@ -0,0 +1,191 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.xbib.raml.yagi.framework.util.NodeSelector; + +public abstract class BaseNode implements Node { + + private Node source; + private Node parent; + private Node contextNode; + protected List children = new ArrayList<>(); + + private List annotations = new ArrayList<>(); + + public BaseNode() { + } + + public BaseNode(BaseNode node) { + setSource(node); + final List children = new ArrayList<>(node.children); + for (Node child : children) { + addChild(child.copy()); + } + annotations = new ArrayList<>(node.annotations); + } + + @Override + public void annotate(NodeAnnotation annotation) { + this.annotations.add(annotation); + } + + @Override + public Collection annotations() { + return this.annotations; + } + + @Override + public Node getParent() { + return parent; + } + + + @Override + public List getChildren() { + return Collections.unmodifiableList(new ArrayList<>(children)); + } + + @Override + public void addChild(Node node) { + node.setParent(this); + children.add(node); + } + + @Override + public void removeChild(Node node) { + children.remove(node); + } + + @Override + public Node getRootNode() { + if (getParent() != null) + return getParent().getRootNode(); + + return this; + } + + @Override + public Node getContextNode() { + return contextNode; + } + + + @Override + public List findDescendantsWith(Class nodeType) { + final List result = new ArrayList<>(); + final List children = getChildren(); + for (Node child : children) { + if (nodeType.isAssignableFrom(child.getClass())) { + result.add(nodeType.cast(child)); + } + result.addAll(child.findDescendantsWith(nodeType)); + } + return result; + } + + + @Override + public T findAncestorWith(Class nodeType) { + Node parent = getParent(); + while (parent != null) { + if (nodeType.isAssignableFrom(parent.getClass())) { + return nodeType.cast(parent); + } + parent = parent.getParent(); + } + return null; + } + + @Override + public void replaceWith(Node newNode) { + if (this != newNode) { + replaceTree(newNode); + for (Node child : getChildren()) { + newNode.addChild(child); + } + } + } + + @Override + public void replaceTree(Node newSubTree) { + if (this != newSubTree) { + newSubTree.setSource(this); + if (getParent() != null) { + // If it has a parent replace it and the same idx + int idx = getParent().getChildren().indexOf(this); + if (idx == -1) { + // Bastard as it has a parent but is not recognized by him ;) + throw new RuntimeException("Trying to replace a bastard child node " + this.getClass().getSimpleName() + " on parent " + getParent() + "."); + } + getParent().setChild(idx, newSubTree); + } + } + } + + @Override + public void removeChildren() { + for (Node child : new ArrayList<>(children)) { + child.setParent(null); + } + children.clear(); + } + + @Override + public void setChild(int idx, Node newNode) { + children.set(idx, newNode); + newNode.setParent(this); + } + + @Override + public void addChild(int idx, Node newNode) { + children.add(idx, newNode); + newNode.setParent(this); + } + + @Override + public void setParent(Node parent) { + if (this.parent != null) { + this.parent.removeChild(this); + } + this.parent = parent; + } + + @Override + public void setSource(Node source) { + this.source = source; + } + + @Override + public Node getSource() { + return source; + } + + @Override + + public Node get(String selector) { + return NodeSelector.selectFrom(selector, this); + } + + @Override + public void setContextNode(Node node) { + this.contextNode = node; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/BooleanNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/BooleanNode.java new file mode 100644 index 0000000..48031fc --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/BooleanNode.java @@ -0,0 +1,21 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public interface BooleanNode extends SimpleTypeNode { + + Boolean getValue(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ContextProviderNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ContextProviderNode.java new file mode 100644 index 0000000..f69a106 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ContextProviderNode.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + + +/** + * Defines a scope for all its children where to search references. + */ +public interface ContextProviderNode { + /** + * Returns the node that defines the naming reference scope for this node. + * + * @return The context node for this node. + */ + + Node getContextNode(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/DefaultPosition.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/DefaultPosition.java new file mode 100644 index 0000000..6e2b82e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/DefaultPosition.java @@ -0,0 +1,90 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + + +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.api.loader.ResourceLoaderFactories; +import org.xbib.raml.api.loader.ResourceLoaderFactory; + +public class DefaultPosition extends AbstractPosition { + + public static final String ARTIFICIAL_NODE = "[artificial node]"; + private final int index; + private final int line; + private final int column; + private final String resource; + private final ResourceLoaderFactory resourceLoader; + private String includedResourceUri; + + public DefaultPosition(int index, int line, int column, String resource, ResourceLoaderFactory resourceLoaderFactory) { + super(resourceLoaderFactory); + this.index = index; + this.line = line; + this.column = column; + this.resource = resource; + this.resourceLoader = resourceLoaderFactory; + } + + @Override + public int getIndex() { + return index; + } + + @Override + public int getLine() { + return line; + } + + @Override + public int getColumn() { + return column; + } + + + @Override + public String getPath() { + return resource; + } + + public String getIncludedResourceUri() { + return includedResourceUri; + } + + @Override + public void setIncludedResourceUri(String includedResourceURI) { + this.includedResourceUri = includedResourceURI; + } + + + @Override + public ResourceLoader createResourceLoader() { + return resourceLoader.createResourceLoader(null); + } + + public static DefaultPosition emptyPosition() { + return new DefaultPosition(UNKNOWN, UNKNOWN, UNKNOWN, ARTIFICIAL_NODE, ResourceLoaderFactories.nullFactory()); + } + + public static boolean isDefaultNode(Node node) { + return node.getStartPosition().getLine() == Position.UNKNOWN + && ARTIFICIAL_NODE.equals(node.getStartPosition().getPath()) + && node.getEndPosition().getLine() == Position.UNKNOWN + && ARTIFICIAL_NODE.equals(node.getEndPosition().getPath()); + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/EmptyErrorNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/EmptyErrorNode.java new file mode 100644 index 0000000..f8e25a1 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/EmptyErrorNode.java @@ -0,0 +1,24 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public class EmptyErrorNode extends ErrorNode { + + public EmptyErrorNode() { + super("Empty document."); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ErrorNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ErrorNode.java new file mode 100644 index 0000000..a86b003 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ErrorNode.java @@ -0,0 +1,86 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +import java.util.Stack; + +public class ErrorNode extends AbstractRamlNode { + private final String errorMessage; + private String path; + + public ErrorNode(String msg) { + this.errorMessage = msg; + } + + public String getErrorMessage() { + return errorMessage; + } + + + public String getPath() { + if (path == null) { + Node previousNode = this; + Node currentNode = previousNode.getParent(); + Stack keysStack = new Stack<>(); + + while (currentNode != null) { + if (currentNode instanceof ArrayNode) { + // In order to get the index of the node containing the error, we compare the previous + // node (which is an element of the array) in the tree with all the children of the current node + keysStack.push(String.valueOf(currentNode.getChildren().indexOf(previousNode))); + } else if (currentNode instanceof KeyValueNode) { + Node key = ((KeyValueNode) currentNode).getKey(); + if (key != null) { + if (key instanceof SimpleTypeNode) { + String currentKey = ((SimpleTypeNode) key).getLiteralValue().replace("/", "~1"); + keysStack.push(currentKey); + } + } + } + previousNode = currentNode; + currentNode = currentNode.getParent(); + } + + // Creating the path + StringBuilder fullPath = new StringBuilder(); + + while (!keysStack.isEmpty()) { + fullPath.append("/").append(keysStack.pop()); + } + + path = fullPath.length() > 0 ? fullPath.toString() : "/"; + } + + return path; + } + + + @Override + public Node copy() { + return this; + } + + + @Override + public NodeType getType() { + return NodeType.Error; + } + + @Override + public String toString() { + return String.format("%s [%s]", getClass().getSimpleName(), getErrorMessage()); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ExecutableNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ExecutableNode.java new file mode 100644 index 0000000..542b26c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ExecutableNode.java @@ -0,0 +1,21 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public interface ExecutableNode extends Node { + + Node execute(ExecutionContext context); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ExecutionContext.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ExecutionContext.java new file mode 100644 index 0000000..443c8f7 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ExecutionContext.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +import java.util.Map; + + +public class ExecutionContext { + + private final Map parameters; + private final Node contextNode; + + public ExecutionContext(Map parameters, Node contextNode) { + this.parameters = parameters; + this.contextNode = contextNode; + } + + public void addVariable(String name, Node value) { + parameters.put(name, value); + } + + + public Node getVariable(String name) { + return parameters.get(name); + } + + public boolean containsVariable(String variable) { + return parameters.containsKey(variable); + } + + public Node getContextNode() { + return contextNode; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/FloatingNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/FloatingNode.java new file mode 100644 index 0000000..889acad --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/FloatingNode.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +import java.math.BigDecimal; + +public interface FloatingNode extends SimpleTypeNode { + BigDecimal getValue(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/IncludeErrorNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/IncludeErrorNode.java new file mode 100644 index 0000000..1120915 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/IncludeErrorNode.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public class IncludeErrorNode extends ErrorNode { + public IncludeErrorNode(String msg) { + super(msg); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/IncludeNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/IncludeNode.java new file mode 100644 index 0000000..5fedf11 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/IncludeNode.java @@ -0,0 +1,23 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public interface IncludeNode { + + String getIncludePath(); + + String getIncludedType(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/IntegerNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/IntegerNode.java new file mode 100644 index 0000000..e888856 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/IntegerNode.java @@ -0,0 +1,20 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public interface IntegerNode extends SimpleTypeNode { + Long getValue(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/KeyValueNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/KeyValueNode.java new file mode 100644 index 0000000..a909010 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/KeyValueNode.java @@ -0,0 +1,25 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public interface KeyValueNode extends Node { + + Node getKey(); + + Node getValue(); + + void setValue(Node valueNode); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/KeyValueNodeImpl.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/KeyValueNodeImpl.java new file mode 100644 index 0000000..9f40167 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/KeyValueNodeImpl.java @@ -0,0 +1,115 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public class KeyValueNodeImpl extends BaseNode implements KeyValueNode { + private Position startPosition; + private Position endPosition; + + public KeyValueNodeImpl() { + } + + public KeyValueNodeImpl(Node keyNode, Node valueNode) { + addChild(keyNode); + addChild(valueNode); + } + + public KeyValueNodeImpl(KeyValueNodeImpl node) { + super(node); + } + + + @Override + public Position getStartPosition() { + if (startPosition == null) { + if (getChildren().size() != 2) { + return DefaultPosition.emptyPosition(); + } else { + return getChildren().get(0).getStartPosition(); + } + } else { + return startPosition; + } + } + + + @Override + public Position getEndPosition() { + if (endPosition == null) { + if (getChildren().size() != 2) { + return DefaultPosition.emptyPosition(); + } else { + return getValue().getEndPosition(); + } + } else { + return endPosition; + } + } + + public void setStartPosition(Position startPosition) { + this.startPosition = startPosition; + } + + public void setEndPosition(Position endPosition) { + this.endPosition = endPosition; + } + + @Override + public void addChild(Node node) { + if (getChildren().size() >= 2) { + throw new IllegalStateException("Can not add '" + node + "' to " + this + " node. It already has key and value."); + } + super.addChild(node); + } + + + @Override + public Node copy() { + return new KeyValueNodeImpl(this); + } + + @Override + public Node getKey() { + if (getChildren().isEmpty()) { + throw new IllegalStateException("Key value pair with no key " + getClass().getSimpleName()); + } + return getChildren().get(0); + } + + @Override + public Node getValue() { + if (getChildren().size() < 2) { + throw new IllegalStateException("Key value pair with no value " + getClass().getSimpleName()); + } + return getChildren().get(1); + } + + @Override + public void setValue(Node valueNode) { + setChild(1, valueNode); + } + + @Override + public String toString() { + return String.format("%s: %s", getKey(), getValue()); + } + + + @Override + public NodeType getType() { + return NodeType.KeyValue; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NamedNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NamedNode.java new file mode 100644 index 0000000..f4fceeb --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NamedNode.java @@ -0,0 +1,22 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public interface NamedNode extends Node { + + String getName(); + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/Node.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/Node.java new file mode 100644 index 0000000..7238fa4 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/Node.java @@ -0,0 +1,195 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +import java.util.Collection; +import java.util.List; + +public interface Node { + + /** + * The start position of this node + * + * @return The position + */ + Position getStartPosition(); + + /** + * The end position of this node + * + * @return The position + */ + Position getEndPosition(); + + /** + * The ancestor that does not has any parent. It is the first node that it parent returns null in the parent path. + * + * @return The root node. + */ + Node getRootNode(); + + /** + * The parent of this node + * + * @return The parent + */ + Node getParent(); + + /** + * All the children + * + * @return The Children + */ + + List getChildren(); + + /** + * Adds a new child. The new child is going to have this as a parent + * + * @param node Adds a new child to this node + */ + void addChild(Node node); + + /** + * Removes a child. The new child is going to have this as a parent + * + * @param node Adds a new child to this node + */ + void removeChild(Node node); + + /** + * Sets the parent node to this node. + * + * @param parent The new parent node + */ + void setParent(Node parent); + + /** + * The source of this node. This is used at transformation phases when the original Yaml node are being replaced by a more specialized node. + * This way the node specialization can be tracked on all the history changes. + * + * @param source The original node. + */ + void setSource(Node source); + + /** + * Returns the list of descendants nodes that are instances of the specified class + * + * @param nodeType The class that the node should implement + * @param The type of the class + * @return The matching types + */ + + List findDescendantsWith(Class nodeType); + + /** + * Returns the nearest ancestor node that is instance of the specified class + * + * @param nodeType The class that the node should implement + * @param The type of the class + * @return The matching type or null if none + */ + + T findAncestorWith(Class nodeType); + + /** + * Return the source of this node. + * + * @return The source cause. + */ + + Node getSource(); + + /** + * Returns the child node that matches the desired selector or null if there is no match + */ + + Node get(String selector); + + /** + * Replace this node in the tree with a new specialized node. The new node will have as a source this node. + * + * @param newNode The new node + */ + void replaceWith(Node newNode); + + /** + * Sets a child at a specified index. The new child is going to have this as a parent + * + * @param idx The index + * @param newNode The new child + */ + void setChild(int idx, Node newNode); + + /** + * Adds a child at a specified index. The new child is going to have this as a parent + * + * @param idx The index + * @param newNode The new child + */ + void addChild(int idx, Node newNode); + + /** + * Creates a new copy of this node + * + * @return a new copy of this node + */ + + Node copy(); + + /** + * Returns the type of this node + * + * @return The node type + */ + NodeType getType(); + + /** + * Removes all the children of this given node. + */ + void removeChildren(); + + /** + * Adds an annotation to this node + * + * @param annotation The annotation + */ + void annotate(NodeAnnotation annotation); + + /** + * Returns all the annotations of this node + * + * @return All the annotations + */ + Collection annotations(); + + /** + * Replace this subtree with the given one. Current children are not going to be transferred to the new one + * + * @param newSubTree The new subtree + */ + void replaceTree(Node newSubTree); + + /** + * Sets the context node. This is used to provide a global context when parsing an isolated fragment, i.e without + * parent node. + * + * @param node The root node. + */ + void setContextNode(Node node); + + Node getContextNode(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NodeAnnotation.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NodeAnnotation.java new file mode 100644 index 0000000..5c9c41c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NodeAnnotation.java @@ -0,0 +1,21 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + + +public interface NodeAnnotation { + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NodeType.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NodeType.java new file mode 100644 index 0000000..8b04c56 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NodeType.java @@ -0,0 +1,29 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public enum NodeType { + Object, + Array, + String, + Integer, + Float, + Boolean, + Null, + KeyValue, + Reference, + Error +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NullNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NullNode.java new file mode 100644 index 0000000..129190a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NullNode.java @@ -0,0 +1,19 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public interface NullNode extends Node { +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NullNodeImpl.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NullNodeImpl.java new file mode 100644 index 0000000..9ec6eaa --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/NullNodeImpl.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + + +public class NullNodeImpl extends AbstractRamlNode implements NullNode { + + public NullNodeImpl() { + } + + protected NullNodeImpl(AbstractRamlNode node) { + super(node); + } + + + @Override + public Node copy() { + return new NullNodeImpl(this); + } + + @Override + public NodeType getType() { + return NodeType.Null; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ObjectNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ObjectNode.java new file mode 100644 index 0000000..566adf1 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ObjectNode.java @@ -0,0 +1,20 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public interface ObjectNode extends Node { + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ObjectNodeImpl.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ObjectNodeImpl.java new file mode 100644 index 0000000..a42e6b6 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ObjectNodeImpl.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + + +public class ObjectNodeImpl extends AbstractObjectNode implements ObjectNode { + + public ObjectNodeImpl() { + } + + protected ObjectNodeImpl(AbstractRamlNode node) { + super(node); + } + + + @Override + public Node copy() { + return new ObjectNodeImpl(this); + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/Position.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/Position.java new file mode 100644 index 0000000..669db40 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/Position.java @@ -0,0 +1,78 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +import org.xbib.raml.api.loader.ResourceLoader; + +/** + * The position of a given node in a specific resource + */ +public interface Position { + int UNKNOWN = -1; + + /** + * The offset from the begining of the file + * + * @return The offset + */ + int getIndex(); + + /** + * The line line number + * + * @return line number + */ + int getLine(); + + /** + * Column number + * + * @return The column number + */ + int getColumn(); + + /** + * Returns the absolute path of the resource where this position is relative to + * + * @return The absolute path + */ + + String getPath(); + + /** + * Returns the resource URI of the current position + * + * @return The resource URI if it is included, null if not + */ + + String getIncludedResourceUri(); + + /** + * Sets the URI of the resource in the current position + * + * @param includedResourceURI The resource URI + */ + void setIncludedResourceUri(String includedResourceURI); + + + Position rightShift(int offset); + + + Position leftShift(int offset); + + + ResourceLoader createResourceLoader(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ReferenceNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ReferenceNode.java new file mode 100644 index 0000000..4d68572 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/ReferenceNode.java @@ -0,0 +1,25 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + + +public interface ReferenceNode extends Node { + + String getRefName(); + + + Node getRefNode(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/SimpleTypeNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/SimpleTypeNode.java new file mode 100644 index 0000000..1cd4c04 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/SimpleTypeNode.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public interface SimpleTypeNode extends Node { + + /** + * @return the value of the node + */ + T getValue(); + + /** + * in some cases the value of the node is different than the literal one + * e.g: (literal value) -> (value) + * 001 -> 1 + * 0xF -> 15 + * + * @return the literal value of the node + */ + String getLiteralValue(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/StringNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/StringNode.java new file mode 100644 index 0000000..d8cc60c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/StringNode.java @@ -0,0 +1,20 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + +public interface StringNode extends SimpleTypeNode { + String getValue(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/StringNodeImpl.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/StringNodeImpl.java new file mode 100644 index 0000000..239eef8 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/StringNodeImpl.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + + +public class StringNodeImpl extends AbstractStringNode { + + public StringNodeImpl(String value) { + super(value); + } + + protected StringNodeImpl(StringNodeImpl node) { + super(node); + } + + + @Override + public Node copy() { + return new StringNodeImpl(this); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/WarningMessageAnnotation.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/WarningMessageAnnotation.java new file mode 100644 index 0000000..4b088af --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/WarningMessageAnnotation.java @@ -0,0 +1,29 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes; + + +public class WarningMessageAnnotation implements NodeAnnotation { + private final String message; + + public WarningMessageAnnotation(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JArrayNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JArrayNode.java new file mode 100644 index 0000000..bbcf218 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JArrayNode.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.jackson; + + +import java.util.List; +import java.util.stream.Collectors; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; + +public class JArrayNode extends JBaseRamlNode implements ArrayNode { + + public JArrayNode(com.fasterxml.jackson.databind.node.ArrayNode arrayNode, String resourcePath, ResourceLoader resourceLoader) { + super(arrayNode, resourcePath, resourceLoader); + } + + private JArrayNode(JArrayNode node) { + super(node); + } + + @Override + public String toString() { + final List children = getChildren(); + final String join = children.stream().map(Object::toString).collect(Collectors.joining(", ")); + return "Array[" + join + "]"; + } + + + @Override + public Node copy() { + return new JArrayNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Array; + } + + @Override + public boolean isJsonStyle() { + return true; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JBaseRamlNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JBaseRamlNode.java new file mode 100644 index 0000000..5991a47 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JBaseRamlNode.java @@ -0,0 +1,76 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.jackson; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.NumericNode; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.BaseNode; +import org.xbib.raml.yagi.framework.nodes.DefaultPosition; +import org.xbib.raml.yagi.framework.nodes.Position; + +public abstract class JBaseRamlNode extends BaseNode { + + private final JsonNode jsonNode; + private final String resourcePath; + private final ResourceLoader resourceLoader; + + public JBaseRamlNode(JsonNode jsonNode, String resourcePath, ResourceLoader resourceLoader) { + this.jsonNode = jsonNode; + this.resourcePath = resourcePath; + this.resourceLoader = resourceLoader; + } + + protected JBaseRamlNode(JBaseRamlNode node) { + super(node); + this.jsonNode = node.getJsonNode(); + this.resourcePath = node.getResourcePath(); + this.resourceLoader = node.getResourceLoader(); + } + + public JsonNode getJsonNode() { + return jsonNode; + } + + public String getResourcePath() { + return resourcePath; + } + + public ResourceLoader getResourceLoader() { + return resourceLoader; + } + + + public String getLiteralValue() { + if (jsonNode instanceof NumericNode) { + return (getJsonNode()).textValue(); + } + return getJsonNode().textValue(); + } + + + @Override + public Position getStartPosition() { + return DefaultPosition.emptyPosition(); + } + + + @Override + public Position getEndPosition() { + return DefaultPosition.emptyPosition(); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JBooleanNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JBooleanNode.java new file mode 100644 index 0000000..efccf7c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JBooleanNode.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.jackson; + + +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.BooleanNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; + +public class JBooleanNode extends JBaseRamlNode implements BooleanNode { + + protected JBooleanNode(JBooleanNode node) { + super(node); + } + + public JBooleanNode(com.fasterxml.jackson.databind.node.BooleanNode booleanNode, String resourcePath, ResourceLoader resourceLoader) { + super(booleanNode, resourcePath, resourceLoader); + } + + @Override + public Boolean getValue() { + return getJsonNode().booleanValue(); + } + + @Override + public String toString() { + return String.valueOf(getValue()); + } + + + @Override + public Node copy() { + return new JBooleanNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Boolean; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JFloatingNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JFloatingNode.java new file mode 100644 index 0000000..1c348d1 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JFloatingNode.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.jackson; + +import com.fasterxml.jackson.databind.node.NumericNode; +import java.math.BigDecimal; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.FloatingNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; + +public class JFloatingNode extends JBaseRamlNode implements FloatingNode { + + protected JFloatingNode(JFloatingNode node) { + super(node); + } + + public JFloatingNode(NumericNode jsonNode, String resourcePath, ResourceLoader resourceLoader) { + super(jsonNode, resourcePath, resourceLoader); + } + + @Override + public BigDecimal getValue() { + return getJsonNode().decimalValue(); + } + + @Override + public String toString() { + return String.valueOf(getValue()); + } + + + @Override + public Node copy() { + return new JFloatingNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Float; + } + + @Override + public NumericNode getJsonNode() { + return (NumericNode) super.getJsonNode(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JIntegerNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JIntegerNode.java new file mode 100644 index 0000000..c93227a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JIntegerNode.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.jackson; + +import com.fasterxml.jackson.databind.node.IntNode; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.IntegerNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; + +public class JIntegerNode extends JBaseRamlNode implements IntegerNode { + + public JIntegerNode(IntNode integerNode, String resourcePath, ResourceLoader resourceLoader) { + super(integerNode, resourcePath, resourceLoader); + } + + protected JIntegerNode(JIntegerNode node) { + super(node); + } + + @Override + public Long getValue() { + return getJsonNode().longValue(); + } + + @Override + public String toString() { + return String.valueOf(getValue()); + } + + + @Override + public Node copy() { + return new JIntegerNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Integer; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JModelWrapper.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JModelWrapper.java new file mode 100644 index 0000000..e50d25c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JModelWrapper.java @@ -0,0 +1,104 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.jackson; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.BooleanNode; +import com.fasterxml.jackson.databind.node.IntNode; +import com.fasterxml.jackson.databind.node.NullNode; +import com.fasterxml.jackson.databind.node.NumericNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; +import java.util.Iterator; +import java.util.Map; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class JModelWrapper { + private final ResourceLoader resourceLoader; + private final String resourcePath; + + public JModelWrapper(ResourceLoader resourceLoader, String resourcePath) { + this.resourceLoader = resourceLoader; + this.resourcePath = resourcePath; + } + + public Node wrap(JsonNode node) { + switch (node.getNodeType()) { + case ARRAY: + return wrap((ArrayNode) node); + case OBJECT: + return wrap((ObjectNode) node); + case BOOLEAN: + return wrap((BooleanNode) node); + case NULL: + return wrap((NullNode) node); + case NUMBER: + if (node instanceof IntNode) { + return wrap((IntNode) node); + } + return wrap((NumericNode) node); + case STRING: + return wrap((TextNode) node); + default: + return null; + } + } + + private JObjectNode wrap(ObjectNode objectNode) { + JObjectNode object = new JObjectNode(objectNode, resourcePath, resourceLoader); + Iterator> fields = objectNode.fields(); + + while (fields.hasNext()) { + Map.Entry node = fields.next(); + Node key = wrap(new TextNode(node.getKey())); + Node value = wrap(node.getValue()); + KeyValueNodeImpl keyValue = new KeyValueNodeImpl(key, value); + object.addChild(keyValue); + } + return object; + } + + private JArrayNode wrap(ArrayNode arrayNode) { + JArrayNode array = new JArrayNode(arrayNode, resourcePath, resourceLoader); + for (JsonNode node : arrayNode) { + array.addChild(wrap(node)); + } + return array; + } + + private JStringNode wrap(TextNode stringNode) { + return new JStringNode(stringNode, resourcePath, resourceLoader); + } + + private JIntegerNode wrap(IntNode integerNode) { + return new JIntegerNode(integerNode, resourcePath, resourceLoader); + } + + private JFloatingNode wrap(NumericNode numericNode) { + return new JFloatingNode(numericNode, resourcePath, resourceLoader); + } + + private JNullNode wrap(NullNode nullNode) { + return new JNullNode(nullNode, resourcePath, resourceLoader); + } + + private JBooleanNode wrap(BooleanNode booleanNode) { + return new JBooleanNode(booleanNode, resourcePath, resourceLoader); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JNodeParser.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JNodeParser.java new file mode 100644 index 0000000..57caa84 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JNodeParser.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.jackson; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import static org.xbib.raml.yagi.framework.nodes.jackson.JsonUtils.parseJson; + +public class JNodeParser { + + + public static Node parse(ResourceLoader resourceLoader, String resourcePath, Reader reader) { + try { + JsonNode rootNode = parseJson(reader); + return new JModelWrapper(resourceLoader, resourcePath).wrap(rootNode); + } catch (JsonMappingException | JsonParseException e) { + return ErrorNodeFactory.createInvalidJsonExampleNode(e.getOriginalMessage()); + } catch (IOException e) { + return new ErrorNode(e.getMessage()); + } + + } + + + public static Node parse(ResourceLoader resourceLoader, String resourcePath, String content) { + return parse(resourceLoader, resourcePath, new StringReader(content)); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JNullNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JNullNode.java new file mode 100644 index 0000000..9f92b2b --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JNullNode.java @@ -0,0 +1,48 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.jackson; + + +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.NullNode; + +public class JNullNode extends JBaseRamlNode implements NullNode { + + public JNullNode(com.fasterxml.jackson.databind.node.NullNode jsonNode, String resourcePath, ResourceLoader resourceLoader) { + super(jsonNode, resourcePath, resourceLoader); + } + + protected JNullNode(JNullNode node) { + super(node); + } + + + @Override + public org.xbib.raml.yagi.framework.nodes.Node copy() { + return new JNullNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Null; + } + + @Override + public String toString() { + return "JNullNode"; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JObjectNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JObjectNode.java new file mode 100644 index 0000000..7565168 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JObjectNode.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.jackson; + + +import java.util.stream.Collectors; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; + +public class JObjectNode extends JBaseRamlNode implements ObjectNode { + + public JObjectNode(com.fasterxml.jackson.databind.node.ObjectNode objectNode, String resourcePath, ResourceLoader resourceLoader) { + super(objectNode, resourcePath, resourceLoader); + } + + protected JObjectNode(JObjectNode node) { + super(node); + } + + @Override + public String toString() { + return "{\n" + getChildren().stream().map(Object::toString).collect(Collectors.joining("\n")) + "\n}"; + } + + + @Override + public Node copy() { + return new JObjectNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Object; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JStringNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JStringNode.java new file mode 100644 index 0000000..0c125c0 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JStringNode.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.jackson; + +import com.fasterxml.jackson.databind.node.TextNode; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.StringNode; + +public class JStringNode extends JBaseRamlNode implements StringNode { + + public JStringNode(TextNode textNode, String resourcePath, ResourceLoader resourceLoader) { + super(textNode, resourcePath, resourceLoader); + } + + protected JStringNode(JStringNode node) { + super(node); + } + + @Override + public String getValue() { + return getJsonNode().textValue(); + } + + + @Override + public Node copy() { + return new JStringNode(this); + } + + @Override + public String toString() { + return getValue(); + } + + @Override + public NodeType getType() { + return NodeType.String; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JsonUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JsonUtils.java new file mode 100644 index 0000000..944f21a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/jackson/JsonUtils.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.jackson; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + +public class JsonUtils { + private static final String JSON_STRICT_DUPLICATE_DETECTION_PROPERTY = "yagi.json_duplicate_keys_detection"; + private static final boolean STRICT_DUPLICATE_DETECTION_VALUE = + Boolean.valueOf(System.getProperty(JSON_STRICT_DUPLICATE_DETECTION_PROPERTY, "true")); + + + public static JsonNode parseJson(String value) throws IOException { + return parseJson(new StringReader(value)); + } + + public static JsonNode parseJson(Reader reader) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + mapper.disableDefaultTyping(); + mapper.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, STRICT_DUPLICATE_DETECTION_VALUE); + return mapper.readValue(reader, JsonNode.class); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/LimitsException.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/LimitsException.java new file mode 100644 index 0000000..ba70352 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/LimitsException.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + +import org.yaml.snakeyaml.error.Mark; + +/** + * Created. There, you have it. + */ +public class LimitsException extends RuntimeException { + + private final String message; + private final Mark startMark; + + public LimitsException(String message, Mark startMark) { + + super(message); + this.message = message; + this.startMark = startMark; + } + + public Mark getStartMark() { + return startMark; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/NodeParser.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/NodeParser.java new file mode 100644 index 0000000..54404f9 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/NodeParser.java @@ -0,0 +1,81 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + +import java.io.Reader; +import java.io.StringReader; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.api.loader.ResourceLoaderFactories; +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.nodes.DefaultPosition; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.error.Mark; +import org.yaml.snakeyaml.error.MarkedYAMLException; +import org.yaml.snakeyaml.reader.ReaderException; + +public class NodeParser { + + + public static Node parse(ResourceLoader resourceLoader, String resourcePath, Reader reader) { + + SmartReader smartReader = new SmartReader(reader); + + try { + Yaml yamlParser = new Yaml(); + org.yaml.snakeyaml.nodes.Node composedNode = yamlParser.compose(smartReader); + if (composedNode == null) { + return null; + } else { + try { + return new SYModelWrapper(resourceLoader, resourcePath).wrap(composedNode, 0); + } catch (LimitsException e) { + + return ErrorNodeFactory.limitsExceptionThrown(e); + } + } + } catch (final MarkedYAMLException e) { + return buildYamlErrorNode(e, resourcePath, resourceLoader); + } catch (ReaderException e) { + + return buildYamlErrorNode(e, smartReader); + } + } + + private static Node buildYamlErrorNode(MarkedYAMLException e, String resourcePath, ResourceLoader resourceLoader) { + final ErrorNode errorNode = new ErrorNode("Underlying error while parsing YAML syntax: '" + e.getMessage() + "'"); + final Mark problemMark = e.getProblemMark(); + errorNode.setStartPosition(new DefaultPosition(problemMark.getIndex(), problemMark.getLine(), 0, resourcePath, ResourceLoaderFactories.identityFactory(resourceLoader))); + errorNode.setEndPosition(new DefaultPosition(problemMark.getIndex() + 1, problemMark.getLine(), problemMark.getColumn(), resourcePath, ResourceLoaderFactories.identityFactory(resourceLoader))); + return errorNode; + } + + private static Node buildYamlErrorNode(ReaderException e, SmartReader reader) { + + final ErrorNode errorNode = new ErrorNode("Underlying error while parsing YAML syntax: '" + e + " around: " + reader.getLastValidString() + "'"); + // errorNode.setStartPosition(new DefaultPosition(e.getPosition(), 0, 0, resourcePath, new DefaultResourceLoader())); + // errorNode.setEndPosition(new DefaultPosition(e.getPosition() + 1, 0,0, resourcePath, new DefaultResourceLoader())); + return errorNode; + } + + + public static Node parse(ResourceLoader resourceLoader, String resourcePath, String content) { + return parse(resourceLoader, resourcePath, new StringReader(content)); + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/RamlParsingLimitsController.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/RamlParsingLimitsController.java new file mode 100644 index 0000000..8c92711 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/RamlParsingLimitsController.java @@ -0,0 +1,92 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.Set; + +/** + * Created. There, you have it. + */ +public class RamlParsingLimitsController { + + private final static boolean shouldVerify = Boolean.parseBoolean(System.getProperty("raml.verifyRaml", "true")); + private final static boolean cycleCheck = Boolean.parseBoolean(System.getProperty("raml.verifyReferenceCycle", "true")); + + private final static int maxRamlDepth = Integer.parseInt(System.getProperty("raml.maxDepth", "2000")); + private final static int maxRamlReferences = Integer.parseInt(System.getProperty("raml.maxReferences", "10000")); + + private final IdentityHashMap seenNodes = new IdentityHashMap<>(); + private final Set currentlyHandling = new HashSet<>(); + + + private final boolean verify; + private final int maxDepth; + private final int maxReferences; + private final boolean verifyCycle; + + public RamlParsingLimitsController(boolean verify, int maxDepth, int maxRamlReferences, boolean verifyCycle) { + this.verify = verify; + this.maxDepth = maxDepth; + this.maxReferences = maxRamlReferences; + this.verifyCycle = verifyCycle; + } + + public RamlParsingLimitsController() { + + verify = shouldVerify; + maxDepth = maxRamlDepth; + maxReferences = maxRamlReferences; + verifyCycle = cycleCheck; + } + + public void verifyNode(org.yaml.snakeyaml.nodes.Node node, int depth) { + + try { + if (!verify) { + return; + } + + if (verifyCycle && currentlyHandling.contains(node)) { + + throw new LimitsException("cycle detected", node.getStartMark()); + } else { + + currentlyHandling.add(node); + } + + if (depth > maxDepth) { + throw new LimitsException("maximum depth exceeded: " + maxDepth, node.getStartMark()); + } + + if (seenNodes.containsKey(node)) { + + seenNodes.put(node, seenNodes.get(node) + 1); + } else { + + seenNodes.put(node, 1); + } + + if (seenNodes.get(node) > maxReferences) { + + throw new LimitsException("reference count exceeded: " + maxReferences, node.getStartMark()); + } + } finally { + currentlyHandling.remove(node); + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYArrayNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYArrayNode.java new file mode 100644 index 0000000..c2e364f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYArrayNode.java @@ -0,0 +1,61 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + +import java.util.List; +import java.util.stream.Collectors; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.nodes.SequenceNode; + +public class SYArrayNode extends SYBaseRamlNode implements ArrayNode { + // For copy + private SYArrayNode(SYArrayNode node) { + super(node); + } + + public SYArrayNode(SequenceNode sequenceNode, String resourcePath, ResourceLoader resourceLoader) { + super(sequenceNode, resourcePath, resourceLoader); + } + + @Override + public String toString() { + + final List children = getChildren(); + final String join = children.stream().map(Object::toString).collect(Collectors.joining(", ")); + return "Array[" + join + "]"; + } + + + @Override + public Node copy() { + return new SYArrayNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Array; + } + + + @Override + public boolean isJsonStyle() { + return ((SequenceNode) getYamlNode()).getFlowStyle() != DumperOptions.FlowStyle.BLOCK; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYBaseRamlNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYBaseRamlNode.java new file mode 100644 index 0000000..2e353b8 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYBaseRamlNode.java @@ -0,0 +1,82 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + + +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.api.loader.ResourceLoaderFactories; +import org.xbib.raml.yagi.framework.nodes.BaseNode; +import org.xbib.raml.yagi.framework.nodes.Position; +import org.yaml.snakeyaml.nodes.Node; +import org.yaml.snakeyaml.nodes.ScalarNode; + +public abstract class SYBaseRamlNode extends BaseNode { + + private final Node yamlNode; + private final String resourcePath; + private final ResourceLoader resourceLoader; + + // For copy use cases + protected SYBaseRamlNode(SYBaseRamlNode node) { + super(node); + this.yamlNode = node.yamlNode; + this.resourcePath = node.getResourcePath(); + this.resourceLoader = node.getResourceLoader(); + } + + public SYBaseRamlNode(Node yamlNode, String resourcePath, ResourceLoader resourceLoader) { + this.yamlNode = yamlNode; + this.resourcePath = resourcePath; + this.resourceLoader = resourceLoader; + } + + protected Node getYamlNode() { + return yamlNode; + } + + public String getResourcePath() { + return resourcePath; + } + + + @Override + public Position getStartPosition() { + return new SYPosition(yamlNode.getStartMark(), ResourceLoaderFactories.identityFactory(resourceLoader), resourcePath); + } + + + @Override + public Position getEndPosition() { + return new SYPosition(yamlNode.getEndMark(), ResourceLoaderFactories.identityFactory(resourceLoader), resourcePath); + } + + + public String getLiteralValue() { + if (yamlNode instanceof ScalarNode) { + return ((ScalarNode) getYamlNode()).getValue(); + } + return null; + } + + @Override + public String toString() { + return getLiteralValue(); + } + + public ResourceLoader getResourceLoader() { + return resourceLoader; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYBooleanNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYBooleanNode.java new file mode 100644 index 0000000..cd51ec9 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYBooleanNode.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + + +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.BooleanNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.yaml.snakeyaml.nodes.ScalarNode; + +public class SYBooleanNode extends SYBaseRamlNode implements BooleanNode { + + public SYBooleanNode(SYBooleanNode node) { + super(node); + } + + public SYBooleanNode(ScalarNode scalarNode, String resourcePath, ResourceLoader resourceLoader) { + super(scalarNode, resourcePath, resourceLoader); + } + + public Boolean getValue() { + final String value = ((ScalarNode) getYamlNode()).getValue(); + return Boolean.parseBoolean(value); + } + + + @Override + public Node copy() { + return new SYBooleanNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Boolean; + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYFloatingNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYFloatingNode.java new file mode 100644 index 0000000..c654799 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYFloatingNode.java @@ -0,0 +1,55 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + +import java.math.BigDecimal; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.FloatingNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.yaml.snakeyaml.nodes.ScalarNode; + +public class SYFloatingNode extends SYBaseRamlNode implements FloatingNode { + public SYFloatingNode(SYFloatingNode node) { + super(node); + } + + public SYFloatingNode(ScalarNode yamlNode, String resourcePath, ResourceLoader resourceLoader) { + super(yamlNode, resourcePath, resourceLoader); + } + + @Override + public BigDecimal getValue() { + final String value = ((ScalarNode) getYamlNode()).getValue(); + return new BigDecimal(value); + } + + @Override + public String toString() { + return ((ScalarNode) getYamlNode()).getValue(); + } + + + @Override + public Node copy() { + return new SYFloatingNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Float; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYIncludeNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYIncludeNode.java new file mode 100644 index 0000000..7560582 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYIncludeNode.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + + +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.IncludeNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.yaml.snakeyaml.nodes.ScalarNode; + +public class SYIncludeNode extends SYStringNode implements IncludeNode { + + private SYIncludeNode(SYIncludeNode node) { + super(node); + } + + public SYIncludeNode(ScalarNode scalarNode, String resourcePath, ResourceLoader resourceLoader) { + super(scalarNode, resourcePath, resourceLoader); + } + + @Override + public String getIncludePath() { + return getValue(); + } + + @Override + public String getIncludedType() { + String[] parts; + parts = this.getValue().split("#"); + if (parts.length == 2) { + return parts[1]; + } else + return null; + } + + + @Override + public Node copy() { + return new SYIncludeNode(this); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYIntegerNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYIntegerNode.java new file mode 100644 index 0000000..ab0a9dd --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYIntegerNode.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + + +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.IntegerNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.yaml.snakeyaml.nodes.ScalarNode; + +public class SYIntegerNode extends SYBaseRamlNode implements IntegerNode { + + // For copy + private SYIntegerNode(SYIntegerNode node) { + super(node); + } + + public SYIntegerNode(ScalarNode scalarNode, String resourcePath, ResourceLoader resourceLoader) { + super(scalarNode, resourcePath, resourceLoader); + } + + public Long getValue() { + final String value = ((ScalarNode) getYamlNode()).getValue(); + if (value != null && (value.startsWith("0x") || value.startsWith("0X"))) { + return Long.valueOf(value.substring(2), 16); + } + return Long.valueOf(value); + } + + + @Override + public Node copy() { + return new SYIntegerNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Integer; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYModelWrapper.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYModelWrapper.java new file mode 100644 index 0000000..358f8a4 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYModelWrapper.java @@ -0,0 +1,122 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.KeyValueNodeImpl; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.constructor.SafeConstructor; +import org.yaml.snakeyaml.nodes.MappingNode; +import org.yaml.snakeyaml.nodes.NodeTuple; +import org.yaml.snakeyaml.nodes.ScalarNode; +import org.yaml.snakeyaml.nodes.SequenceNode; +import org.yaml.snakeyaml.nodes.Tag; +import static org.yaml.snakeyaml.nodes.NodeId.mapping; +import static org.yaml.snakeyaml.nodes.NodeId.scalar; +import static org.yaml.snakeyaml.nodes.NodeId.sequence; + +public class SYModelWrapper { + + private final ResourceLoader resourceLoader; + private final String resourcePath; + private final RamlParsingLimitsController controller = new RamlParsingLimitsController(); + + public SYModelWrapper(ResourceLoader resourceLoader, String resourcePath) { + this.resourceLoader = resourceLoader; + this.resourcePath = resourcePath; + } + + private static class MappingNodeMerger extends SafeConstructor { + MappingNodeMerger(LoaderOptions loaderOptions) { + super(loaderOptions); + } + + void merge(MappingNode mappingNode) { + flattenMapping(mappingNode); + } + } + + public static final Tag INCLUDE_TAG = new Tag("!include"); + + public Node wrap(org.yaml.snakeyaml.nodes.Node node, int depth) { + controller.verifyNode(node, depth); + + if (node.getNodeId() == mapping) { + return wrap((MappingNode) node, depth); + } + if (node.getNodeId() == sequence) { + return wrap((SequenceNode) node, depth); + } + if (node.getNodeId() == scalar) { + return wrap((ScalarNode) node); + } else { + throw new IllegalStateException("Invalid node type"); + } + } + + + private SYObjectNode wrap(MappingNode mappingNode, int depth) { + if (mappingNode.isMerged()) { + new MappingNodeMerger(null).merge(mappingNode); + } + SYObjectNode mapping = new SYObjectNode(mappingNode, resourceLoader, resourcePath); + for (NodeTuple nodeTuple : mappingNode.getValue()) { + Node key = wrap(nodeTuple.getKeyNode(), depth + 1); + Node value = wrap(nodeTuple.getValueNode(), depth + 1); + KeyValueNodeImpl keyValue = new KeyValueNodeImpl(key, value); + mapping.addChild(keyValue); + } + return mapping; + } + + + private Node wrap(ScalarNode scalarNode) { + final Tag tag = scalarNode.getTag(); + if (INCLUDE_TAG.equals(tag)) { + return new SYIncludeNode(scalarNode, resourcePath, resourceLoader); + } else if (Tag.NULL.equals(tag)) { + return new SYNullNode(scalarNode, resourcePath, resourceLoader); + } else if (Tag.FLOAT.equals(tag)) { + return new SYFloatingNode(scalarNode, resourcePath, resourceLoader); + } else if (Tag.INT.equals(tag)) { + SYIntegerNode syIntegerNode = new SYIntegerNode(scalarNode, resourcePath, resourceLoader); + try { + syIntegerNode.getValue(); + return syIntegerNode; + } catch (NumberFormatException e) { + // wrap with string node if number is invalid e.g: 12:30:00 + return new SYStringNode(scalarNode, resourcePath, resourceLoader); + } + } else { + final String value = scalarNode.getValue(); + // We only use true or false as boolean possibilities for yaml 1.2 and not yes no. + if (Tag.BOOL.equals(tag) && (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false"))) { + return new SYBooleanNode(scalarNode, resourcePath, resourceLoader); + } else { + return new SYStringNode(scalarNode, resourcePath, resourceLoader); + } + } + } + + private SYArrayNode wrap(SequenceNode sequenceNode, int depth) { + SYArrayNode sequence = new SYArrayNode(sequenceNode, resourcePath, resourceLoader); + for (org.yaml.snakeyaml.nodes.Node node : sequenceNode.getValue()) { + sequence.addChild(wrap(node, depth + 1)); + } + return sequence; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYNullNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYNullNode.java new file mode 100644 index 0000000..6c4d993 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYNullNode.java @@ -0,0 +1,48 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + + +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.NullNode; +import org.yaml.snakeyaml.nodes.Node; + +public class SYNullNode extends SYBaseRamlNode implements NullNode { + public SYNullNode(SYNullNode node) { + super(node); + } + + public SYNullNode(Node yamlNode, String resourcePath, ResourceLoader resourceLoader) { + super(yamlNode, resourcePath, resourceLoader); + } + + + @Override + public org.xbib.raml.yagi.framework.nodes.Node copy() { + return new SYNullNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Null; + } + + @Override + public String toString() { + return "null"; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYObjectNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYObjectNode.java new file mode 100644 index 0000000..f83a165 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYObjectNode.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + + +import java.util.stream.Collectors; +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.yaml.snakeyaml.nodes.MappingNode; + +public class SYObjectNode extends SYBaseRamlNode implements ObjectNode { + + public SYObjectNode(MappingNode mappingNode, ResourceLoader resourceLoader, String resourcePath) { + super(mappingNode, resourcePath, resourceLoader); + } + + // For copy reasons + public SYObjectNode(SYBaseRamlNode baseRamlNode) { + super(baseRamlNode); + } + + @Override + public String toString() { + return "{\n" + getChildren().stream().map(Object::toString).collect(Collectors.joining("\n")) + "\n}"; + } + + + @Override + public Node copy() { + return new SYObjectNode(this); + } + + @Override + public NodeType getType() { + return NodeType.Object; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYPosition.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYPosition.java new file mode 100644 index 0000000..88c5b77 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYPosition.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + + +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.api.loader.ResourceLoaderFactory; +import org.xbib.raml.yagi.framework.nodes.AbstractPosition; +import org.yaml.snakeyaml.error.Mark; + +public class SYPosition extends AbstractPosition { + + private final Mark mark; + private final ResourceLoaderFactory resourceLoaderFactory; + private final String resourcePath; + private String includedResourceURI; + + public SYPosition(Mark mark, ResourceLoaderFactory resourceLoaderFactory, String resourcePath) { + super(resourceLoaderFactory); + this.mark = mark; + this.resourceLoaderFactory = resourceLoaderFactory; + this.resourcePath = resourcePath; + } + + @Override + public int getIndex() { + return mark.getIndex(); + } + + @Override + public int getLine() { + return mark.getLine(); + } + + @Override + public int getColumn() { + return mark.getColumn(); + } + + + @Override + public String getPath() { + return resourcePath; + } + + @Override + public String getIncludedResourceUri() { + return includedResourceURI; + } + + @Override + public void setIncludedResourceUri(String includedResourceURI) { + this.includedResourceURI = includedResourceURI; + } + + + public ResourceLoader createResourceLoader() { + return resourceLoaderFactory.createResourceLoader(null); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYStringNode.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYStringNode.java new file mode 100644 index 0000000..29190cd --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SYStringNode.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + + +import org.xbib.raml.api.loader.ResourceLoader; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NodeType; +import org.xbib.raml.yagi.framework.nodes.StringNode; +import org.yaml.snakeyaml.nodes.ScalarNode; + +public class SYStringNode extends SYBaseRamlNode implements StringNode { + + // For copy + protected SYStringNode(SYStringNode node) { + super(node); + } + + + public SYStringNode(ScalarNode scalarNode, String resourcePath, ResourceLoader resourceLoader) { + super(scalarNode, resourcePath, resourceLoader); + } + + public String getValue() { + return getLiteralValue(); + } + + + @Override + public Node copy() { + return new SYStringNode(this); + } + + @Override + public NodeType getType() { + return NodeType.String; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SmartReader.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SmartReader.java new file mode 100644 index 0000000..43fbdd8 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/nodes/snakeyaml/SmartReader.java @@ -0,0 +1,127 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.nodes.snakeyaml; + +import java.io.IOException; +import java.io.Reader; +import java.nio.CharBuffer; +import java.util.ArrayDeque; +import java.util.Queue; +import org.yaml.snakeyaml.reader.StreamReader; + +/** + * Created. There, you have it. + */ +class SmartReader extends Reader { + + private final Reader delegate; + private char[] lastBufferRead; + private int lastBufferSize; + private int lastOffset; + + public SmartReader(Reader delegate) { + this.delegate = delegate; + } + + @Override + public int read(CharBuffer target) throws IOException { + return delegate.read(target); + } + + @Override + public int read() throws IOException { + return delegate.read(); + } + + @Override + public int read(char[] cbuf) throws IOException { + return read(cbuf, 0, cbuf.length); + } + + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + try { + int numberOfRead = delegate.read(cbuf, off, len); + lastBufferRead = cbuf; + lastOffset = off; + lastBufferSize = numberOfRead; + return numberOfRead; + } catch (IOException e) { + + lastBufferSize = 0; + throw e; + } + } + + @Override + public long skip(long n) throws IOException { + return delegate.skip(n); + } + + @Override + public boolean ready() throws IOException { + return delegate.ready(); + } + + @Override + public boolean markSupported() { + return delegate.markSupported(); + } + + @Override + public void mark(int readAheadLimit) throws IOException { + delegate.mark(readAheadLimit); + } + + @Override + public void reset() throws IOException { + delegate.reset(); + } + + @Override + public void close() throws IOException { + delegate.close(); + } + + public String getLastValidString() { + + Queue seen = new ArrayDeque<>(64); + + for (int i = lastOffset; i < this.lastBufferSize; i++) { + if (!StreamReader.isPrintable(this.lastBufferRead[i])) { + + + for (char c : ("[BAD: " + this.lastBufferRead[i] + "]").toCharArray()) { + + seen.add(c); + } + + break; + } + + seen.add(this.lastBufferRead[i]); + } + + Character[] foo = seen.toArray(new Character[0]); + StringBuilder sb = new StringBuilder(); + for (Character character : foo) { + + sb.append(character); + } + + return sb.toString(); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/phase/GrammarPhase.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/phase/GrammarPhase.java new file mode 100644 index 0000000..d46674b --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/phase/GrammarPhase.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.phase; + +import org.xbib.raml.yagi.framework.grammar.rule.ErrorNodeFactory; +import org.xbib.raml.yagi.framework.grammar.rule.Rule; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; + +public class GrammarPhase implements Phase { + + private final Rule rootRule; + + public GrammarPhase(Rule rootRule) { + this.rootRule = rootRule; + } + + @Override + public Node apply(Node node) { + if (rootRule.matches(node)) { + final Node result = rootRule.apply(node); + node.replaceWith(result); + return result; + } else if (node instanceof ErrorNode) { + // trying not to wrap an existing error so that clients won't have to know whether to strip or not to strip + return node; + } else { + final ErrorNode errorNode = ErrorNodeFactory.createInvalidRootElement(node, rootRule.getDescription()); + node.replaceWith(errorNode); + return errorNode; + } + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/phase/Phase.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/phase/Phase.java new file mode 100644 index 0000000..0039796 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/phase/Phase.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.phase; + +import org.xbib.raml.yagi.framework.nodes.Node; + +/** + * A phase applies a given logic into a node recursively. + */ +public interface Phase { + + Node apply(Node tree); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/phase/TransformationPhase.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/phase/TransformationPhase.java new file mode 100644 index 0000000..af1e06b --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/phase/TransformationPhase.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.phase; + +import java.util.Arrays; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.Node; + +/** + * Applies a list of Transformers in a pipeline way + */ +public class TransformationPhase implements Phase { + + private final List transformers; + + public TransformationPhase(Transformer... transformers) { + this.transformers = Arrays.asList(transformers); + } + + @Override + public Node apply(Node tree) { + // first pass may replace child nodes + Node result = tree; + for (Transformer transformer : transformers) { + if (transformer.matches(result)) { + result = transformer.transform(result); + } + } + if (tree != result && tree.getParent() != null) { + tree.replaceWith(result); + } + for (Node node : result.getChildren()) { + apply(node); + } + return result; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/phase/Transformer.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/phase/Transformer.java new file mode 100644 index 0000000..94acbff --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/phase/Transformer.java @@ -0,0 +1,29 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.phase; + +import org.xbib.raml.yagi.framework.nodes.Node; + +/** + * Applies a transformation to a specific node and returns the new node. + */ +public interface Transformer { + + boolean matches(Node node); + + Node transform(Node node); + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/DefaultSuggestion.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/DefaultSuggestion.java new file mode 100644 index 0000000..47dfc32 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/DefaultSuggestion.java @@ -0,0 +1,93 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.suggester; + +public class DefaultSuggestion implements Suggestion, Comparable { + + public static final String RAML_1_0_HEADER = "RAML 1.0 Header"; + + private final String label; + private final String description; + private final String value; + private final String prefix; + + public DefaultSuggestion(String value, String description, String label) { + this(value, description, label, ""); + } + + public DefaultSuggestion(String value, String description, String label, String prefix) { + this.value = value; + this.description = description; + this.label = label; + this.prefix = prefix; + } + + public String getPrefix() { + return prefix; + } + + @Override + public String getLabel() { + return label; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getValue() { + return value; + } + + @Override + public Suggestion withDescription(String description) { + return new DefaultSuggestion(getValue(), description, getLabel()); + } + + @Override + public Suggestion withValue(String value) { + return new DefaultSuggestion(value, getDescription(), getLabel()); + } + + @Override + public Suggestion withPrefix(String prefix) { + return new DefaultSuggestion(getValue(), getDescription(), getLabel(), prefix); + } + + @Override + public String toString() { + return "DefaultSuggestion{" + + "label='" + label + '\'' + + ", description='" + description + '\'' + + ", value='" + value + '\'' + + '}'; + } + + @Override + public int compareTo(Suggestion other) { + if (RAML_1_0_HEADER.equals(label)) { + return -1; + } + + if (RAML_1_0_HEADER.equals(other.getLabel())) { + return 1; + } + + return this.getLabel().compareTo(other.getLabel()); + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/DocumentContentAccessor.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/DocumentContentAccessor.java new file mode 100644 index 0000000..fd4db19 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/DocumentContentAccessor.java @@ -0,0 +1,21 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.suggester; + +public interface DocumentContentAccessor { + + String getCharacter(int offset); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/ParsingContext.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/ParsingContext.java new file mode 100644 index 0000000..5fe5467 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/ParsingContext.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.suggester; + +public class ParsingContext { + + private final ParsingContextType contextType; + private final String content; + private final int location; + + public ParsingContext(ParsingContextType contextType, String content, int location) { + this.contextType = contextType; + this.content = content; + this.location = location; + } + + public String getContent() { + return content; + } + + public ParsingContextType getContextType() { + return contextType; + } + + public int getLocation() { + return location; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/ParsingContextType.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/ParsingContextType.java new file mode 100644 index 0000000..beb5c9e --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/ParsingContextType.java @@ -0,0 +1,20 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.suggester; + +public enum ParsingContextType { + FUNCTION_CALL, LIBRARY_CALL, VALUE, ITEM, STRING_TEMPLATE, HEADER, ANY +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/Suggestion.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/Suggestion.java new file mode 100644 index 0000000..c7a8699 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/Suggestion.java @@ -0,0 +1,63 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.suggester; + +public interface Suggestion extends Comparable { + + /** + * @return the label displayed as the suggestion + */ + String getLabel(); + + /** + * @return short description of the suggestion + */ + String getDescription(); + + /** + * @return actual value added by the editor + */ + String getValue(); + + /** + * @return the prefix that must be append to the value when inserting into de document + */ + String getPrefix(); + + /** + * Creates a new Suggestion based on this suggestion but changing the description with the specified + * + * @param description The new description + * @return A new suggestion with the new description. + */ + Suggestion withDescription(String description); + + /** + * Creates a new Suggestion based on this suggestion but changing the value with the specified + * + * @param value The new value + * @return A new suggestion with the new value. + */ + Suggestion withValue(String value); + + /** + * Creates a new Suggestion based on this but changing the prefix + * + * @param prefix The prefix + * @return A new suggestion with the prefix changed. + */ + Suggestion withPrefix(String prefix); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/Suggestions.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/Suggestions.java new file mode 100644 index 0000000..78bee9f --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/suggester/Suggestions.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.suggester; + +import java.util.List; + +/** + * Represent a set of suggestions. + */ +public class Suggestions { + private final int location; + private final String replaceWord; + private final List suggestions; + + + public Suggestions(List suggestions, String replaceWord, int location) { + this.suggestions = suggestions; + this.replaceWord = replaceWord; + this.location = location; + } + + public List getSuggestions() { + return suggestions; + } + + public String getReplaceWord() { + return replaceWord; + } + + public int getLocation() { + return location; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/DateType.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/DateType.java new file mode 100644 index 0000000..92c7c70 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/DateType.java @@ -0,0 +1,20 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.util; + +public enum DateType { + date_only, time_only, datetime_only, datetime +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/DateUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/DateUtils.java new file mode 100644 index 0000000..0f391e3 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/DateUtils.java @@ -0,0 +1,194 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.util; + +import org.joda.time.DateTimeFieldType; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.DateTimeFormatterBuilder; + +public class DateUtils { + private static final String DATE_ONLY_FOUR_DIGITS_YEAR_LENGTH_VALIDATION = "yagi.date_only_four_digits_year_length_validation"; + private static final String DATE_ONLY_FOUR_DIGITS_YEAR_LENGTH_VALIDATION_ALTERNATE = "org.raml.date_only_four_digits_year_length_validation"; + + private static final String STRICT_DATES_RFC3339 = "org.raml.dates_rfc3339_validation"; + private static final String STRICT_DATES_RFC2616 = "org.raml.dates_rfc2616_validation"; + + private static final String FALLBACK_DATETIME = "org.raml.fallback_datetime_to_datetime-only"; + + public static boolean FOUR_YEARS_VALIDATION = Boolean.parseBoolean(System.getProperty( + DATE_ONLY_FOUR_DIGITS_YEAR_LENGTH_VALIDATION, System.getProperty(DATE_ONLY_FOUR_DIGITS_YEAR_LENGTH_VALIDATION_ALTERNATE, "true"))); + public static boolean STRICT_DATES_VALIDATION_3339 = Boolean.parseBoolean(System.getProperty(STRICT_DATES_RFC3339, "true")); + public static boolean STRICT_DATES_VALIDATION_2616 = Boolean.parseBoolean(System.getProperty(STRICT_DATES_RFC2616, "true")); + + public static boolean FALLBACK_DATETIME_TO_DATETIME_ONLY = Boolean.parseBoolean(System.getProperty(FALLBACK_DATETIME, "false")); + + private final boolean fallbackDatetime; + + private DateUtils(boolean strictYear, boolean strictDates3339, boolean strictDates2616, boolean fallbackDatetime) { + this.fallbackDatetime = fallbackDatetime; + setFormatters(strictYear, strictDates3339, strictDates2616); + } + + public static DateUtils createStrictDateUtils() { + return new DateUtils(true, true, true, false); + } + + public static DateUtils createNonStrictDateUtils() { + return new DateUtils(false, false, false, true); + } + + public static DateUtils createFromProperties() { + return new DateUtils(FOUR_YEARS_VALIDATION, STRICT_DATES_VALIDATION_3339, STRICT_DATES_VALIDATION_2616, FALLBACK_DATETIME_TO_DATETIME_ONLY); + } + + public void setFormatters(boolean strictYear, boolean strictDates3339, boolean strictDates2616) { + + dateOnlyFormatter = yearMonthDayFormat(strictYear, strictDates3339).toFormatter(); + timeOnlyFormatter = timeOnlyFormatter(strictDates3339).toFormatter(); + dateTimeOnlyFormatterNoMillis = dateTimeFormat(strictYear, strictDates3339).toFormatter(); + dateTimeOnlyFormatterMillis = dateTimeFormat(strictYear, strictDates3339) + .appendLiteral(".") + .appendFractionOfSecond(1, 9) + .toFormatter(); + + rfc2616Formatter = new DateTimeFormatterBuilder() + .append(DateTimeFormat.forPattern("EEE, dd MMM ")) + .append(yearFormat(strictYear, strictDates2616).toFormatter()) + .appendLiteral(' ') + .append(timeOnlyFormatter(strictDates2616).toFormatter()) + .append(DateTimeFormat.forPattern(" zzz")).toFormatter(); + + rfc3339FormatterMillis = dateTimeFormat(strictYear, strictDates3339) + .appendLiteral(".") + .appendFractionOfSecond(1, 9) + .appendTimeZoneOffset("Z", true, 2, 4) + .toFormatter(); + rfc3339FormatterNoMillis = dateTimeFormat(strictYear, strictDates3339) + .appendTimeZoneOffset("Z", true, 2, 4) + .toFormatter(); + } + + private DateTimeFormatterBuilder yearMonthDayFormat(boolean strictYear, boolean strictDates) { + if (strictDates) { + return yearFormat(strictYear, strictDates).appendLiteral('-') + .appendFixedDecimal(DateTimeFieldType.monthOfYear(), 2) + .appendLiteral('-') + .appendFixedDecimal(DateTimeFieldType.dayOfMonth(), 2); + } else { + return yearFormat(strictYear, strictDates).appendLiteral('-') + .appendDecimal(DateTimeFieldType.monthOfYear(), 1, 2) + .appendLiteral('-') + .appendDecimal(DateTimeFieldType.dayOfMonth(), 1, 2); + + } + } + + private DateTimeFormatterBuilder dateTimeFormat(boolean strictYear, boolean strictDates) { + return yearMonthDayFormat(strictYear, strictDates).appendLiteral('T').append(timeOnlyFormatter(strictDates).toFormatter()); + } + + private DateTimeFormatterBuilder timeOnlyFormatter(boolean strictDates) { + if (strictDates) { + return new DateTimeFormatterBuilder() + .appendFixedDecimal(DateTimeFieldType.hourOfDay(), 2).appendLiteral(':') + .appendFixedDecimal(DateTimeFieldType.minuteOfHour(), 2).appendLiteral(':') + .appendFixedDecimal(DateTimeFieldType.secondOfMinute(), 2); + } else { + + return new DateTimeFormatterBuilder() + .appendDecimal(DateTimeFieldType.hourOfDay(), 1, 2).appendLiteral(':') + .appendDecimal(DateTimeFieldType.minuteOfHour(), 1, 2).appendLiteral(':') + .appendDecimal(DateTimeFieldType.secondOfMinute(), 1, 2); + } + } + + private DateTimeFormatter dateOnlyFormatter; + private DateTimeFormatter timeOnlyFormatter; + + private DateTimeFormatter dateTimeOnlyFormatterNoMillis; + private DateTimeFormatter dateTimeOnlyFormatterMillis; + + private DateTimeFormatter rfc3339FormatterMillis; + private DateTimeFormatter rfc3339FormatterNoMillis; + + private DateTimeFormatter rfc2616Formatter; + + + public boolean isValidDate(String date, DateType format, String rfc) { + + try { + switch (format) { + case date_only: + dateOnlyFormatter.parseLocalDate(date); + break; + case time_only: + timeOnlyFormatter.parseLocalTime(date); + break; + case datetime_only: + checkDatetimeOnly(date); + break; + case datetime: + // Mon., 20 Jan. 2020 19:21:21 EST + // Mon, 20 Jan 2020 19:23:30 EST + if ("rfc2616".equals(rfc)) { + rfc2616Formatter.parseLocalDateTime(date); + break; + } else { + try { + rfc3339FormatterMillis.parseLocalDateTime(date); + } catch (IllegalArgumentException e) { + try { + rfc3339FormatterNoMillis.parseLocalDateTime(date); + } catch (IllegalArgumentException e2) { + + if (fallbackDatetime) { + checkDatetimeOnly(date); + } else { + throw e2; + } + } + } + break; + } + default: + return false; + } + return true; + } catch (Exception e) { + return false; + } + } + + private void checkDatetimeOnly(String date) { + try { + dateTimeOnlyFormatterNoMillis.parseLocalDateTime(date); + } catch (IllegalArgumentException e) { + dateTimeOnlyFormatterMillis.parseLocalDateTime(date); + } + } + + private DateTimeFormatterBuilder yearFormat(boolean strictYear, boolean strictDates) { + + if (strictYear || strictDates) { + + return new DateTimeFormatterBuilder().appendFixedSignedDecimal(DateTimeFieldType.year(), 4); + } else { + + return new DateTimeFormatterBuilder().append(DateTimeFormat.forPattern("YYYY")); + } + } +} \ No newline at end of file diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/FasterTreeNodeDumper.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/FasterTreeNodeDumper.java new file mode 100644 index 0000000..39a6432 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/FasterTreeNodeDumper.java @@ -0,0 +1,118 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.util; + +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.Collection; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.Position; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; + + +public class FasterTreeNodeDumper { + + private static final int TAB_SPACES = 4; + protected PrintWriter dump; + private int indent = 0; + private boolean dumpOn = true; + + private FasterTreeNodeDumper(PrintWriter dump) { + this.dump = dump; + } + + public FasterTreeNodeDumper() { + this(new PrintWriter(new OutputStreamWriter(System.out))); + } + + public String dump(Node node) { + printIndent(); + dumpNode(node); + dump.print(" ("); + dump.print("Start: " + node.getStartPosition().getIndex()); + dump.print(" , End: " + node.getEndPosition().getIndex()); + if (node.getStartPosition().getIndex() != Position.UNKNOWN && + node.getEndPosition().getIndex() != Position.UNKNOWN && dumpOn) { + dump.print(", On: " + node.getStartPosition().getPath()); + } + if (node.getSource() != null) { + dump.print(", Source: "); + dump.print(node.getSource().getClass().getSimpleName()); + } + dump.print(")"); + dump.print("\n"); + indent(); + dumpChildren(node); + dedent(); + return ""; + } + + protected void dumpChildren(Node node) { + for (Node child : getChildren(node)) { + dump(child); + } + } + + public FasterTreeNodeDumper dumpOn(boolean dumpOn) { + this.dumpOn = dumpOn; + return this; + } + + protected Collection getChildren(Node node) { + return node.getChildren(); + } + + protected void dumpNode(Node node) { + + dump.append(node.getClass().getSimpleName()); + if (node instanceof ReferenceNode) { + dumpReference((ReferenceNode) node); + } else if (node instanceof StringNode) { + dump.append(": \"").append(((StringNode) node).getValue().replace("\n", "\\n")).append("\""); + } else if (node instanceof SimpleTypeNode) { + dump.append(": ").print(((SimpleTypeNode) node).getValue()); + } else if (node instanceof ErrorNode) { + dump.append(": \"").append(((ErrorNode) node).getErrorMessage()).append("\""); + } + } + + private void dumpReference(ReferenceNode node) { + final ReferenceNode referenceNode = node; + final Node refNode = referenceNode.getRefNode(); + dump.print(" " + referenceNode.getRefName() + " -> {" + ((refNode == null ? "null" : refNode.getClass().getSimpleName()))); + if (refNode != null) { + dump.append(" RefStart: " + refNode.getStartPosition().getIndex()); + dump.append(" , RefEnd: " + refNode.getEndPosition().getIndex()); + } + dump.append("}"); + } + + protected void dedent() { + indent--; + } + + protected void indent() { + indent++; + } + + protected void printIndent() { + dump.append(" ".repeat(indent * TAB_SPACES)); + } + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/NodeAppender.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/NodeAppender.java new file mode 100644 index 0000000..64a6352 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/NodeAppender.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.util; + +/** + * Created. There, you have it. + */ +public interface NodeAppender { + + NodeAppender append(Object o); + + NodeAppender append(String s); + + NodeAppender append(int s); + + NodeAppender dump(); +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/NodeAppenderFactory.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/NodeAppenderFactory.java new file mode 100644 index 0000000..aeec0ae --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/NodeAppenderFactory.java @@ -0,0 +1,63 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.util; + +import java.io.IOException; +import java.io.Writer; + +/** + * Created. There, you have it. + */ +public class NodeAppenderFactory { + + public static NodeAppender stringBuilder(final Writer output) { + + final StringBuilder sb = new StringBuilder(); + + return new NodeAppender() { + + @Override + public NodeAppender append(Object o) { + sb.append(o); + return this; + } + + @Override + public NodeAppender append(String s) { + sb.append(s); + return this; + } + + @Override + public NodeAppender append(int s) { + sb.append(s); + return this; + } + + public NodeAppender dump() { + + try { + output.append(sb.toString()); + sb.delete(0, sb.length()); + return this; + } catch (IOException e) { + + throw new RuntimeException(e); + } + } + }; + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/NodeSelector.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/NodeSelector.java new file mode 100644 index 0000000..c69579c --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/NodeSelector.java @@ -0,0 +1,194 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.ArrayNode; +import org.xbib.raml.yagi.framework.nodes.KeyValueNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NullNode; +import org.xbib.raml.yagi.framework.nodes.ObjectNode; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; + +public class NodeSelector { + + public static final String PARENT_EXPR = ".."; + public static final String WILDCARD_SELECTOR = "*"; + public static final String ENCODED_SLASH = "\\\\/"; + + /** + * Resolves a path in the specified node. The path uses a very simple expression system like xpath where each element is separated by /. + *

"name" -> return the value of field with key that matches the specified name.
+ * .. -> returns the parent
+ * * -> wild card selector
+ * [number] -> returns the element at that index zero base index. The number should be equal or greater than zero


+ * + * @param path The path example schemas/foo + * @param from The source where to query + * @return The result null if no match + */ + + public static Node selectFrom(String path, Node from) { + if (path.startsWith("/")) { + Node result = selectFrom(path.substring(1), from.getRootNode()); + Node contextNode = from.getRootNode().getContextNode(); + if (result == null && contextNode != null && !contextNode.equals(from.getRootNode())) + return selectFrom(path, contextNode); + return result; + } else { + final String[] tokens = path.split("(? Integer.MAX_VALUE) { + throw new IllegalArgumentException(longValue + " cannot be cast to int."); + } + + return longValue.intValue(); + } + + + public static Number selectNumberValue(String path, Node from) { + return selectType(path, from, null); + } + + + public static Boolean selectBooleanValue(String path, Node from) { + return selectType(path, from, null); + } + + + public static String selectStringValue(String path, Node from) { + return selectType(path, from, null); + } + + public static T selectType(String path, Node from, T defaultValue) { + Node node = selectFrom(path, from); + if (node != null && !(node instanceof NullNode)) { + return ((SimpleTypeNode) node).getValue(); + } + return defaultValue; + } + + + public static List selectStringCollection(String path, Node from) { + return selectCollection(path, from); + } + + private static List selectCollection(String path, Node from) { + ArrayList selectedValues = new ArrayList<>(); + Node selectedNode = NodeSelector.selectFrom(path, from); + if (selectedNode != null) { + if (selectedNode instanceof SimpleTypeNode) { + selectedValues.add(((SimpleTypeNode) selectedNode).getValue()); + } else if (selectedNode instanceof ArrayNode) { + for (Node node : selectedNode.getChildren()) { + if (node instanceof SimpleTypeNode) { + selectedValues.add(((SimpleTypeNode) node).getValue()); + } + } + } + } + return selectedValues; + } + + + private static Node selectFrom(List pathTokens, Node from) { + Node currentNode = from; + for (int i = 0; i < pathTokens.size() && currentNode != null; i++) { + String token = pathTokens.get(i); + if (token.equals(WILDCARD_SELECTOR)) { + if (currentNode instanceof ArrayNode) { + final List children = currentNode.getChildren(); + final List remainingTokens = pathTokens.subList(i + 1, pathTokens.size()); + for (Node child : children) { + final Node resolve = selectFrom(remainingTokens, child); + if (resolve != null) { + currentNode = resolve; + break; + } + } + break; + } + // else we ignore the * + } else if (token.equals(PARENT_EXPR)) { + currentNode = currentNode.getParent(); + } else if (token.matches("^\\[\\d+\\]$")) // child access by index + { + int index = Integer.parseInt(token.substring(1, token.length() - 1)); + if (currentNode.getChildren().size() > index) { + currentNode = currentNode.getChildren().get(index); + } else { + currentNode = null; + } + } else if (currentNode instanceof ObjectNode) { + currentNode = findValueWithName(currentNode, token); + } else if (currentNode instanceof ArrayNode) { + final int index = Integer.parseInt(token); + currentNode = findElementAtIndex(currentNode, index); + } else { + currentNode = null; + } + } + + return currentNode; + } + + + private static Node findElementAtIndex(final Node currentNode, int index) { + Node result = null; + final List children = currentNode.getChildren(); + if (children.size() > index) { + result = children.get(index); + } + return result; + } + + + private static Node findValueWithName(final Node currentNode, String token) { + Node result = null; + final List children = currentNode.getChildren(); + for (Node child : children) { + if (child instanceof KeyValueNode) { + final Node key = ((KeyValueNode) child).getKey(); + if (key instanceof SimpleTypeNode) { + if (token.equals(encodePath(String.valueOf(((SimpleTypeNode) key).getValue())))) { + result = ((KeyValueNode) child).getValue(); + break; + } + } + } + } + return result; + } + + public static String encodePath(final String path) { + return path.replaceAll("/", ENCODED_SLASH); + } + + +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/NodeUtils.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/NodeUtils.java new file mode 100644 index 0000000..7a5153a --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/NodeUtils.java @@ -0,0 +1,143 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.util; + +import java.util.List; +import org.xbib.raml.yagi.framework.nodes.ContextProviderNode; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.NullNode; + +public class NodeUtils { + + private static final int DEFAULT_COLUMN_STEP = 2; + + public static String computeColumnForChild(Node node) { + return " ".repeat(node.getStartPosition().getColumn() + DEFAULT_COLUMN_STEP); + } + + + public static Node getAncestor(Node node, int level) { + int i = 1; + Node parent = node.getParent(); + while (i < level && parent != null) { + parent = parent.getParent(); + i++; + } + return parent; + } + + + public static T getAncestor(Node node, Class ancestorType) { + Node parent = node.getParent(); + while (parent != null && !ancestorType.isAssignableFrom(parent.getClass())) { + parent = parent.getParent(); + } + return ancestorType.cast(parent); + } + + + public static T getSource(Node node, Class ancestorType) { + Node parent = node.getSource(); + while (parent != null && !ancestorType.isAssignableFrom(parent.getClass())) { + parent = parent.getSource(); + } + return ancestorType.cast(parent); + } + + public static Node getType(Node node) { + return node.get("type") != null ? node.get("type") : node.get("schema"); + } + + public static boolean isErrorResult(Node node) { + return node != null && (node instanceof ErrorNode || node.findDescendantsWith(ErrorNode.class).size() > 0); + } + + + public static Node searchNodeAt(Node root, int location) { + if (root.getEndPosition().getIndex() != location || !root.getChildren().isEmpty()) { + final List children = root.getChildren(); + for (Node child : children) { + if (child.getEndPosition().getIndex() == location) { + if (child.getChildren().isEmpty()) { + return child; + } else { + return searchNodeAt(child, location); + } + } else if (child.getEndPosition().getIndex() > location || isLastNode(child)) { + if (child.getChildren().isEmpty()) { + return child; + } else { + return searchNodeAt(child, location); + } + } + } + return null; + } else { + return root; + } + } + + private static boolean isLastNode(Node node) { + final Node parent = node.getParent(); + if (parent == null) { + return false; + } + List children = parent.getChildren(); + Node lastChild = children.get(children.size() - 1); + return node.equals(lastChild); + } + + public static boolean isNull(Node node) { + return node == null || node instanceof NullNode; + } + + public static Node getRootSource(Node child) { + Node result = child; + while (result != null && result.getSource() != null) { + result = result.getSource(); + } + return result; + } + + + public static Node traverseToRoot(Node node) { + if (node == null) { + return null; + } else if (node.getParent() == null) { + return node; + } else { + return traverseToRoot(node.getParent()); + } + } + + /** + * Returns the node that defines the scope for the specified node. + * + * @param node The node + * @return The context node for the specified node + */ + + public static Node getContextNode(Node node) { + if (node.getParent() == null) { + return node; + } else if (node instanceof ContextProviderNode) { + return ((ContextProviderNode) node).getContextNode(); + } else { + return getContextNode(node.getParent()); + } + } +} diff --git a/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/TreeNodeDumper.java b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/TreeNodeDumper.java new file mode 100644 index 0000000..8e9d023 --- /dev/null +++ b/datastructures-raml/src/main/java/org/xbib/raml/yagi/framework/util/TreeNodeDumper.java @@ -0,0 +1,119 @@ +/* + * Copyright 2013 (c) MuleSoft, 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.xbib.raml.yagi.framework.util; + +import java.io.Writer; +import java.util.Collection; +import org.xbib.raml.yagi.framework.nodes.ErrorNode; +import org.xbib.raml.yagi.framework.nodes.Node; +import org.xbib.raml.yagi.framework.nodes.Position; +import org.xbib.raml.yagi.framework.nodes.ReferenceNode; +import org.xbib.raml.yagi.framework.nodes.SimpleTypeNode; +import org.xbib.raml.yagi.framework.nodes.StringNode; + + +public class TreeNodeDumper { + + private static final int TAB_SPACES = 4; + protected NodeAppender dump; + private int indent = 0; + + private boolean dumpOn = true; + + public TreeNodeDumper(NodeAppender dump) { + this.dump = dump; + } + + public TreeNodeDumper(Writer writer) { + this(NodeAppenderFactory.stringBuilder(writer)); + } + + public String dump(Node node) { + printIndent(); + dumpNode(node); + dump.append(" ("); + dump.append("Start: ").append(node.getStartPosition().getIndex()); + dump.append(" , End: ").append(node.getEndPosition().getIndex()); + if (node.getStartPosition().getIndex() != Position.UNKNOWN && + node.getEndPosition().getIndex() != Position.UNKNOWN && dumpOn) { + dump.append(", On: ").append(node.getStartPosition().getPath()); + } + if (node.getSource() != null) { + dump.append(", Source: "); + dump.append(node.getSource().getClass().getSimpleName()); + } + dump.append(")"); + dump.append("\n"); + indent(); + dumpChildren(node); + dedent(); + dump.dump(); + return ""; + } + + protected void dumpChildren(Node node) { + for (Node child : getChildren(node)) { + dump(child); + } + } + + public TreeNodeDumper dumpOn(boolean dumpOn) { + this.dumpOn = dumpOn; + return this; + } + + protected Collection getChildren(Node node) { + return node.getChildren(); + } + + protected void dumpNode(Node node) { + + dump.append(node.getClass().getSimpleName()); + if (node instanceof ReferenceNode) { + dumpReference((ReferenceNode) node); + } else if (node instanceof StringNode) { + dump.append(": \"").append(((StringNode) node).getValue()).append("\""); + } else if (node instanceof SimpleTypeNode) { + dump.append(": ").append(((SimpleTypeNode) node).getValue()); + } else if (node instanceof ErrorNode) { + dump.append(": \"").append(((ErrorNode) node).getErrorMessage()).append("\""); + } + } + + private void dumpReference(ReferenceNode node) { + final ReferenceNode referenceNode = node; + final Node refNode = referenceNode.getRefNode(); + dump.append(" ").append(referenceNode.getRefName()).append(" -> {").append(refNode == null ? "null" : refNode.getClass().getSimpleName()); + if (refNode != null) { + dump.append(" RefStart: ").append(refNode.getStartPosition().getIndex()); + dump.append(" , RefEnd: ").append(refNode.getEndPosition().getIndex()); + } + dump.append("}"); + } + + protected void dedent() { + indent--; + } + + protected void indent() { + indent++; + } + + protected void printIndent() { + dump.append(" ".repeat(indent * TAB_SPACES)); + } + +} diff --git a/gradle.properties b/gradle.properties index 18fced2..fbd93cc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group = org.xbib name = datastructures -version = 2.0.0 +version = 2.1.0 org.gradle.warning.mode = all diff --git a/settings.gradle b/settings.gradle index 3eb7066..6127a57 100644 --- a/settings.gradle +++ b/settings.gradle @@ -63,3 +63,4 @@ include 'datastructures-json-tiny' include 'datastructures-yaml-tiny' include 'datastructures-validation' include 'datastructures-trie' +include 'datastructures-raml'