Skip to content

Commit

Permalink
Preliminary definitionProcessing=ONLY_IF_EXISTS handling; enabled whe…
Browse files Browse the repository at this point in the history
…n exporting shadows (MID-4076)

Fixed deepClone for ObjectClassCTD.
Optimized deepClone for PrismContainerValue.
  • Loading branch information
mederly committed Jul 15, 2017
1 parent 76db2a5 commit 3b0ef13
Show file tree
Hide file tree
Showing 18 changed files with 419 additions and 93 deletions.
Expand Up @@ -4,6 +4,7 @@
import java.io.OutputStream;
import java.util.List;

import com.evolveum.midpoint.web.component.data.SelectableBeanObjectDataProvider;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
import org.apache.wicket.extensions.markup.html.repeater.data.table.export.CSVDataExporter;
Expand Down Expand Up @@ -41,15 +42,23 @@ private void initLayout(boolean isAudit) {
@Override
public <T> void exportData(IDataProvider<T> dataProvider, List<IExportableColumn<T, ?>> columns,
OutputStream outputStream) throws IOException {
if (isAudit) {
((AuditEventRecordProvider) dataProvider).setExportSize(true);
super.exportData(dataProvider, columns, outputStream);
((AuditEventRecordProvider) dataProvider).setExportSize(false);

} else {
super.exportData(dataProvider, columns, outputStream);
}

try {
if (dataProvider instanceof SelectableBeanObjectDataProvider) {
((SelectableBeanObjectDataProvider) dataProvider).setExport(true);
}
if (isAudit) {
((AuditEventRecordProvider) dataProvider).setExportSize(true);
super.exportData(dataProvider, columns, outputStream);
((AuditEventRecordProvider) dataProvider).setExportSize(false);

} else {
super.exportData(dataProvider, columns, outputStream);
}
} finally {
if (dataProvider instanceof SelectableBeanObjectDataProvider) {
((SelectableBeanObjectDataProvider) dataProvider).setExport(false);
}
}
}
};
final AbstractAjaxDownloadBehavior ajaxDownloadBehavior = new AbstractAjaxDownloadBehavior() {
Expand Down
Expand Up @@ -25,6 +25,8 @@
import java.util.Map;
import java.util.Set;

import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
import org.apache.commons.lang.Validate;
import org.apache.wicket.Component;
import org.apache.wicket.RestartResponseException;
Expand All @@ -45,6 +47,9 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;

import static com.evolveum.midpoint.schema.DefinitionProcessingOption.FULL;
import static com.evolveum.midpoint.schema.DefinitionProcessingOption.ONLY_IF_EXISTS;

/**
* @author lazyman
* @author semancik
Expand All @@ -61,6 +66,9 @@ public class SelectableBeanObjectDataProvider<O extends ObjectType> extends Base

private boolean emptyListOnNullQuery = false;
private boolean useObjectCounting = true;

// we use special options when exporting to CSV (due to bulk nature of the operation)
private boolean export;

/**
* The number of all objects that the query can return. Defaults to a really big number
Expand Down Expand Up @@ -151,7 +159,21 @@ public Iterator<SelectableBean<O>> internalIterator(long offset, long pageSize)
if (ResourceType.class.equals(type) && (options == null || options.isEmpty())){
options = SelectorOptions.createCollection(GetOperationOptions.createNoFetch());
}
List<PrismObject<? extends O>> list = (List)getModel().searchObjects(type, query, options, task, result);
Collection<SelectorOptions<GetOperationOptions>> currentOptions = options;
if (export) {
// TODO also for other classes
if (ShadowType.class.equals(type)) {
currentOptions = SelectorOptions.set(currentOptions, ItemPath.EMPTY_PATH, () -> new GetOperationOptions(),
(o) -> o.setDefinitionProcessing(ONLY_IF_EXISTS));
currentOptions = SelectorOptions
.set(currentOptions, new ItemPath(ShadowType.F_FETCH_RESULT), GetOperationOptions::new,
(o) -> o.setDefinitionProcessing(FULL));
currentOptions = SelectorOptions
.set(currentOptions, new ItemPath(ShadowType.F_AUXILIARY_OBJECT_CLASS), GetOperationOptions::new,
(o) -> o.setDefinitionProcessing(FULL));
}
}
List<PrismObject<? extends O>> list = (List)getModel().searchObjects(type, query, currentOptions, task, result);

if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Query {} resulted in {} objects", type.getSimpleName(), list.size());
Expand Down Expand Up @@ -268,7 +290,15 @@ public void setEmptyListOnNullQuery(boolean emptyListOnNullQuery) {
this.emptyListOnNullQuery = emptyListOnNullQuery;
}

// public int getSize() {
public boolean isExport() {
return export;
}

public void setExport(boolean export) {
this.export = export;
}

// public int getSize() {
// return size;
// }
//
Expand Down
Expand Up @@ -676,4 +676,16 @@ public CompositeRefinedObjectClassDefinitionImpl deepClone(Map<QName, ComplexTyp
public boolean isListMarker() {
return structuralObjectClassDefinition.isListMarker();
}

@Override
public void trimTo(@NotNull Collection<ItemPath> paths) {
structuralObjectClassDefinition.trimTo(paths);
auxiliaryObjectClassDefinitions.forEach(def -> def.trimTo(paths));
}

// TODO
@Override
public boolean isShared() {
return false;
}
}
Expand Up @@ -611,4 +611,19 @@ public String toString() {
+ refinedObjectClassDefinition + ")";
}

@Override
public void trimTo(@NotNull Collection<ItemPath> paths) {
if (refinedObjectClassDefinition != null) {
refinedObjectClassDefinition.trimTo(paths);
}
}

@Override
public boolean isShared() {
if (refinedObjectClassDefinition != null) {
return refinedObjectClassDefinition.isShared();
} else {
return true; // ok?
}
}
}
Expand Up @@ -49,7 +49,6 @@
import javax.xml.namespace.QName;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

Expand All @@ -73,6 +72,7 @@ public class RefinedObjectClassDefinitionImpl implements RefinedObjectClassDefin
private String displayName;
private String description;
private boolean isDefault;
private boolean shared = true; // experimental
@NotNull private final List<RefinedAttributeDefinition<?>> identifiers = new ArrayList<>();
@NotNull private final List<RefinedAttributeDefinition<?>> secondaryIdentifiers = new ArrayList<>();
@NotNull private final List<ResourceObjectPattern> protectedObjectPatterns = new ArrayList<>();
Expand Down Expand Up @@ -542,6 +542,7 @@ public boolean isObjectCountingEnabled() {
public RefinedObjectClassDefinitionImpl clone() {
RefinedObjectClassDefinitionImpl clone = new RefinedObjectClassDefinitionImpl(resourceType, originalObjectClassDefinition);
copyDefinitionData(clone);
shared = false;
return clone;
}

Expand All @@ -566,7 +567,11 @@ private void copyDefinitionData(RefinedObjectClassDefinitionImpl clone) {
@Override
public RefinedObjectClassDefinition deepClone(Map<QName, ComplexTypeDefinition> ctdMap) {
// TODO TODO TODO (note that in original implementation this was also missing...)
return clone();
RefinedObjectClassDefinitionImpl clone = new RefinedObjectClassDefinitionImpl(resourceType, originalObjectClassDefinition.deepClone(ctdMap));
copyDefinitionData(clone);
shared = false;
return clone;

}

private Collection<RefinedAssociationDefinition> cloneAssociations(Collection<RefinedAssociationDefinition> origAsoc) {
Expand Down Expand Up @@ -1261,4 +1266,19 @@ public <X> RefinedAttributeDefinition<X> findAttributeDefinition(@NotNull QName

//endregion

@Override
public void trimTo(@NotNull Collection<ItemPath> paths) {
originalObjectClassDefinition.trimTo(paths);
List<QName> names = paths.stream()
.filter(p -> p.isSingleName())
.map(p -> p.asSingleName())
.collect(Collectors.toList());
attributeDefinitions.removeIf(itemDefinition -> !QNameUtil.contains(names, itemDefinition.getName()));
associationDefinitions.removeIf(itemDefinition -> !QNameUtil.contains(names, itemDefinition.getName()));
}

@Override
public boolean isShared() {
return shared;
}
}
Expand Up @@ -16,10 +16,12 @@

package com.evolveum.midpoint.prism;

import com.evolveum.midpoint.prism.path.ItemPath;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.xml.namespace.QName;
import java.util.Collection;
import java.util.List;
import java.util.Map;

Expand All @@ -46,6 +48,14 @@ public interface ComplexTypeDefinition extends TypeDefinition, LocalDefinitionSt
@NotNull
List<? extends ItemDefinition> getDefinitions();

/**
* Is this definition shared, i.e. used by more than one prism object?
* If so, it should not be e.g. trimmed.
*
* EXPERIMENTAL
*/
boolean isShared();

/**
* If not null, indicates that this type defines the structure of 'extension' element of a given type.
* E.g. getExtensionForType() == c:UserType means that this complex type defines structure of
Expand Down Expand Up @@ -122,4 +132,10 @@ public interface ComplexTypeDefinition extends TypeDefinition, LocalDefinitionSt
*/
@NotNull
ComplexTypeDefinition deepClone(Map<QName, ComplexTypeDefinition> ctdMap);

/**
* Trims the definition (and any definitions it refers to) to contain only items related to given paths.
* USE WITH CARE. Be sure no shared definitions would be affected by this operation!
*/
void trimTo(@NotNull Collection<ItemPath> paths);
}
Expand Up @@ -26,7 +26,6 @@
import com.evolveum.midpoint.util.PrettyPrinter;
import org.jetbrains.annotations.NotNull;
import com.evolveum.midpoint.util.QNameUtil;
import org.apache.commons.lang.StringUtils;

import java.util.*;

Expand All @@ -51,6 +50,10 @@ public class ComplexTypeDefinitionImpl extends TypeDefinitionImpl implements Com
private String defaultNamespace;
@NotNull private List<String> ignoredNamespaces = new ArrayList<>();

// temporary/experimental - to avoid trimming "standard" definitions
// we reset this flag when cloning
protected boolean shared = true;

public ComplexTypeDefinitionImpl(@NotNull QName typeName, @NotNull PrismContext prismContext) {
super(typeName, prismContext);
}
Expand Down Expand Up @@ -78,6 +81,11 @@ public void add(ItemDefinition<?> definition) {
itemDefinitions.add(definition);
}

@Override
public boolean isShared() {
return shared;
}

@Override
public QName getExtensionForType() {
return extensionForType;
Expand Down Expand Up @@ -262,6 +270,7 @@ public boolean isEmpty() {
public ComplexTypeDefinitionImpl clone() {
ComplexTypeDefinitionImpl clone = new ComplexTypeDefinitionImpl(this.typeName, prismContext);
copyDefinitionData(clone);
clone.shared = false;
return clone;
}

Expand Down Expand Up @@ -419,7 +428,27 @@ public String getDocClassName() {
return "complex type";
}

// @Override
@Override
public void trimTo(@NotNull Collection<ItemPath> paths) {
if (shared) {
// TODO switch this to warning before releasing this code (3.6.1 or 3.7)
throw new IllegalStateException("Couldn't trim shared definition: " + this);
}
for (Iterator<ItemDefinition> iterator = itemDefinitions.iterator(); iterator.hasNext(); ) {
ItemDefinition<?> itemDef = iterator.next();
ItemPath itemPath = new ItemPath(itemDef.getName());
if (!ItemPath.containsSuperpathOrEquivalent(paths, itemPath)) {
iterator.remove();
} else if (itemDef instanceof PrismContainerDefinition) {
PrismContainerDefinition<?> itemPcd = (PrismContainerDefinition<?>) itemDef;
if (itemPcd.getComplexTypeDefinition() != null) {
itemPcd.getComplexTypeDefinition().trimTo(ItemPath.remainder(paths, itemPath, false));
}
}
}
}

// @Override
// public void accept(Visitor visitor) {
// super.accept(visitor);
// itemDefinitions.forEach(def -> def.accept(visitor));
Expand Down
Expand Up @@ -26,6 +26,7 @@
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;

import javax.xml.namespace.QName;
Expand Down Expand Up @@ -912,4 +913,31 @@ public static <V extends PrismContainerValue> void createParentIfNeeded(V value,
PrismContainer<?> rv = (PrismContainer) definition.instantiate();
rv.add(value);
}

/**
* Optimizes (trims) definition tree by removing any definitions not corresponding to items in this container.
* Works recursively by sub-containers of this one.
* USE WITH CARE. Make sure the definitions are not shared by other objects!
*/
public void trimDefinitionTree(Collection<ItemPath> alwaysKeep) {
PrismContainerDefinition<C> def = getDefinition();
if (def == null || def.getComplexTypeDefinition() == null) {
return;
}
Set<ItemPath> allPaths = getAllItemPaths(alwaysKeep);
def.getComplexTypeDefinition().trimTo(allPaths);
values.forEach(v -> v.trimItemsDefinitionsTrees(alwaysKeep));
}

// TODO implement more efficiently
private Set<ItemPath> getAllItemPaths(Collection<ItemPath> alwaysKeep) {
Set<ItemPath> paths = new HashSet<>();
paths.addAll(CollectionUtils.emptyIfNull(alwaysKeep));
this.accept(v -> {
if (v instanceof PrismValue) {
paths.add(((PrismValue) v).getPath());
}
});
return paths;
}
}

0 comments on commit 3b0ef13

Please sign in to comment.