/* * Copyright 2014 Red Hat, Inc. and/or its affiliates. * * 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 org.dashbuilder.dataset; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.ArrayList; import java.util.Map; import java.util.Set; import org.dashbuilder.dataprovider.DataSetProvider; import org.dashbuilder.dataprovider.DataSetProviderRegistry; import org.dashbuilder.dataprovider.DataSetProviderType; import org.dashbuilder.dataset.def.DataSetDefRegistryListener; import org.dashbuilder.dataset.def.DataSetPreprocessor; import org.dashbuilder.dataset.date.TimeAmount; import org.dashbuilder.dataset.def.DataSetDef; import org.dashbuilder.dataset.def.DataSetDefRegistry; import org.dashbuilder.scheduler.Scheduler; import org.dashbuilder.scheduler.SchedulerTask; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Data set definitions registry */ public class DataSetDefRegistryImpl implements DataSetDefRegistry { protected Logger log = LoggerFactory.getLogger(DataSetDefRegistryImpl.class); protected DataSetProviderRegistry dataSetProviderRegistry; protected Scheduler scheduler; protected Map<String, DataSetDefEntry> dataSetDefMap = new HashMap<>(); protected Set<DataSetDefRegistryListener> listenerSet = new HashSet<>(); public DataSetDefRegistryImpl() { } public DataSetDefRegistryImpl(DataSetProviderRegistry dataSetProviderRegistry, Scheduler scheduler) { this.dataSetProviderRegistry = dataSetProviderRegistry; this.scheduler = scheduler; if (scheduler == null) { log.warn("No scheduler set. Data set refresh features are disabled."); } } public DataSetProviderRegistry getDataSetProviderRegistry() { return dataSetProviderRegistry; } public void setDataSetProviderRegistry(DataSetProviderRegistry dataSetProviderRegistry) { this.dataSetProviderRegistry = dataSetProviderRegistry; } public Scheduler getScheduler() { return scheduler; } public void setScheduler(Scheduler scheduler) { this.scheduler = scheduler; } protected class DataSetDefEntry extends SchedulerTask { DataSetDef def; long lastRefreshTime; long refreshInMillis; List<DataSetPreprocessor> preprocessors; public DataSetDefEntry(DataSetDef def) { this.def = def; this.lastRefreshTime = System.currentTimeMillis(); this.refreshInMillis = -1; if (def.getRefreshTime() != null && def.getRefreshTime().trim().length() > 0) { TimeAmount tf = TimeAmount.parse(def.getRefreshTime()); this.refreshInMillis = tf.toMillis(); } } public void registerDataSetPreprocessor(DataSetPreprocessor preprocessor) { if (preprocessors == null) { preprocessors = new ArrayList<>(); } preprocessors.add(preprocessor); } public List<DataSetPreprocessor> getDataSetPreprocessors() { return preprocessors; } public void schedule() { if (refreshInMillis != -1 && scheduler != null) { scheduler.schedule(this, refreshInMillis / 1000); } } public void unschedule() { if (scheduler != null) { scheduler.unschedule(getKey()); } } public boolean isStale() { if (refreshInMillis == -1) { return false; } if (!def.isRefreshAlways()) { DataSetProvider provider = resolveProvider(def); return provider.isDataSetOutdated(def); } return System.currentTimeMillis() >= lastRefreshTime + refreshInMillis; } public void stale() { lastRefreshTime = System.currentTimeMillis(); onDataSetDefStale(def); } @Override public String getDescription() { return "DataSetDef refresh task " + def.getUUID(); } @Override public String getKey() { return def.getUUID(); } @Override public void execute() { if (isStale()) { stale(); } } } protected DataSetProvider resolveProvider(DataSetDef dataSetDef) { DataSetProviderType type = dataSetDef.getProvider(); if (type != null) { DataSetProvider dataSetProvider = dataSetProviderRegistry.getDataSetProvider(type); if (dataSetProvider != null) return dataSetProvider; } throw new IllegalStateException("DataSetProvider not found: " + dataSetDef.getProvider()); } public synchronized List<DataSetDef> getDataSetDefs(boolean onlyPublic) { List<DataSetDef> results = new ArrayList<>(); for (DataSetDefEntry r : dataSetDefMap.values()) { if (!onlyPublic || r.def.isPublic()) { results.add(r.def); } } return results; } public synchronized DataSetDef getDataSetDef(String uuid) { DataSetDefEntry record = dataSetDefMap.get(uuid); if (record == null) return null; return record.def; } public synchronized void registerPreprocessor(String uuid, DataSetPreprocessor preprocessor) { DataSetDefEntry record = dataSetDefMap.get(uuid); if (record == null) { throw new IllegalStateException("DataSetDef not found: " + uuid); } record.registerDataSetPreprocessor(preprocessor); } public synchronized List<DataSetPreprocessor> getDataSetDefPreProcessors(String uuid) { DataSetDefEntry record = dataSetDefMap.get(uuid); if (record == null) { return null; } return record.getDataSetPreprocessors(); } public synchronized void registerDataSetDef(DataSetDef newDef) { registerDataSetDef(newDef, "system", "register(" + newDef.getUUID() + ")"); } public synchronized DataSetDef removeDataSetDef(String uuid) { return removeDataSetDef(uuid, "system", "remove(" + uuid + ")"); } public synchronized void registerDataSetDef(DataSetDef newDef, String subjectId, String message) { // Register the new entry DataSetDefEntry oldEntry = _removeDataSetDef(newDef.getUUID()); dataSetDefMap.put(newDef.getUUID(), new DataSetDefEntry(newDef)); DataSetDefEntry newEntry = dataSetDefMap.get(newDef.getUUID()); // Notify the proper event if (oldEntry != null) { onDataSetDefModified(oldEntry.def, newDef); } else { onDataSetDefRegistered(newDef); } // Register the data set into the scheduler newEntry.schedule(); } public synchronized DataSetDef removeDataSetDef(String uuid, String subjectId, String message) { DataSetDefEntry oldEntry = _removeDataSetDef(uuid); if (oldEntry == null) { return null; } // Notify about the removal onDataSetDefRemoved(oldEntry.def); return oldEntry.def; } protected DataSetDefEntry _removeDataSetDef(String uuid) { DataSetDefEntry oldEntry = dataSetDefMap.remove(uuid); if (oldEntry == null) { return null; } // Remove from the scheduler oldEntry.unschedule(); // Make any data set reference stale oldEntry.stale(); return oldEntry; } @Override public void addListener(DataSetDefRegistryListener listener) { listenerSet.add(listener); } public Set<DataSetDefRegistryListener> getListeners() { return listenerSet; } protected void onDataSetDefStale(DataSetDef def) { for (DataSetDefRegistryListener listener : listenerSet) { listener.onDataSetDefStale(def); } } protected void onDataSetDefModified(DataSetDef olDef, DataSetDef newDef) { for (DataSetDefRegistryListener listener : listenerSet) { listener.onDataSetDefModified(olDef, newDef); } } protected void onDataSetDefRegistered(DataSetDef newDef) { for (DataSetDefRegistryListener listener : listenerSet) { listener.onDataSetDefRegistered(newDef); } } protected void onDataSetDefRemoved(DataSetDef oldDef) { for (DataSetDefRegistryListener listener : listenerSet) { listener.onDataSetDefRemoved(oldDef); } } }