package com.epam.cisen.core.api;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.jongo.MongoCollection;
import org.jongo.MongoCursor;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.epam.cisen.core.api.dto.CiJob;
import com.epam.cisen.core.api.dto.CiUser;
import com.epam.cisen.core.api.dto.ConfigDTO;
import com.epam.cisen.core.api.dto.ConfigDTO.BaseType;
import com.epam.cisen.core.api.dto.Constants;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@Component(componentAbstract = true)
public abstract class AbstractPlugin<T extends ConfigDTO> {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractPlugin.class);
private T configTemplate;
@Reference
protected MongoDBService mongoDBService;
protected abstract T getPluginTemplateConfig();
private List<T> testData;
protected List<T> getTestData() {
return null;
}
/**
* In case, you need do some action during service activation use this method.
*
* @param componentContext {@link ComponentContext}
*/
protected void activatePlugin(ComponentContext componentContext) {
//nothing to do
}
/**
* In case, you need do some action during service deactivation.
*/
protected void deactivatePlugin() {
//nothing to do
}
protected abstract Constants.DB getTemplateTableName();
protected abstract Constants.DB getConfigTableName();
/**
* @return active configs set for selected plugin
*/
protected Set<T> getPluginConfigs() {
HashSet<T> configsByType = Sets.newHashSet();
MongoCollection collection = mongoDBService.getCollection(getConfigTableName());
try {
MongoCursor<? extends ConfigDTO> mongoCursor = collection.find("{type:'" + configTemplate.getType() + "'}")
.as(configTemplate.getClass());
for (ConfigDTO configDTO : mongoCursor) {
configsByType.add((T) configDTO);
}
mongoCursor.close();
} catch (IOException e) {
e.printStackTrace();
}
return configsByType;
}
protected Map<String, T> getJobs(Set<T> configs) {
Map<String, T> jobsByIds = Maps.newHashMap();
try {
MongoCollection collection = mongoDBService.getCollection(Constants.DB.USERS);
for (T config : configs) {
String query = String.format("{ jobs:{$elemMatch:{%s: '%s'} } }", config.getBaseType().getDbName(),
config.getId());
List<CiJob> jobs = collection.distinct("jobs").query(query).as(CiJob.class);
for (CiJob job : jobs) {
jobsByIds.put(job.getId(), config);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return jobsByIds;
}
protected Map<String, T> getJobs() {
return getJobs(getPluginConfigs());
}
@Activate
public void activate(ComponentContext componentContext) {
registerPlugin();
activatePlugin(componentContext);
}
@Deactivate
public void deactivate() {
unregisterPlugin();
}
protected MongoCollection getCollection() {
return mongoDBService.getCollection(getTemplateTableName());
}
/**
* Use for setup test data only.
*/
private void updateUser(String userName, String jobName, T info) throws Exception {
MongoCollection collection = mongoDBService.getCollection(Constants.DB.USERS);
MongoCursor<CiUser> users = collection.find(String.format("{name:'%s'}", userName)).as(CiUser.class);
CiUser ciUser;
if (users.hasNext()) {
ciUser = users.next();
} else {
ciUser = new CiUser();
ciUser.setName(userName);
collection.save(ciUser);
}
users.close();
if (ciUser.getJobs() == null || ciUser.getJobs().isEmpty()) {
ciUser.setJobs(new ArrayList<CiJob>());
CiJob job = new CiJob();
job.setName(jobName);
ciUser.getJobs().add(job);
}
CiJob job = ciUser.getJobs().get(0);
if (BaseType.CI.equals(info.getBaseType())) {
job.setCi(info.getId());
} else if (BaseType.MESSENGER.equals(info.getBaseType())) {
job.setMessenger(info.getId());
} else if (BaseType.PROCESSOR.equals(info.getBaseType())) {
job.setProcessor(info.getId());
}
collection.update("{name: '" + userName + "'}").with(ciUser);
}
protected void registerPlugin() {
try {
testData = getTestData();
if (Constants.DEBUG && testData != null && testData.size() > 0) {
MongoCollection testCollection = mongoDBService.getCollection(getConfigTableName());
testCollection.insert(testData.toArray());
updateUser("Luke", "TeamCity CISEN mail notifications", testData.get(0));
}
} catch (Exception ex) {
ex.printStackTrace();
}
configTemplate = getPluginTemplateConfig();
if (configTemplate == null) {
throw new IllegalArgumentException("Provide a valid plugin info");
}
try {
final String type = configTemplate.getType();
LOGGER.info("Try to register plugin [{}]", type);
final MongoCollection collection = getCollection();
try (MongoCursor previousConfig = collection.find(String.format("{type: '%s'}", type)).as(
configTemplate.getClass())) {
if (previousConfig.hasNext()) {
LOGGER.info("Plugin [{}] already registered!", type);
return;
}
}
LOGGER.info("Plugin not register yet. Register plugin with [{}] type.", type);
collection.save(configTemplate);
LOGGER.info("Plugin [{}] was registered successfully.", type);
} catch (IOException ex) {
LOGGER.error("Fail to close cursor ", ex);
}
}
protected void unregisterPlugin() {
MongoCollection collection = getCollection();
final String type = configTemplate.getType();
LOGGER.info("Try to unregister plugin [{}]", type);
collection.remove(String.format("{type: '%s'}", type));
LOGGER.info("Plugin [{}] was removed successfully.", type);
if (Constants.DEBUG && testData != null && testData.size() > 0) {
MongoCollection testCollection = mongoDBService.getCollection(getConfigTableName());
for (T item : testData) {
String query = String.format("{id : '%s'}", item.getId());
testCollection.remove(query);
}
}
}
}