/*****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.cayenne.pref;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.access.DataContext;
import org.apache.cayenne.access.DataDomain;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.DbGenerator;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DataMap;
/**
* A Cayenne-based PreferenceService.
*
* @author Andrei Adamchik
*/
public abstract class CayennePreferenceService implements PreferenceService {
public static final int MIN_SAVE_INTERVAL = 500;
public static final int DEFAULT_SAVE_INTERVAL = 20000;
public static final String SAVE_INTERVAL_KEY = "saveInterval";
protected int saveInterval = DEFAULT_SAVE_INTERVAL;
protected Timer saveTimer;
protected DataContext dataContext;
protected String defaultDomain;
public CayennePreferenceService(String defaultDomain) {
this.defaultDomain = defaultDomain;
}
public DataContext getDataContext() {
return dataContext;
}
public void setDataContext(DataContext preferencesContext) {
this.dataContext = preferencesContext;
}
public int getSaveInterval() {
return saveInterval;
}
public void setSaveInterval(int ms) {
if (this.saveInterval != ms) {
this.saveInterval = ms;
// save to preferences
getPreferenceDomain()
.getDetail(SAVE_INTERVAL_KEY, true)
.setIntProperty(SAVE_INTERVAL_KEY, ms);
}
}
/**
* Returns a top-level domain.
*/
public Domain getDomain(String name, boolean create) {
List results = getDataContext().performQuery(
"TopLevelDomain",
Collections.singletonMap("name", name),
false);
if (results.size() > 1) {
throw new CayenneRuntimeException("Found "
+ results.size()
+ " Domain objects for name '"
+ name
+ "', only one expected.");
}
if (results.size() == 1) {
return (Domain) results.get(0);
}
if (!create) {
return null;
}
Domain domain = (Domain) getDataContext()
.createAndRegisterNewObject(Domain.class);
domain.setLevel(new Integer(0));
domain.setName(name);
savePreferences();
return domain;
}
/**
* Configures service to run stopService on JVM shutdown.
*/
public void stopOnShutdown() {
Thread shutdown = new Thread("CayennePrefrencesService Shutdown") {
public void run() {
stopService();
}
};
Runtime.getRuntime().addShutdownHook(shutdown);
}
public void savePreferences() {
DataContext context = this.dataContext;
if (context != null) {
context.commitChanges();
}
}
protected Domain getPreferenceDomain() {
Domain defaultDomain = getDomain(this.defaultDomain, true);
return defaultDomain.getSubdomain(getClass());
}
/**
* Initializes service own prefrences.
*/
protected void initPreferences() {
Domain preferenceDomain = getPreferenceDomain();
PreferenceDetail saveInterval = preferenceDomain.getDetail(
SAVE_INTERVAL_KEY,
false);
if (saveInterval != null) {
setSaveInterval(saveInterval.getIntProperty(
SAVE_INTERVAL_KEY,
DEFAULT_SAVE_INTERVAL));
}
}
/**
* Helper method that provides an easy way for subclasses to create preferences schema
* on the fly.
*/
protected void initSchema() {
DataDomain domain = dataContext.getParentDataDomain();
Iterator maps = domain.getDataMaps().iterator();
while (maps.hasNext()) {
DataMap map = (DataMap) maps.next();
DataNode node = domain.lookupDataNode(map);
DbAdapter adapter = node.getAdapter();
DbGenerator generator = new DbGenerator(adapter, map);
try {
generator.runGenerator(node.getDataSource());
}
catch (Throwable th) {
throw new PreferenceException("Error creating preferences DB", th);
}
}
}
/**
* Starts preferences save timer.
*/
protected void startTimer() {
TimerTask saveTask = new TimerTask() {
public void run() {
savePreferences();
}
};
int interval = (saveInterval > MIN_SAVE_INTERVAL)
? saveInterval
: MIN_SAVE_INTERVAL;
saveTimer = new Timer(true);
saveTimer.schedule(saveTask, interval, interval);
}
}