/* * 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.service.room; import android.content.Context; import android.content.Intent; import android.support.annotation.NonNull; import com.google.common.base.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.inject.Singleton; import li.klass.fhem.constants.Actions; import li.klass.fhem.domain.core.RoomDeviceList; import li.klass.fhem.service.Command; import li.klass.fhem.service.CommandExecutionService; import static li.klass.fhem.constants.BundleExtraKeys.DO_REFRESH; @Singleton public class RoomListUpdateService { private static final Logger LOG = LoggerFactory.getLogger(RoomListUpdateService.class); @Inject CommandExecutionService commandExecutionService; @Inject DeviceListParser deviceListParser; @Inject RoomListHolderService roomListHolderService; @Inject public RoomListUpdateService() { } public void updateSingleDevice(String deviceName, int delay, Optional<String> connectionId, Context context, RoomListUpdateListener roomListUpdateListener) { executeXmllistPartial(delay, connectionId, context, roomListUpdateListener, deviceName); } public void updateRoom(String roomName, Optional<String> connectionId, Context context, RoomListUpdateListener roomListUpdateListener) { executeXmllistPartial(0, connectionId, context, roomListUpdateListener, "room=" + roomName); } public void updateAllDevices(Optional<String> connectionId, Context context, RoomListUpdateListener roomListUpdateListener) { executeXmllist(0, connectionId, context, roomListUpdateListener, "", new UpdateHandler() { @Override public RoomDeviceList handle(RoomDeviceList cached, RoomDeviceList parsed) { return parsed; } }); } private boolean update(Context context, Optional<String> connectionId, Optional<RoomDeviceList> result) { boolean success = false; if (result.isPresent()) { success = roomListHolderService.storeDeviceListMap(result.get(), connectionId, context); if (success) LOG.info("update - update was successful, sending result"); } else { LOG.info("update - update was not successful, sending empty device list"); } return success; } private void executeXmllistPartial(int delay, Optional<String> connectionId, final Context context, RoomListUpdateListener updateListener, String devSpec) { LOG.info("executeXmllist(devSpec={}) - fetching xmllist from remote", devSpec); executeXmllist(delay, connectionId, context, updateListener, " " + devSpec, new UpdateHandler() { @Override public RoomDeviceList handle(RoomDeviceList cached, RoomDeviceList parsed) { cached.addAllDevicesOf(parsed, context); return cached; } }); } private void executeXmllist(final int delay, final Optional<String> connectionId, final Context context, final RoomListUpdateListener updateListener, String xmllistSuffix, final UpdateHandler updateHandler) { Command command = new Command("xmllist" + xmllistSuffix, connectionId); commandExecutionService.executeSafely(command, delay, context, new CommandExecutionService.ResultListener() { @Override public void onResult(String result) { Optional<RoomDeviceList> roomDeviceList = parseResult(connectionId, context, result, updateHandler); boolean success = update(context, connectionId, roomDeviceList); updateListener.onUpdateFinished(success); if (delay > 0) { context.sendBroadcast(new Intent(Actions.DO_UPDATE).putExtra(DO_REFRESH, false)); } } @Override public void onError() { updateListener.onUpdateFinished(false); } }); } @NonNull private Optional<RoomDeviceList> parseResult(Optional<String> connectionId, Context context, String result, UpdateHandler updateHandler) { Optional<RoomDeviceList> parsed = Optional.fromNullable(deviceListParser.parseAndWrapExceptions(result, context)); Optional<RoomDeviceList> cached = roomListHolderService.getCachedRoomDeviceListMap(connectionId, context); if (parsed.isPresent()) { RoomDeviceList newDeviceList = updateHandler.handle(cached.or(parsed.get()), parsed.get()); roomListHolderService.storeDeviceListMap(newDeviceList, connectionId, context); return Optional.of(newDeviceList); } return Optional.absent(); } public interface RoomListUpdateListener { void onUpdateFinished(boolean result); } private interface UpdateHandler { RoomDeviceList handle(RoomDeviceList cached, RoomDeviceList parsed); } }