/*
* Copyright 2004-2009 the original author or authors.
*
* 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.compass.needle.gigaspaces.datasource;
import java.util.List;
import java.util.Properties;
import com.gigaspaces.datasource.BulkDataPersister;
import com.gigaspaces.datasource.BulkItem;
import com.gigaspaces.datasource.DataIterator;
import com.gigaspaces.datasource.DataPersister;
import com.gigaspaces.datasource.DataSourceException;
import org.compass.core.Compass;
import org.compass.core.CompassCallbackWithoutResult;
import org.compass.core.CompassException;
import org.compass.core.CompassSession;
import org.compass.core.CompassTemplate;
import org.compass.core.config.CompassConfigurationFactory;
import org.compass.core.spi.InternalCompass;
/**
* A Compass data source to be used with GigaSpaces mirror.
*
* <p>GigaSpaces mirror allows to mirror changes done to the Space into an external data source
* in a reliable async manner. The Compass data source allows to mirror changes done to the
* Space into the search engine using Compass.
*
* <p>This extenal data source can be injected with a {@link Compass} instance, or it can be
* configured using the extenal data source proeprties configuration to create a Compass instance.
* The proeprty <code>compass-config-file</code> will point to Compass configuration file.
*
* @author kimchy
*/
public class CompassDataSource implements DataPersister<Object>, BulkDataPersister {
public static final String COMPASS_CFG_PROPERTY = "compass-config-file";
private Compass compass;
private CompassTemplate compassTemplate;
public void setCompass(Compass compass) {
this.compass = compass;
}
public void init(Properties properties) throws DataSourceException {
if (compass == null) {
String compassConfig = properties.getProperty(COMPASS_CFG_PROPERTY);
compass = CompassConfigurationFactory.newConfiguration().configure(compassConfig).buildCompass();
}
compassTemplate = new CompassTemplate(compass);
}
public void shutdown() throws DataSourceException {
if (compass != null) {
compass.close();
compass = null;
}
}
/**
* Write given new object to the data store
*/
public void write(Object object) throws DataSourceException {
if (hasMapping(object)) {
compassTemplate.save(object);
}
}
/**
* Update the given object in the data store
*/
public void update(Object object) throws DataSourceException {
if (hasMapping(object)) {
compassTemplate.save(object);
}
}
/**
* Remove the given object from the data store
*/
public void remove(Object object) throws DataSourceException {
if (hasMapping(object)) {
compassTemplate.delete(object);
}
}
/**
* Write given new objects to the data store.
*
* <p>If the implementation uses transactions, all the objects must be written
* in one transaction.
*/
public void writeBatch(final List<Object> objects) throws DataSourceException {
compassTemplate.execute(new CompassCallbackWithoutResult() {
protected void doInCompassWithoutResult(CompassSession session) throws CompassException {
for (Object object : objects) {
if (hasMapping(object)) {
session.save(object);
}
}
}
});
}
/**
* Update given objects in the data store.
*
* <p>If the implementation uses transactions, all the objects must be updated
* in one transaction.
*
* <p>* This operation is not currently supported by the space.
*/
public void updateBatch(final List<Object> objects) throws DataSourceException {
compassTemplate.execute(new CompassCallbackWithoutResult() {
protected void doInCompassWithoutResult(CompassSession session) throws CompassException {
for (Object object : objects) {
if (hasMapping(object)) {
session.save(object);
}
}
}
});
}
/**
* Remove given objects from the data store.
*
* <p>If the implementation uses transactions, All the objects must be removed
* in one transaction.
*
* <p>This operation is not currently supported by the space.<br>
*/
public void removeBatch(final List<Object> objects) throws DataSourceException {
compassTemplate.execute(new CompassCallbackWithoutResult() {
protected void doInCompassWithoutResult(CompassSession session) throws CompassException {
for (Object object : objects) {
if (hasMapping(object)) {
session.delete(object);
}
}
}
});
}
/**
* Execute given bulk of operations. Each {@link BulkItem} contains one of
* the following operation -<br>
*
* <p>
* WRITE - given object should be inserted to the data store,<br>
* UPDATE - given object should be updated in the data store,<br>
* REMOVE - given object should be deleted from the data store<br>
* <br>
* If the implementation uses transactions,<br>
* all the bulk operations must be executed in one transaction.<br>
*/
public void executeBulk(final List<BulkItem> bulkItems) throws DataSourceException {
compassTemplate.execute(new CompassCallbackWithoutResult() {
protected void doInCompassWithoutResult(CompassSession session) throws CompassException {
for (BulkItem bulkItem : bulkItems) {
switch (bulkItem.getOperation()) {
case BulkItem.REMOVE:
if (hasMapping(bulkItem.getItem())) {
session.delete(bulkItem.getItem());
}
break;
case BulkItem.WRITE:
if (hasMapping(bulkItem.getItem())) {
session.save(bulkItem.getItem());
}
break;
case BulkItem.UPDATE:
if (hasMapping(bulkItem.getItem())) {
session.save(bulkItem.getItem());
}
break;
default:
break;
}
}
}
});
}
/**
* Read one object that matches the given template. <br>
* Used by the space for read templates with UID.<br>
*/
public Object read(Object template) throws DataSourceException {
throw new UnsupportedOperationException();
}
/**
* Create an iterator over all objects that match the given template.<br>
* Note: null value can be passed - in case of a null template or at initial
* space load
*/
public DataIterator<Object> iterator(Object template) throws DataSourceException {
throw new UnsupportedOperationException();
}
/**
* Count number of object in the data source that match given template.<br>
* Note: null value can be passed - in case of a null template.
*/
public int count(Object template) throws DataSourceException {
throw new UnsupportedOperationException();
}
/**
* Creates and returns an iterator over all the entries that should be
* loaded into space.
*
* @return a {@link DataIterator} or null if no data should be loaded into
* space
* @throws DataSourceException
*/
public DataIterator<Object> initialLoad() throws DataSourceException {
throw new UnsupportedOperationException();
}
private boolean hasMapping(Object object) {
return ((InternalCompass) compass).getMapping().getRootMappingByClass(object.getClass()) != null;
}
}