use of org.apache.sis.internal.simple.SimpleAttributeType in project sis by apache.
the class DefaultRecordSchema method createRecordType.
/**
* Creates a new record type of the given name, which will contains the given members.
* Members are declared in iteration order.
*
* @param typeName the record type name.
* @param members the name of each record member, together with the expected value types.
* @return a record type of the given name and members.
* @throws IllegalArgumentException if a record already exists for the given name but with different members.
*/
public RecordType createRecordType(final CharSequence typeName, final Map<CharSequence, Class<?>> members) throws IllegalArgumentException {
ArgumentChecks.ensureNonNull("typeName", typeName);
ArgumentChecks.ensureNonNull("members", members);
final TypeName name = nameFactory.createTypeName(namespace, typeName);
final Map<CharSequence, Type> memberTypes = ObjectConverters.derivedValues(members, CharSequence.class, toTypes);
RecordType record;
synchronized (description) {
record = description.get(typeName);
if (record == null) {
record = new DefaultRecordType(name, this, memberTypes, nameFactory);
description.put(name, record);
return record;
}
}
/*
* If a record type already exists for the given name, verify that it contains the same members.
*/
final Iterator<Map.Entry<CharSequence, Class<?>>> it1 = members.entrySet().iterator();
final Iterator<Map.Entry<MemberName, Type>> it2 = record.getMemberTypes().entrySet().iterator();
boolean hasNext;
while ((hasNext = it1.hasNext()) == it2.hasNext()) {
if (!hasNext) {
// Finished comparison successfully.
return record;
}
final Map.Entry<CharSequence, Class<?>> e1 = it1.next();
final Map.Entry<MemberName, Type> e2 = it2.next();
if (!e2.getKey().tip().toString().equals(e1.toString())) {
// Member names differ.
break;
}
if (!((SimpleAttributeType) e2.getValue()).getValueClass().equals(e1.getValue())) {
// Value classes differ.
break;
}
}
throw new IllegalArgumentException(Errors.format(Errors.Keys.RecordAlreadyDefined_2, getSchemaName(), typeName));
}
use of org.apache.sis.internal.simple.SimpleAttributeType in project sis by apache.
the class RecordDefinition method computeTransientFields.
/**
* Invoked on construction or deserialization for computing the transient fields.
*
* @param memberTypes the (<var>name</var>, <var>type</var>) pairs in this record type.
* @return the values in the given map. This information is not stored in {@code RecordDefinition}
* because not needed by this class, but the {@link DefaultRecordType} subclass will store it.
*/
final Type[] computeTransientFields(final Map<? extends MemberName, ? extends Type> memberTypes) {
final int size = memberTypes.size();
members = new MemberName[size];
memberIndices = new LinkedHashMap<>(Containers.hashMapCapacity(size));
final Type[] types = new Type[size];
int i = 0;
for (final Map.Entry<? extends MemberName, ? extends Type> entry : memberTypes.entrySet()) {
final Type type = entry.getValue();
if (type instanceof SimpleAttributeType) {
final Class<?> c = ((SimpleAttributeType) type).getValueClass();
if (c != Object.class) {
if (valueClasses == null) {
valueClasses = new Class<?>[size];
}
valueClasses[i] = c;
baseValueClass = Classes.findCommonClass(baseValueClass, c);
}
}
final MemberName name = entry.getKey();
members[i] = name;
memberIndices.put(name, i);
types[i] = type;
i++;
}
memberIndices = CollectionsExt.unmodifiableOrCopy(memberIndices);
baseValueClass = (baseValueClass != null) ? Numbers.wrapperToPrimitive(baseValueClass) : Object.class;
return types;
}
use of org.apache.sis.internal.simple.SimpleAttributeType in project sis by apache.
the class DefaultRecordSchemaTest method testCreateRecordType.
/**
* Tests {@link DefaultRecordSchema#createRecordType(CharSequence, Map)}.
*/
@Test
public void testCreateRecordType() {
final DefaultRecordSchema schema = new DefaultRecordSchema(null, null, "MySchema");
final Map<CharSequence, Class<?>> members = new LinkedHashMap<>(8);
assertNull(members.put("city", String.class));
assertNull(members.put("latitude", Double.class));
assertNull(members.put("longitude", Double.class));
assertNull(members.put("population", Integer.class));
final RecordType recordType = schema.createRecordType("MyRecordType", members);
/*
* Inspect properties.
*/
assertSame("container", schema, recordType.getContainer());
assertEquals("typeName", Names.createTypeName("MySchema", ":", "MyRecordType"), recordType.getTypeName());
int count = 0;
for (final Map.Entry<MemberName, Type> entry : recordType.getMemberTypes().entrySet()) {
final String expectedName;
final String expectedType;
final Class<?> expectedClass;
switch(count) {
case 0:
{
expectedName = "city";
expectedType = "OGC:CharacterString";
expectedClass = String.class;
break;
}
case 1:
{
expectedName = "latitude";
expectedType = "OGC:Real";
expectedClass = Double.class;
break;
}
case 2:
{
expectedName = "longitude";
expectedType = "OGC:Real";
expectedClass = Double.class;
break;
}
case 3:
{
expectedName = "population";
expectedType = "OGC:Integer";
expectedClass = Integer.class;
break;
}
default:
{
throw new AssertionError(count);
}
}
final Type type = entry.getValue();
assertEquals(expectedName, entry.getKey().toString());
assertEquals(expectedType, type.getTypeName().toFullyQualifiedName().toString());
assertEquals(expectedClass, ((SimpleAttributeType) type).getValueClass());
count++;
}
/*
* The DefaultRecordType(TypeName, RecordSchema, Map) constructor performs many argument checks, so
* we use that constructor as a way to perform a final validation, especially regarding namespaces.
*/
final DefaultRecordType copy = new DefaultRecordType(recordType.getTypeName(), recordType.getContainer(), recordType.getMemberTypes());
assertEquals(recordType, copy);
}
use of org.apache.sis.internal.simple.SimpleAttributeType in project sis by apache.
the class DefaultRecordSchema method toAttributeType.
/**
* Suggests an attribute type for the given value class. The {@code TypeName} will use the UML identifier
* of OGC/ISO specification when possible, e.g. {@code "GCO:CharacterString"} for {@code java.lang.String}.
* See <cite>Mapping Java classes to type names</cite> in {@link DefaultTypeName} javadoc for more information.
*
* @param valueClass the value class to represent as an attribute type.
* @return attribute type for the given value class.
*/
final Type toAttributeType(final Class<?> valueClass) {
if (!TypeNames.isValid(valueClass)) {
return null;
}
Type type = attributeTypes.get(valueClass);
if (type == null) {
if (valueClass == Void.TYPE) {
throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "valueClass", "void"));
}
final TypeName name = nameFactory.toTypeName(valueClass);
type = new SimpleAttributeType<>(name, valueClass);
final Type old = attributeTypes.putIfAbsent(valueClass, type);
if (old != null) {
// May happen if the type has been computed concurrently.
return old;
}
}
return type;
}
Aggregations