This is an automated email from the ASF dual-hosted git repository. hasan pushed a commit to branch reunited in repository https://gitbox.apache.org/repos/asf/clerezza.git
commit 9647fd3c481ce6a569ba38f0b89c52e718024919 Author: Hasan <[email protected]> AuthorDate: Mon May 14 00:52:52 2018 +0200 CLEREZZA-1025: Copy serializedform in core to a new module called representation --- representation/pom.xml | 80 ++++++ .../org/apache/clerezza/representation/Parser.java | 311 +++++++++++++++++++++ .../clerezza/representation/ParsingProvider.java | 49 ++++ .../apache/clerezza/representation/Serializer.java | 253 +++++++++++++++++ .../representation/SerializingProvider.java | 49 ++++ .../clerezza/representation/SupportedFormat.java | 61 ++++ .../representation/UnsupportedFormatException.java | 37 +++ .../UnsupportedParsingFormatException.java | 35 +++ .../UnsupportedSerializationFormatException.java | 35 +++ .../apache/clerezza/representation/ParserTest.java | 88 ++++++ .../clerezza/representation/SerializerTest.java | 87 ++++++ .../representation/TestServiceManagedProvider.java | 50 ++++ ....apache.clerezza.representation.ParsingProvider | 18 ++ 13 files changed, 1153 insertions(+) diff --git a/representation/pom.xml b/representation/pom.xml new file mode 100644 index 0000000..274fc53 --- /dev/null +++ b/representation/pom.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>clerezza</artifactId> + <groupId>org.apache.clerezza</groupId> + <version>8-SNAPSHOT</version> + <relativePath>../parent/pom.xml</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>representation</artifactId> + + <dependencies> + <dependency> + <groupId>org.apache.clerezza.commons-rdf</groupId> + <artifactId>commons-rdf-api</artifactId> + <version>0.2</version> + </dependency> + <dependency> + <groupId>org.apache.clerezza.commons-rdf</groupId> + <artifactId>commons-rdf-impl-utils</artifactId> + <version>0.2</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.scr.annotations</artifactId> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.scr.ds-annotations</artifactId> + <version>1.2.8</version> + </dependency> + <dependency> + <groupId>org.apache.clerezza</groupId> + <artifactId>utils</artifactId> + <version>0.2</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Package>org.apache.clerezza.representation.*</Export-Package> + </instructions> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-scr-plugin</artifactId> + <executions> + <execution> + <id>generate-scr-scrdescriptor</id> + <goals> + <goal>scr</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/representation/src/main/java/org/apache/clerezza/representation/Parser.java b/representation/src/main/java/org/apache/clerezza/representation/Parser.java new file mode 100644 index 0000000..4202ad6 --- /dev/null +++ b/representation/src/main/java/org/apache/clerezza/representation/Parser.java @@ -0,0 +1,311 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.clerezza.representation; + +import org.apache.clerezza.commons.rdf.Graph; +import org.apache.clerezza.commons.rdf.IRI; +import org.apache.clerezza.commons.rdf.ImmutableGraph; +import org.apache.clerezza.commons.rdf.impl.utils.simple.SimpleMGraph; +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.*; + +/** + * This singleton class provides a method + * <code>parse</code> to transform serialized RDF forms into {@link ImmutableGraph}s. + * + * Functionality is delegated to registered {@link ParsingProvider}s. Such + * <code>ParsingProvider</code>s can be registered and unregistered, later + * registered + * <code>ParsingProvider</code>s shadow previously registered providers for the + * same format. + * + * Note on synchronization: + * <code>ParsingProvider</code>s must be able to handle concurrent requests. + * + * @author reto + * + */ +@Component(service = Parser.class) +public class Parser { + + private ConfigurationAdmin configurationAdmin; + /** + * The list of providers in the order of registration + */ + private List<ParsingProvider> providerList = new ArrayList<ParsingProvider>(); + /** + * A map to quickly locate a provider + */ + private volatile Map<String, ParsingProvider> providerMap = new HashMap<String, ParsingProvider>(); + /** + * The singleton instance + */ + private volatile static Parser instance; + private boolean active; + + private static final Logger log = LoggerFactory.getLogger(Parser.class); + /** + * the constructor sets the singleton instance to allow instantiation + * by OSGi-DS. This constructor should not be called except by OSGi-DS, + * otherwise the static <code>getInstance</code> method should be used. + */ + public Parser() { + log.info("constructing Parser"); + Parser.instance = this; + } + + /** + * A constructor for tests, which doesn't set the singleton instance + * + * @param dummy an ignored argument to distinguish this from the other constructor + */ + Parser(Object dummy) { + active = true; + } + + /** + * This returns the singleton instance, if an instance has been previously + * created (e.g. by OSGi declarative services) this instance is returned, + * otherwise a new instance is created and providers are injected using + * the service provider interface (META-INF/services/) + * + * @return the singleton Parser instance + */ + public static Parser getInstance() { + if (instance == null) { + synchronized (Parser.class) { + if (instance == null) { + new Parser(); + Iterator<ParsingProvider> parsingProviders = + ServiceLoader.load(ParsingProvider.class).iterator(); + while (parsingProviders.hasNext()) { + ParsingProvider parsingProvider = parsingProviders.next(); + instance.bindParsingProvider(parsingProvider); + } + instance.active = true; + instance.refreshProviderMap(); + } + } + } + return instance; + + } + + @Activate + protected void activate(final ComponentContext componentContext) { + active = true; + refreshProviderMap(); + //changing the congiguration before this finshed activating causes a new instance to be created + /*(new Thread() { + @Override + public void run() { + try { + Thread.sleep(100); + } catch (InterruptedException ex) { + return; + } + refreshProviderMap(); + } + + + }).start();*/ + } + + @Deactivate + protected void deactivate(final ComponentContext componentContext) { + active = false; + } + + @Modified + void modified(ComponentContext ctx) { + log.debug("modified"); + } + + /** + * Parses a serialized ImmutableGraph from an InputStream. This delegates the + * processing to the provider registered for the specified format, if + * the formatIdentifier contains a ';'-character only the section before + * that character is used for choosing the provider. + * + * @param serializedGraph an inputstream with the serialization + * @param formatIdentifier a string identifying the format (usually the MIME-type) + * @return the ImmutableGraph read from the stream + * @throws UnsupportedFormatException + */ + public ImmutableGraph parse(InputStream serializedGraph, + String formatIdentifier) throws UnsupportedFormatException { + return parse(serializedGraph, formatIdentifier, null); + } + + /** + * Parses a serialized ImmutableGraph from an InputStream. This delegates the + * processing to the provider registered for the specified format, if + * the formatIdentifier contains a ';'-character only the section before + * that character is used for choosing the provider. + * + * @param target the Graph to which the parsed triples are added + * @param serializedGraph an inputstream with the serialization + * @param formatIdentifier a string identifying the format (usually the MIME-type) + * @throws UnsupportedFormatException + */ + public void parse(Graph target, InputStream serializedGraph, + String formatIdentifier) throws UnsupportedFormatException { + parse(target, serializedGraph, formatIdentifier, null); + } + + /** + * Parses a serialized ImmutableGraph from an InputStream. This delegates the + * processing to the provider registered for the specified format, if + * the formatIdentifier contains a ';'-character only the section before + * that character is used for choosing the provider. + * + * @param serializedGraph an inputstream with the serialization + * @param formatIdentifier a string identifying the format (usually the MIME-type) + * @param baseUri the uri against which relative uri-refs are evaluated + * @return the ImmutableGraph read from the stream + * @throws UnsupportedFormatException + */ + public ImmutableGraph parse(InputStream serializedGraph, + String formatIdentifier, IRI baseUri) throws UnsupportedFormatException { + Graph graph = new SimpleMGraph(); + parse(graph, serializedGraph, formatIdentifier, baseUri); + return graph.getImmutableGraph(); + } + + /** + * Parses a serialized ImmutableGraph from an InputStream. This delegates the + * processing to the provider registered for the specified format, if + * the formatIdentifier contains a ';'-character only the section before + * that character is used for choosing the provider. + * + * @param target the Graph to which the parsed triples are added + * @param serializedGraph an inputstream with the serialization + * @param formatIdentifier a string identifying the format (usually the MIME-type) + * @param baseUri the uri against which relative uri-refs are evaluated + * @throws UnsupportedFormatException + */ + public void parse(Graph target, InputStream serializedGraph, + String formatIdentifier, IRI baseUri) throws UnsupportedFormatException { + String deParameterizedIdentifier; + int semicolonPos = formatIdentifier.indexOf(';'); + if (semicolonPos > -1) { + deParameterizedIdentifier = formatIdentifier.substring(0, semicolonPos); + } else { + deParameterizedIdentifier = formatIdentifier; + } + ParsingProvider provider = providerMap.get(deParameterizedIdentifier); + if (provider == null) { + throw new UnsupportedParsingFormatException(formatIdentifier); + } + provider.parse(target, serializedGraph, formatIdentifier, baseUri); + } + + /** + * Get a set of supported formats + * + * @return a set if stings identifying formats (usually the MIME-type) + */ + public Set<String> getSupportedFormats() { + return Collections.unmodifiableSet(providerMap.keySet()); + } + + /** + * Registers a parsing provider + * + * @param provider the provider to be registered + */ + @Reference(policy = ReferencePolicy.DYNAMIC, + cardinality = ReferenceCardinality.MULTIPLE) + public void bindParsingProvider(ParsingProvider provider) { + providerList.add(provider); + refreshProviderMap(); + } + + /** + * Unregister a parsing provider + * + * @param provider the provider to be deregistered + */ + public void unbindParsingProvider(ParsingProvider provider) { + providerList.remove(provider); + refreshProviderMap(); + } + + /** + * Update providerMap with the providers in the providerList + * + */ + private void refreshProviderMap() { + if (active) { + try { + final Map<String, ParsingProvider> newProviderMap = new HashMap<String, ParsingProvider>(); + for (ParsingProvider provider : providerList) { + String[] formatIdentifiers = getFormatIdentifiers(provider); + for (String formatIdentifier : formatIdentifiers) { + newProviderMap.put(formatIdentifier, provider); + } + } + providerMap = newProviderMap; + if (configurationAdmin != null) { //i.e. when we are in an OSGi environment + Dictionary<String, Object> newConfig = configurationAdmin.getConfiguration(getClass().getName()).getProperties(); + if (newConfig == null) { + newConfig = new Hashtable<String, Object>(); + } + Set<String> supportedFormats = getSupportedFormats(); + String[] supportedFromatsArray = supportedFormats.toArray(new String[supportedFormats.size()]); + newConfig.put(SupportedFormat.supportedFormat, supportedFromatsArray); + configurationAdmin.getConfiguration(getClass().getName()).update(newConfig); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + } + + + + /** + * Extract format identifiers for a parsing provider + * + * @param provider the provider to be registered + * @return formatIdentifiers + */ + private String[] getFormatIdentifiers(ParsingProvider parsingProvider) { + Class<? extends ParsingProvider> clazz = parsingProvider.getClass(); + SupportedFormat supportedFormatAnnotation = clazz.getAnnotation(SupportedFormat.class); + String[] formatIdentifiers = supportedFormatAnnotation.value(); + return formatIdentifiers; + } + + @Reference + protected void bindConfigurationAdmin(ConfigurationAdmin configurationAdmin) { + this.configurationAdmin = configurationAdmin; + } + + protected void unbindConfigurationAdmin(ConfigurationAdmin configurationAdmin) { + this.configurationAdmin = null; + } +} diff --git a/representation/src/main/java/org/apache/clerezza/representation/ParsingProvider.java b/representation/src/main/java/org/apache/clerezza/representation/ParsingProvider.java new file mode 100644 index 0000000..fbdf721 --- /dev/null +++ b/representation/src/main/java/org/apache/clerezza/representation/ParsingProvider.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.clerezza.representation; + +import org.apache.clerezza.commons.rdf.Graph; +import org.apache.clerezza.commons.rdf.IRI; + +import java.io.InputStream; + +/** + * An instance of this class parses RDF-ImmutableGraph from one or more serialization + * formats. The supported formats are indicated using the {@link SupportedFormat} + * annotation. + * + * @author reto + */ +public interface ParsingProvider { + + /** + * Parses a stream as the specified RDF-format. This method will be invoked + * for a supported format, a format is considered as supported if the part + * before a ';'-character in the <code>formatIdentifier</code> matches + * a <code>SupportedFormat</code> annotation of the implementing class. + * + * @param target the mutable ImmutableGraph to which the read triples shall be added + * @param serializedGraph the stream from which the serialized ImmutableGraph is read + * @param formatIdentifier a String identifying the format + * @param baseUri the baseUri for interpreting relative uris, may be null + */ + void parse(Graph target, InputStream serializedGraph, + String formatIdentifier, IRI baseUri); + +} diff --git a/representation/src/main/java/org/apache/clerezza/representation/Serializer.java b/representation/src/main/java/org/apache/clerezza/representation/Serializer.java new file mode 100644 index 0000000..e36b9c7 --- /dev/null +++ b/representation/src/main/java/org/apache/clerezza/representation/Serializer.java @@ -0,0 +1,253 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.clerezza.representation; + +import org.apache.clerezza.commons.rdf.Graph; +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.*; + +/** + * This singleton class provides a method <code>serialize</code> to transform a + * {@link ImmutableGraph} into serialized RDF forms. + * + * Functionality is delegated to registered {@link SerializingProvider}s. Such + * <code>SerializingProvider</code>s can be registered and unregistered, later + * registered <code>SerializingProvider</code>s shadow previously registered + * providers for the same format. + * + * Note on synchronization: <code>SerializingProvider</code>s must be able to + * handle concurrent requests. + * + * @author mir + * + */ +@Component(service = Serializer.class) +public class Serializer { + + private ConfigurationAdmin configurationAdmin; + + /** + * The list of providers in the order of registration + */ + private List<SerializingProvider> providerList = new ArrayList<SerializingProvider>(); + + /** + * A map to quickly locate a provider + */ + private volatile Map<String, SerializingProvider> providerMap = new HashMap<String, SerializingProvider>(); + + /** + * The singleton instance + */ + private volatile static Serializer instance; + + private static final Logger log = LoggerFactory.getLogger(Serializer.class); + + private boolean active; + + /** + * the constructor sets the singleton instance to allow instantiation + * by OSGi-DS. This constructor should not be called except by OSGi-DS, + * otherwise the static <code>getInstance</code> method should be used. + */ + public Serializer() { + Serializer.instance = this; + } + + /** + * A constructor for tests, which doesn't set the singleton instance + * + * @param dummy + * an ignored argument to distinguish this from the other + * constructor + */ + Serializer(Object dummy) { + active = true; + } + + /** + * This returns the singleton instance, if an instance has been previously + * created (e.g. by OSGi declarative services) this instance is returned, + * otherwise a new instance is created and providers are injected using the + * service provider interface (META-INF/services/) + * + * @return the singleton Serializer instance + */ + public static Serializer getInstance() { + if (instance == null) { + synchronized (Serializer.class) { + if (instance == null) { + new Serializer(); + Iterator<SerializingProvider> SerializingProviders = ServiceLoader + .load(SerializingProvider.class).iterator(); + while (SerializingProviders.hasNext()) { + SerializingProvider SerializingProvider = SerializingProviders + .next(); + instance.bindSerializingProvider(SerializingProvider); + } + instance.active = true; + instance.refreshProviderMap(); + } + } + } + return instance; + + } + + @Activate + protected void activate(final ComponentContext componentContext) { + active = true; + refreshProviderMap(); + } + + @Deactivate + protected void deactivate(final ComponentContext componentContext) { + active = false; + } + + @Modified + void modified(ComponentContext ctx) { + log.debug("modified"); + } + + /** + * Serializes a ImmutableGraph into an OutputStream. This delegates the + * processing to the provider registered for the specified format, if + * the formatIdentifier contains a ';'-character only the section before + * that character is used for choosing the provider. + * + * @param serializedGraph + * an outputStream into which the ImmutableGraph will be serialized + * @param tc the <code>Graph</code> to be serialized + * @param formatIdentifier + * a string specifying the serialization format (usually the + * MIME-type) + * @throws UnsupportedFormatException + */ + public void serialize(OutputStream serializedGraph, Graph tc, + String formatIdentifier) throws UnsupportedFormatException { + String deParameterizedIdentifier; + int semicolonPos = formatIdentifier.indexOf(';'); + if (semicolonPos > -1) { + deParameterizedIdentifier = formatIdentifier.substring(0, semicolonPos); + } else { + deParameterizedIdentifier = formatIdentifier; + } + SerializingProvider provider = providerMap.get(deParameterizedIdentifier); + if (provider == null) { + throw new UnsupportedSerializationFormatException(formatIdentifier); + } + provider.serialize(serializedGraph, tc, formatIdentifier); + } + + /** + * Get a set of supported formats + * + * @return a set if stings identifying formats (usually the MIME-type) + */ + public Set<String> getSupportedFormats() { + return Collections.unmodifiableSet(providerMap.keySet()); + } + + /** + * Registers a Serializing provider + * + * @param provider + * the provider to be registered + */ + @Reference(policy = ReferencePolicy.DYNAMIC, + cardinality = ReferenceCardinality.MULTIPLE) + public void bindSerializingProvider(SerializingProvider provider) { + providerList.add(provider); + refreshProviderMap(); + + } + + /** + * Unregister a Serializing provider + * + * @param provider + * the provider to be unregistered + */ + public void unbindSerializingProvider(SerializingProvider provider) { + providerList.remove(provider); + refreshProviderMap(); + + } + + private void refreshProviderMap() { + if (active) { + final Map<String, SerializingProvider> newProviderMap = new HashMap<String, SerializingProvider>(); + //we want more generic providers first so they get overridden by more specific ones + Collections.sort(providerList, new Comparator<SerializingProvider>() { + @Override + public int compare(SerializingProvider s1, SerializingProvider s2) { + return getFormatIdentifiers(s2).length - getFormatIdentifiers(s1).length; + } + }); + for (SerializingProvider provider : providerList) { + String[] formatIdentifiers = getFormatIdentifiers(provider); + for (String formatIdentifier : formatIdentifiers) { + newProviderMap.put(formatIdentifier, provider); + } + } + providerMap = newProviderMap; + if (configurationAdmin != null) { //we are in OSGi environment + try { + Dictionary<String, Object> newConfig = configurationAdmin.getConfiguration(getClass().getName()).getProperties(); + if (newConfig == null) { + newConfig = new Hashtable<String, Object>(); + } + Set<String> supportedFormats = getSupportedFormats(); + String[] supportedFromatsArray = supportedFormats.toArray(new String[supportedFormats.size()]); + newConfig.put(SupportedFormat.supportedFormat, supportedFromatsArray); + configurationAdmin.getConfiguration(getClass().getName()).update(newConfig); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + } + } + + private String[] getFormatIdentifiers( + SerializingProvider SerializingProvider) { + Class<? extends SerializingProvider> clazz = SerializingProvider + .getClass(); + SupportedFormat supportedFormatAnnotation = clazz + .getAnnotation(SupportedFormat.class); + String[] formatIdentifiers = supportedFormatAnnotation.value(); + return formatIdentifiers; + } + + @Reference + protected void bindConfigurationAdmin(ConfigurationAdmin configurationAdmin) { + this.configurationAdmin = configurationAdmin; + } + + protected void unbindConfigurationAdmin(ConfigurationAdmin configurationAdmin) { + this.configurationAdmin = null; + } +} diff --git a/representation/src/main/java/org/apache/clerezza/representation/SerializingProvider.java b/representation/src/main/java/org/apache/clerezza/representation/SerializingProvider.java new file mode 100644 index 0000000..3053e45 --- /dev/null +++ b/representation/src/main/java/org/apache/clerezza/representation/SerializingProvider.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.clerezza.representation; + +import org.apache.clerezza.commons.rdf.Graph; + +import java.io.OutputStream; + + +/** + * An instance of this class serializes <code>Graph</code>s to a + * specified serialization format. The supported formats are indicated using the + * {@link SupportedFormat} annotation. + * + * @author mir + */ +public interface SerializingProvider { + + /** Serializes a <code>Graph</code> to a specified + * <code>OutputStream</code> in the format identified by + * <code>formatIdentifier</code>. This method will be invoked + * for a supported format, a format is considered as supported if the part + * before a ';'-character in the <code>formatIdentifier</code> matches + * a <code>SupportedFormat</code> annotation of the implementing class. + * + * @param outputStream + * @param tc + * @param formatIdentifier + */ + public void serialize(OutputStream outputStream, Graph tc, + String formatIdentifier); + +} diff --git a/representation/src/main/java/org/apache/clerezza/representation/SupportedFormat.java b/representation/src/main/java/org/apache/clerezza/representation/SupportedFormat.java new file mode 100644 index 0000000..d246a39 --- /dev/null +++ b/representation/src/main/java/org/apache/clerezza/representation/SupportedFormat.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.clerezza.representation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation is used to annotate {@link ParsingProvider}s to indicate + * the format(s) they support. + * + * @author reto + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface SupportedFormat { + + /** + * used as a key for the OSGi service property + */ + public static final String supportedFormat = "supportedFormat"; + public static final String RDF_XML = "application/rdf+xml"; + public static final String TURTLE = "text/turtle"; + public static final String X_TURTLE = "application/x-turtle"; + public static final String N_TRIPLE = "application/n-triples"; + /** + * @deprecated: The mime-type for N Triples is "application/n-triples": http://www.w3.org/TR/n-triples/#sec-mediaReg-n-triples + */ + @Deprecated + public static final String TEXT_RDF_NT = "text/rdf+nt"; + public static final String N3 = "text/rdf+n3"; + public static final String RDF_JSON = "application/rdf+json"; + //both html and xhtml can be rdf formats with RDFa + public static final String XHTML = "application/xhtml+xml"; + public static final String HTML = "text/html"; + + /** + * A list of format Identifiers (typically MIME-types) types without + * parameter (without ';'-character). + * E.g. {"application/rdf+xml","application/turtle"} + */ + String[] value(); +} diff --git a/representation/src/main/java/org/apache/clerezza/representation/UnsupportedFormatException.java b/representation/src/main/java/org/apache/clerezza/representation/UnsupportedFormatException.java new file mode 100644 index 0000000..d914a3d --- /dev/null +++ b/representation/src/main/java/org/apache/clerezza/representation/UnsupportedFormatException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.clerezza.representation; + +/** + * + * This exception is thrown on an attempt to parse a format for which no + * <code>ParsingProvider</code> is known. + * + * @author reto + */ +public abstract class UnsupportedFormatException extends RuntimeException { + + public UnsupportedFormatException(String message) { + super(message); + } + + + + +} diff --git a/representation/src/main/java/org/apache/clerezza/representation/UnsupportedParsingFormatException.java b/representation/src/main/java/org/apache/clerezza/representation/UnsupportedParsingFormatException.java new file mode 100644 index 0000000..51fafc9 --- /dev/null +++ b/representation/src/main/java/org/apache/clerezza/representation/UnsupportedParsingFormatException.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.clerezza.representation; + +/** + * + * @author reto + */ +public class UnsupportedParsingFormatException extends UnsupportedFormatException { + /** + * Creates an instance for a specified unsupported format. + * + * @param formatIdentifier the unsupported format + */ + public UnsupportedParsingFormatException(String formatIdentifier) { + super("No parser available for "+formatIdentifier); + } + +} diff --git a/representation/src/main/java/org/apache/clerezza/representation/UnsupportedSerializationFormatException.java b/representation/src/main/java/org/apache/clerezza/representation/UnsupportedSerializationFormatException.java new file mode 100644 index 0000000..b2bf5cc --- /dev/null +++ b/representation/src/main/java/org/apache/clerezza/representation/UnsupportedSerializationFormatException.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.clerezza.representation; + +/** + * + * @author reto + */ +public class UnsupportedSerializationFormatException extends UnsupportedFormatException { + /** + * Creates an instance for a specified unsupported format. + * + * @param formatIdentifier the unsupported format + */ + public UnsupportedSerializationFormatException(String formatIdentifier) { + super("No serializer available for "+formatIdentifier); + } + +} diff --git a/representation/src/test/java/org/apache/clerezza/representation/ParserTest.java b/representation/src/test/java/org/apache/clerezza/representation/ParserTest.java new file mode 100644 index 0000000..97f6e69 --- /dev/null +++ b/representation/src/test/java/org/apache/clerezza/representation/ParserTest.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.clerezza.representation; + +import junit.framework.Assert; +import org.apache.clerezza.commons.rdf.Graph; +import org.apache.clerezza.commons.rdf.IRI; +import org.junit.Test; + +import java.io.InputStream; + +/** + * + * @author reto + */ +public class ParserTest { + + private static boolean providerAInvoked; + private static boolean providerBInvoked; + private ParsingProvider parsingProviderA = new ParsingProviderA(); + private ParsingProvider parsingProviderB = new ParsingProviderB(); + + @Test + public void registerOneProvider() { + Parser parser = new Parser(null); + parser.bindParsingProvider(parsingProviderA); + providerAInvoked = false; + parser.parse(null, "application/x-fantasy2+rdf"); + Assert.assertTrue(providerAInvoked); + } + + @Test + public void registerAndUnregisterSecond() { + Parser parser = new Parser(null); + parser.bindParsingProvider(parsingProviderA); + parser.bindParsingProvider(parsingProviderB); + providerAInvoked = false; + providerBInvoked = false; + parser.parse(null, "application/x-fantasy2+rdf"); + Assert.assertFalse(providerAInvoked); + Assert.assertTrue(providerBInvoked); + providerAInvoked = false; + providerBInvoked = false; + parser.parse(null, "application/x-fantasy1+rdf"); + Assert.assertTrue(providerAInvoked); + Assert.assertFalse(providerBInvoked); + parser.unbindParsingProvider(parsingProviderB); + providerAInvoked = false; + providerBInvoked = false; + parser.parse(null, "application/x-fantasy2+rdf"); + Assert.assertTrue(providerAInvoked); + Assert.assertFalse(providerBInvoked); + + } + + @SupportedFormat({"application/x-fantasy1+rdf", "application/x-fantasy2+rdf"}) + static class ParsingProviderA implements ParsingProvider { + + @Override + public void parse(Graph target, InputStream serializedGraph, String formatIdentifier, IRI baseUri) { + providerAInvoked = true; + } + }; + @SupportedFormat("application/x-fantasy2+rdf") + static class ParsingProviderB implements ParsingProvider { + + @Override + public void parse(Graph target, InputStream serializedGraph, String formatIdentifier, IRI baseUri) { + providerBInvoked = true; + } + }; +} diff --git a/representation/src/test/java/org/apache/clerezza/representation/SerializerTest.java b/representation/src/test/java/org/apache/clerezza/representation/SerializerTest.java new file mode 100644 index 0000000..feae79a --- /dev/null +++ b/representation/src/test/java/org/apache/clerezza/representation/SerializerTest.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.clerezza.representation; + +import junit.framework.Assert; +import org.apache.clerezza.commons.rdf.Graph; +import org.junit.Test; + +import java.io.OutputStream; + +/** + * + * @author mir + */ +public class SerializerTest { + + private static boolean providerAInvoked; + private static boolean providerBInvoked; + private SerializingProvider serializingProviderA = new SerializingProviderA(); + private SerializingProvider serializingProviderB = new SerializingProviderB(); + + @Test + public void registerOneProvider() { + Serializer serializer = new Serializer(null); + serializer.bindSerializingProvider(serializingProviderA); + providerAInvoked = false; + serializer.serialize(null, null, "application/x-fantasy2+rdf"); + Assert.assertTrue(providerAInvoked); + } + + @Test + public void registerAndUnregisterSecond() { + Serializer serializer = new Serializer(null); + serializer.bindSerializingProvider(serializingProviderA); + serializer.bindSerializingProvider(serializingProviderB); + providerAInvoked = false; + providerBInvoked = false; + serializer.serialize(null, null, "application/x-fantasy2+rdf"); + Assert.assertFalse(providerAInvoked); + Assert.assertTrue(providerBInvoked); + providerAInvoked = false; + providerBInvoked = false; + serializer.serialize(null, null, "application/x-fantasy1+rdf"); + Assert.assertTrue(providerAInvoked); + Assert.assertFalse(providerBInvoked); + serializer.unbindSerializingProvider(serializingProviderB); + providerAInvoked = false; + providerBInvoked = false; + serializer.serialize(null, null, "application/x-fantasy2+rdf"); + Assert.assertTrue(providerAInvoked); + Assert.assertFalse(providerBInvoked); + + } + + @SupportedFormat({"application/x-fantasy1+rdf", "application/x-fantasy2+rdf"}) + static class SerializingProviderA implements SerializingProvider { + + @Override + public void serialize(OutputStream serializedGraph, Graph tc, String formatIdentifier) { + providerAInvoked = true; + } + }; + @SupportedFormat("application/x-fantasy2+rdf") + static class SerializingProviderB implements SerializingProvider { + + @Override + public void serialize(OutputStream serializedGraph, Graph tc, String formatIdentifier) { + providerBInvoked = true; + } + }; +} diff --git a/representation/src/test/java/org/apache/clerezza/representation/TestServiceManagedProvider.java b/representation/src/test/java/org/apache/clerezza/representation/TestServiceManagedProvider.java new file mode 100644 index 0000000..ec6fe9c --- /dev/null +++ b/representation/src/test/java/org/apache/clerezza/representation/TestServiceManagedProvider.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.clerezza.representation; + +import org.apache.clerezza.commons.rdf.Graph; +import org.apache.clerezza.commons.rdf.IRI; +import org.junit.Assert; +import org.junit.Test; + +import java.io.InputStream; + +/** + * This class is listed in + * META-INF/services/org.apache.clerezza.serializedform.ParsingProvider + * + * @author reto + */ +@SupportedFormat("application/x-test+rdf") +public class TestServiceManagedProvider implements ParsingProvider { + + private static boolean parseInvoked; + + @Override + public void parse(Graph target, InputStream serializedGraph, String formatIdentifier, IRI baseUri) { + parseInvoked = true; + } + + @Test + public void registerOneProvider() { + Parser parser = Parser.getInstance(); + parser.parse(null, "application/x-test+rdf"); + Assert.assertTrue(parseInvoked); + } +} diff --git a/representation/src/test/resources/META-INF/services/org.apache.clerezza.representation.ParsingProvider b/representation/src/test/resources/META-INF/services/org.apache.clerezza.representation.ParsingProvider new file mode 100644 index 0000000..16e04f4 --- /dev/null +++ b/representation/src/test/resources/META-INF/services/org.apache.clerezza.representation.ParsingProvider @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +org.apache.clerezza.representation.TestServiceManagedProvider \ No newline at end of file
