Optimized implementation of VirtualPropertyReplacer.

Added auto configuration for VirtualPropertyResolver.

Signed-off-by: Dominik Herbst <dominik.herbst@bosch-si.com>
This commit is contained in:
Dominik Herbst
2016-09-28 13:54:54 +02:00
parent 9265f17e19
commit b1d9930d94
18 changed files with 106 additions and 76 deletions

View File

@@ -0,0 +1,55 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* 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.hawkbit.repository.jpa;
import java.time.Duration;
import java.time.Instant;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
/**
* Calculates non-persistent timestamps , e.g. the point a time a
* target is declared as overdue.<br>
* Therefore tenant specific configuration may be considered.
*
*/
public class TimestampCalculator {
/**
* Calculates the overdue timestamp (<em>overdue_ts</em>) based on the
* current timestamp and the intervals for polling and poll-overdue:
* <p>
* <em>overdue_ts = now_ts - pollingInterval -
* pollingOverdueInterval</em>;<br>
* <em>pollingInterval</em> and <em>pollingOverdueInterval</em> are
* retrieved from tenant-specific system configuration.
*
* @return <em>overdue_ts</em> in milliseconds since Unix epoch as long
* value
*/
public long calculateOverdueTimestamp() {
return Instant.now().toEpochMilli() - getDurationForKey(TenantConfigurationKey.POLLING_TIME_INTERVAL).toMillis()
- getDurationForKey(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL).toMillis();
}
private Duration getDurationForKey(TenantConfigurationKey key) {
return DurationHelper.formattedStringToDuration(getRawStringForKey(key));
}
private String getRawStringForKey(TenantConfigurationKey key) {
return getTenantConfigurationManagement().getConfigurationValue(key, String.class).getValue();
}
protected TenantConfigurationManagement getTenantConfigurationManagement() {
return TenantConfigurationManagementHolder.getInstance().getTenantConfigurationManagement();
}
}

View File

@@ -0,0 +1,44 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* 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.hawkbit.repository.jpa.model.helper;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.springframework.beans.factory.annotation.Autowired;
/**
* A singleton bean which holds {@link TenantConfigurationManagement} service
* and makes it accessible to beans which are not managed by spring, e.g. JPA
* entities.
*/
public final class TenantConfigurationManagementHolder {
private static final TenantConfigurationManagementHolder INSTANCE = new TenantConfigurationManagementHolder();
@Autowired
private TenantConfigurationManagement tenantConfiguration;
private TenantConfigurationManagementHolder() {
}
/**
* @return the singleton {@link TenantConfigurationManagementHolder}
* instance
*/
public static TenantConfigurationManagementHolder getInstance() {
return INSTANCE;
}
/**
* @return the {@link TenantConfigurationManagement} service
*/
public TenantConfigurationManagement getTenantConfigurationManagement() {
return tenantConfiguration;
}
}

View File

@@ -0,0 +1,74 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* 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.hawkbit.repository.jpa.rsql;
import java.time.Instant;
import org.apache.commons.lang3.text.StrLookup;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.eclipse.hawkbit.repository.jpa.TimestampCalculator;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
/**
* Adds macro capabilities to RSQL expressions that are used to filter for
* targets.
* <p>
* Some (virtual) properties do not have a representation in the database (in
* general these properties are time-related, or more explicitly, they deal with
* time intervals).<br>
* Such a virtual property needs to be calculated on Java-side before it may be
* used in a target filter query that is passed to the database. Therefore a
* placeholder is used in the RSQL expression that is expanded when the RSQL is
* parsed
* <p>
* A virtual property may either be a system value like the current date (aka
* <em>now_ts</em>) or a value derived from (tenant-specific) system
* configuration (e.g. <em>overdue_ts</em>).
* <p>
* Known values are:<br>
* <ul>
* <li><em>now_ts</em>: maps to system UTC time in milliseconds since Unix epoch
* as long value</li>
* <li><em>overdue_ts</em>: is a calculated value: <em>overdue_ts = now_ts -
* pollingInterval - pollingOverdueInterval</em>; pollingInterval and
* pollingOverdueInterval are retrieved from tenant-specific system
* configuration.</li>
* </ul>
*/
public class VirtualPropertyResolver extends StrLookup<String> implements VirtualPropertyReplacer {
private final TimestampCalculator timestampCalculator = new TimestampCalculator();
private StrSubstitutor substitutor;
@Override
public String lookup(String rhs) {
String resolved = null;
if ("now_ts".equalsIgnoreCase(rhs)) {
resolved = String.valueOf(Instant.now().toEpochMilli());
} else if ("overdue_ts".equalsIgnoreCase(rhs)) {
resolved = String.valueOf(getTimestampCalculator().calculateOverdueTimestamp());
}
return resolved;
}
@Override
public String replace(String input) {
if (substitutor == null) {
substitutor = new StrSubstitutor(this, StrSubstitutor.DEFAULT_PREFIX, StrSubstitutor.DEFAULT_SUFFIX,
StrSubstitutor.DEFAULT_ESCAPE);
}
return substitutor.replace(input);
}
TimestampCalculator getTimestampCalculator() {
return timestampCalculator;
}
}