/*
 * 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.sling.event;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.InputStream;
import java.util.Calendar;
import java.util.Properties;

import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.ValueFormatException;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.osgi.service.event.Event;

/**
 * Tests for the EventUtil utility methods.
 */
@RunWith(JMock.class)
public class EventUtilTest {

    protected Mockery context;

    public EventUtilTest() {
        this.context = new JUnit4Mockery();
    }

    @Test public void testDistributeFlag() {
        final Event distributableEvent = EventUtil.createDistributableEvent("some/topic", null);
        assertTrue(EventUtil.shouldDistribute(distributableEvent));
        final Event nonDistributableEvent = new Event("another/topic", null);
        assertFalse(EventUtil.shouldDistribute(nonDistributableEvent));
    }

    @Test public void testLocalFlag() {
        final Event localEvent = new Event("local/event", null);
        assertTrue(EventUtil.isLocal(localEvent));
        final Properties props = new Properties();
        props.put(EventUtil.PROPERTY_APPLICATION, "application1");
        final Event remoteEvent = new Event("remote/event", props);
        assertFalse(EventUtil.isLocal(remoteEvent));
    }

    @Test public void testGetNodePropertyValue() {
        final ValueFactory factory = this.context.mock(ValueFactory.class);
        this.context.checking(new Expectations() {{
            allowing(factory).createValue(true);
            will(returnValue(new ValueImpl(PropertyType.BOOLEAN)));
            allowing(factory).createValue(false);
            will(returnValue(new ValueImpl(PropertyType.BOOLEAN)));
            allowing(factory).createValue(with(any(Long.class)));
            will(returnValue(new ValueImpl(PropertyType.LONG)));
            allowing(factory).createValue(with(any(String.class)));
            will(returnValue(new ValueImpl(PropertyType.STRING)));
            allowing(factory).createValue(with(any(Calendar.class)));
            will(returnValue(new ValueImpl(PropertyType.DATE)));
        }});
        // boolean
        assertEquals(PropertyType.BOOLEAN, EventUtil.getNodePropertyValue(factory, true).getType());
        assertEquals(PropertyType.BOOLEAN, EventUtil.getNodePropertyValue(factory, false).getType());
        assertEquals(PropertyType.BOOLEAN, EventUtil.getNodePropertyValue(factory, Boolean.TRUE).getType());
        assertEquals(PropertyType.BOOLEAN, EventUtil.getNodePropertyValue(factory, Boolean.FALSE).getType());
        // long
        assertEquals(PropertyType.LONG, EventUtil.getNodePropertyValue(factory, (long)5).getType());
        // int = not possible
        assertEquals(null, EventUtil.getNodePropertyValue(factory, 5));
        // string
        assertEquals(PropertyType.STRING, EventUtil.getNodePropertyValue(factory, "something").getType());
        // calendar
        assertEquals(PropertyType.DATE, EventUtil.getNodePropertyValue(factory, Calendar.getInstance()).getType());
    }

    private final static class ValueImpl implements Value {

        private final int type;

        public ValueImpl(int type) {
            this.type = type;
        }

        public boolean getBoolean() throws ValueFormatException,
                IllegalStateException, RepositoryException {
            return false;
        }

        public Calendar getDate() throws ValueFormatException,
                IllegalStateException, RepositoryException {
            return null;
        }

        public double getDouble() throws ValueFormatException,
                IllegalStateException, RepositoryException {
            return 0;
        }

        public long getLong() throws ValueFormatException,
                IllegalStateException, RepositoryException {
            return 0;
        }

        public InputStream getStream() throws IllegalStateException,
                RepositoryException {
            return null;
        }

        public String getString() throws ValueFormatException,
                IllegalStateException, RepositoryException {
            return null;
        }

        public int getType() {
            return this.type;
        }
    }
}

@@ -971,36 +971,8 @@
 e;%0A%0A
-import java.io.InputStream;%0A
 impo
@@ -1059,46 +1059,8 @@
 pe;%0A
-import javax.jcr.RepositoryException;%0A
 impo
@@ -1113,47 +1113,8 @@
 ory;
-%0Aimport javax.jcr.ValueFormatException;
 %0A%0Aim
@@ -2333,32 +2333,290 @@
 Event));%0A    %7D%0A%0A
+    protected Value getValueOfType(final int type) %7B%0A        final Value v = this.context.mock(Value.class);%0A        this.context.checking(new Expectations() %7B%7B%0A            allowing(v).getType();will(returnValue(type));%0A        %7D%7D);%0A        return v;%0A    %7D%0A%0A
     @Test public
@@ -2852,37 +2852,38 @@
 returnValue(
-new 
+get
 Value
-Impl
+OfType
 (PropertyTyp
@@ -2971,37 +2971,38 @@
 returnValue(
-new 
+get
 Value
-Impl
+OfType
 (PropertyTyp
@@ -3106,37 +3106,38 @@
 returnValue(
-new 
+get
 Value
-Impl
+OfType
 (PropertyTyp
@@ -3240,37 +3240,38 @@
 returnValue(
-new 
+get
 Value
-Impl
+OfType
 (PropertyTyp
@@ -3386,21 +3386,22 @@
 lue(
-new 
+get
 Value
-Impl
+OfType
 (Pro
@@ -4362,1193 +4362,7 @@
    %7D
-%0A%0A    private final static class ValueImpl implements Value %7B%0A%0A        private final int type;%0A%0A        public ValueImpl(int type) %7B%0A            this.type = type;%0A        %7D%0A%0A        public boolean getBoolean() throws ValueFormatException,%0A                IllegalStateException, RepositoryException %7B%0A            return false;%0A        %7D%0A%0A        public Calendar getDate() throws ValueFormatException,%0A                IllegalStateException, RepositoryException %7B%0A            return null;%0A        %7D%0A%0A        public double getDouble() throws ValueFormatException,%0A                IllegalStateException, RepositoryException %7B%0A            return 0;%0A        %7D%0A%0A        public long getLong() throws ValueFormatException,%0A                IllegalStateException, RepositoryException %7B%0A            return 0;%0A        %7D%0A%0A        public InputStream getStream() throws IllegalStateException,%0A                RepositoryException %7B%0A            return null;%0A        %7D%0A%0A        public String getString() throws ValueFormatException,%0A                IllegalStateException, RepositoryException %7B%0A            return null;%0A        %7D%0A%0A        public int getType() %7B%0A            return this.type;%0A        %7D%0A    %7D
 %0A%7D%0A

Use mock for value implementation