Package org.apache.cayenne

Source Code of org.apache.cayenne.CayenneContextTest

/*****************************************************************
*   Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF licenses this file
*  to you 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 org.apache.cayenne;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.apache.cayenne.di.Inject;
import org.apache.cayenne.event.DefaultEventManager;
import org.apache.cayenne.event.EventManager;
import org.apache.cayenne.event.MockEventManager;
import org.apache.cayenne.graph.CompoundDiff;
import org.apache.cayenne.graph.GraphDiff;
import org.apache.cayenne.graph.MockGraphDiff;
import org.apache.cayenne.graph.NodeIdChangeOperation;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.remote.BootstrapMessage;
import org.apache.cayenne.remote.ClientChannel;
import org.apache.cayenne.remote.ClientConnection;
import org.apache.cayenne.remote.ClientMessage;
import org.apache.cayenne.testdo.mt.ClientMtTable1;
import org.apache.cayenne.testdo.mt.MtTable1;
import org.apache.cayenne.unit.di.client.ClientCase;
import org.apache.cayenne.unit.di.server.UseServerRuntime;
import org.apache.cayenne.util.GenericResponse;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

@UseServerRuntime(ClientCase.MULTI_TIER_PROJECT)
public class CayenneContextTest extends ClientCase {

    @Inject
    private ObjectContext serverContext;

    public void testConstructor() {

        CayenneContext context = new CayenneContext();

        // test default property parameters
        assertNotNull(context.getGraphManager());
        assertNull(context.channel);

        MockDataChannel channel = new MockDataChannel();
        context.setChannel(channel);
        assertSame(channel, context.getChannel());
    }

    public void testLocalObject() {

        DataChannel channel = mock(DataChannel.class);

        CayenneContext src = new CayenneContext(channel);
        src
                .setEntityResolver(serverContext
                        .getEntityResolver()
                        .getClientEntityResolver());

        List<Persistent> sources = new ArrayList<Persistent>();

        ClientMtTable1 s1 = new ClientMtTable1();
        s1.setPersistenceState(PersistenceState.COMMITTED);
        s1.setObjectId(new ObjectId("MtTable1", MtTable1.TABLE1_ID_PK_COLUMN, 1));
        s1.setGlobalAttribute1("abc");
        s1.setObjectContext(src);
        src.getGraphManager().registerNode(s1.getObjectId(), s1);
        sources.add(s1);

        ClientMtTable1 s2 = new ClientMtTable1();
        s2.setPersistenceState(PersistenceState.COMMITTED);
        s2.setObjectId(new ObjectId("MtTable1", MtTable1.TABLE1_ID_PK_COLUMN, 2));
        s2.setGlobalAttribute1("xyz");
        s2.setObjectContext(src);
        src.getGraphManager().registerNode(s2.getObjectId(), s2);
        sources.add(s2);

        ClientMtTable1 s3 = new ClientMtTable1();
        s3.setPersistenceState(PersistenceState.HOLLOW);
        s3.setObjectId(new ObjectId("MtTable1", MtTable1.TABLE1_ID_PK_COLUMN, 3));
        s3.setObjectContext(src);
        src.getGraphManager().registerNode(s3.getObjectId(), s3);
        sources.add(s3);

        CayenneContext target = new CayenneContext(channel);
        target.setEntityResolver(serverContext
                .getEntityResolver()
                .getClientEntityResolver());

        for (int i = 0; i < sources.size(); i++) {
            Persistent srcObject = sources.get(i);
            Persistent targetObject = target.localObject(
                    srcObject.getObjectId(),
                    srcObject);

            assertSame(target, targetObject.getObjectContext());
            assertSame(src, srcObject.getObjectContext());
            assertEquals(srcObject.getObjectId(), targetObject.getObjectId());
            assertSame(targetObject, target.getGraphManager().getNode(
                    targetObject.getObjectId()));
        }
    }

    public void testChannel() {
        MockDataChannel channel = new MockDataChannel();
        CayenneContext context = new CayenneContext(channel);

        assertSame(channel, context.getChannel());
    }

    public void testCommitUnchanged() {

        MockDataChannel channel = new MockDataChannel();
        CayenneContext context = new CayenneContext(channel);

        // no context changes so no connector access is expected
        context.commitChanges();
        assertTrue(channel.getRequestObjects().isEmpty());
    }

    public void testCommitCommandExecuted() {

        MockDataChannel channel = new MockDataChannel(new MockGraphDiff());
        channel.setEntityResolver(serverContext
                .getEntityResolver()
                .getClientEntityResolver());
        CayenneContext context = new CayenneContext(channel);

        // test that a command is being sent via connector on commit...

        context.internalGraphManager().nodePropertyChanged(
                new ObjectId("MtTable1"),
                "x",
                "y",
                "z");

        context.commitChanges();
        assertEquals(1, channel.getRequestObjects().size());

        // expect a sync/commit chain
        Object mainMessage = channel.getRequestObjects().iterator().next();
        assertTrue(mainMessage instanceof GraphDiff);
    }

    public void testCommitChangesNew() {
        final CompoundDiff diff = new CompoundDiff();
        final Object newObjectId = new ObjectId("test", "key", "generated");
        final EventManager eventManager = new DefaultEventManager(0);

        // test that ids that are passed back are actually propagated to the right
        // objects...

        MockDataChannel channel = new MockDataChannel() {

            @Override
            public GraphDiff onSync(
                    ObjectContext originatingContext,
                    GraphDiff changes,
                    int syncType) {

                return diff;
            }

            // must provide a channel with working event manager
            @Override
            public EventManager getEventManager() {
                return eventManager;
            }
        };

        CayenneContext context = new CayenneContext(channel);
        ObjEntity entity = new ObjEntity("test_entity");
        entity.setClassName(MockPersistentObject.class.getName());

        DataMap dataMap = new DataMap("test");
        dataMap.addObjEntity(entity);
        Collection<DataMap> entities = Collections.singleton(dataMap);
        context.setEntityResolver(new EntityResolver(entities));
        Persistent object = context.newObject(MockPersistentObject.class);

        // record change here to make it available to the anonymous connector method..
        diff.add(new NodeIdChangeOperation(object.getObjectId(), newObjectId));

        // check that a generated object ID is assigned back to the object...
        assertNotSame(newObjectId, object.getObjectId());
        context.commitChanges();
        assertSame(newObjectId, object.getObjectId());
        assertSame(object, context.graphManager.getNode(newObjectId));
    }

    public void testNewObject() {

        CayenneContext context = new CayenneContext(new MockDataChannel());

        ObjEntity entity = new ObjEntity("test_entity");
        entity.setClassName(MockPersistentObject.class.getName());

        DataMap dataMap = new DataMap("test");
        dataMap.addObjEntity(entity);
        Collection<DataMap> entities = Collections.singleton(dataMap);
        context.setEntityResolver(new EntityResolver(entities));

        Persistent object = context.newObject(MockPersistentObject.class);
        assertNotNull(object);
        assertTrue(object instanceof MockPersistentObject);
        assertEquals(PersistenceState.NEW, object.getPersistenceState());
        assertSame(context, object.getObjectContext());
        assertTrue(context
                .internalGraphManager()
                .dirtyNodes(PersistenceState.NEW)
                .contains(object));
        assertNotNull(object.getObjectId());
        assertTrue(object.getObjectId().isTemporary());
    }

    public void testDeleteObject() {

        CayenneContext context = new CayenneContext(new MockDataChannel());
        ObjEntity entity = new ObjEntity("test_entity");
        entity.setClassName(MockPersistentObject.class.getName());

        DataMap dataMap = new DataMap("test");
        dataMap.addObjEntity(entity);
        Collection<DataMap> entities = Collections.singleton(dataMap);
        context.setEntityResolver(new EntityResolver(entities));

        // TRANSIENT ... should quietly ignore it
        Persistent transientObject = new MockPersistentObject();
        context.deleteObject(transientObject);
        assertEquals(PersistenceState.TRANSIENT, transientObject.getPersistenceState());

        // NEW ... should make it TRANSIENT
        // create via context to make sure that object store would register it
        Persistent newObject = context.newObject(MockPersistentObject.class);
        assertNotNull(newObject.getObjectContext());
        context.deleteObject(newObject);
        assertNull(newObject.getObjectContext());
        assertEquals(PersistenceState.TRANSIENT, newObject.getPersistenceState());
        assertFalse(context.internalGraphManager().dirtyNodes().contains(
                newObject.getObjectId()));

        // see CAY-547 for details...
        assertFalse(context.internalGraphManager().dirtyNodes().contains(null));

        // COMMITTED
        Persistent committed = new MockPersistentObject();
        committed.setPersistenceState(PersistenceState.COMMITTED);
        committed.setObjectId(new ObjectId("test_entity", "key", "value1"));
        committed.setObjectContext(context);
        context.deleteObject(committed);
        assertEquals(PersistenceState.DELETED, committed.getPersistenceState());

        // MODIFIED
        Persistent modified = new MockPersistentObject();
        modified.setPersistenceState(PersistenceState.MODIFIED);
        modified.setObjectId(new ObjectId("test_entity", "key", "value2"));
        modified.setObjectContext(context);
        context.deleteObject(modified);
        assertEquals(PersistenceState.DELETED, modified.getPersistenceState());

        // DELETED
        Persistent deleted = new MockPersistentObject();
        deleted.setPersistenceState(PersistenceState.DELETED);
        deleted.setObjectId(new ObjectId("test_entity", "key", "value3"));
        deleted.setObjectContext(context);
        context.deleteObject(deleted);
        assertEquals(PersistenceState.DELETED, committed.getPersistenceState());
    }

    public void testBeforePropertyReadShouldInflateHollow() {

        ObjectId gid = new ObjectId("MtTable1", "a", "b");
        final ClientMtTable1 inflated = new ClientMtTable1();
        inflated.setPersistenceState(PersistenceState.COMMITTED);
        inflated.setObjectId(gid);
        inflated.setGlobalAttribute1("abc");

        ClientConnection connection = mock(ClientConnection.class);
        when(connection.sendMessage((ClientMessage) any())).thenAnswer(
                new Answer<Object>() {

                    public Object answer(InvocationOnMock invocation) {
                        ClientMessage arg = (ClientMessage) invocation.getArguments()[0];

                        if (arg instanceof BootstrapMessage) {
                            return new EntityResolver();
                        }
                        else {
                            return new GenericResponse(Arrays.asList(inflated));
                        }
                    }
                });

        ClientChannel channel = new ClientChannel(
                connection,
                false,
                new MockEventManager(),
                false);

        // check that a HOLLOW object is infalted on "beforePropertyRead"
        ClientMtTable1 hollow = new ClientMtTable1();
        hollow.setPersistenceState(PersistenceState.HOLLOW);
        hollow.setObjectId(gid);

        final boolean[] selectExecuted = new boolean[1];
        CayenneContext context = new CayenneContext(channel) {

            @Override
            public List<?> performQuery(Query query) {
                selectExecuted[0] = true;
                return super.performQuery(query);
            }
        };

        context.setEntityResolver(serverContext
                .getEntityResolver()
                .getClientEntityResolver());

        context.graphManager.registerNode(hollow.getObjectId(), hollow);

        // testing this...
        context
                .prepareForAccess(
                        hollow,
                        ClientMtTable1.GLOBAL_ATTRIBUTE1_PROPERTY,
                        false);
        assertTrue(selectExecuted[0]);
        assertSame(hollow, context.getGraphManager().getNode(gid));
        assertEquals(inflated.getGlobalAttribute1Direct(), hollow
                .getGlobalAttribute1Direct());
        assertEquals(PersistenceState.COMMITTED, hollow.getPersistenceState());
    }

    public void testBeforeHollowDeleteShouldChangeStateToCommited() {

        ObjectId gid = new ObjectId("MtTable1", "a", "b");
        final ClientMtTable1 inflated = new ClientMtTable1();
        inflated.setPersistenceState(PersistenceState.COMMITTED);
        inflated.setObjectId(gid);
        inflated.setGlobalAttribute1("abc");

        ClientConnection connection = mock(ClientConnection.class);
        when(connection.sendMessage((ClientMessage) any())).thenAnswer(
                new Answer<Object>() {

                    public Object answer(InvocationOnMock invocation) {
                        ClientMessage arg = (ClientMessage) invocation.getArguments()[0];

                        if (arg instanceof BootstrapMessage) {
                            return new EntityResolver();
                        }
                        else {
                            return new GenericResponse(Arrays.asList(inflated));
                        }
                    }
                });
        ClientChannel channel = new ClientChannel(
                connection,
                false,
                new MockEventManager(),
                false);

        CayenneContext context = new CayenneContext(channel);
        context.setEntityResolver(serverContext
                .getEntityResolver()
                .getClientEntityResolver());
        ClientMtTable1 hollow = (ClientMtTable1) context.localObject(gid, null);
        assertEquals(PersistenceState.HOLLOW, hollow.getPersistenceState());

        // testing this...
        context.deleteObject(hollow);
        assertSame(hollow, context.getGraphManager().getNode(gid));
        assertEquals(inflated.getGlobalAttribute1Direct(), hollow
                .getGlobalAttribute1Direct());
        assertEquals(PersistenceState.DELETED, hollow.getPersistenceState());
    }

}
TOP

Related Classes of org.apache.cayenne.CayenneContextTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.