Skip to content

Commit

Permalink
Increasing webster coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
adamcin committed Aug 24, 2019
1 parent bd5f145 commit 4aea608
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 52 deletions.
17 changes: 9 additions & 8 deletions core/src/main/java/net/adamcin/oakpal/core/JsonCnd.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,17 +131,18 @@ public final class JsonCnd {
new ImmutableRoot(InitialContent.INITIAL_CONTENT))));

static final NamePathResolver BUILTIN_RESOLVER = new DefaultNamePathResolver(BUILTIN_MAPPINGS);
public static final List<String> BUILTIN_NODETYPES = StreamSupport.stream(
InitialContent.INITIAL_CONTENT
public static final List<String> BUILTIN_NODETYPES = Collections.unmodifiableList(
StreamSupport.stream(InitialContent.INITIAL_CONTENT
.getChildNode(JcrConstants.JCR_SYSTEM)
.getChildNode(NodeTypeConstants.JCR_NODE_TYPES)
.getChildNodeNames().spliterator(), false)
.collect(Collectors.toList());
public static final List<String> BUILTIN_PRIVILEGES = Stream.concat(Stream.of(PrivilegeConstants.JCR_ALL),
Stream.concat(
PrivilegeConstants.NON_AGGREGATE_PRIVILEGES.stream(),
PrivilegeConstants.AGGREGATE_PRIVILEGES.keySet().stream()))
.collect(Collectors.toList());
.collect(Collectors.toList()));
public static final List<String> BUILTIN_PRIVILEGES = Collections.unmodifiableList(
Stream.concat(Stream.of(PrivilegeConstants.JCR_ALL),
Stream.concat(
PrivilegeConstants.NON_AGGREGATE_PRIVILEGES.stream(),
PrivilegeConstants.AGGREGATE_PRIVILEGES.keySet().stream()))
.collect(Collectors.toList()));
static final String PRIVILEGE_KEY_ABSTRACT = "abstract";
static final String PRIVILEGE_KEY_CONTAINS = "contains";

Expand Down
26 changes: 15 additions & 11 deletions webster/src/main/java/net/adamcin/oakpal/webster/CndExporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@
* Interface independent logic for exporting .cnd files from a JCR session.
*/
public final class CndExporter {

public static final class Builder {
private List<Rule> scopeExportNames;
private List<Rule> scopeReplaceNames;
Expand Down Expand Up @@ -187,10 +186,7 @@ public void writeNodetypes(final @NotNull WriterOpener writerOpener,
.flatMap(JsonCnd::streamNsPrefix)
.collect(Collectors.toSet()).stream().map(result1(session::getNamespaceURI)).collect(Collectors.toList());

final String allPrefixMessages = combineCauseMessages(resolvedUris.stream(), NamespaceException.class);
if (!allPrefixMessages.isEmpty()) {
throw new RepositoryException(allPrefixMessages);
}
combineCauseMessages(resolvedUris.stream(), NamespaceException.class, RepositoryException.class);

final Function<String, Name> mapper = Fun.tryOrDefault1(resolver::getQName, null);
final Function<Name, String> qualifier = Fun.tryOrDefault1(resolver::getJCRName, null);
Expand Down Expand Up @@ -327,22 +323,30 @@ public static Map<Name, NodeTypeDefinition> retrieveNodeTypes(final @NotNull Ses
}
}).collect(Collectors.toList());

final String allMessages = combineCauseMessages(typesToAdd.stream(), NoSuchNodeTypeException.class);
if (!allMessages.isEmpty()) {
throw new NoSuchNodeTypeException(allMessages);
}
combineCauseMessages(typesToAdd.stream(), NoSuchNodeTypeException.class, NoSuchNodeTypeException.class);

typesToAdd.stream().flatMap(Result::stream).forEachOrdered(def -> addType(resolver, exportedTypes, def));
return exportedTypes;
}

static <T> String combineCauseMessages(final @NotNull Stream<Result<T>> results, final Class<? extends Throwable> causeType) {
return results.filter(Result::isFailure)
static <T, E extends Throwable> void combineCauseMessages(final @NotNull Stream<Result<T>> results,
final @NotNull Class<? extends Throwable> causeType,
final @NotNull Class<E> andThrow) throws E {
final String combined = results.filter(Result::isFailure)
.map(result -> result.findCause(causeType))
.filter(Optional::isPresent)
.map(Optional::get)
.map(Throwable::getMessage)
.collect(Collectors.joining(", "));
if (!combined.isEmpty()) {
E rethrow;
try {
rethrow = andThrow.getConstructor(String.class).newInstance(combined);
} catch (final ReflectiveOperationException e) {
throw new IllegalStateException(combined, e);
}
throw rethrow;
}
}

static <T> Stream<T> optStream(final T element) {
Expand Down
58 changes: 25 additions & 33 deletions webster/src/main/java/net/adamcin/oakpal/webster/QName.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@
import javax.jcr.NamespaceException;
import java.util.Objects;

import static net.adamcin.oakpal.core.Fun.result1;

/**
* Representation of a Qualified Name.
*/
public final class QName {
private static final Logger LOGGER = LoggerFactory.getLogger(QName.class);
private final Type type;
private final String prefix;
private final String localName;
Expand All @@ -44,57 +45,48 @@ public final class QName {
* @param localName the unqualified local name
* @param uri the namespace URI
*/
public QName(@NotNull final Type type,
public QName(final @NotNull Type type,
final @Nullable String prefix,
@NotNull final String localName,
final @NotNull String localName,
final @Nullable String uri) {
this.type = type;
this.prefix = prefix;
this.localName = localName;
this.uri = uri;
}

public static QName parseQName(final NamespaceMapping mapping, final Type type, final String qName) {
public static final class UnqualifiedNameException extends RuntimeException {
UnqualifiedNameException(final @NotNull String jcrName) {
super(jcrName + " is not a qualified name (expected prefix:localName or {uri}localName format)");
}
}

public static QName parseQName(final @NotNull NamespaceMapping mapping,
final @NotNull Type type,
final @NotNull String qName) {
if (qName.contains(":")) {
final String[] parts = qName.split(":", 2);
final String prefix = parts[0];
final String localName = parts[1];
String uri = null;
try {
uri = mapping.getURI(prefix);
} catch (final NamespaceException e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("[parseQName prefixed] type={} qName={} error={}", type, qName, e.getMessage());
}
}
return new QName(type, prefix, localName, uri);
return new QName(type, prefix, localName,
result1(mapping::getURI).apply(prefix).toOptional().orElse(null));
} else if (qName.startsWith("{") && qName.contains("}")) {
final int lastBrace = qName.indexOf("}");
final String uri = qName.substring(1, lastBrace);
final String localName = qName.substring(lastBrace + 1);
String prefix = null;
try {
prefix = mapping.getPrefix(uri);
} catch (final NamespaceException e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("[parseQName expanded] type={} qName={} error={}", type, qName, e.getMessage());
}
}
return new QName(type, prefix, localName, uri);
return new QName(type,
result1(mapping::getPrefix).apply(uri).toOptional().orElse(null),
localName, uri);
}
return null;
throw new UnqualifiedNameException(qName);
}

public static QName adaptName(final NamespaceMapping mapping, final Type type, final Name name) {
String prefix = null;
try {
prefix = mapping.getPrefix(name.getNamespaceURI());
} catch (NamespaceException e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("[parseQName expanded] type={} name={} error={}", type, name, e.getMessage());
}
}
return new QName(type, prefix, name.getLocalName(), name.getNamespaceURI());
public static QName adaptName(final @NotNull NamespaceMapping mapping,
final @NotNull Type type,
final @NotNull Name name) {
return new QName(type, result1(mapping::getPrefix)
.apply(name.getNamespaceURI()).toOptional().orElse(null),
name.getLocalName(), name.getNamespaceURI());
}

public Type getType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package net.adamcin.oakpal.webster;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
Expand All @@ -29,9 +30,15 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
import java.util.function.Function;
import java.util.stream.Stream;
import javax.jcr.Workspace;
import javax.jcr.nodetype.NodeTypeManager;

import net.adamcin.oakpal.core.JcrNs;
import net.adamcin.oakpal.core.JsonCnd;
import net.adamcin.oakpal.core.Result;
import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
import org.junit.Test;

public class CndExporterTest {
Expand Down Expand Up @@ -165,4 +172,33 @@ public void testWriteNodetypesByName() throws Exception {
ntManager.hasNodeType("sling:OrderedFolder"));
});
}

static final class NoStringConstructorException extends Exception {
public NoStringConstructorException() {
super("NoStringConstructorException");
}
}

@Test(expected = IllegalStateException.class)
public void testCombineCauseMessages_reflectiveError() throws NoStringConstructorException {
CndExporter.combineCauseMessages(
Stream.of(
Result.failure(new Exception("one")),
Result.failure(new Exception("two"))),
Exception.class,
NoStringConstructorException.class);
}

@Test
public void testNsRemapName() {
final NamespaceMapping from = JsonCnd
.toNamespaceMapping(Collections
.singletonList(JcrNs.create("fooFrom", "http://foo.com")));
final NamespaceMapping to = JsonCnd
.toNamespaceMapping(Collections
.singletonList(JcrNs.create("fooTo", "http://foo.com")));

final Function<String, String> remapper = ChecklistExporter.nsRemapName(from, to);
assertEquals("expect new prefix", "fooTo:mixin", remapper.apply("fooFrom:mixin"));
}
}

0 comments on commit 4aea608

Please sign in to comment.