io.devbench.uibuilder.data.common.datasource.CommonDataSourceReferenceHolder Maven / Gradle / Ivy
/*
*
* Copyright © 2018 Webvalto Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.devbench.uibuilder.data.common.datasource;
import com.vaadin.flow.component.Component;
import io.devbench.uibuilder.data.api.datasource.interfaces.DataSourceRefreshNotifiable;
import io.devbench.uibuilder.data.api.exceptions.DataSourceReferenceException;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class CommonDataSourceReferenceHolder {
private final Map> referringComponentsTypeMap;
@Getter
private DATA_SOURCE dataSource;
CommonDataSourceReferenceHolder(Component initialReference, DATA_SOURCE dataSource) {
this.dataSource = dataSource;
referringComponentsTypeMap = new ConcurrentHashMap<>();
referringComponentsTypeMap.put(createKey(initialReference), createWeakReferenceThenPrepareForCleanupFor(initialReference));
}
boolean containsReferences() {
return referringComponentsTypeMap.values().stream()
.anyMatch(componentWeakReference -> componentWeakReference.get() != null);
}
boolean canHoldReference(Component component) {
return !referringComponentsTypeMap.containsKey(createKey(component))
|| referringComponentsTypeMap.get(createKey(component)).get() == component;
}
void registerReference(Component component) {
if (canHoldReference(component)) {
if (referringComponentsTypeMap.containsKey(createKey(component))) {
return;
}
referringComponentsTypeMap.put(createKey(component), createWeakReferenceThenPrepareForCleanupFor(component));
} else {
throw new DataSourceReferenceException("Reference cannot be registered, because the holder already contains a reference with this class.");
}
}
boolean hasReferenceTo(Component component) {
return referringComponentsTypeMap.containsKey(createKey(component))
&& referringComponentsTypeMap.get(createKey(component)).get() == component;
}
void notifyReferencesAboutRefresh() {
referringComponentsTypeMap.values().stream()
.map(WeakReference::get)
.filter(DataSourceRefreshNotifiable.class::isInstance)
.map(DataSourceRefreshNotifiable.class::cast)
.forEach(DataSourceRefreshNotifiable::refresh);
}
private WeakReference createWeakReferenceThenPrepareForCleanupFor(Component component) {
WeakReference componentWeakReference = createWeakReferenceFor(component);
component.addDetachListener(event -> componentWeakReference.clear());
return componentWeakReference;
}
WeakReference createWeakReferenceFor(Component component) {
return new WeakReference<>(component);
}
@SuppressWarnings("unchecked")
void notifyReferencesAboutDataSourceChange(String dataSourceId, CommonDataSourceSelector selector) {
referringComponentsTypeMap.values().stream()
.map(WeakReference::get)
.filter(DataSourceChangeNotifiable.class::isInstance)
.map(DataSourceChangeNotifiable.class::cast)
.forEach(changeListener -> changeListener.dataSourceChanged(dataSourceId, selector, dataSource));
}
void setDataSource(DATA_SOURCE dataSource) {
this.dataSource = dataSource;
}
private ContextKey createKey(Component component) {
if (component instanceof SupportsDataSourceReuse) {
return new ContextKey(component.getClass(), ((SupportsDataSourceReuse) component).getContextId());
}
return new ContextKey(component.getClass(), "");
}
@Getter
@EqualsAndHashCode
@AllArgsConstructor
static class ContextKey {
private Class extends Component> clazz;
private String contextId;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy