com.evolveum.midpoint.repo.sql.AddGetObjectTest.java Source code

Java tutorial

Introduction

Here is the source code for com.evolveum.midpoint.repo.sql.AddGetObjectTest.java

Source

/*
 * 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.repo.sql;

import com.evolveum.midpoint.common.refinery.RefinedResourceSchema;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.delta.ReferenceDelta;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.prism.util.ValueSerializationUtil;
import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType;
import com.evolveum.midpoint.repo.sql.util.RUtil;
import com.evolveum.midpoint.schema.*;
import com.evolveum.midpoint.schema.processor.ResourceSchema;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ShadowUtil;
import com.evolveum.midpoint.test.util.TestUtil;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.stat.Statistics;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.testng.AssertJUnit;
import org.testng.annotations.Test;

import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;

import java.io.File;
import java.util.*;

/**
 * @author lazyman
 */
@ContextConfiguration(locations = { "../../../../../ctx-test.xml" })
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class AddGetObjectTest extends BaseSQLRepoTest {

    private static final Trace LOGGER = TraceManager.getTrace(AddGetObjectTest.class);

    @Test(enabled = false)
    public <T extends ObjectType> void perfTest() throws Exception {
        Statistics stats = getFactory().getStatistics();
        stats.setStatisticsEnabled(true);

        final File OBJECTS_FILE = new File("./src/test/resources/10k-users.xml");
        List<PrismObject<? extends Objectable>> elements = prismContext.parseObjects(OBJECTS_FILE);

        long previousCycle = 0;
        long time = System.currentTimeMillis();
        for (int i = 0; i < elements.size(); i++) {
            if (i % 500 == 0) {
                LOGGER.info("Previous cycle time {}. Next cycle: {}",
                        new Object[] { (System.currentTimeMillis() - time - previousCycle), i });
                previousCycle = System.currentTimeMillis() - time;
            }

            PrismObject<T> object = (PrismObject<T>) elements.get(i);
            repositoryService.addObject(object, null, new OperationResult("add performance test"));
        }
        LOGGER.info("Time to add objects ({}): {}",
                new Object[] { elements.size(), (System.currentTimeMillis() - time) });

        stats.logSummary();
    }

    @Test
    public void addSameName() throws Exception {
        final File user = new File(FOLDER_BASIC, "objects-user.xml");
        addGetCompare(user);
        try {
            // WHEN
            addGetCompare(user);

            assert false : "Unexpected success";
        } catch (ObjectAlreadyExistsException e) {
            TestUtil.assertExceptionSanity(e);
        }
    }

    @Test
    public void addGetDSEESyncDoubleTest() throws Exception {
        final File OBJECTS_FILE = new File("./../../samples/dsee/odsee-localhost-advanced-sync.xml");
        if (!OBJECTS_FILE.exists()) {
            LOGGER.warn("skipping addGetDSEESyncDoubleTest, file {} not found.",
                    new Object[] { OBJECTS_FILE.getPath() });
            return;
        }
        addGetCompare(OBJECTS_FILE);
        try {
            // WHEN
            addGetCompare(OBJECTS_FILE);

            assert false : "Unexpected success";
        } catch (ObjectAlreadyExistsException e) {
            TestUtil.assertExceptionSanity(e);
        }
    }

    @Test
    public void simpleAddGetTest() throws Exception {
        LOGGER.info("===[ simpleAddGetTest ]===");
        final File OBJECTS_FILE = new File(FOLDER_BASIC, "objects.xml");
        addGetCompare(OBJECTS_FILE);
    }

    private void addGetCompare(File file) throws Exception {
        List<PrismObject<? extends Objectable>> elements = prismContext.parseObjects(file);
        List<String> oids = new ArrayList<String>();

        OperationResult result = new OperationResult("Simple Add Get Test");
        long time = System.currentTimeMillis();
        for (int i = 0; i < elements.size(); i++) {
            PrismObject object = elements.get(i);
            LOGGER.info("Adding object {}, type {}",
                    new Object[] { (i + 1), object.getCompileTimeClass().getSimpleName() });
            oids.add(repositoryService.addObject(object, null, result));
        }
        LOGGER.info("Time to add objects ({}): {}",
                new Object[] { elements.size(), (System.currentTimeMillis() - time), });

        int count = 0;
        elements = prismContext.parseObjects(file);
        for (int i = 0; i < elements.size(); i++) {
            try {
                PrismObject object = elements.get(i);
                object.asObjectable().setOid(oids.get(i));

                Class<? extends ObjectType> clazz = object.getCompileTimeClass();

                Collection o = null;
                if (UserType.class.equals(clazz)) {
                    o = SelectorOptions.createCollection(UserType.F_JPEG_PHOTO,
                            GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE));
                }
                PrismObject<? extends ObjectType> newObject = repositoryService.getObject(clazz, oids.get(i), o,
                        result);
                LOGGER.info("Old\n{}\nnew\n{}", new Object[] { object.debugDump(3), newObject.debugDump(3) });
                checkContainersSize(newObject, object);
                System.out.println("OLD: " + object.findProperty(ObjectType.F_NAME).getValue());
                System.out.println("NEW: " + newObject.findProperty(ObjectType.F_NAME).getValue());

                ObjectDelta delta = object.diff(newObject);
                if (delta == null) {
                    continue;
                }

                count += delta.getModifications().size();
                if (delta.getModifications().size() > 0) {
                    if (delta.getModifications().size() == 1) {
                        ItemDelta d = (ItemDelta) delta.getModifications().iterator().next();

                        if (ShadowType.F_DEAD.equals(d.getElementName())) {
                            count -= delta.getModifications().size();
                            continue;
                        }
                    }
                    LOGGER.error(">>> {} Found {} changes for {}\n{}", new Object[] { (i + 1),
                            delta.getModifications().size(), newObject.toString(), delta.debugDump(3) });
                    ItemDelta id = (ItemDelta) delta.getModifications().iterator().next();
                    if (id.isReplace()) {
                        System.out.println(id.getValuesToReplace().iterator().next());
                    }
                    LOGGER.error("{}", prismContext.serializeObjectToString(newObject, PrismContext.LANG_XML));
                }
            } catch (Exception ex) {
                LOGGER.error("Exception occurred", ex);
                throw ex;
            }
        }

        AssertJUnit.assertEquals("Found changes during add/get test " + count, 0, count);
    }

    private Integer size(PrismContainerValue value) {
        if (value == null) {
            return null;
        }

        return value.getItems() != null ? value.getItems().size() : 0;
    }

    private void checkContainerValuesSize(QName parentName, PrismContainerValue newValue,
            PrismContainerValue oldValue) {
        LOGGER.info("Checking: " + parentName);
        AssertJUnit.assertEquals("Count doesn't match for '" + parentName + "'", size(oldValue), size(newValue));

        List<QName> checked = new ArrayList<QName>();

        for (Item item : (List<Item>) newValue.getItems()) {
            if (!(item instanceof PrismContainer)) {
                continue;
            }

            PrismContainer newContainer = (PrismContainer) item;
            PrismContainer oldContainer = oldValue.findContainer(newContainer.getElementName());
            AssertJUnit.assertNotNull("Container '" + newContainer.getElementName() + "' doesn't exist.",
                    oldContainer);

            checkContainersSize(newContainer, oldContainer);
            checked.add(oldContainer.getElementName());
        }

        for (Item item : (List<Item>) oldValue.getItems()) {
            if (!(item instanceof PrismContainer) || checked.contains(item.getElementName())) {
                continue;
            }

            PrismContainer oldContainer = (PrismContainer) item;
            PrismContainer newContainer = newValue.findContainer(oldContainer.getElementName());
            checkContainersSize(newContainer, oldContainer);
        }
    }

    private void checkContainersSize(PrismContainer newContainer, PrismContainer oldContainer) {
        LOGGER.info("checkContainersSize {} new {}  old {}",

                new Object[] { newContainer.getElementName(), newContainer.size(), oldContainer.size() });
        AssertJUnit.assertEquals(newContainer.size(), oldContainer.size());

        List<Long> checked = new ArrayList<Long>();
        List<PrismContainerValue> newValues = newContainer.getValues();
        for (PrismContainerValue value : newValues) {
            PrismContainerValue oldValue = oldContainer.getValue(value.getId());

            checkContainerValuesSize(newContainer.getElementName(), value, oldValue);
            checked.add(value.getId());
        }

        List<PrismContainerValue> oldValues = oldContainer.getValues();
        for (PrismContainerValue value : oldValues) {
            if (checked.contains(value.getId())) {
                continue;
            }

            PrismContainerValue newValue = newContainer.getValue(value.getId());
            checkContainerValuesSize(newContainer.getElementName(), newValue, value);
        }
    }

    @Test
    public void addUserWithAssignmentExtension() throws Exception {
        LOGGER.info("===[ addUserWithAssignmentExtension ]===");
        File file = new File(FOLDER_BASIC, "user-assignment-extension.xml");
        List<PrismObject<? extends Objectable>> elements = prismContext.parseObjects(file);

        OperationResult result = new OperationResult("ADD");
        String oid = repositoryService.addObject((PrismObject) elements.get(0), null, result);

        PrismObject<UserType> fileUser = (PrismObject<UserType>) prismContext.parseObjects(file).get(0);
        long id = 1;
        for (AssignmentType assignment : fileUser.asObjectable().getAssignment()) {
            assignment.setId(id);
            id++;
        }

        PrismObject<UserType> repoUser = repositoryService.getObject(UserType.class, oid, null, result);

        ObjectDelta<UserType> delta = fileUser.diff(repoUser);
        AssertJUnit.assertNotNull(delta);
        LOGGER.info("delta\n{}", new Object[] { delta.debugDump(3) });
        AssertJUnit.assertTrue(delta.isEmpty());
    }

    /**
     * Attempt to store full account in the repo and then get it out again. The
     * potential problem is that there are attributes that do not have a fixed
     * (static) definition.
     */
    @Test
    public void addGetFullAccount() throws Exception {
        LOGGER.info("===[ addGetFullAccount ]===");
        File file = new File(FOLDER_BASIC, "account-full.xml");
        PrismObject<ShadowType> fileAccount = prismContext.parseObject(new File(FOLDER_BASIC, "account-full.xml"));

        // apply appropriate schema
        PrismObject<ResourceType> resource = prismContext
                .parseObject(new File(FOLDER_BASIC, "resource-opendj.xml"));
        ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext);
        ShadowUtil.applyResourceSchema(fileAccount, resourceSchema);

        OperationResult result = new OperationResult("ADD");
        String oid = repositoryService.addObject(fileAccount, null, result);

        PrismObject<ShadowType> repoAccount = repositoryService.getObject(ShadowType.class, oid, null, result);

        ObjectDelta<ShadowType> delta = fileAccount.diff(repoAccount);
        AssertJUnit.assertNotNull(delta);
        LOGGER.info("delta\n{}", new Object[] { delta.debugDump(3) });
        AssertJUnit.assertTrue(delta.isEmpty());
        ShadowType repoShadow = repoAccount.asObjectable();
        AssertJUnit.assertNotNull(repoShadow.getSynchronizationSituation());
        AssertJUnit.assertEquals(SynchronizationSituationType.LINKED, repoShadow.getSynchronizationSituation());
        AssertJUnit.assertNotNull(repoShadow.getSynchronizationSituationDescription());
        AssertJUnit.assertEquals(1, repoShadow.getSynchronizationSituationDescription().size());
        AssertJUnit.assertEquals(SynchronizationSituationType.LINKED,
                repoShadow.getSynchronizationSituationDescription().get(0).getSituation());
        AssertJUnit.assertEquals("syncChannel",
                repoShadow.getSynchronizationSituationDescription().get(0).getChannel());
    }

    @Test
    public void addGetSystemConfigFile() throws Exception {
        LOGGER.info("===[ addGetPasswordPolicy ]===");
        File file = new File(FOLDER_BASIC, "password-policy.xml");
        PrismObject<ValuePolicyType> filePasswordPolicy = prismContext
                .parseObject(new File(FOLDER_BASIC, "password-policy.xml"));

        OperationResult result = new OperationResult("ADD");
        String pwdPolicyOid = "00000000-0000-0000-0000-000000000003";
        String oid = repositoryService.addObject(filePasswordPolicy, null, result);
        AssertJUnit.assertNotNull(oid);
        AssertJUnit.assertEquals(pwdPolicyOid, oid);
        PrismObject<ValuePolicyType> repoPasswordPolicy = repositoryService.getObject(ValuePolicyType.class, oid,
                null, result);
        AssertJUnit.assertNotNull(repoPasswordPolicy);

        String systemCongigOid = "00000000-0000-0000-0000-000000000001";
        PrismObject<SystemConfigurationType> fileSystemConfig = prismContext
                .parseObject(new File(FOLDER_BASIC, "systemConfiguration.xml"));
        LOGGER.info("System config from file: {}", fileSystemConfig.debugDump());
        oid = repositoryService.addObject(fileSystemConfig, null, result);
        AssertJUnit.assertNotNull(oid);
        AssertJUnit.assertEquals(systemCongigOid, oid);

        PrismObject<SystemConfigurationType> repoSystemConfig = repositoryService
                .getObject(SystemConfigurationType.class, systemCongigOid, null, result);
        //      AssertJUnit.assertNotNull("global password policy null", repoSystemConfig.asObjectable().getGlobalPasswordPolicy());
        LOGGER.info("System config from repo: {}", repoSystemConfig.debugDump());
        AssertJUnit.assertNull("global password policy not null",
                repoSystemConfig.asObjectable().getGlobalPasswordPolicyRef());

        ReferenceDelta refDelta = ReferenceDelta.createModificationAdd(
                SystemConfigurationType.F_GLOBAL_PASSWORD_POLICY_REF, repoSystemConfig.getDefinition(),
                PrismReferenceValue.createFromTarget(repoPasswordPolicy));
        List<ReferenceDelta> refDeltas = new ArrayList<ReferenceDelta>();
        refDeltas.add(refDelta);
        repositoryService.modifyObject(SystemConfigurationType.class, systemCongigOid, refDeltas, result);
        repoSystemConfig = repositoryService.getObject(SystemConfigurationType.class, systemCongigOid, null,
                result);
        LOGGER.info("system config after modify: {}", repoSystemConfig.debugDump());
        AssertJUnit.assertNotNull("global password policy null",
                repoSystemConfig.asObjectable().getGlobalPasswordPolicyRef());
        AssertJUnit.assertNull("default user template not null",
                repoSystemConfig.asObjectable().getDefaultUserTemplateRef());
    }

    @Test
    public void addGetSyncDescription() throws Exception {
        PrismObjectDefinition accDef = prismContext.getSchemaRegistry()
                .findObjectDefinitionByCompileTimeClass(ShadowType.class);
        PrismObject<ShadowType> shadow = accDef.instantiate();
        final Date TIME = new Date();
        ShadowType shadowType = shadow.asObjectable();
        shadowType.setName(new PolyStringType("sync desc test"));
        SynchronizationSituationDescriptionType desc = new SynchronizationSituationDescriptionType();
        desc.setChannel("channel");
        desc.setSituation(SynchronizationSituationType.LINKED);
        desc.setTimestamp(XMLGregorianCalendarType.asXMLGregorianCalendar(TIME));
        shadowType.getSynchronizationSituationDescription().add(desc);

        OperationResult result = new OperationResult("sync desc test");
        String oid = repositoryService.addObject(shadowType.asPrismObject(), null, result);

        shadow = repositoryService.getObject(ShadowType.class, oid, null, result);
        shadowType = shadow.asObjectable();
        desc = shadowType.getSynchronizationSituationDescription().get(0);
        AssertJUnit.assertEquals("Times don't match", TIME, XMLGregorianCalendarType.asDate(desc.getTimestamp()));
    }

    /**
     * creates <iterationToken/> element in shadow
     */
    @Test
    public void emtpyIterationToken() throws Exception {
        String token = testIterationToken("");
        AssertJUnit.assertNotNull(token);
        AssertJUnit.assertTrue(token.equals(""));
    }

    /**
     * doesn't create <iterationToken/> element in shadow
     */
    @Test
    public void nullIterationToken() throws Exception {
        String token = testIterationToken(null);
        AssertJUnit.assertNull(token);
    }

    /**
     * creates <iterationToken>some value</iterationToken> element in shadow
     */
    @Test
    public void valueInIterationToken() throws Exception {
        String token = testIterationToken("foo");
        AssertJUnit.assertNotNull(token);
        AssertJUnit.assertEquals(token, "foo");
    }

    private String testIterationToken(String token) throws Exception {
        PrismObjectDefinition accDef = prismContext.getSchemaRegistry()
                .findObjectDefinitionByCompileTimeClass(ShadowType.class);
        PrismObject<ShadowType> shadow = accDef.instantiate();

        ShadowType shadowType = shadow.asObjectable();
        shadowType.setName(new PolyStringType("testIterationToken"));
        shadowType.setIterationToken(token);

        OperationResult result = new OperationResult("sync desc test");
        final String oid = repositoryService.addObject(shadowType.asPrismObject(), null, result);

        shadow = repositoryService.getObject(ShadowType.class, oid, null, result);
        shadowType = shadow.asObjectable();

        token = shadowType.getIterationToken();
        repositoryService.deleteObject(ShadowType.class, oid, result);

        return token;
    }

    @Test(enabled = false)
    public void deltaOperationSerializationPerformanceTest() throws Exception {
        List<PrismObject<? extends Objectable>> elements = prismContext
                .parseObjects(new File(FOLDER_BASIC, "objects.xml"));

        //get user from objects.xml
        ObjectDelta delta = ObjectDelta.createAddDelta(elements.get(0));

        final int COUNT = 10000;
        //first conversion option
        System.out.println(DeltaConvertor.toObjectDeltaTypeXml(delta));
        //second conversion option
        System.out.println("\n" + toRepo(DeltaConvertor.toObjectDeltaType(delta), prismContext));

        long time = System.currentTimeMillis();
        for (int i = 0; i < COUNT; i++) {
            String xml = DeltaConvertor.toObjectDeltaTypeXml(delta);
        }
        time = System.currentTimeMillis() - time;
        System.out.println(">>> " + time);

        time = System.currentTimeMillis();
        for (int i = 0; i < COUNT; i++) {
            ObjectDeltaType type = DeltaConvertor.toObjectDeltaType(delta);
            String xml = toRepo(type, prismContext);
        }
        time = System.currentTimeMillis() - time;
        System.out.println(">>> " + time);
    }

    private <T> String toRepo(T value, PrismContext prismContext) throws SchemaException, JAXBException {
        if (value == null) {
            return null;
        }

        // PrismDomProcessor domProcessor = prismContext.getPrismDomProcessor();
        if (value instanceof Objectable) {
            return prismContext.serializeObjectToString(((Objectable) value).asPrismObject(),
                    PrismContext.LANG_XML);
        }

        if (value instanceof Containerable) {
            // TODO: createFakeParentElement??? why we don't use the real
            // name???
            return prismContext.serializeContainerValueToString(((Containerable) value).asPrismContainerValue(),
                    QNameUtil.getNodeQName(RUtil.createFakeParentElement()), prismContext.LANG_XML);
        }

        return ValueSerializationUtil.serializeValue(value, new QName("fake"), prismContext, PrismContext.LANG_XML);

    }

    @Test
    public void test() throws Exception {
        OperationResult result = new OperationResult("asdf");
        final List<PrismObject> objects = new ArrayList<PrismObject>();
        ResultHandler<ObjectType> handler = new ResultHandler<ObjectType>() {

            @Override
            public boolean handle(PrismObject<ObjectType> object, OperationResult parentResult) {
                objects.add(object);
                return true;
            }
        };

        repositoryService.searchObjectsIterative(ObjectType.class, null, handler, null, result);
        AssertJUnit.assertTrue(!objects.isEmpty());
    }

    @Test
    private void addGetFullAccountShadow() throws Exception {
        LOGGER.info("===[ simpleAddAccountShadowTest ]===");
        OperationResult result = new OperationResult("testAddAccountShadow");
        File file = new File(FOLDER_BASIC, "account-accountTypeShadow.xml");
        try {
            PrismObject<ShadowType> account = prismContext.parseObject(file);

            // apply appropriate schema
            PrismObject<ResourceType> resource = prismContext
                    .parseObject(new File(FOLDER_BASIC, "resource-opendj.xml"));
            ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext);
            ShadowUtil.applyResourceSchema(account, resourceSchema);

            repositoryService.addObject(account, null, result);

            PrismObject<ShadowType> afterAdd = repositoryService.getObject(ShadowType.class, account.getOid(), null,
                    result);
            AssertJUnit.assertNotNull(afterAdd);

        } catch (Exception ex) {
            LOGGER.error("Exception occurred", ex);
            throw ex;
        }
    }

    @Test
    public void test100AddUserWithoutAssignmentIds() throws Exception {
        OperationResult result = new OperationResult("test100AddUserWithoutAssignmentIds");
        PrismObject<UserType> user = PrismTestUtil.parseObject(new File(FOLDER_BASIC, "user-big.xml"));

        //remove ids from assignment values
        PrismContainer container = user.findContainer(UserType.F_ASSIGNMENT);
        for (PrismContainerValue value : (List<PrismContainerValue>) container.getValues()) {
            value.setId(null);
        }
        final String OID = repositoryService.addObject(user, null, result);
        result.computeStatusIfUnknown();

        //get user
        user = repositoryService.getObject(UserType.class, OID, null, result);
        result.computeStatusIfUnknown();

        container = user.findContainer(UserType.F_ASSIGNMENT);
        List<Short> xmlShorts = new ArrayList<>();
        for (PrismContainerValue value : (List<PrismContainerValue>) container.getValues()) {
            AssertJUnit.assertNotNull(value.getId());
            xmlShorts.add(value.getId().shortValue());
        }
        Collections.sort(xmlShorts);

        Session session = open();
        try {
            Query query = session.createSQLQuery("select id from m_assignment where owner_oid=:oid");
            query.setString("oid", OID);
            List<Short> dbShorts = new ArrayList<>();
            for (Number n : (List<Number>) query.list()) {
                dbShorts.add(n.shortValue());
            }
            Collections.sort(dbShorts);

            LOGGER.info("assigments ids: expected {} db {}", Arrays.toString(xmlShorts.toArray()),
                    Arrays.toString(dbShorts.toArray()));
            AssertJUnit.assertArrayEquals(xmlShorts.toArray(), dbShorts.toArray());
        } finally {
            close(session);
        }
    }
}