/**
* This file is part of Graylog.
*
* Graylog is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Graylog is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Graylog. If not, see <http://www.gnu.org/licenses/>.
*/
package org.graylog2.streams;
import com.google.common.collect.Sets;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import org.bson.types.ObjectId;
import org.graylog2.bindings.providers.MongoJackObjectMapperProvider;
import org.graylog2.database.CollectionName;
import org.graylog2.database.MongoConnection;
import org.graylog2.database.NotFoundException;
import org.graylog2.outputs.OutputRegistry;
import org.graylog2.plugin.Tools;
import org.graylog2.plugin.database.ValidationException;
import org.graylog2.plugin.streams.Output;
import org.graylog2.rest.models.streams.outputs.requests.CreateOutputRequest;
import org.mongojack.DBQuery;
import org.mongojack.DBUpdate;
import org.mongojack.JacksonDBCollection;
import org.mongojack.WriteResult;
import javax.inject.Inject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class OutputServiceImpl implements OutputService {
private final JacksonDBCollection<OutputImpl, String> coll;
private final DBCollection dbCollection;
private final StreamService streamService;
private final OutputRegistry outputRegistry;
@Inject
public OutputServiceImpl(MongoConnection mongoConnection,
MongoJackObjectMapperProvider mapperProvider,
StreamService streamService,
OutputRegistry outputRegistry) {
this.streamService = streamService;
final String collectionName = OutputImpl.class.getAnnotation(CollectionName.class).value();
this.dbCollection = mongoConnection.getDatabase().getCollection(collectionName);
this.coll = JacksonDBCollection.wrap(dbCollection, OutputImpl.class, String.class, mapperProvider.get());
this.outputRegistry = outputRegistry;
}
@Override
public Output load(String streamOutputId) throws NotFoundException {
final Output output = coll.findOneById(streamOutputId);
if (output == null) {
throw new NotFoundException("Couldn't find output with id " + streamOutputId);
}
return output;
}
@Override
public Set<Output> loadAll() {
return toAbstractSetType(coll.find().toArray());
}
private Set<Output> toAbstractSetType(List<OutputImpl> outputs) {
final Set<Output> result = Sets.newHashSet();
result.addAll(outputs);
return result;
}
@Override
public Output create(Output request) throws ValidationException {
final OutputImpl outputImpl = implOrFail(request);
final WriteResult<OutputImpl, String> writeResult = coll.save(outputImpl);
return writeResult.getSavedObject();
}
@Override
public Output create(CreateOutputRequest request, String userId) throws ValidationException {
return create(OutputImpl.create(new ObjectId().toHexString(), request.title(), request.type(), userId, request.configuration(),
Tools.nowUTC().toDate(), request.contentPack()));
}
@Override
public void destroy(Output model) throws NotFoundException {
coll.removeById(model.getId());
outputRegistry.removeOutput(model);
streamService.removeOutputFromAllStreams(model);
}
@Override
public Output update(String id, Map<String, Object> deltas) {
DBUpdate.Builder update = new DBUpdate.Builder();
for (Map.Entry<String, Object> fields : deltas.entrySet())
update = update.set(fields.getKey(), fields.getValue());
return coll.findAndModify(DBQuery.is("_id", id), update);
}
@Override
public long count() {
return coll.count();
}
@Override
public Map<String, Long> countByType() {
final DBCursor outputTypes = dbCollection.find(null, new BasicDBObject(OutputImpl.FIELD_TYPE, 1));
final Map<String, Long> outputsCountByType = new HashMap<>(outputTypes.count());
for (DBObject outputType : outputTypes) {
final String type = (String) outputType.get(OutputImpl.FIELD_TYPE);
if (type != null) {
final Long oldValue = outputsCountByType.get(type);
final Long newValue = (oldValue == null) ? 1 : oldValue + 1;
outputsCountByType.put(type, newValue);
}
}
return outputsCountByType;
}
private OutputImpl implOrFail(Output output) {
final OutputImpl outputImpl;
if (output instanceof OutputImpl) {
outputImpl = (OutputImpl) output;
return outputImpl;
} else {
throw new IllegalArgumentException("Supplied output must be of implementation type OutputImpl, not " + output.getClass());
}
}
}