Skip to content
This repository has been archived by the owner on Apr 13, 2019. It is now read-only.

Commit

Permalink
op output projections: reversed + semantics
Browse files Browse the repository at this point in the history
  • Loading branch information
Konstantin Sobolev committed Nov 9, 2017
1 parent 8604a77 commit 473becd
Show file tree
Hide file tree
Showing 19 changed files with 201 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ resource books: map[BookId, BookRecord] {
title,
author :(
id,
`record` (+firstName, middleName, +lastName)
`record` (firstName, +middleName, lastName)
),
text :+plain {
text :plain {
;offset: Long, // input parameter
;count: Long { default: 100 }, // input parameter with default
meta: (offset, count) // supported meta-data projection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,13 @@ TagApi findTag(
if (retroTag == null) {
if (type.kind() == TypeKind.ENTITY) return null;
else tag = ((DatumTypeApi) type).self();
} else
tag = retroTag;
} else {
if (op == null || op.tagProjections().containsKey(retroTag.name())) {
tag = retroTag;
} else {
tag = null;
}
}

} else {
tag = type.tagsMap().get(tagName);
Expand All @@ -142,7 +147,9 @@ TagApi findTag(
);
}

verifyTag(type, tag, op, location, context);
if (tag != null)
verifyTag(type, tag, op, location, context);

return tag;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,17 +346,15 @@ static List<OpEntityProjection> parseTails(
if (tailPsi == null) tails = null;
else {
tails = new ArrayList<>();
boolean flagged = rootProjection.flag(); // todo separate flag for tails

@Nullable SchemaOpEntityTailItem singleTail = tailPsi.getOpEntityTailItem();
if (singleTail == null) {
@Nullable SchemaOpEntityMultiTail multiTail = tailPsi.getOpEntityMultiTail();
assert multiTail != null;
for (SchemaOpEntityTailItem tailItem : multiTail.getOpEntityTailItemList()) {
tails.add(parseEntityTailItem(tailItem, flagged, dataType, rootProjection, typesResolver, context));
tails.add(parseEntityTailItem(tailItem, dataType, rootProjection, typesResolver, context));
}
} else {
tails.add(parseEntityTailItem(singleTail, flagged, dataType, rootProjection, typesResolver, context));
tails.add(parseEntityTailItem(singleTail, dataType, rootProjection, typesResolver, context));
}

SchemaProjectionPsiParserUtil.checkDuplicatingEntityTails(tails, context);
Expand All @@ -367,7 +365,6 @@ static List<OpEntityProjection> parseTails(

private static @NotNull OpEntityProjection parseEntityTailItem(
final @NotNull SchemaOpEntityTailItem tailItem,
final boolean flagged,
final @NotNull DataTypeApi dataType,
final @NotNull OpEntityProjection rootProjection,
final @NotNull TypesResolver typesResolver,
Expand All @@ -377,7 +374,7 @@ static List<OpEntityProjection> parseTails(
@NotNull SchemaOpEntityProjection psiTailProjection = tailItem.getOpEntityProjection();
return buildTailProjection(
dataType,
flagged,
tailItem.getPlus() != null,
tailTypeRef,
psiTailProjection,
rootProjection,
Expand Down Expand Up @@ -965,6 +962,7 @@ else return parseUnnamedModelProjection(
tailItemPsi.getTypeRef(),
tailItemPsi.getOpModelProjection(),
rootProjection,
tailItemPsi.getPlus() != null,
typesResolver,
context
)
Expand All @@ -977,6 +975,7 @@ else return parseUnnamedModelProjection(
singleTailPsi.getTypeRef(),
singleTailPsi.getOpModelProjection(),
rootProjection,
singleTailPsi.getPlus() != null,
typesResolver,
context
)
Expand All @@ -995,6 +994,7 @@ else return parseUnnamedModelProjection(
@NotNull SchemaTypeRef tailTypeRefPsi,
@NotNull SchemaOpModelProjection modelProjectionPsi,
@NotNull MP rootProjection,
boolean flagged,
@NotNull TypesResolver typesResolver,
@NotNull OpPsiProcessingContext context) throws PsiProcessingException {

Expand All @@ -1006,7 +1006,7 @@ else return parseUnnamedModelProjection(
MP mp = parseModelProjection(
modelClass,
tailType,
false, // todo add flags to tails?
flagged,
modelProjectionPsi,
rootProjection,
typesResolver,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
* @author <a href="mailto:[email protected]">Konstantin Sobolev</a>
*/
public final class DefaultsPopulatingTransformer extends OpProjectionTransformer {
// todo unused, delete (since '+' semantics is reversed now)

public DefaultsPopulatingTransformer() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package ws.epigraph.projections.op.output;

import ws.epigraph.lang.MessagesContext;
import ws.epigraph.projections.op.CompositeOpProjectionTransformer;
import ws.epigraph.projections.op.PostProcessingOpProjectionPsiParser;
import ws.epigraph.projections.op.postprocess.OpFlagSynchronizer;

Expand All @@ -29,10 +28,7 @@ public final class OpOutputProjectionsPsiParser extends PostProcessingOpProjecti
public OpOutputProjectionsPsiParser(MessagesContext context) {
super(
null,
new CompositeOpProjectionTransformer(
new DefaultsPopulatingTransformer(),
new OpFlagSynchronizer("default", context)
)
new OpFlagSynchronizer("default", context)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -541,15 +541,15 @@ public void testParseMapWithKeyProjection() throws PsiProcessingException {
public void testFlag() throws PsiProcessingException {
testParsingEntityProjection(":+id");
testParsingEntityProjection(":+`record` ( +id )");
testParsingEntityProjection(":`record` ( id+ )", ":+`record` ( +id )");
testParsingEntityProjection(":`record` ( bestFriend2+ )", ":+`record` ( +bestFriend2 :+id )");
testParsingEntityProjection(":`record` ( +bestFriend2 )", ":+`record` ( +bestFriend2 :+id )");
testParsingEntityProjection(":`record` ( id+ )", ":`record` ( +id )");
testParsingEntityProjection(":`record` ( bestFriend2+ )", ":`record` ( bestFriend2 :+id )");
testParsingEntityProjection(":`record` ( +bestFriend2 )", ":`record` ( +bestFriend2 :+id )");

// todo: enable smarter output in pretty printer
testParsingEntityProjection(":`record` ( friends*+:id )", ":+`record` ( +friends *+( :id ) )");
testParsingEntityProjection(":`record` ( friends*+:id )", ":`record` ( friends *+( :id ) )");
testParsingEntityProjection(
":`record` ( friendsMap[forbidden]+:id)",
":+`record` ( +friendsMap [ forbidden ]+( :id ) )"
":`record` ( friendsMap [ forbidden ]+( :id ) )"
);

testParsingEntityProjection(":`record` ( friendsMap2 { meta: +( start ) } [ required ]( :id ) )");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import ws.epigraph.gdata.GDatum;
import ws.epigraph.lang.TextLocation;
import ws.epigraph.projections.ProjectionsParsingUtil;
import ws.epigraph.projections.abs.AbstractModelProjection;
import ws.epigraph.projections.abs.AbstractTagProjectionEntry;
import ws.epigraph.projections.gen.ProjectionReferenceName;
import ws.epigraph.projections.op.*;
Expand All @@ -46,14 +45,17 @@
@NotThreadSafe
public class DefaultReqProjectionConstructor {
public enum Mode {
/** Include nothing but $self and retro tags */
INCLUDE_NONE,
INCLUDE_FLAGGED_ONLY,
/** Include only things not flagged in op projection, plus $self and retro tags */
INCLUDE_UNFLAGGED_ONLY,
/** Include everything */
INCLUDE_ALL
}

private final @NotNull Mode mode;
private final boolean checkForRequiredMapKeys;
private final boolean copyFlagsFromOp;
private final boolean copyFlagsFromOp; // flags are currently inverted, until '+' on req means 'optional' (currently it means 'required')

private final WeakHashMap<ProjectionReferenceName, ReqEntityProjection> visitedEntityRefs = new WeakHashMap<>();

Expand All @@ -68,7 +70,7 @@ public DefaultReqProjectionConstructor(
}

public static DefaultReqProjectionConstructor outputProjectionDefaultConstructor() {
return new DefaultReqProjectionConstructor(Mode.INCLUDE_FLAGGED_ONLY, true, false);
return new DefaultReqProjectionConstructor(Mode.INCLUDE_UNFLAGGED_ONLY, true, false);
}

public static DefaultReqProjectionConstructor inputProjectionDefaultConstructor(boolean includeAll) {
Expand Down Expand Up @@ -107,22 +109,24 @@ public static DefaultReqProjectionConstructor updateProjectionDefaultConstructor
final Iterable<TagApi> tags;

Collection<OpTagProjectionEntry> opTagEntries = op.tagProjections().values();
@Nullable TagApi defaultTag = ProjectionsParsingUtil.findTag(dataType, null, op, location, context);

switch (mode) {
case INCLUDE_NONE:
@Nullable TagApi defaultTag = ProjectionsParsingUtil.findTag(dataType, null, op, location, context);
tags = defaultTag == null ?
Collections.emptyList() :
Collections.singletonList(defaultTag);
break;

case INCLUDE_FLAGGED_ONLY:
case INCLUDE_UNFLAGGED_ONLY:
if (type.kind() == TypeKind.ENTITY) {
tags = opTagEntries
.stream()
.filter(tpe -> tpe.projection().flag())
.map(AbstractTagProjectionEntry::tag)
.collect(Collectors.toList());
tags = defaultTag == null ?
opTagEntries
.stream()
.filter(tpe -> !tpe.projection().flag())
.map(AbstractTagProjectionEntry::tag)
.collect(Collectors.toList()) :
Collections.singletonList(defaultTag);
} else {
OpTagProjectionEntry opSingleTag = op.singleTagProjection();
assert opSingleTag != null;
Expand Down Expand Up @@ -178,7 +182,8 @@ private ReqEntityProjection createDefaultEntityProjection(
createDefaultModelProjection(
ReqRecordModelProjection.class,
tag.type(),
opTagProjection.projection(), copyFlagsFromOp && opTagProjection.projection().flag(),
opTagProjection.projection(),
copyFlagsFromOp && !opTagProjection.projection().flag(),
null,
Directives.EMPTY,
datums,
Expand All @@ -202,12 +207,12 @@ private ReqEntityProjection createDefaultEntityProjection(
else {
tails = new ArrayList<>(opTails.size());
for (final OpEntityProjection opTail : opTails) {
if (mode == Mode.INCLUDE_ALL || opTail.flag()) {
if (mode == Mode.INCLUDE_ALL || !opTail.flag()) {
tails.add(
createDefaultEntityProjection(
opTail.type().dataType(),
opTail,
copyFlagsFromOp && opTail.flag(),
copyFlagsFromOp && !opTail.flag(),
datas,
resolver,
location,
Expand Down Expand Up @@ -271,7 +276,7 @@ private ReqEntityProjection createDefaultEntityProjection(
recordDatums.stream().map(rd -> rd._raw().getData((Field) fpe.field()))
.collect(Collectors.toList());

if ((mode == Mode.INCLUDE_ALL || fieldProjection.flag()) && (fieldDatas != null || datums == null)) {
if ((mode == Mode.INCLUDE_ALL || !fieldProjection.flag()) && (fieldDatas != null || datums == null)) {
fields.put(
entry.getKey(),
new ReqFieldProjectionEntry(
Expand All @@ -280,7 +285,7 @@ private ReqEntityProjection createDefaultEntityProjection(
createDefaultEntityProjection(
fpe.field().dataType(),
fieldProjection.entityProjection(),
copyFlagsFromOp && fieldProjection.flag(),
copyFlagsFromOp && !fieldProjection.flag(),
fieldDatas,
resolver,
location,
Expand Down Expand Up @@ -434,14 +439,14 @@ private ReqEntityProjection createDefaultEntityProjection(
return null;

return Optional.ofNullable(op.metaProjection()).map(mp -> {
if (mode == Mode.INCLUDE_FLAGGED_ONLY && !mp.flag())
if (mode == Mode.INCLUDE_UNFLAGGED_ONLY && mp.flag())
return null;
try {
return createDefaultModelProjection(
modelClass,
mp.type(),
mp,
copyFlagsFromOp && mp.flag(),
copyFlagsFromOp && !mp.flag(),
null,
Directives.EMPTY,
metaDatas,
Expand Down Expand Up @@ -472,9 +477,9 @@ private ReqEntityProjection createDefaultEntityProjection(
case INCLUDE_NONE:
opTailsToInclude = null;
break;
case INCLUDE_FLAGGED_ONLY:
case INCLUDE_UNFLAGGED_ONLY:
opTailsToInclude =
opTailsToInclude.stream().filter(AbstractModelProjection::flag).collect(Collectors.toList());
opTailsToInclude.stream().filter(projection -> !projection.flag()).collect(Collectors.toList());
break;
case INCLUDE_ALL: // keep all
}
Expand All @@ -486,7 +491,7 @@ private ReqEntityProjection createDefaultEntityProjection(
modelClass,
ot.type(),
ot,
copyFlagsFromOp && ot.flag(),
copyFlagsFromOp && !ot.flag(),
null,
Directives.EMPTY,
datums,
Expand Down
Loading

0 comments on commit 473becd

Please sign in to comment.