Skip to content

Commit

Permalink
Completed refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
david-waltermire committed Oct 24, 2024
1 parent ebdf350 commit 33f2e5d
Show file tree
Hide file tree
Showing 79 changed files with 1,754 additions and 932 deletions.
4 changes: 4 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import gov.nist.secauto.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Lock;
Expand All @@ -32,9 +33,10 @@ public abstract class AbstractDataTypeProvider implements IDataTypeProvider {
@Override
public List<? extends IDataTypeAdapter<?>> getJavaTypeAdapters() {
Lock readLock = libraryLock.readLock();
readLock.lock();
try {
readLock.lock();
return CollectionUtil.unmodifiableList(library);
// make a defensive copy to protect callers from potential modifications
return CollectionUtil.unmodifiableList(new ArrayList<>(library));
} finally {
readLock.unlock();
}
Expand All @@ -53,8 +55,8 @@ protected void registerDatatype(@NonNull IDataTypeAdapter<?> adapter) {
throw new IllegalArgumentException("The adapter has no name: " + adapter.getClass().getName());
}
Lock writeLock = libraryLock.writeLock();
writeLock.lock();
try {
writeLock.lock();
library.add(adapter);
} finally {
writeLock.unlock();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

package gov.nist.secauto.metaschema.core.metapath;

import com.github.benmanes.caffeine.cache.Caffeine;

import gov.nist.secauto.metaschema.core.configuration.DefaultConfiguration;
import gov.nist.secauto.metaschema.core.configuration.IConfiguration;
import gov.nist.secauto.metaschema.core.configuration.IMutableConfiguration;
Expand All @@ -23,6 +25,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import javax.xml.namespace.QName;

Expand Down Expand Up @@ -87,7 +90,10 @@ public SharedState(@NonNull StaticContext staticContext) {
this.implicitTimeZone = ObjectUtils.notNull(clock.getZone());
this.currentDateTime = ObjectUtils.notNull(ZonedDateTime.now(clock));
this.availableDocuments = new HashMap<>();
this.functionResultCache = new HashMap<>();
this.functionResultCache = ObjectUtils.notNull(Caffeine.newBuilder()
.maximumSize(5000)
.expireAfterAccess(10, TimeUnit.MINUTES)
.<CallingContext, ISequence<?>>build().asMap());
this.configuration = new DefaultConfiguration<>();
this.configuration.enableFeature(MetapathEvaluationFeature.METAPATH_EVALUATE_PREDICATES);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ private void registerFunctionByQName(@NonNull IFunction function) {
QName qname = function.getQName();
IFunction duplicate;
Lock writeLock = instanceLock.writeLock();
writeLock.lock();
try {
writeLock.lock();
NamedFunctionSet functions = libraryByQName.get(qname);
if (functions == null) {
functions = new NamedFunctionSet();
Expand All @@ -66,8 +66,8 @@ private void registerFunctionByQName(@NonNull IFunction function) {
private void registerFunctionByName(@NonNull IFunction function) {
String name = function.getName();
Lock writeLock = instanceLock.writeLock();
writeLock.lock();
try {
writeLock.lock();
NamedFunctionSet functions = libraryByName.get(name);
if (functions == null) {
functions = new NamedFunctionSet();
Expand All @@ -83,8 +83,8 @@ private void registerFunctionByName(@NonNull IFunction function) {
@Override
public Stream<IFunction> stream() {
Lock readLock = instanceLock.readLock();
readLock.lock();
try {
readLock.lock();
return ObjectUtils.notNull(libraryByQName.values().stream().flatMap(NamedFunctionSet::getFunctionsAsStream));
} finally {
readLock.unlock();
Expand All @@ -95,8 +95,8 @@ public Stream<IFunction> stream() {
public IFunction getFunction(@NonNull String name, int arity) {
IFunction retval = null;
Lock readLock = instanceLock.readLock();
readLock.lock();
try {
readLock.lock();
NamedFunctionSet functions = libraryByName.get(name);
if (functions != null) {
retval = functions.getFunctionWithArity(arity);
Expand All @@ -111,8 +111,8 @@ public IFunction getFunction(@NonNull String name, int arity) {
public IFunction getFunction(@NonNull QName name, int arity) {
IFunction retval = null;
Lock readLock = instanceLock.readLock();
readLock.lock();
try {
readLock.lock();
NamedFunctionSet functions = libraryByQName.get(name);
if (functions != null) {
retval = functions.getFunctionWithArity(arity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,9 @@
import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils;
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
import gov.nist.secauto.metaschema.core.metapath.function.IFunction;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidTypeFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;

import java.util.List;

Expand Down Expand Up @@ -79,12 +76,10 @@ private static ISequence<IIntegerItem> executeOneArg(@NonNull IFunction function
// From the XPath 3.1 specification:
// If the value of $arg is the empty sequence, the function returns the
// xs:integer value zero (0).
if (arguments.get(0).size() == 0) {
return ISequence.of(IIntegerItem.valueOf(0));
}

IStringItem arg = FunctionUtils.asTypeOrNull(arguments.get(0).getFirstItem(true));
return ISequence.of(fnStringLength(arg));
return ISequence.of(arg == null
? IIntegerItem.ZERO
: fnStringLength(arg));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
import gov.nist.secauto.metaschema.core.metapath.function.IFunction;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDecimalItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import org.apache.commons.lang3.StringUtils;

import java.util.List;

import edu.umd.cs.findbugs.annotations.NonNull;

import org.apache.commons.lang3.StringUtils;

/**
* Implements <a href=
* "https://www.w3.org/TR/xpath-functions-31/#func-substring-after">fn:substring-after</a>.
Expand Down Expand Up @@ -61,13 +60,17 @@ private static ISequence<IStringItem> executeTwoArg(
@NonNull List<ISequence<?>> arguments,
@NonNull DynamicContext dynamicContext,
IItem focus) {

// From the XPath 3.1 specification:
// If the value of $arg1 or $arg2 is the empty sequence, or contains only
// ignorable collation units, it is interpreted as the zero-length string.
IStringItem arg1 = arguments.get(0).isEmpty() ? IStringItem.valueOf("") : FunctionUtils.asTypeOrNull(arguments.get(0).getFirstItem(true));
IStringItem arg2 = arguments.get(1).isEmpty() ? IStringItem.valueOf("") : FunctionUtils.asTypeOrNull(arguments.get(1).getFirstItem(true));

IStringItem arg1 = arguments.get(0).isEmpty()
? IStringItem.valueOf("")
: FunctionUtils.asType(ObjectUtils.notNull(arguments.get(0).getFirstItem(true)));
IStringItem arg2 = arguments.get(1).isEmpty()
? IStringItem.valueOf("")
: FunctionUtils.asType(ObjectUtils.notNull(arguments.get(1).getFirstItem(true)));

return ISequence.of(IStringItem.valueOf(fnSubstringAfter(arg1.asString(), arg2.asString())));
}

Expand All @@ -78,7 +81,8 @@ private static ISequence<IStringItem> executeTwoArg(
* @param arg1
* the source string to get a substring from
* @param arg2
* the substring to match and find the substring to return after the match
* the substring to match and find the substring to return after the
* match
* @return the substring
*/
@NonNull
Expand All @@ -87,4 +91,4 @@ public static String fnSubstringAfter(
@NonNull String arg2) {
return StringUtils.substringAfter(arg1, arg2);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
import gov.nist.secauto.metaschema.core.metapath.function.IFunction;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDecimalItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import org.apache.commons.lang3.StringUtils;

import java.util.List;

import edu.umd.cs.findbugs.annotations.NonNull;

import org.apache.commons.lang3.StringUtils;

/**
* Implements <a href=
* "https://www.w3.org/TR/xpath-functions-31/#func-substring-before">fn:substring-before</a>.
Expand Down Expand Up @@ -65,9 +64,13 @@ private static ISequence<IStringItem> executeTwoArg(
// From the XPath 3.1 specification:
// If the value of $arg1 or $arg2 is the empty sequence, or contains only
// ignorable collation units, it is interpreted as the zero-length string.
IStringItem arg1 = arguments.get(0).isEmpty() ? IStringItem.valueOf("") : FunctionUtils.asTypeOrNull(arguments.get(0).getFirstItem(true));
IStringItem arg2 = arguments.get(1).isEmpty() ? IStringItem.valueOf("") : FunctionUtils.asTypeOrNull(arguments.get(1).getFirstItem(true));

IStringItem arg1 = arguments.get(0).isEmpty()
? IStringItem.valueOf("")
: FunctionUtils.asType(ObjectUtils.notNull(arguments.get(0).getFirstItem(true)));
IStringItem arg2 = arguments.get(1).isEmpty()
? IStringItem.valueOf("")
: FunctionUtils.asType(ObjectUtils.notNull(arguments.get(1).getFirstItem(true)));

return ISequence.of(IStringItem.valueOf(fnSubstringBefore(arg1.asString(), arg2.asString())));
}

Expand All @@ -78,13 +81,14 @@ private static ISequence<IStringItem> executeTwoArg(
* @param arg1
* the source string to get a substring from
* @param arg2
* the substring to match and find the substring to return before the match
* the substring to match and find the substring to return before the
* match
* @return the substring
*/
@NonNull
public static String fnSubstringBefore(
@NonNull String arg1,
@NonNull String arg2) {
return StringUtils.substringBefore(arg1,arg2);
return StringUtils.substringBefore(arg1, arg2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ public StreamSequence(@NonNull Stream<ITEM> stream) {

@Override
public List<ITEM> getValue() {
instanceLock.lock();
try {
instanceLock.lock();
if (list == null) {
list = stream().collect(Collectors.toUnmodifiableList());
}
Expand All @@ -62,8 +62,8 @@ public List<ITEM> getValue() {
public Stream<ITEM> stream() {
@NonNull Stream<ITEM> retval;
// Ensure thread safety and prevent multiple consumptions of the stream
instanceLock.lock();
try {
instanceLock.lock();
if (list == null) {
if (stream == null) {
throw new IllegalStateException("stream is already consumed");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

package gov.nist.secauto.metaschema.core.model;

import com.github.benmanes.caffeine.cache.Caffeine;

import gov.nist.secauto.metaschema.core.util.CollectionUtil;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

Expand All @@ -19,9 +21,9 @@
import java.nio.file.Path;
import java.util.Collection;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import edu.umd.cs.findbugs.annotations.NonNull;
Expand All @@ -30,7 +32,10 @@ public abstract class AbstractLoader<T> implements ILoader<T> {
private static final Logger LOGGER = LogManager.getLogger(AbstractLoader.class);

@NonNull
private final Map<URI, T> cache = new LinkedHashMap<>(); // NOPMD - intentional
private final Map<URI, T> cache = ObjectUtils.notNull(Caffeine.newBuilder()
.maximumSize(100)
.expireAfterAccess(10, TimeUnit.MINUTES)
.<URI, T>build().asMap());

@Override
@NonNull
Expand Down Expand Up @@ -142,10 +147,8 @@ protected T loadInternal(@NonNull URI resource, @NonNull Deque<URI> visitedResou
visitedResources.pop();
}
cache.put(resource, retval);
} else {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Found resource in cache '{}'", resource);
}
} else if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Found resource in cache '{}'", resource);
}
return ObjectUtils.notNull(retval);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ private static <DEF extends IDefinition> DEF handleShadowedDefinitions(
@NonNull QName key,
@NonNull DEF oldDef,
@NonNull DEF newDef) {
if (!oldDef.equals(newDef) && LOGGER.isInfoEnabled()) {
LOGGER.info("The {} '{}' from metaschema '{}' is shadowing '{}' from metaschema '{}'",
if (!oldDef.equals(newDef) && LOGGER.isWarnEnabled()) {
LOGGER.warn("The {} '{}' from metaschema '{}' is shadowing '{}' from metaschema '{}'",
newDef.getModelType().name().toLowerCase(Locale.ROOT),
newDef.getName(),
newDef.getContainingModule().getShortName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

package gov.nist.secauto.metaschema.core.model;

import gov.nist.secauto.metaschema.core.util.CollectionUtil;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import java.io.IOException;
Expand Down Expand Up @@ -34,29 +33,12 @@
public abstract class AbstractModuleLoader<T, M extends IModuleExtended<M, ?, ?, ?, ?>>
extends AbstractLoader<M>
implements IModuleLoader<M> {
@NonNull
private final List<IModuleLoader.IModulePostProcessor> modulePostProcessors;

/**
* Construct a new Metaschema module loader, which use the provided module post
* processors when loading a module.
*
* @param modulePostProcessors
* post processors to perform additional module customization when
* loading
*/
protected AbstractModuleLoader(@NonNull List<IModuleLoader.IModulePostProcessor> modulePostProcessors) {
this.modulePostProcessors = CollectionUtil.unmodifiableList(new ArrayList<>(modulePostProcessors));
}

/**
* Get the set of module post processors associated with this loader.
*
* @return the set of constraints
*/
@NonNull
protected List<IModuleLoader.IModulePostProcessor> getModulePostProcessors() {
return modulePostProcessors;
protected AbstractModuleLoader() {
// only allow construction by extending classes
}

/**
Expand Down Expand Up @@ -115,12 +97,7 @@ protected M parseResource(@NonNull URI resource, @NonNull Deque<URI> visitedReso
// now create this metaschema
Collection<M> values = importedModules.values();
try {
M module = newModule(resource, binding, new ArrayList<>(values));

for (IModuleLoader.IModulePostProcessor postProcessor : getModulePostProcessors()) {
postProcessor.processModule(module);
}
return module;
return newModule(resource, binding, new ArrayList<>(values));
} catch (MetaschemaException ex) {
throw new IOException(ex);
}
Expand Down
Loading

0 comments on commit 33f2e5d

Please sign in to comment.