/* (c) 2017 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.notification;
import java.util.HashMap;
import java.util.Map;
import net.opengis.wfs.TransactionResponseType;
import net.opengis.wfs.TransactionType;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CatalogInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.impl.ModificationProxy;
import org.geoserver.notification.common.Bounds;
import org.geoserver.notification.common.Notification;
import org.geoserver.wfs.TransactionEvent;
import org.geoserver.wfs.TransactionEventType;
import org.geoserver.wfs.WFSException;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.opengis.feature.type.FeatureType;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
public class NotificationTransactionListener extends NotificationListener implements
INotificationTransactionListener {
protected static final String INSERTED = "inserted";
protected static final String DELETED = "deleted";
protected static final String UPDATED = "updated";
protected static final String TYPE = "type";
protected static final String BOUNDS = "bounds";
private Catalog catalog;
private ThreadLocal<Map<String, Map<String, Object>>> layersChangesResume = new ThreadLocal<Map<String, Map<String, Object>>>();
public NotificationTransactionListener(Catalog catalog) {
super();
this.catalog = catalog;
}
@Override
public TransactionType beforeTransaction(TransactionType request) throws WFSException {
layersChangesResume = new ThreadLocal<Map<String, Map<String, Object>>>() {
@Override
protected Map<String, Map<String, Object>> initialValue() {
return new HashMap<String, Map<String, Object>>();
}
};
return null;
}
@Override
public void beforeCommit(TransactionType request) throws WFSException {
}
@Override
public void afterTransaction(TransactionType request, TransactionResponseType result,
boolean committed) {
if (committed) {
String handle = request.getHandle();
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String user = (auth != null) ? auth.getName() : null;
Map<String, Map<String, Object>> lcrs = layersChangesResume.get();
for (String layer : lcrs.keySet()) {
Map<String, Object> prop = lcrs.get(layer);
Object ft = prop.remove(TYPE);
Notification n = new NotificationImpl(Notification.Type.Data, handle, null, ft,
prop, user);
notify(n);
}
}
}
@Override
public int getPriority() {
return 0;
}
@Override
public void dataStoreChange(TransactionEvent event) throws WFSException {
TransactionEventType eventType = event.getType();
Integer affectedFeatures = event.getAffectedFeatures().size();
FeatureType featureType = event.getAffectedFeatures().getSchema();
ReferencedEnvelope featureBound = event.getAffectedFeatures().getBounds();
FeatureTypeInfo fti = this.catalog.getFeatureTypeByName(featureType.getName());
CatalogInfo info = ModificationProxy.unwrap(fti);
String featureTypeName = featureType.getName().getURI();
Map<String, Map<String, Object>> map = layersChangesResume.get();
Map<String, Object> properties = map.get(featureTypeName);
if (properties == null) {
properties = new HashMap<String, Object>();
properties.put(TYPE, info);
map.put(featureTypeName, properties);
}
if (eventType == TransactionEventType.POST_INSERT) {
Integer inserted = properties.get(INSERTED) != null ? (Integer) properties
.get(INSERTED) : 0;
properties.put(INSERTED, inserted + affectedFeatures);
}
if (eventType == TransactionEventType.POST_UPDATE) {
Integer inserted = properties.get(UPDATED) != null ? (Integer) properties.get(UPDATED)
: 0;
properties.put(UPDATED, inserted + affectedFeatures);
}
if (eventType == TransactionEventType.PRE_DELETE) {
Integer inserted = properties.get(DELETED) != null ? (Integer) properties.get(DELETED)
: 0;
properties.put(DELETED, inserted + affectedFeatures);
}
if (properties.get(BOUNDS) != null) {
featureBound.expandToInclude(((Bounds) properties.get(BOUNDS)).getBb());
}
properties.put(BOUNDS, new Bounds(featureBound));
}
@Override
public void setMessageMultiplexer(MessageMultiplexer messageMultiplexer) {
this.messageMultiplexer = messageMultiplexer;
}
@Override
public MessageMultiplexer getMessageMultiplexer() {
return messageMultiplexer;
}
}