/*
* Copyright 2013 JBoss Inc
*
* 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.overlord.rtgov.analytics.situation.store.jpa;
import java.net.URL;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Singleton;
import org.hibernate.Query;
import org.hibernate.Session;
import org.overlord.rtgov.analytics.situation.Situation;
import org.overlord.rtgov.analytics.situation.store.SituationStore;
import org.overlord.rtgov.analytics.situation.store.SituationsQuery;
import org.overlord.rtgov.analytics.situation.store.AbstractSituationStore;
import org.overlord.rtgov.analytics.situation.store.ResolutionState;
import org.overlord.rtgov.common.jpa.JpaStore;
import org.overlord.rtgov.common.jpa.JpaStore.JpaWork;
/**
* This class provides the JPA based implementation of the SituationsStore
* interface.
*
*/
@Singleton
public class JPASituationStore extends AbstractSituationStore implements SituationStore {
private static final int PROPERTY_VALUE_MAX_LENGTH = 250;
private static final Logger LOG = Logger.getLogger(JPASituationStore.class.getName());
private static final String JNDI_PROPERTY = "JPASituationStore.jndi.datasource";
private final JpaStore _jpaStore;
/**
* Constructor.
*/
public JPASituationStore() {
final URL configXml = this.getClass().getClassLoader().getResource("situationstore.hibernate.cfg.xml");
_jpaStore = new JpaStore(configXml, JNDI_PROPERTY);
}
/**
* Constructor.
*
* @param jpaStore Explicit JpaStore to use
*/
public JPASituationStore(JpaStore jpaStore) {
_jpaStore = jpaStore;
}
/**
* {@inheritDoc}
*/
protected void doStore(final Situation situation) throws Exception {
_jpaStore.withJpa(new JpaWork<Void>() {
public Void perform(Session s) {
if (LOG.isLoggable(Level.FINEST)) {
LOG.finest("Persist situation id["+situation.getId()+"] "+situation); //$NON-NLS-1$
}
s.persist(situation);
return null;
}
});
}
/**
* {@inheritDoc}
*/
protected Situation doGetSituation(final String id) {
if (LOG.isLoggable(Level.FINEST)) {
LOG.finest("Get situation: "+id); //$NON-NLS-1$
}
Situation ret = _jpaStore.withJpa(new JpaWork<Situation>() {
public Situation perform(Session s) {
return loadSituation(s, id);
}
});
if (LOG.isLoggable(Level.FINEST)) {
LOG.finest("Situation="+ret); //$NON-NLS-1$
}
return (ret);
}
protected Situation loadSituation(final Session s, final String id) {
return (Situation) s.createQuery("SELECT sit FROM Situation sit " //$NON-NLS-1$
+ "WHERE sit.id = '" + id + "'") //$NON-NLS-1$ //$NON-NLS-2$
.uniqueResult();
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public List<Situation> getSituations(final SituationsQuery sitQuery) {
// RTGOV-649 Unfortunate work around as jpql query for no resolution state or state != resolved
// fails
boolean isOpen=sitQuery.getResolutionState() != null
&& sitQuery.getResolutionState().equalsIgnoreCase(ResolutionState.OPEN.name());
final String queryString = createQuery("SELECT sit from Situation sit ", sitQuery);
List<Situation> situations = _jpaStore.withJpa(new JpaWork<List<Situation>>() {
public List<Situation> perform(Session s) {
Query query = s.createQuery(queryString);
return query.list();
}
});
if (isOpen) {
sitQuery.setResolutionState(ResolutionState.UNRESOLVED.name());
final String queryString2 = createQuery("SELECT sit from Situation sit ", sitQuery);
List<Situation> situations2 = _jpaStore.withJpa(new JpaWork<List<Situation>>() {
public List<Situation> perform(Session s) {
Query query = s.createQuery(queryString2);
return query.list();
}
});
if (situations2 != null) {
if (situations != null) {
situations.addAll(situations2);
} else {
situations = situations2;
}
}
}
if (LOG.isLoggable(Level.FINEST)) {
LOG.finest("Situations="+situations); //$NON-NLS-1$
}
return (situations);
}
/**
* Check if the supplied string is null or empty (after removing
* whitespaces).
*
* @param str The string to test
* @return Whether the supplied string is null or empty
*/
protected boolean isNullOrEmpty(String str) {
return (str == null || str.trim().length() == 0);
}
private String createQuery(String selectOrDelete, SituationsQuery sitQuery) {
// Build the query string
StringBuffer queryString = new StringBuffer();
if (sitQuery.getSeverity() != null) {
queryString.append("sit.severity = "+sitQuery.getSeverity().ordinal()+" "); //$NON-NLS-1$
}
if (!isNullOrEmpty(sitQuery.getSubject())) {
if (queryString.length() > 0) {
queryString.append("AND "); //$NON-NLS-1$
}
queryString.append("upper(sit.subject) like '%" + sitQuery.getSubject().toUpperCase() + "%' "); //$NON-NLS-1$//$NON-NLS-2$
}
if (sitQuery.getProperties() != null && !sitQuery.getProperties().isEmpty()) {
Set<Entry<Object,Object>> entrySet = sitQuery.getProperties().entrySet();
for (Entry<Object, Object> entry : entrySet) {
if (queryString.length() > 0) {
queryString.append("AND "); //$NON-NLS-1$
}
Object key = entry.getKey();
Object value = entry.getValue();
queryString.append("upper(sit.situationProperties['" + key + "']) like '%"
+ value.toString().toUpperCase() + "%'");
}
}
if (!isNullOrEmpty(sitQuery.getDescription())) {
if (queryString.length() > 0) {
queryString.append("AND "); //$NON-NLS-1$
}
queryString
.append("upper(sit.description) like '%" + sitQuery.getDescription().toUpperCase() + "%' "); //$NON-NLS-1$//$NON-NLS-2$
}
if (sitQuery.getType() != null && sitQuery.getType().trim().length() > 0) {
if (queryString.length() > 0) {
queryString.append("AND "); //$NON-NLS-1$
}
queryString.append("sit.type = '" + sitQuery.getType() + "' "); //$NON-NLS-1$//$NON-NLS-2$
}
if (sitQuery.getFromTimestamp() > 0) {
if (queryString.length() > 0) {
queryString.append("AND "); //$NON-NLS-1$
}
queryString.append("sit.timestamp >= " + sitQuery.getFromTimestamp() + " "); //$NON-NLS-1$//$NON-NLS-2$
}
if (sitQuery.getToTimestamp() > 0) {
if (queryString.length() > 0) {
queryString.append("AND "); //$NON-NLS-1$
}
// NOTE: As only the day is returned currently, will need to add a
// day on, so that
// the 'to' time represents the end of the day.
queryString.append("sit.timestamp <= " + sitQuery.getToTimestamp() + " "); //$NON-NLS-1$//$NON-NLS-2$
}
if (sitQuery.getResolutionState() != null) {
if (queryString.length() > 0) {
queryString.append("AND "); //$NON-NLS-1$
}
if (ResolutionState.UNRESOLVED == ResolutionState.valueOf(sitQuery.getResolutionState())) {
queryString.append("'resolutionState' not in indices(sit.situationProperties)");
// RTGOV-649 - not currently used as not working - so instread have to issue the query twice for now
} else if (ResolutionState.OPEN == ResolutionState.valueOf(sitQuery.getResolutionState())) {
queryString.append("('resolutionState' not in indices(sit.situationProperties) or "
+ "('resolutionState' in indices(sit.situationProperties) AND "
+ "sit.situationProperties['resolutionState']!='" + ResolutionState.RESOLVED.name()
+ "' ))");
} else {
queryString.append("sit.situationProperties['resolutionState']='" + sitQuery.getResolutionState()
+ "'");
}
}
if (queryString.length() > 0) {
queryString.insert(0, "WHERE "); //$NON-NLS-1$
}
queryString.insert(0, selectOrDelete); //$NON-NLS-1$
return queryString.toString();
}
/**
* {@inheritDoc}
*/
public void assignSituation(final String situationId, final String userName) {
_jpaStore.withJpa(new JpaWork<Void>() {
public Void perform(Session s) {
doAssignSituation(loadSituation(s, situationId), userName);
return null;
}
});
}
/**
* {@inheritDoc}
*/
public void unassignSituation(final String situationId) {
_jpaStore.withJpa(new JpaWork<Void>() {
public Void perform(Session s) {
doUnassignSituation(loadSituation(s, situationId));
return null;
}
});
}
/**
* {@inheritDoc}
*/
public void updateResolutionState(final String situationId, final ResolutionState resolutionState) {
_jpaStore.withJpa(new JpaWork<Void>() {
public Void perform(Session s) {
doUpdateResolutionState(loadSituation(s, situationId), resolutionState);
return null;
}
});
}
@Override
public void recordSuccessfulResubmit(final String situationId, final String userName) {
_jpaStore.withJpa(new JpaWork<Void>() {
public Void perform(Session s) {
doRecordSuccessfulResubmit(loadSituation(s, situationId), userName);
return null;
}
});
}
@Override
public void recordResubmitFailure(final String situationId, final String errorMessage, final String userName) {
_jpaStore.withJpa(new JpaWork<Void>() {
public Void perform(Session s) {
String message = (errorMessage == null ? "" : errorMessage);
if (message.length() > PROPERTY_VALUE_MAX_LENGTH) {
message = message.substring(0, PROPERTY_VALUE_MAX_LENGTH);
}
doRecordResubmitFailure(loadSituation(s, situationId), message, userName);
return null;
}
});
}
/**
* This method deletes the supplied situation.
*
* @param situation The situation
*/
protected void doDelete(final Situation situation) {
_jpaStore.withJpa(new JpaWork<Void>() {
public Void perform(Session s) {
s.delete(situation);
return null;
}
});
}
}