/* * Copyright (c) 2010-2013 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.evolveum.midpoint.web.component.data; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.PrismReference; import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.ObjectPaging; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.RetrieveOption; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.page.admin.configuration.dto.DebugObjectItem; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import org.apache.commons.lang.Validate; import org.apache.wicket.Component; import java.io.Serializable; import java.util.*; /** * @author lazyman */ public class RepositoryObjectDataProvider extends BaseSortableDataProvider<DebugObjectItem> { private static final String DOT_CLASS = RepositoryObjectDataProvider.class.getName() + "."; private static final String OPERATION_SEARCH_OBJECTS = DOT_CLASS + "searchObjects"; private static final String OPERATION_LOAD_RESOURCE = DOT_CLASS + "loadResource"; private static final String OPERATION_COUNT_OBJECTS = DOT_CLASS + "countObjects"; private static final Trace LOGGER = TraceManager.getTrace(RepositoryObjectDataProvider.class); private Class<? extends ObjectType> type; private Map<String, ResourceDescription> resourceCache = new HashMap<String, ResourceDescription>(); public RepositoryObjectDataProvider(Component component, Class<? extends ObjectType> type) { super(component, true); setType(type); } @Override public Iterator<DebugObjectItem> internalIterator(long first, long count) { LOGGER.trace("begin::iterator() from {} count {}.", new Object[]{first, count}); getAvailableData().clear(); OperationResult result = new OperationResult(OPERATION_SEARCH_OBJECTS); try { ObjectPaging paging = createPaging(first, count); ObjectQuery query = getQuery(); if (query == null) { query = new ObjectQuery(); } query.setPaging(paging); //RAW and DEFAULT retrieve option selected Collection<SelectorOptions<GetOperationOptions>> options = new ArrayList<SelectorOptions<GetOperationOptions>>(); GetOperationOptions opt = GetOperationOptions.createRaw(); opt.setRetrieve(RetrieveOption.DEFAULT); options.add(SelectorOptions.create(ItemPath.EMPTY_PATH, opt)); List<PrismObject<? extends ObjectType>> list = getModel().searchObjects((Class) type, query, options, getPage().createSimpleTask(OPERATION_SEARCH_OBJECTS), result); for (PrismObject<? extends ObjectType> object : list) { getAvailableData().add(createItem(object, result)); } } catch (Exception ex) { result.recordFatalError("Couldn't list objects.", ex); } finally { result.computeStatusIfUnknown(); } getPage().showResult(result, false); LOGGER.trace("end::iterator()"); return getAvailableData().iterator(); } private DebugObjectItem createItem(PrismObject<? extends ObjectType> object, OperationResult result) { DebugObjectItem item = DebugObjectItem.createDebugObjectItem(object); if (ShadowType.class.isAssignableFrom(object.getCompileTimeClass())) { PrismReference ref = object.findReference(new ItemPath(ShadowType.F_RESOURCE_REF)); if (ref == null || ref.getValue() == null) { return item; } PrismReferenceValue refValue = ref.getValue(); String resourceOid = refValue.getOid(); ResourceDescription desc = resourceCache.get(resourceOid); if (desc == null) { desc = loadDescription(resourceOid, result); resourceCache.put(resourceOid, desc); } item.setResourceName(desc.getName()); item.setResourceType(desc.getType()); } return item; } private ResourceDescription loadDescription(String oid, OperationResult result) { Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(ResourceType.F_CONNECTOR, GetOperationOptions.createResolve()); OperationResult subResult = result.createSubresult(OPERATION_LOAD_RESOURCE); subResult.addParam("oid", oid); PrismObject<ResourceType> resource = null; String type = null; try { resource = getModel().getObject(ResourceType.class, oid, options, getPage().createSimpleTask(OPERATION_LOAD_RESOURCE), subResult); PrismReference ref = resource.findReference(ResourceType.F_CONNECTOR_REF); if (ref != null && ref.getValue() != null) { PrismReferenceValue refValue = ref.getValue(); if (refValue.getObject() != null) { PrismObject connector = refValue.getObject(); PrismProperty<String> pType = connector.findProperty(ConnectorType.F_CONNECTOR_TYPE); if (pType != null && pType.getRealValue() != null) { type = pType.getRealValue(String.class); } } } subResult.recordSuccess(); } catch (Exception ex) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load resource for account", ex); subResult.recordFatalError("Couldn't load resource for account."); } finally { subResult.recomputeStatus(); } return new ResourceDescription(oid, WebComponentUtil.getName(resource), type); } @Override protected int internalSize() { LOGGER.trace("begin::internalSize()"); int count = 0; OperationResult result = new OperationResult(OPERATION_COUNT_OBJECTS); try { count = getModel().countObjects(type, getQuery(), SelectorOptions.createCollection(new ItemPath(), GetOperationOptions.createRaw()), getPage().createSimpleTask(OPERATION_COUNT_OBJECTS), result); } catch (Exception ex) { result.recordFatalError("Couldn't count objects.", ex); } finally { result.computeStatusIfUnknown(); } getPage().showResult(result, false); LOGGER.trace("end::internalSize()"); return count; } public void setType(Class<? extends ObjectType> type) { Validate.notNull(type); this.type = type; } public Class<? extends ObjectType> getType() { return type; } @Override protected CachedSize getCachedSize(Map<Serializable, CachedSize> cache) { return cache.get(new TypedCacheKey(getQuery(), type)); } @Override protected void addCachedSize(Map<Serializable, CachedSize> cache, CachedSize newSize) { cache.put(new TypedCacheKey(getQuery(), type), newSize); } private static class ResourceDescription implements Serializable { private String oid; private String name; private String type; private ResourceDescription(String oid, String name, String type) { this.oid = oid; this.name = name; this.type = type; } public String getName() { return name; } public String getOid() { return oid; } public String getType() { return type; } } }