use of com.linkedin.data.schema.TyperefDataSchema in project rest.li by linkedin.
the class PathSpecBasedSchemaAnnotationVisitor method createOrReUseSchemaAndAttachToParent.
/**
* This function try to process the current dataSchema being visited inside the context and create a skeleton copy of it.
* But if the current dataSchema has been already processed, will fetch the cached copy of the skeleton schema.
*
* @param context {@link TraverserContext} context that contains current data schema.
* @param hasOverridesNotResolved a boolean to tell whether there are non-resolved overrides that will be resolved into the new schema
* @return the new schema
* @throws CloneNotSupportedException
*/
private DataSchema createOrReUseSchemaAndAttachToParent(TraverserContext context, boolean hasOverridesNotResolved) throws CloneNotSupportedException {
DataSchema currentDataSchema = context.getCurrentSchema();
CurrentSchemaEntryMode currentSchemaEntryMode = context.getCurrentSchemaEntryMode();
// newSchema could be created as skeletonSchema, or fetched from cache if currentDataSchema has already been processed.
DataSchema newSchema = null;
if (hasOverridesNotResolved) {
// if there are overrides that not resolved, always build skeleton schema
newSchema = CopySchemaUtil.buildSkeletonSchema(currentDataSchema);
} else {
if (_seenDataSchemaMapping.containsKey(currentDataSchema)) {
newSchema = _seenDataSchemaMapping.get(currentDataSchema);
} else {
newSchema = CopySchemaUtil.buildSkeletonSchema(currentDataSchema);
_seenDataSchemaMapping.put(currentDataSchema, newSchema);
}
}
// attach based on visitorContext's schema, need to create new fields or union members
PathSpecTraverseVisitorContext oldVisitorContext = (PathSpecTraverseVisitorContext) (context.getVisitorContext());
DataSchema outputParentSchema = oldVisitorContext.getOutputParentSchema();
if (outputParentSchema == null) {
_schemaConstructed = newSchema;
return newSchema;
}
switch(currentSchemaEntryMode) {
case FIELD:
assert (outputParentSchema.getType() == DataSchema.Type.RECORD);
addField(context.getEnclosingField(), newSchema, (RecordDataSchema) outputParentSchema);
break;
case MAP_KEY:
assert (outputParentSchema.getType() == DataSchema.Type.MAP);
MapDataSchema mapDataSchema = (MapDataSchema) outputParentSchema;
mapDataSchema.setKey((StringDataSchema) newSchema);
break;
case MAP_VALUE:
assert (outputParentSchema.getType() == DataSchema.Type.MAP);
mapDataSchema = (MapDataSchema) outputParentSchema;
mapDataSchema.setValues(newSchema);
break;
case ARRAY_VALUE:
assert (outputParentSchema.getType() == DataSchema.Type.ARRAY);
ArrayDataSchema arrayDataSchema = (ArrayDataSchema) outputParentSchema;
arrayDataSchema.setItems(newSchema);
break;
case UNION_MEMBER:
assert (outputParentSchema.getType() == DataSchema.Type.UNION);
addUnionMember(context.getEnclosingUnionMember(), newSchema, (UnionDataSchema) outputParentSchema);
break;
case TYPEREF_REF:
TyperefDataSchema typerefDataSchema = (TyperefDataSchema) outputParentSchema;
typerefDataSchema.setReferencedType(newSchema);
break;
default:
break;
}
return newSchema;
}
use of com.linkedin.data.schema.TyperefDataSchema in project rest.li by linkedin.
the class DataSchemaAnnotationValidator method validateSchema.
private final void validateSchema(ValidatorContext context, DataSchema schema) {
if (schema.getType() == DataSchema.Type.TYPEREF) {
DataSchema refSchema = ((TyperefDataSchema) schema).getRef();
validateSchema(context, refSchema);
getAndInvokeValidatorList(context, schema);
} else {
getAndInvokeValidatorList(context, schema);
}
}
use of com.linkedin.data.schema.TyperefDataSchema in project rest.li by linkedin.
the class CompatibilityChecker method check.
private void check(DataSchema older, DataSchema newer) {
Checked toCheck = new Checked(older, newer);
if (_checked.contains(toCheck)) {
return;
}
_checked.add(toCheck);
if (older == newer) {
return;
}
int pathCount = 1;
if (_options.getMode() == CompatibilityOptions.Mode.DATA || _options.getMode() == CompatibilityOptions.Mode.EXTENSION) {
older = older.getDereferencedDataSchema();
while (newer.getType() == DataSchema.Type.TYPEREF) {
TyperefDataSchema typerefDataSchema = ((TyperefDataSchema) newer);
_path.addLast(typerefDataSchema.getFullName());
_path.addLast(DataSchemaConstants.REF_KEY);
pathCount++;
newer = typerefDataSchema.getRef();
}
}
if (newer.getType() == DataSchema.Type.TYPEREF) {
_path.addLast(((TyperefDataSchema) newer).getFullName());
} else {
_path.addLast(newer.getUnionMemberKey());
}
switch(newer.getType()) {
case TYPEREF:
if (isSameType(older, newer))
checkTyperef((TyperefDataSchema) older, (TyperefDataSchema) newer);
break;
case RECORD:
if (isSameType(older, newer))
checkRecord((RecordDataSchema) older, (RecordDataSchema) newer);
break;
case ARRAY:
if (isSameType(older, newer))
checkArray((ArrayDataSchema) older, (ArrayDataSchema) newer);
break;
case MAP:
if (isSameType(older, newer))
checkMap((MapDataSchema) older, (MapDataSchema) newer);
break;
case ENUM:
if (isSameType(older, newer))
checkEnum((EnumDataSchema) older, (EnumDataSchema) newer);
break;
case FIXED:
if (isSameType(older, newer))
checkFixed((FixedDataSchema) older, (FixedDataSchema) newer);
break;
case UNION:
if (isSameType(older, newer))
checkUnion((UnionDataSchema) older, (UnionDataSchema) newer);
break;
default:
if (newer instanceof PrimitiveDataSchema)
checkPrimitive(older, newer);
else
throw new IllegalStateException("Unknown schema type " + newer.getType() + ", checking old schema " + older + ", new schema " + newer);
break;
}
for (; pathCount > 0; pathCount--) {
_path.removeLast();
}
return;
}
use of com.linkedin.data.schema.TyperefDataSchema in project rest.li by linkedin.
the class DataSchemaRichContextTraverser method doRecursiveTraversal.
private void doRecursiveTraversal(TraverserContextImpl context) {
// Add full name to the context's TraversePath
DataSchema schema = context.getCurrentSchema();
ArrayDeque<String> path = context.getTraversePath();
path.add(schema.getUnionMemberKey());
// visitors
_schemaVisitor.callbackOnContext(context, DataSchemaTraverse.Order.PRE_ORDER);
/**
* By default {@link DataSchemaRichContextTraverser} will only decide whether or not keep traversing based on whether the new
* data schema has been seen.
*
* But the {@link SchemaVisitor} has the chance to override this control by setting {@link TraverserContext#_shouldContinue}
* If this variable set to be {@link Boolean#TRUE}, the {@link DataSchemaRichContextTraverser} will traverse to next level (if applicable)
* If this variable set to be {@link Boolean#FALSE}, the {@link DataSchemaRichContextTraverser} will stop traversing to next level
* If this variable not set, the {@link DataSchemaRichContextTraverser} will decide whether or not to continue traversing based on whether
* this data schema has been seen.
*/
if (context.shouldContinue() == Boolean.TRUE || !(context.shouldContinue() == Boolean.FALSE || _seenAncestorsDataSchema.containsKey(schema))) {
_seenAncestorsDataSchema.put(schema, Boolean.TRUE);
// Pass new context in every recursion
TraverserContextImpl nextContext = null;
switch(schema.getType()) {
case TYPEREF:
TyperefDataSchema typerefDataSchema = (TyperefDataSchema) schema;
nextContext = context.getNextContext(DataSchemaConstants.REF_KEY, null, typerefDataSchema.getRef(), CurrentSchemaEntryMode.TYPEREF_REF);
doRecursiveTraversal(nextContext);
break;
case MAP:
// traverse key
MapDataSchema mapDataSchema = (MapDataSchema) schema;
nextContext = context.getNextContext(DataSchemaConstants.MAP_KEY_REF, DataSchemaConstants.MAP_KEY_REF, mapDataSchema.getKey(), CurrentSchemaEntryMode.MAP_KEY);
doRecursiveTraversal(nextContext);
// then traverse values
nextContext = context.getNextContext(PathSpec.WILDCARD, PathSpec.WILDCARD, mapDataSchema.getValues(), CurrentSchemaEntryMode.MAP_VALUE);
doRecursiveTraversal(nextContext);
break;
case ARRAY:
ArrayDataSchema arrayDataSchema = (ArrayDataSchema) schema;
nextContext = context.getNextContext(PathSpec.WILDCARD, PathSpec.WILDCARD, arrayDataSchema.getItems(), CurrentSchemaEntryMode.ARRAY_VALUE);
doRecursiveTraversal(nextContext);
break;
case RECORD:
RecordDataSchema recordDataSchema = (RecordDataSchema) schema;
for (RecordDataSchema.Field field : recordDataSchema.getFields()) {
nextContext = context.getNextContext(field.getName(), field.getName(), field.getType(), CurrentSchemaEntryMode.FIELD);
nextContext.setEnclosingField(field);
doRecursiveTraversal(nextContext);
}
break;
case UNION:
UnionDataSchema unionDataSchema = (UnionDataSchema) schema;
for (UnionDataSchema.Member member : unionDataSchema.getMembers()) {
nextContext = context.getNextContext(member.getUnionMemberKey(), member.getUnionMemberKey(), member.getType(), CurrentSchemaEntryMode.UNION_MEMBER);
nextContext.setEnclosingUnionMember(member);
doRecursiveTraversal(nextContext);
}
break;
default:
// will stop recursively traversing if the current schema is a leaf node.
assert isLeafSchema(schema);
break;
}
_seenAncestorsDataSchema.remove(schema);
}
_schemaVisitor.callbackOnContext(context, DataSchemaTraverse.Order.POST_ORDER);
}
use of com.linkedin.data.schema.TyperefDataSchema in project rest.li by linkedin.
the class ResourceSchemaToResourceSpecTranslator method toType.
public Class<?> toType(DataSchema schema) {
if (schema.getType() == DataSchema.Type.TYPEREF) {
Class<?> javaClass = CustomTypeUtil.getJavaCustomTypeClassFromSchema((TyperefDataSchema) schema);
if (javaClass != null)
return javaClass;
}
DataSchema.Type dereferencedType = schema.getDereferencedType();
DataSchema dereferencedDataSchema = schema.getDereferencedDataSchema();
if (dereferencedDataSchema.isPrimitive()) {
return DataSchemaUtil.dataSchemaTypeToPrimitiveDataSchemaClass(dereferencedType);
} else if (dereferencedDataSchema instanceof EnumDataSchema) {
return _bindingResolver.resolveEnumClass((EnumDataSchema) dereferencedDataSchema);
} else {
return _bindingResolver.resolveTemplateClass(dereferencedDataSchema);
}
}
Aggregations