Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
david-waltermire committed Nov 18, 2024
1 parent 0e26e6b commit ece3b63
Show file tree
Hide file tree
Showing 177 changed files with 1,639 additions and 943 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@ public abstract class AbstractCustomJavaDataTypeAdapter<
* Construct a new Java type adapter for the class based on
* {@link ICustomJavaDataType}.
*
* @param clazz
* @param valueClass
* a data type class based on {@link ICustomJavaDataType}
* @param itemClass
* the Java type of the Matepath item this adapter supports
*/
public AbstractCustomJavaDataTypeAdapter(@NonNull Class<TYPE> clazz) {
super(clazz);
public AbstractCustomJavaDataTypeAdapter(
@NonNull Class<TYPE> valueClass,
@NonNull Class<ITEM_TYPE> itemClass) {
super(valueClass, itemClass);
}

@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import com.fasterxml.jackson.core.JsonParser;

import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
import gov.nist.secauto.metaschema.core.metapath.type.IAtomicOrUnionType;
import gov.nist.secauto.metaschema.core.metapath.type.impl.DataTypeItemType;
import gov.nist.secauto.metaschema.core.model.util.JsonUtil;
import gov.nist.secauto.metaschema.core.model.util.XmlEventUtil;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
Expand Down Expand Up @@ -47,16 +49,23 @@ public abstract class AbstractDataTypeAdapter<TYPE, ITEM_TYPE extends IAnyAtomic
public static final String DEFAULT_JSON_FIELD_VALUE_NAME = "STRVALUE";

@NonNull
private final Class<TYPE> clazz;
private final Class<TYPE> valueClass;
@NonNull
private final IAtomicOrUnionType<ITEM_TYPE> itemType;

/**
* Construct a new Java type adapter for a provided class.
*
* @param clazz
* the Java type this adapter supports
* @param valueClass
* the Java value object type this adapter supports
* @param itemClass
* the Java type of the Matepath item this adapter supports
*/
protected AbstractDataTypeAdapter(@NonNull Class<TYPE> clazz) {
this.clazz = clazz;
protected AbstractDataTypeAdapter(
@NonNull Class<TYPE> valueClass,
@NonNull Class<ITEM_TYPE> itemClass) {
this.valueClass = valueClass;
this.itemType = new DataTypeItemType<>(this, itemClass);
}

@Override
Expand All @@ -67,7 +76,12 @@ public TYPE toValue(Object value) {

@Override
public Class<TYPE> getJavaClass() {
return clazz;
return valueClass;
}

@Override
public IAtomicOrUnionType getItemType() {
return itemType;
}

@Override
Expand Down Expand Up @@ -191,9 +205,6 @@ public void writeJsonValue(Object value, JsonGenerator generator) throws IOExcep
}
}

@Override
public abstract Class<ITEM_TYPE> getItemClass();

@Override
public abstract ITEM_TYPE newItem(Object value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@

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

import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
import gov.nist.secauto.metaschema.core.qname.QNameCache;
import gov.nist.secauto.metaschema.core.util.CustomCollectors;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand All @@ -15,7 +19,6 @@
import java.util.ServiceLoader;
import java.util.ServiceLoader.Provider;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.xml.namespace.QName;
Expand All @@ -30,11 +33,11 @@
*/
public final class DataTypeService {
private static final Logger LOGGER = LogManager.getLogger(DataTypeService.class);
private static final Lazy<DataTypeService> INSTANCE = Lazy.lazy(() -> new DataTypeService());
private static final Lazy<DataTypeService> INSTANCE = Lazy.lazy(DataTypeService::new);

private final Map<String, IDataTypeAdapter<?>> typeByName;
private final Map<QName, IDataTypeAdapter<?>> typeByQName;
private final Map<Class<? extends IDataTypeAdapter<?>>, IDataTypeAdapter<?>> typeByClass;
private final Map<Integer, IDataTypeAdapter<?>> typeByQNameIndex;
private final Map<Class<? extends IDataTypeAdapter<?>>, IDataTypeAdapter<?>> typeByAdapterClass;
private final Map<Class<? extends IAnyAtomicItem>, IDataTypeAdapter<?>> typeByItemClass;

/**
* Get the singleton service instance, which will be lazy constructed on first
Expand All @@ -44,21 +47,20 @@ public final class DataTypeService {
*/
@SuppressWarnings("null")
@NonNull
public static DataTypeService getInstance() {
public static DataTypeService instance() {
return INSTANCE.get();
}

private DataTypeService() {

ServiceLoader<IDataTypeProvider> loader = ServiceLoader.load(IDataTypeProvider.class);
List<IDataTypeAdapter<?>> dataTypes = loader.stream()
.map(Provider<IDataTypeProvider>::get)
.flatMap(provider -> provider.getJavaTypeAdapters().stream())
.collect(Collectors.toList());

Map<String, IDataTypeAdapter<?>> typeByName = dataTypes.stream()
this.typeByQNameIndex = dataTypes.stream()
.flatMap(dataType -> dataType.getNames().stream()
.map(qname -> Map.entry(qname.getLocalPart(), dataType)))
.map(qname -> Map.entry(qname.getIndexPosition(), dataType)))
.collect(CustomCollectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
Expand All @@ -73,44 +75,37 @@ private DataTypeService() {
},
ConcurrentHashMap::new));

Map<QName, IDataTypeAdapter<?>> typeByQName = dataTypes.stream()
.flatMap(dataType -> dataType.getNames().stream()
.map(qname -> Map.entry(qname, dataType)))
this.typeByAdapterClass = dataTypes.stream()
.collect(CustomCollectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
dataType -> ObjectUtils.asNullableType(dataType.getClass()),
CustomCollectors.identity(),
(key, v1, v2) -> {
if (LOGGER.isWarnEnabled()) {
LOGGER.warn("Data types '{}' and '{}' have duplicate name '{}'. Using the first.",
v1.getClass().getName(),
v2.getClass().getName(),
key);
LOGGER.warn("Duplicate data type class '{}'. Using the first.",
key.getClass().getName());
}
return v1;
},
ConcurrentHashMap::new));

@SuppressWarnings({ "unchecked", "null" })
Map<Class<? extends IDataTypeAdapter<?>>,
IDataTypeAdapter<?>> typeByClass = dataTypes.stream()
.collect(CustomCollectors.toMap(
dataType -> (Class<? extends IDataTypeAdapter<?>>) dataType.getClass(),
Function.identity(),
(key, v1, v2) -> {
if (LOGGER.isWarnEnabled()) {
LOGGER.warn("Duplicate data type class '{}'. Using the first.",
key.getClass().getName());
}
return v1;
},
ConcurrentHashMap::new));
this.typeByName = typeByName;
this.typeByQName = typeByQName;
this.typeByClass = typeByClass;
this.typeByItemClass = dataTypes.stream()
.collect(CustomCollectors.toMap(
dataType -> ObjectUtils.asNullableType(dataType.getItemType().getItemClass()),
CustomCollectors.identity(),
(key, v1, v2) -> {
if (LOGGER.isWarnEnabled()) {
LOGGER.warn("Duplicate item class '{}' declared by adapters '%s' and '%s'. Using the first.",
key.getClass().getName(),
v1.getClass().getName(),
v2.getClass().getName());
}
return v1;
},
ConcurrentHashMap::new));
}

/**
* Lookup a specific {@link IDataTypeAdapter} instance by its name.
* Lookup a specific {@link IDataTypeAdapter} instance by its QName.
*
* @param qname
* the qualified name of data type adapter to get the instance for
Expand All @@ -119,20 +114,23 @@ private DataTypeService() {
*/
@Nullable
public IDataTypeAdapter<?> getJavaTypeAdapterByQName(@NonNull QName qname) {
return typeByQName.get(qname);
IEnhancedQName result = QNameCache.instance().get(qname);
return result == null ? null : getJavaTypeAdapterByQNameIndex(result.getIndexPosition());
}

/**
* Lookup a specific {@link IDataTypeAdapter} instance by its name.
* Lookup a specific {@link IDataTypeAdapter} instance by its QName index
* position.
*
* @param name
* the name of data type adapter to get the instance for
* @param qnameIndexPosition
* the position in the global QName index for the qualified name of
* data type adapter to get the instance for
* @return the instance or {@code null} if the instance is unknown to the type
* system
*/
@Nullable
public IDataTypeAdapter<?> getJavaTypeAdapterByName(@NonNull String name) {
return typeByName.get(name);
public IDataTypeAdapter<?> getJavaTypeAdapterByQNameIndex(int qnameIndexPosition) {
return typeByQNameIndex.get(qnameIndexPosition);
}

/**
Expand All @@ -148,6 +146,11 @@ public IDataTypeAdapter<?> getJavaTypeAdapterByName(@NonNull String name) {
@SuppressWarnings("unchecked")
@Nullable
public <TYPE extends IDataTypeAdapter<?>> TYPE getJavaTypeAdapterByClass(@NonNull Class<TYPE> clazz) {
return (TYPE) typeByClass.get(clazz);
return (TYPE) typeByAdapterClass.get(clazz);
}

@Nullable
public IDataTypeAdapter<?> getJavaTypeAdapterByItemClass(Class<? extends IAnyAtomicItem> clazz) {
return typeByItemClass.get(clazz);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes;

import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
import gov.nist.secauto.metaschema.core.metapath.type.IAtomicOrUnionType;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import org.codehaus.stax2.XMLEventReader2;
Expand Down Expand Up @@ -46,15 +48,15 @@ public interface IDataTypeAdapter<TYPE> {
* @return the name
*/
@NonNull
List<QName> getNames();
List<IEnhancedQName> getNames();

/**
* Get the most preferred name for this data type.
*
* @return the name
*/
@NonNull
default QName getPreferredName() {
default IEnhancedQName getPreferredName() {
return ObjectUtils.notNull(getNames().iterator().next());
}

Expand Down Expand Up @@ -121,13 +123,12 @@ default boolean isAtomic() {
}

/**
* Get the java type of the associated item.
* Get the item type information of the associated item.
*
* @return the java associated item type
* @return the item type information
*/
// TODO: move to IAnyAtomicItem
@NonNull
Class<? extends IAnyAtomicItem> getItemClass();
IAtomicOrUnionType<?> getItemType();

/**
* Construct a new item of this type using the provided value.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import java.io.IOException;
import java.math.BigInteger;

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

/**
* Provides a common base class for integer-based data types.
* <p>
Expand All @@ -27,9 +29,13 @@ public abstract class AbstractIntegerAdapter<ITEM_TYPE extends IIntegerItem>

/**
* Construct a new integer-based adapter.
*
* @param itemClass
* the Java type of the Matepath item this adapter supports
*/
protected AbstractIntegerAdapter() {
super(BigInteger.class);
protected AbstractIntegerAdapter(
@NonNull Class<ITEM_TYPE> itemClass) {
super(BigInteger.class, itemClass);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import gov.nist.secauto.metaschema.core.datatype.AbstractDataTypeAdapter;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;

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

/**
* Provides a common base class for string-based data types.
*
Expand All @@ -21,9 +23,12 @@ public abstract class AbstractStringAdapter<ITEM_TYPE extends IStringItem>

/**
* Construct a new string-based adapter.
*
* @param itemClass
* the Java type of the Matepath item this adapter supports
*/
protected AbstractStringAdapter() {
super(String.class);
protected AbstractStringAdapter(@NonNull Class<ITEM_TYPE> itemClass) {
super(String.class, itemClass);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
import gov.nist.secauto.metaschema.core.datatype.AbstractDataTypeAdapter;
import gov.nist.secauto.metaschema.core.metapath.MetapathConstants;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBase64BinaryItem;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
import gov.nist.secauto.metaschema.core.qname.QNameCache;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import java.nio.ByteBuffer;
import java.util.Base64;
import java.util.List;

import javax.xml.namespace.QName;

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

/**
Expand All @@ -28,18 +28,18 @@
public class Base64Adapter
extends AbstractDataTypeAdapter<ByteBuffer, IBase64BinaryItem> {
@NonNull
private static final List<QName> NAMES = ObjectUtils.notNull(
private static final List<IEnhancedQName> NAMES = ObjectUtils.notNull(
List.of(
new QName(MetapathConstants.NS_METAPATH.toASCIIString(), "base64"),
QNameCache.instance().of(MetapathConstants.NS_METAPATH, "base64"),
// for backwards compatibility with original type name
new QName(MetapathConstants.NS_METAPATH.toASCIIString(), "base64Binary")));
QNameCache.instance().of(MetapathConstants.NS_METAPATH, "base64Binary")));

Base64Adapter() {
super(ByteBuffer.class);
super(ByteBuffer.class, IBase64BinaryItem.class);
}

@Override
public List<QName> getNames() {
public List<IEnhancedQName> getNames() {
return NAMES;
}

Expand Down Expand Up @@ -83,11 +83,6 @@ public String asString(Object value) {
return ObjectUtils.notNull(encoder.encodeToString(array));
}

@Override
public Class<IBase64BinaryItem> getItemClass() {
return IBase64BinaryItem.class;
}

@Override
public IBase64BinaryItem newItem(Object value) {
ByteBuffer item = toValue(value);
Expand Down
Loading

0 comments on commit ece3b63

Please sign in to comment.