package li.klass.fhem.domain.log; import com.google.api.client.repackaged.com.google.common.base.Predicate; import java.util.regex.Pattern; import li.klass.fhem.service.room.xmllist.XmlListDevice; public class ConcernsDevicePredicate implements Predicate<XmlListDevice> { private final Pattern concerningDeviceRegexp; private ConcernsDevicePredicate(String concerningDeviceRegexp) { this.concerningDeviceRegexp = Pattern.compile(concerningDeviceRegexp); } @Override public boolean apply(XmlListDevice xmlListDevice) { if (xmlListDevice == null) { return false; } String name = xmlListDevice.getName(); if (".".equals(name)) { name = ".*"; } return concerningDeviceRegexp.matcher(name).matches(); } public static ConcernsDevicePredicate forPattern(String regexpAttributeFromLogDevice) { return new ConcernsDevicePredicate(extractConcerningDeviceRegexpFromDefinition(regexpAttributeFromLogDevice)); } /** * We extract the device names from the current log regexp. As the regexp always concerns * device name and reading, we have to skip the reading. * <p/> * The default format is <i>deviceName:reading </i>, so we have to skip the reading part and * the colon. In addition, we have to make sure that we can still write regexp style expressions, * including OR expressions on different levels. * * @param definition regexp definition for the log device (including device events). * @return regexp definition for the log device names. */ static String extractConcerningDeviceRegexpFromDefinition(String definition) { definition = definition.replaceAll(":\\|", "\\|"); boolean isName = true; StringBuilder out = new StringBuilder(); boolean firstCharFound = false; int level = 0; int baseLevel = 0; for (int i = 0; i < definition.length(); i++) { char c = definition.charAt(i); if (c == '(' || c == ')') { if (c == '(') level++; if (c == ')') level--; } if (!firstCharFound && c != '(') { baseLevel = level; firstCharFound = true; } if (!firstCharFound || c == '(' || c == ')') continue; if (level <= baseLevel) { if (isName && c != '|' && c != ':') { out.append(c); continue; } if (c == ':' && isName) { isName = false; continue; } if (c == '|' && !isName) { isName = true; } if (c == '|') { out.append('|'); } } else if (isName) { out.append(c); } } String result = out.toString(); return result .replaceAll("\\.\\|", ".*|") .replaceAll("\\.$", ".*"); } }