Search in sources :

Example 21 with PathSpec

use of com.linkedin.data.schema.PathSpec in project rest.li by linkedin.

the class TestMaskCreation method testPositiveMaskMultipleFields.

@Test
public void testPositiveMaskMultipleFields() {
    MaskTree mask = MaskCreator.createPositiveMask(new PathSpec("foo"), new PathSpec("bar"));
    // "{foo=1, bar=1}"
    final DataMap fooBarMap = new DataMap();
    fooBarMap.put("foo", MaskOperation.POSITIVE_MASK_OP.getRepresentation());
    fooBarMap.put("bar", MaskOperation.POSITIVE_MASK_OP.getRepresentation());
    Assert.assertEquals(mask.getDataMap(), fooBarMap, "The MaskTree DataMap should match");
}
Also used : MaskTree(com.linkedin.data.transform.filter.request.MaskTree) PathSpec(com.linkedin.data.schema.PathSpec) DataMap(com.linkedin.data.DataMap) Test(org.testng.annotations.Test)

Example 22 with PathSpec

use of com.linkedin.data.schema.PathSpec in project rest.li by linkedin.

the class PathSpecBasedSchemaAnnotationVisitor method callbackOnContext.

@Override
public void callbackOnContext(TraverserContext context, DataSchemaTraverse.Order order) {
    if (order == DataSchemaTraverse.Order.POST_ORDER) {
        // Use post order visit to validate override paths
        VisitorContext postVisitContext = context.getVisitorContext();
        List<AnnotationEntry> annotationEntries = ((PathSpecTraverseVisitorContext) postVisitContext).getAnnotationEntriesFromParentSchema();
        // Do annotationEntry validity checking
        for (AnnotationEntry annotationEntry : annotationEntries) {
            if (annotationEntry.isOverride() && (annotationEntry.getOverridePathValidStatus() == AnnotationEntry.OverridePathValidStatus.UNCHECKED)) {
                markAnnotationEntryInvalid(annotationEntry, OverridePathErrorMsg.DOES_NOT_MATCH_NAME);
            }
        }
        if (context.getParentSchema() == null) {
            getSchemaVisitorTraversalResult().setConstructedSchema(_schemaConstructed);
        }
        return;
    }
    VisitorContext visitorContext = context.getVisitorContext();
    // Prepare visitorContext for next level recursion
    PathSpecTraverseVisitorContext newVisitorContext = new PathSpecTraverseVisitorContext();
    // {@link PathSpecBasedSchemaAnnotationVisitor} will build new skeleton schema on the fly, after seeing the original schema
    // If there has been a skeleton schema already built for one data schema, it will reuse that cached one
    // also see {@link PathSpecTraverseVisitorContext}
    DataSchema newSchema = null;
    DataSchema parentSchema = context.getParentSchema();
    DataSchema currentSchema = context.getCurrentSchema();
    List<AnnotationEntry> currentAnnotationEntries = ((PathSpecTraverseVisitorContext) visitorContext).getAnnotationEntriesFromParentSchema();
    // match & filter current overrides
    if (parentSchema != null && !(parentSchema.getType() == DataSchema.Type.TYPEREF)) {
        // skip if parent is Typeref because schemaPathSpec would not contain Typeref component.
        String pathSpecMatchingSegment = context.getSchemaPathSpec().peekLast();
        currentAnnotationEntries = currentAnnotationEntries.stream().filter(annotationEntry -> (annotationEntry.getOverridePathValidStatus() == AnnotationEntry.OverridePathValidStatus.UNCHECKED) && annotationEntry.getRemainingPaths().size() > 0 && Objects.equals(annotationEntry.getRemainingPaths().peekFirst(), pathSpecMatchingSegment)).peek(annotationEntry -> {
            annotationEntry.getMatchedPaths().add(pathSpecMatchingSegment);
            annotationEntry.getRemainingPaths().pollFirst();
        }).collect(toList());
    }
    assert (currentAnnotationEntries.stream().filter(AnnotationEntry::isOverride).allMatch(annotationEntry -> annotationEntry.getOverridePathValidStatus() == AnnotationEntry.OverridePathValidStatus.UNCHECKED));
    // add {@link annotationEntry}s from enclosing schema or field
    if (parentSchema != null) {
        switch(parentSchema.getType()) {
            case RECORD:
                RecordDataSchema.Field enclosingField = context.getEnclosingField();
                ArrayDeque<String> fullTraversePath = new ArrayDeque<>(context.getTraversePath());
                // Need to exclude this currentSchema's path so that it is field's path
                fullTraversePath.pollLast();
                currentAnnotationEntries.addAll(generateAnnotationEntryFromField(enclosingField, fullTraversePath));
                break;
            case TYPEREF:
                currentAnnotationEntries.addAll(generateAnnotationEntryFromTypeRefSchema((TyperefDataSchema) parentSchema, context.getTraversePath()));
                break;
            default:
                break;
        }
    }
    // add {@link annotationEntry}s from named schema
    currentAnnotationEntries.addAll(generateAnnotationEntryFromNamedSchema(currentSchema, context.getTraversePath()));
    // Note: cyclic annotation in TypeRef is also handled through its de-referenced record schema
    if (currentSchema.getType() == DataSchema.Type.RECORD) {
        String currentSchemaFullName = ((RecordDataSchema) currentSchema).getFullName();
        for (AnnotationEntry annotationEntry : currentAnnotationEntries) {
            String overrideStartSchemaName = annotationEntry.getStartSchemaName();
            if (detectCycle(overrideStartSchemaName, currentSchemaFullName)) {
                // If cycles found, report errors
                getSchemaVisitorTraversalResult().addMessage(context.getTraversePath(), "Found overrides that forms a cyclic-referencing: Overrides entry in " + "traverser path \"%s\" with its pathSpec value \"%s\" is pointing to the field " + "with traverser path \"%s\" and schema name \"%s\", this is causing cyclic-referencing.", new PathSpec(annotationEntry.getPathToAnnotatedTarget().toArray(new String[0])).toString(), annotationEntry.getOverridePathSpecStr(), new PathSpec(context.getTraversePath().toArray(new String[0])).toString(), currentSchemaFullName);
                context.setShouldContinue(Boolean.FALSE);
                newVisitorContext.setAnnotationEntriesFromParentSchema(currentAnnotationEntries);
                context.setVisitorContext(newVisitorContext);
                return;
            } else {
                // If no cycles found, add to current edges seen
                _directedEdges.computeIfAbsent(overrideStartSchemaName, key -> new HashSet<>()).add(currentSchemaFullName);
            }
        }
    }
    // process current schema
    try {
        if (DataSchemaRichContextTraverser.isLeafSchema(currentSchema)) {
            newSchema = createOrReUseSchemaAndAttachToParent(context, (currentAnnotationEntries.size() != 0));
            newSchema.getResolvedProperties().putAll(resolveAnnotationEntries(currentAnnotationEntries, context.getSchemaPathSpec()));
            // Do annotationEntry validity checking
            for (AnnotationEntry annotationEntry : currentAnnotationEntries) {
                if (annotationEntry.isOverride()) {
                    if (annotationEntry.getRemainingPaths().size() == 0) {
                        annotationEntry.setOverridePathValidStatus(AnnotationEntry.OverridePathValidStatus.VALID);
                    } else {
                        markAnnotationEntryInvalid(annotationEntry, OverridePathErrorMsg.TOO_LONG);
                    }
                }
            }
        } else if (currentSchema.isComplex()) {
            // Either all non-overrides to TypeRefDataSchema, or all overrides to other complex dataSchema
            assert (currentAnnotationEntries.stream().noneMatch(AnnotationEntry::isOverride) || currentAnnotationEntries.stream().allMatch(AnnotationEntry::isOverride));
            // Do annotationEntry validity checking
            if ((currentSchema.getType() != DataSchema.Type.TYPEREF)) {
                for (AnnotationEntry annotationEntry : currentAnnotationEntries) {
                    if (annotationEntry.isOverride() && (annotationEntry.getRemainingPaths().size() == 0)) {
                        markAnnotationEntryInvalid(annotationEntry, OverridePathErrorMsg.TOO_SHORT);
                    }
                }
            }
            if (currentAnnotationEntries.stream().anyMatch(annotationEntry -> // non-overrides from typeref
            !annotationEntry.isOverride() || (annotationEntry.getOverridePathValidStatus() == AnnotationEntry.OverridePathValidStatus.UNCHECKED))) {
                // If there are unresolved annotation entries that resolving to complex data schema and its descendants.
                // Need to tell the traverser to continue traversing
                newSchema = createOrReUseSchemaAndAttachToParent(context, true);
                context.setShouldContinue(Boolean.TRUE);
            } else {
                // Order matters: Need to check "seen" before creating new or reuse
                context.setShouldContinue(!_seenDataSchemaMapping.containsKey(currentSchema));
                newSchema = createOrReUseSchemaAndAttachToParent(context, false);
            }
        }
    } catch (CloneNotSupportedException e) {
        throw new IllegalStateException(String.format("encounter unexpected CloneNotSupportedException at traverse path location %s", Arrays.toString(context.getTraversePath().toArray())), e);
    }
    // Process record schema with "included" fields, before setting overrides for next visitorContext
    currentAnnotationEntries.addAll(generateAnnotationEntryFromInclude(currentSchema, context.getTraversePath()));
    newVisitorContext.setAnnotationEntriesFromParentSchema(currentAnnotationEntries);
    newVisitorContext.setOutputParentSchema(newSchema);
    context.setVisitorContext(newVisitorContext);
}
Also used : Arrays(java.util.Arrays) DataSchema(com.linkedin.data.schema.DataSchema) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Pair(org.apache.commons.lang3.tuple.Pair) UnionDataSchema(com.linkedin.data.schema.UnionDataSchema) Map(java.util.Map) MapDataSchema(com.linkedin.data.schema.MapDataSchema) PathSpec(com.linkedin.data.schema.PathSpec) IdentityHashMap(java.util.IdentityHashMap) DataSchemaTraverse(com.linkedin.data.schema.DataSchemaTraverse) Set(java.util.Set) Collectors(java.util.stream.Collectors) ImmutablePair(org.apache.commons.lang3.tuple.ImmutablePair) TyperefDataSchema(com.linkedin.data.schema.TyperefDataSchema) Objects(java.util.Objects) List(java.util.List) Collectors.toList(java.util.stream.Collectors.toList) RecordDataSchema(com.linkedin.data.schema.RecordDataSchema) StringDataSchema(com.linkedin.data.schema.StringDataSchema) ArrayDataSchema(com.linkedin.data.schema.ArrayDataSchema) ArrayDeque(java.util.ArrayDeque) CopySchemaUtil(com.linkedin.data.schema.util.CopySchemaUtil) Collections(java.util.Collections) PathSpec(com.linkedin.data.schema.PathSpec) ArrayDeque(java.util.ArrayDeque) DataSchema(com.linkedin.data.schema.DataSchema) UnionDataSchema(com.linkedin.data.schema.UnionDataSchema) MapDataSchema(com.linkedin.data.schema.MapDataSchema) TyperefDataSchema(com.linkedin.data.schema.TyperefDataSchema) RecordDataSchema(com.linkedin.data.schema.RecordDataSchema) StringDataSchema(com.linkedin.data.schema.StringDataSchema) ArrayDataSchema(com.linkedin.data.schema.ArrayDataSchema) TyperefDataSchema(com.linkedin.data.schema.TyperefDataSchema) RecordDataSchema(com.linkedin.data.schema.RecordDataSchema) HashSet(java.util.HashSet)

Example 23 with PathSpec

use of com.linkedin.data.schema.PathSpec in project rest.li by linkedin.

the class AnnotationCheckResolvedPropertiesVisitor method callbackOnContext.

@Override
public void callbackOnContext(TraverserContext context, DataSchemaTraverse.Order order) {
    // Only execute this callback when order is PRE_ORDER.
    if (order == DataSchemaTraverse.Order.POST_ORDER) {
        return;
    }
    DataSchema currentSchema = context.getCurrentSchema();
    RecordDataSchema.Field schemaField = context.getEnclosingField();
    UnionDataSchema.Member unionMember = context.getEnclosingUnionMember();
    ArrayDeque<String> pathToSchema = context.getSchemaPathSpec().clone();
    pathToSchema.addFirst(((NamedDataSchema) context.getTopLevelSchema()).getName());
    // to avoid this node and it's child node have the same pathSpec.
    if (currentSchema instanceof TyperefDataSchema) {
        context.getSchemaPathSpec().addLast(TYPEREF_INDICATOR);
    }
    if (schemaField != null && pathToSchema.getLast().equals(context.getEnclosingField().getName())) {
        // Current node is a field of a record schema, get the field's annotation.
        // Add FIELD_INDICATOR in the pathSpec to differentiate field annotation and field type schema annotation.
        pathToSchema.addLast(FIELD_INDICATOR);
        PathSpec pathSpec = new PathSpec(pathToSchema);
        _nodeToResolvedPropertiesMap.put(pathSpec, new ImmutablePair<>(generateCompatibilityCheckContext(schemaField, unionMember, currentSchema, pathSpec), chooseProperties(schemaField.getResolvedProperties(), schemaField.getProperties())));
        pathToSchema.removeLast();
    } else if (unionMember != null && pathToSchema.getLast().equals(context.getEnclosingUnionMember().getUnionMemberKey())) {
        // Current node is a union member, get the union member key's annotation.
        // Add UNION_MEMBER_KEY_INDICATOR in the pathSpec to differentiate union member key annotation and union type schema annotation.
        pathToSchema.addLast(UNION_MEMBER_KEY_INDICATOR);
        PathSpec pathSpec = new PathSpec(pathToSchema);
        _nodeToResolvedPropertiesMap.put(pathSpec, new ImmutablePair<>(generateCompatibilityCheckContext(schemaField, unionMember, currentSchema, pathSpec), unionMember.getProperties()));
        pathToSchema.removeLast();
    }
    // If there are no resolvedProperties but properties, used the properties for annotation check.
    Map<String, Object> properties = chooseProperties(currentSchema.getResolvedProperties(), currentSchema.getProperties());
    PathSpec pathSpec = new PathSpec(pathToSchema);
    _nodeToResolvedPropertiesMap.put(pathSpec, new ImmutablePair<>(generateCompatibilityCheckContext(schemaField, unionMember, currentSchema, pathSpec), properties));
}
Also used : PathSpec(com.linkedin.data.schema.PathSpec) DataSchema(com.linkedin.data.schema.DataSchema) TyperefDataSchema(com.linkedin.data.schema.TyperefDataSchema) RecordDataSchema(com.linkedin.data.schema.RecordDataSchema) UnionDataSchema(com.linkedin.data.schema.UnionDataSchema) NamedDataSchema(com.linkedin.data.schema.NamedDataSchema) UnionDataSchema(com.linkedin.data.schema.UnionDataSchema) TyperefDataSchema(com.linkedin.data.schema.TyperefDataSchema) ImmutablePair(org.apache.commons.lang3.tuple.ImmutablePair) RecordDataSchema(com.linkedin.data.schema.RecordDataSchema)

Example 24 with PathSpec

use of com.linkedin.data.schema.PathSpec in project rest.li by linkedin.

the class ResolvedPropertiesReaderVisitor method callbackOnContext.

@Override
public void callbackOnContext(TraverserContext context, DataSchemaTraverse.Order order) {
    if (order == DataSchemaTraverse.Order.POST_ORDER) {
        return;
    }
    DataSchema currentSchema = context.getCurrentSchema();
    if ((currentSchema.isPrimitive() || (currentSchema instanceof EnumDataSchema) || (currentSchema instanceof FixedDataSchema))) {
        Map<String, Object> resolvedProperties = currentSchema.getResolvedProperties();
        _leafFieldsToResolvedPropertiesMap.put(new PathSpec(context.getSchemaPathSpec()), resolvedProperties);
        if (LOG.isDebugEnabled()) {
            String mapStringified = resolvedProperties.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&"));
            LOG.debug(String.format("/%s ::: %s", String.join("/", context.getSchemaPathSpec()), mapStringified));
        }
    }
}
Also used : EnumDataSchema(com.linkedin.data.schema.EnumDataSchema) FixedDataSchema(com.linkedin.data.schema.FixedDataSchema) DataSchema(com.linkedin.data.schema.DataSchema) EnumDataSchema(com.linkedin.data.schema.EnumDataSchema) Logger(org.slf4j.Logger) DataSchemaTraverse(com.linkedin.data.schema.DataSchemaTraverse) FixedDataSchema(com.linkedin.data.schema.FixedDataSchema) DataSchema(com.linkedin.data.schema.DataSchema) Map(java.util.Map) LoggerFactory(org.slf4j.LoggerFactory) PathSpec(com.linkedin.data.schema.PathSpec) HashMap(java.util.HashMap) Collectors(java.util.stream.Collectors) EnumDataSchema(com.linkedin.data.schema.EnumDataSchema) FixedDataSchema(com.linkedin.data.schema.FixedDataSchema) PathSpec(com.linkedin.data.schema.PathSpec)

Example 25 with PathSpec

use of com.linkedin.data.schema.PathSpec in project rest.li by linkedin.

the class TestTransformer method testReplaceAtPathNested.

@Test
public void testReplaceAtPathNested() throws Exception {
    SimpleTestData data = IteratorTestData.createSimpleTestData();
    Builder.create(data.getDataElement(), IterationOrder.PRE_ORDER).filterBy(Predicates.pathMatchesPathSpec(new PathSpec("nested", "nested"))).replace(new DataMap());
    int count = Builder.create(data.getDataElement(), IterationOrder.PRE_ORDER).filterBy(Predicates.pathMatchesPathSpec(new PathSpec("nested", "nested", "foo"))).count();
    assertEquals(count, 0);
}
Also used : SimpleTestData(com.linkedin.data.it.IteratorTestData.SimpleTestData) PathSpec(com.linkedin.data.schema.PathSpec) DataMap(com.linkedin.data.DataMap) Test(org.testng.annotations.Test)

Aggregations

PathSpec (com.linkedin.data.schema.PathSpec)101 Test (org.testng.annotations.Test)74 MaskTree (com.linkedin.data.transform.filter.request.MaskTree)40 DataMap (com.linkedin.data.DataMap)31 HashSet (java.util.HashSet)16 RecordTemplate (com.linkedin.data.template.RecordTemplate)11 Map (java.util.Map)10 Set (java.util.Set)10 PatchTree (com.linkedin.data.transform.patch.request.PatchTree)9 HashMap (java.util.HashMap)8 DataList (com.linkedin.data.DataList)7 RoutingResult (com.linkedin.restli.internal.server.RoutingResult)7 ResourceMethodDescriptor (com.linkedin.restli.internal.server.model.ResourceMethodDescriptor)7 List (java.util.List)7 ByteString (com.linkedin.data.ByteString)6 DataSchema (com.linkedin.data.schema.DataSchema)5 MaskOperation (com.linkedin.data.transform.filter.request.MaskOperation)5 Foo (com.linkedin.pegasus.generator.examples.Foo)5 RequestContext (com.linkedin.r2.message.RequestContext)5 ServerResourceContext (com.linkedin.restli.internal.server.ServerResourceContext)5