Skip to content

Commit

Permalink
Use "addIgnoringEquivalents" where possible
Browse files Browse the repository at this point in the history
In particular, when parsing data from trusted sources (like the repo),
we can skip checking for equivalent values. This can be problematic
only when the schema changes, but I assume it's not worth the waste
of CPU cycles by repeated equivalence checking.

Trusted sources are marked by ParsingContext#fastAddOperations.
  • Loading branch information
mederly committed Apr 27, 2023
1 parent f389d5c commit 382f87b
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 15 deletions.
Expand Up @@ -47,4 +47,8 @@ public interface ParsingContext extends Cloneable {
boolean isConvertUnknownTypes();

ParsingContext convertUnknownTypes(boolean value);

boolean isFastAddOperations();

ParsingContext fastAddOperations();
}
Expand Up @@ -106,6 +106,12 @@ public interface PrismParser {
@NotNull
PrismParser compat();

/**
* Does not check for existing values during parsing. To be used in situations where the data can be trusted
* to not contain duplicates - for example, when reading from the repository.
*/
@NotNull PrismParser fastAddOperations();

/**
* Tells parser which definition to use when parsing item (or an item value). Optional.
* @param itemDefinition The definition
Expand Down
Expand Up @@ -46,6 +46,8 @@ public interface PrismParserNoIO extends PrismParser {
@NotNull
PrismParserNoIO compat();
@Override
@NotNull PrismParserNoIO fastAddOperations();
@Override
@NotNull
PrismParserNoIO definition(ItemDefinition<?> itemDefinition);
@Override
Expand Down
Expand Up @@ -24,8 +24,10 @@ public class ParsingContextImpl implements ParsingContext {
private boolean allowMissingRefTypes;
private boolean convertUnknownTypesToRaw;
private final List<String> warnings = new ArrayList<>();
/** Not checking for duplicates when adding parsed data. For trusted sources. */
private boolean fastAddOperations;

ParsingContextImpl() {
private ParsingContextImpl() {
}

static ParsingContext allowMissingRefTypes() {
Expand All @@ -34,12 +36,11 @@ static ParsingContext allowMissingRefTypes() {
return pc;
}


public static ParsingContext createForCompatibilityMode() {
static ParsingContext createForCompatibilityMode() {
return forMode(XNodeProcessorEvaluationMode.COMPAT);
}

static ParsingContext forMode(XNodeProcessorEvaluationMode mode) {
private static ParsingContext forMode(XNodeProcessorEvaluationMode mode) {
ParsingContextImpl pc = new ParsingContextImpl();
pc.setEvaluationMode(mode);
return pc;
Expand Down Expand Up @@ -150,4 +151,15 @@ public ParsingContext convertUnknownTypes(boolean value) {
convertUnknownTypesToRaw = value;
return this;
}

@Override
public boolean isFastAddOperations() {
return fastAddOperations;
}

@Override
public ParsingContext fastAddOperations() {
fastAddOperations = true;
return this;
}
}
Expand Up @@ -196,13 +196,13 @@ public void setValue(@NotNull PrismContainerValue<C> value) throws SchemaExcepti
if (getDefinition() != null) {
if (getDefinition().isSingleValue()) {
clear();
add(value);
addIgnoringEquivalents(value);
} else {
throw new IllegalStateException("Attempt to set single value to a multivalued container "+ getElementName());
}
} else {
clear();
add(value);
addIgnoringEquivalents(value);
}
}

Expand Down
Expand Up @@ -104,6 +104,11 @@ public PrismParser compat() {
return create(source, language, context.clone().compat(), prismContext, itemDefinition, itemName, typeName, typeClass);
}

@Override
public @NotNull PrismParser fastAddOperations() {
return create(source, language, context.clone().fastAddOperations(), prismContext, itemDefinition, itemName, typeName, typeClass);
}

@Override
public PrismParser convertMissingTypes() {
return create(source, language, context.clone().convertUnknownTypes(true), prismContext, itemDefinition, itemName, typeName, typeClass);
Expand Down
Expand Up @@ -68,6 +68,11 @@ public PrismParserNoIO compat() {
return (PrismParserNoIO) super.compat();
}

@Override
public @NotNull PrismParserNoIO fastAddOperations() {
return (PrismParserNoIO) super.fastAddOperations();
}

@NotNull
@Override
public PrismParserNoIO definition(ItemDefinition<?> itemDefinition) {
Expand Down
Expand Up @@ -224,8 +224,12 @@ private <C extends Containerable> void parseContainerValueToContainer(PrismConta
if (node instanceof IncompleteMarkerXNodeImpl) {
container.setIncomplete(true);
} else {
container.add(
parseContainerValue(node, container.getDefinition(), pc));
PrismContainerValue<C> newValue = parseContainerValue(node, container.getDefinition(), pc);
if (pc.isFastAddOperations()) {
container.addIgnoringEquivalents(newValue);
} else {
container.add(newValue);
}
if (node instanceof MapXNodeImpl && container instanceof PrismObject) {
MapXNodeImpl map = (MapXNodeImpl) node;
PrismObject<?> object = (PrismObject<?>) container;
Expand Down Expand Up @@ -477,7 +481,11 @@ private <T> PrismProperty<T> parseProperty(@NotNull XNodeImpl node, @NotNull QNa
PrismPropertyValue<T> pval = parsePropertyValue(node, itemDefinition, pc);
if (pval != null) {
try {
property.add(pval);
if (pc.isFastAddOperations()) {
property.addIgnoringEquivalents(pval);
} else {
property.add(pval);
}
} catch (SchemaException e) {
if (pc.isCompat()) {
// Most probably the "apply definition" call while adding the value failed. This occurs for raw
Expand All @@ -502,10 +510,15 @@ private <T> PrismProperty<T> parseProperty(@NotNull XNodeImpl node, @NotNull QNa
return property;
}

private <V extends PrismValue, D extends ItemDefinition<?>> void addItemValueIfPossible(Item<V, D> item, V value, ParsingContext pc) throws SchemaException {
private <V extends PrismValue, D extends ItemDefinition<?>> void addItemValueIfPossible(
Item<V, D> item, V value, ParsingContext pc) throws SchemaException {
if (value != null) {
try {
item.add(value);
if (pc.isFastAddOperations()) {
item.addIgnoringEquivalents(value);
} else {
item.add(value);
}
} catch (SchemaException e) {
pc.warnOrThrow(LOGGER, "Couldn't add a value of " + value + " to the containing item: " + e.getMessage(), e);
}
Expand Down Expand Up @@ -554,11 +567,20 @@ private void addMetadataIfPresent(PrismValue prismValue, XNode node, @NotNull Pa
}

private void parseMetadataNodes(PrismValue prismValue, List<MapXNode> metadataNodes, ParsingContext pc) throws SchemaException {
if (metadataNodes.isEmpty()) {
return;
}
ValueMetadata valueMetadata = prismValue.getValueMetadata();
for (MapXNode metadataNode : metadataNodes) {
PrismContainerValue pcv =
parseContainerValueFromMap((MapXNodeImpl) metadataNode, schemaRegistry.getValueMetadataDefinition(), pc);
//noinspection unchecked
prismValue.getValueMetadata().add(pcv);
if (pc.isFastAddOperations()) {
//noinspection unchecked
valueMetadata.addIgnoringEquivalents(pcv);
} else {
//noinspection unchecked
valueMetadata.add(pcv);
}
}
}

Expand Down Expand Up @@ -619,11 +641,21 @@ private PrismReference parseReference(@NotNull XNodeImpl node, @NotNull QName it
if (subNode instanceof IncompleteMarkerXNodeImpl) {
ref.setIncomplete(true);
} else {
ref.add(parseReferenceValueFromXNode(subNode, definition, itemName, pc));
PrismReferenceValue subValue = parseReferenceValueFromXNode(subNode, definition, itemName, pc);
if (pc.isFastAddOperations()) {
ref.addIgnoringEquivalents(subValue);
} else {
ref.add(subValue);
}
}
}
} else if (node instanceof MapXNodeImpl) {
ref.add(parseReferenceValueFromXNode(node, definition, itemName, pc));
PrismReferenceValue newValue = parseReferenceValueFromXNode(node, definition, itemName, pc);
if (pc.isFastAddOperations()) {
ref.addIgnoringEquivalents(newValue);
} else {
ref.add(newValue);
}
} else if (node instanceof PrimitiveXNodeImpl) {
// empty
} else if (node instanceof IncompleteMarkerXNodeImpl) {
Expand Down

0 comments on commit 382f87b

Please sign in to comment.