Skip to content
15 changes: 15 additions & 0 deletions src/main/java/fr/inria/corese/core/next/api/IPrefixHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ public interface IPrefixHandler {
*/
boolean hasPrefix(String prefix);

/**
* Checks if a namespace has a prefix
*
* @param namespace the namespace to check
* @return true if the namespace exists in mappings, false otherwise
*/
boolean hasNamespace(String namespace);

/**
* Returns all registered prefixes.
* Order of iteration is implementation-dependent but should be consistent
Expand All @@ -60,6 +68,13 @@ public interface IPrefixHandler {
*/
Map<String, String> getPrefixMap();

/**
* Returns all namespaces mappings as an unmodifiable map.
*
* @return an unmodifiable map where keys are namespaces IRIs and values are prefixes
*/
Map<String, String> getNamespaceMap();

/**
* Returns all namespace objects as an immutable set.
* Each Namespace object contains both prefix and IRI.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package fr.inria.corese.core.next.api.io.common;

import fr.inria.corese.core.next.api.io.IOOptions;

/**
* Options for RDF parsers and serializers that support a base IRI.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package fr.inria.corese.core.next.api.io.serializer;

/**
* Interface for options that determine the generation of blank node Ids for serializers.
*/
public interface BlankNodeIdGenerationOptions {

/**
* Checks if deterministic blank node IDs should be generated.
*
* @return {@code true} if stable blank node IDs are enabled, {@code false} otherwise.
*/
boolean stableBlankNodeIds();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fr.inria.corese.core.next.api.io.serializer;

import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum;

/**
* Interface for serializer options to determine the policy for the literal datatypes
*/
public interface DatatypePolicyOptions {


/**
* Returns the policy for how literal datatypes are printed.
*
* @return The {@link LiteralDatatypePolicyEnum} indicating the literal datatype serialization policy.
*/
LiteralDatatypePolicyEnum getLiteralDatatypePolicy();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package fr.inria.corese.core.next.api.io.serializer;

/**
* Interface to specify which line ending a serializer must use.
*/
public interface LineEndingOptions {

/**
*
* @return the end line characters
*/
String getLineEnding();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package fr.inria.corese.core.next.api.io.serializer;

import fr.inria.corese.core.next.impl.io.serialization.option.PrefixOrderingEnum;

/**
* Interface for the options of serializer allowing for pretty printing.
*/
public interface PrettyPrintOptions {

/**
* Returns the string used for indentation when pretty-printing.
*
* @return The indentation string.
*/
String getIndent();

/**
* Checks if human-readable formatting (pretty-printing) is enabled.
*
* @return {@code true} if pretty-printing is enabled, {@code false} otherwise.
*/
boolean prettyPrint();

/**
* Returns the maximum desired line length before the serializer attempts to break lines.
*
* @return The maximum line length.
*/
int getMaxLineLength();

/**
* Checks if subjects should be sorted alphabetically in the output.
*
* @return {@code true} if subject sorting is enabled, {@code false} otherwise.
*/
boolean sortSubjects();

/**
* Checks if predicates should be sorted alphabetically within a subject group.
*
* @return {@code true} if predicate sorting is enabled, {@code false} otherwise.
*/
boolean sortPredicates();

/**
* Returns the policy for ordering prefix declarations.
*
* @return The {@link PrefixOrderingEnum} for prefix ordering.
*/
PrefixOrderingEnum getPrefixOrdering();
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package fr.inria.corese.core.next.api.io.serialization;
package fr.inria.corese.core.next.api.io.serializer;

import java.io.Writer;

Expand Down Expand Up @@ -37,7 +37,7 @@ public interface RDFSerializer {
*/
default String getFormatName() {
return getRDFFormat().getName();
};
}

/**
* Gets the RDF format that this serializer generates.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package fr.inria.corese.core.next.api.io.serialization;
package fr.inria.corese.core.next.api.io.serializer;

import fr.inria.corese.core.next.api.Model;
import fr.inria.corese.core.next.api.base.io.RDFFormat;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package fr.inria.corese.core.next.api.io.serializer;

import fr.inria.corese.core.next.impl.common.prefix.PrefixHandler;
import fr.inria.corese.core.next.impl.io.serialization.option.PrefixOrderingEnum;

/**
* Interface for the options of serializer that can declare prefixes
*/
public interface UsesPrefixOptions {

/**
* Checks if prefix declarations should be used for compact IRIs.
*
* @return {@code true} if prefixes are used, {@code false} otherwise.
*/
boolean usePrefixes();
/**
* Checks if the serializer should automatically discover and declare prefixes.
*
* @return {@code true} if auto-declaration is enabled, {@code false} otherwise.
*/
boolean autoDeclarePrefixes();
/**
* Returns the policy for ordering prefix declarations.
*
* @return The {@link PrefixOrderingEnum} for prefix ordering.
*/
PrefixOrderingEnum getPrefixOrdering();
/**
* Returns an unmodifiable map of custom URI prefixes.
*
* @return The {@link PrefixHandler} managing all prefix mappings.
*/
PrefixHandler getPrefixHandler();
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ public PrefixHandler(boolean includeStandardVocabularies) {
}
}

/**
* Copy constructor
*/
public PrefixHandler(PrefixHandler oHandler) {
this.prefixToNamespace = new ConcurrentHashMap<>(oHandler.prefixToNamespace);
this.namespaceToPrefix = new ConcurrentHashMap<>(oHandler.namespaceToPrefix);
this.defaultNamespace = oHandler.defaultNamespace;
}

/**
* Initializes the handler with standard W3C vocabulary prefixes by using the
* dedicated Vocabulary enum classes.
Expand All @@ -57,14 +66,11 @@ private void initializeStandardVocabularies() {
OWL.class,
FOAF.class
);

for (Class<? extends Enum<? extends Vocabulary>> vocabClass : vocabularyClasses) {
Enum<? extends Vocabulary>[] constants = vocabClass.getEnumConstants();
if (constants.length > 0) {
Vocabulary vocabInstance = (Vocabulary) constants[0];
setPrefix(vocabInstance.getPreferredPrefix(), vocabInstance.getNamespace());
}
}
setPrefix(RDF.getVocabularyPreferredPrefix(), RDF.getVocabularyNamespace());
setPrefix(RDFS.getVocabularyPreferredPrefix(), RDFS.getVocabularyNamespace());
setPrefix(XSD.getVocabularyPreferredPrefix(), XSD.getVocabularyNamespace());
setPrefix(OWL.getVocabularyPreferredPrefix(), OWL.getVocabularyNamespace());
setPrefix(FOAF.getVocabularyPreferredPrefix(), FOAF.getVocabularyNamespace());
}

/**
Expand All @@ -87,8 +93,14 @@ public void setPrefix(String prefix, String namespace) {
}

String oldNamespace = prefixToNamespace.get(prefix);
if (oldNamespace != null && !oldNamespace.equals(namespace)) {
if (oldNamespace != null && ! oldNamespace.equals(namespace)) {
namespaceToPrefix.remove(oldNamespace);
prefixToNamespace.remove(prefix);
}
String oldPrefix = namespaceToPrefix.get(namespace);
if(oldPrefix != null && ! oldPrefix.equals(prefix)) {
namespaceToPrefix.remove(namespace);
prefixToNamespace.remove(oldPrefix);
}

prefixToNamespace.put(prefix, namespace);
Expand Down Expand Up @@ -142,6 +154,11 @@ public boolean hasPrefix(String prefix) {
return prefixToNamespace.containsKey(prefix);
}

@Override
public boolean hasNamespace(String namespace) {
return namespaceToPrefix.containsKey(namespace);
}

/**
* Gets the default namespace
*
Expand Down Expand Up @@ -218,6 +235,16 @@ public Map<String, String> getPrefixMap() {
return Collections.unmodifiableMap(new HashMap<>(prefixToNamespace));
}

/**
* Returns all namespaces mappings as an unmodifiable map.
*
* @return an unmodifiable map where keys are namespaces IRIs and values are prefixes
*/
@Override
public Map<String, String> getNamespaceMap() {
return Collections.unmodifiableMap(new HashMap<>(namespaceToPrefix));
}

/**
* Returns all namespace objects as an immutable set.
* Each Namespace object contains both prefix and IRI.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@
*/
public class IRIUtils {

private static final Pattern IRI_PATTERN = Pattern.compile("^(?<namespace>" +
"(?<protocol>[\\w\\-]+):(?<dblSlashes>\\/\\/)?" +
"(?<domain>([\\w\\-_:@]+\\.)*[\\w\\-_:]*))" +
"((?<path>\\/([\\w\\-\\._\\:]+\\/)*)" +
"(?<finalPath>[\\w\\-\\._\\:]+)?" +
"(?<query>\\?[\\w\\-_\\:\\?\\=]+)?" +
"(?<anchor>(\\#))?" +
"(?<fragment>([\\w\\-_]+))?)?$");
// Example 1 : http://webisa.webdatacommons.org/data/sparql?query=q#line1
private static final Pattern IRI_PATTERN = Pattern.compile("^(?<rootnamespace>" + // http://webisa.webdatacommons.org
"(?<protocol>[\\w\\-]+):" + // http:
"(?<dblSlashes>\\/\\/)?" + // //
"(?<domain>([\\w\\[\\]\\-_:@]+\\.)*[\\w\\-_:]*)" + // webisa.webdatacommons.org
")" +
"(?<path>\\/([\\w\\-\\._\\:]+\\/)*)*" + // /data/
"(?<finalPath>[\\w&<>;\\-\\._\\:\\\"\\\']+)?" + // sparql
"(?<query>\\?[\\w\\-\\\"\\\'_\\:\\?\\=]+)?" + // ?query=q
"(?<anchor>\\#)?" + // #
"(?<fragment>[\\w\\-_]+)?" + // line1
"$"
);
private static final Pattern STANDARD_IRI_PATTERN = Pattern.compile("^(([^:/?#\\s]+):)(\\/\\/([^/?#\\s]*))?([^?#\\s]*)(\\?([^#\\s]*))?(#(.*))?");
private static final int MAX_IRI_LENGTH = 2048;
private static final long REGEX_TIMEOUT_MS = 100;
Expand Down Expand Up @@ -54,20 +59,21 @@ public static String guessNamespace(String iri) {
return iri;
}
} else if (matcher.matches()) {
// This is a blank node
if (matcher.group("protocol") != null && matcher.group("protocol").equals("_")) {
return "";
}

StringBuilder namespace = new StringBuilder();
namespace.append(matcher.group("protocol")).append(":");
if (matcher.group("dblSlashes") != null) {
namespace.append(matcher.group("dblSlashes"));
}
namespace.append(matcher.group("domain"));
namespace.append(matcher.group("rootnamespace"));
if (matcher.group("path") != null) {
namespace.append(matcher.group("path"));
}
if((matcher.group("fragment") != null || matcher.group("anchor") != null) && matcher.group("finalPath") != null) {
namespace.append(matcher.group("finalPath")).append("#");
if(matcher.group("anchor") != null) {
if(matcher.group("finalPath") != null) {
namespace.append(matcher.group("finalPath"));
}
namespace.append(matcher.group("anchor"));
}

return namespace.toString();
Expand Down
Loading