/** * Copyright (c) 2014-2017 by the respective copyright holders. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.smarthome.core.transform; import java.util.Collection; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TransformationHelper { private final static Logger logger = LoggerFactory.getLogger(TransformationHelper.class); /* RegEx to extract and parse a function String <code>'(.*?)\((.*)\):(.*)'</code> */ protected static final Pattern EXTRACT_TRANSFORMFUNCTION_PATTERN = Pattern.compile("(.*?)\\((.*)\\):(.*)"); /** * determines whether a pattern refers to a transformation service * * @param pattern the pattern to check * @return true, if the pattern contains a transformation */ static public boolean isTransform(String pattern) { return EXTRACT_TRANSFORMFUNCTION_PATTERN.matcher(pattern).matches(); } /** * Queries the OSGi service registry for a service that provides a transformation service of * a given transformation type (e.g. REGEX, XSLT, etc.) * * @param transformationType the desired transformation type * @return a service instance or null, if none could be found */ static public TransformationService getTransformationService(BundleContext context, String transformationType) { if (context != null) { Logger logger = LoggerFactory.getLogger(TransformationHelper.class); String filter = "(smarthome.transform=" + transformationType + ")"; try { Collection<ServiceReference<TransformationService>> refs = context.getServiceReferences( TransformationService.class, filter); if (refs != null && refs.size() > 0) { return context.getService(refs.iterator().next()); } else { logger.warn("Cannot get service reference for transformation service of type " + transformationType); } } catch (InvalidSyntaxException e) { logger.warn("Cannot get service reference for transformation service of type " + transformationType, e); } } return null; } /** * Transforms a state string using transformation functions within a given pattern. * * @param context a valid bundle context, required for accessing the services * @param stateDescPattern the pattern that contains the transformation instructions * @param state the state to be formatted before being passed into the transformation function * @return the result of the transformation. If no transformation was done, the state is returned */ public static String transform(BundleContext context, String stateDescPattern, String state) { Matcher matcher = EXTRACT_TRANSFORMFUNCTION_PATTERN.matcher(stateDescPattern); if (matcher.find()) { String type = matcher.group(1); String pattern = matcher.group(2); String value = matcher.group(3); TransformationService transformation = TransformationHelper.getTransformationService(context, type); if (transformation != null) { value = String.format(value, state); try { pattern = transformation.transform(pattern, value); } catch (TransformationException e) { logger.warn("transformation throws exception [transformation=" + transformation + ", value=" + value + "]", e); pattern = state; } } else { logger.warn( "couldn't transform value because transformationService of type '{}' is unavailable", type); pattern = state; } return pattern; } else { return state; } } }