li.klass.fhem.domain.core.DeviceXMLParsingBase.java Source code

Java tutorial

Introduction

Here is the source code for li.klass.fhem.domain.core.DeviceXMLParsingBase.java

Source

/*
 * AndFHEM - Open Source Android application to control a FHEM home automation
 * server.
 *
 * Copyright (c) 2011, Matthias Klass or third-party contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.  All third-party contributions are
 * distributed under license by Red Hat Inc.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU GENERAL PUBLIC LICENSE, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU GENERAL PUBLIC LICENSE
 * for more details.
 *
 * You should have received a copy of the GNU GENERAL PUBLIC LICENSE
 * along with this distribution; if not, write to:
 *   Free Software Foundation, Inc.
 *   51 Franklin Street, Fifth Floor
 *   Boston, MA  02110-1301  USA
 */

package li.klass.fhem.domain.core;

import android.content.Context;

import com.google.common.base.Charsets;
import com.google.common.collect.Maps;
import com.google.common.io.CharStreams;
import com.google.common.io.Resources;

import org.junit.Before;
import org.junit.Rule;
import org.junit.experimental.categories.Category;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import dagger.ObjectGraph;
import li.klass.fhem.AndFHEMApplication;
import li.klass.fhem.R;
import li.klass.fhem.service.DeviceConfigurationProvider;
import li.klass.fhem.service.connection.ConnectionService;
import li.klass.fhem.service.graph.gplot.GPlotHolder;
import li.klass.fhem.service.room.DeviceListParser;
import li.klass.fhem.service.room.xmllist.DeviceNode;
import li.klass.fhem.service.room.xmllist.XmlListParser;
import li.klass.fhem.testsuite.category.DeviceTestBase;
import li.klass.fhem.testutil.MockitoRule;
import li.klass.fhem.util.CloseableUtil;

import static li.klass.fhem.util.ReflectionUtil.setFieldValue;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;

@Category(DeviceTestBase.class)
public abstract class DeviceXMLParsingBase {

    public static final String DEFAULT_TEST_ROOM_NAME = "room";
    public static final String DEFAULT_TEST_DEVICE_NAME = "device";

    protected RoomDeviceList roomDeviceList;

    @Mock
    protected ConnectionService connectionService;

    @InjectMocks
    protected DeviceListParser deviceListParser;

    @Rule
    public MockitoRule mockitoRule = new MockitoRule();

    @Mock
    protected Context context;

    @Before
    public void before() throws Exception {
        AndFHEMApplication.setContext(context);

        ObjectGraph graph = AndFHEMApplication.createDaggerGraph();
        setFieldValue(deviceListParser, "parser", graph.get(XmlListParser.class));
        setFieldValue(deviceListParser, "gPlotHolder", graph.get(GPlotHolder.class));
        setFieldValue(deviceListParser, "deviceConfigurationProvider",
                graph.get(DeviceConfigurationProvider.class));

        mockStrings();

        doReturn(true).when(connectionService).mayShowInCurrentConnectionType(any(DeviceType.class), eq(context));

        InputStream inputStream = null;
        InputStreamReader inputStreamReader = null;
        try {

            inputStream = getTestFileBaseClass().getResourceAsStream(getFileName());

            if (inputStream == null) {
                throw new IllegalArgumentException("cannot find " + getFileName());
            }

            inputStreamReader = new InputStreamReader(inputStream, Charsets.UTF_8);
            String content = CharStreams.toString(inputStreamReader);

            roomDeviceList = deviceListParser.parseXMLListUnsafe(content, context);
        } finally {
            CloseableUtil.close(inputStream, inputStreamReader);
        }
    }

    protected void mockStrings() {
        try {
            String content = Resources.toString(
                    new File("src/main/res/values/strings.xml").getAbsoluteFile().toURI().toURL(), Charsets.UTF_8);
            Pattern pattern = Pattern.compile("<string name=\"([^\"]+)\">([^<]+)</string>");
            Matcher matcher = pattern.matcher(content);

            Map<String, String> values = Maps.newHashMap();
            while (matcher.find()) {
                values.put(matcher.group(1), matcher.group(2));
            }

            for (Field field : R.string.class.getDeclaredFields()) {
                int value = (int) field.get(R.string.class);
                given(context.getString(value)).willReturn(values.get(field.getName()));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Base class used as context for loading the input file.
     *
     * @return base class
     */
    protected Class<?> getTestFileBaseClass() {
        return getClass();
    }

    protected abstract String getFileName();

    protected <T extends FhemDevice<T>> T getDefaultDevice(Class<T> clazz) {
        return getDeviceFor(DEFAULT_TEST_DEVICE_NAME, clazz);
    }

    // Careful: The Java-Compiler needs some class instance of <T> here to infer the type correctly!
    protected <T extends FhemDevice<T>> T getDeviceFor(String deviceName,
            @SuppressWarnings("unused") Class<T> clazz) {
        return roomDeviceList.getDeviceFor(deviceName);
    }

    protected String stateValueFor(Device device, String key) {
        return xmllistValueFor(key, device.getXmlListDevice().getStates());
    }

    protected String attributeValueFor(Device device, String key) {
        return xmllistValueFor(key, device.getXmlListDevice().getAttributes());
    }

    private String xmllistValueFor(String key, Map<String, DeviceNode> map) {
        DeviceNode deviceNode = map.get(key);
        if (deviceNode == null)
            return null;
        return deviceNode.getValue();
    }
}