/* * ToroDB * Copyright © 2014 8Kdata Technology (www.8kdata.com) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.torodb.mongodb.commands.signatures.admin; import com.eightkdata.mongowp.bson.BsonDocument; import com.eightkdata.mongowp.bson.BsonValue; import com.eightkdata.mongowp.exceptions.BadValueException; import com.eightkdata.mongowp.exceptions.MongoException; import com.eightkdata.mongowp.exceptions.NoSuchKeyException; import com.eightkdata.mongowp.exceptions.TypesMismatchException; import com.eightkdata.mongowp.fields.DocField; import com.eightkdata.mongowp.fields.DoubleField; import com.eightkdata.mongowp.fields.StringField; import com.eightkdata.mongowp.server.api.MarshalException; import com.eightkdata.mongowp.server.api.impl.AbstractNotAliasableCommand; import com.eightkdata.mongowp.utils.BsonDocumentBuilder; import com.eightkdata.mongowp.utils.BsonReaderTool; import com.torodb.mongodb.commands.pojos.CollectionOptions; import com.torodb.mongodb.commands.pojos.CursorResult; import com.torodb.mongodb.commands.signatures.admin.ListCollectionsCommand.ListCollectionsArgument; import com.torodb.mongodb.commands.signatures.admin.ListCollectionsCommand.ListCollectionsResult; import java.util.function.Function; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; /** * */ @Immutable public class ListCollectionsCommand extends AbstractNotAliasableCommand<ListCollectionsArgument, ListCollectionsResult> { public static final ListCollectionsCommand INSTANCE = new ListCollectionsCommand(); private static final String COMMAND_NAME = "listCollections"; private ListCollectionsCommand() { super(COMMAND_NAME); } @Override public boolean shouldAffectCommandCounter() { return false; } @Override public Class<? extends ListCollectionsArgument> getArgClass() { return ListCollectionsArgument.class; } @Override public ListCollectionsArgument unmarshallArg(BsonDocument requestDoc) throws TypesMismatchException, NoSuchKeyException, BadValueException { return ListCollectionsArgument.unmarshall(requestDoc); } @Override public BsonDocument marshallArg(ListCollectionsArgument request) { return request.marshall(); } @Override public Class<? extends ListCollectionsResult> getResultClass() { return ListCollectionsResult.class; } @Override public BsonDocument marshallResult(ListCollectionsResult reply) throws MarshalException { try { return reply.marshall(); } catch (MongoException ex) { throw new MarshalException(ex); } } @Override public ListCollectionsResult unmarshallResult(BsonDocument reply) throws TypesMismatchException, NoSuchKeyException, BadValueException { return ListCollectionsResult.unmarshall(reply); } @Immutable public static class ListCollectionsArgument { private static final DoubleField LIST_COLLECTIONS_FIELD = new DoubleField("listCollections"); private static final DocField FILTER_FIELD = new DocField("filter"); private final BsonDocument filter; public ListCollectionsArgument(@Nullable BsonDocument filter) { this.filter = filter; } @Nullable public BsonDocument getFilter() { return filter; } private static ListCollectionsArgument unmarshall( BsonDocument requestDoc) throws TypesMismatchException { BsonDocument filter; try { filter = BsonReaderTool.getDocument(requestDoc, FILTER_FIELD, null); } catch (TypesMismatchException ex) { throw ex.newWithMessage("\"filter\" must be of type Object, not " + ex.getFoundType()); } return new ListCollectionsArgument(filter); } private BsonDocument marshall() { BsonDocumentBuilder builder = new BsonDocumentBuilder(); builder.append(LIST_COLLECTIONS_FIELD, 1); if (filter != null) { builder.append(FILTER_FIELD, filter); } return builder.build(); } } @Immutable public static class ListCollectionsResult { private static final DocField CURSOR_FIELD = new DocField("cursor"); private static final StringField NAME_FIELD = new StringField("name"); private static final DocField OPTIONS_FIELD = new DocField("options"); private final CursorResult<Entry> cursor; public ListCollectionsResult(CursorResult<Entry> cursor) { this.cursor = cursor; } private static ListCollectionsResult unmarshall(BsonDocument resultDoc) throws TypesMismatchException, NoSuchKeyException, BadValueException { BsonDocument cursorDoc = BsonReaderTool.getDocument(resultDoc, CURSOR_FIELD); return new ListCollectionsResult( CursorResult.unmarshall(cursorDoc, Entry.TO_ENTRY) ); } private BsonDocument marshall() throws MongoException { BsonDocumentBuilder builder = new BsonDocumentBuilder(); return builder .append(CURSOR_FIELD, cursor.marshall(Entry.FROM_ENTRY)) .build(); } public CursorResult<Entry> getCursor() { return cursor; } public static class Entry { private final String name; private final CollectionOptions options; public static final Function<BsonValue<?>, Entry> TO_ENTRY = new ToEntryConverter(); public static final Function<Entry, BsonDocument> FROM_ENTRY = new FromEntryConverter(); public Entry(String name, CollectionOptions options) { this.name = name; this.options = options; } public String getCollectionName() { return name; } public CollectionOptions getCollectionOptions() { return options; } } private static class ToEntryConverter implements Function<BsonValue<?>, Entry> { @Override public Entry apply(@Nonnull BsonValue<?> from) { if (!from.isDocument()) { throw new IllegalArgumentException("Expected a document, " + "but a " + from.getType() + " was found"); } try { BsonDocument doc = from.asDocument(); return new Entry( BsonReaderTool.getString(doc, NAME_FIELD), CollectionOptions.unmarshal( BsonReaderTool.getDocument(doc, OPTIONS_FIELD) ) ); } catch (TypesMismatchException | NoSuchKeyException | BadValueException ex) { throw new IllegalArgumentException(ex); } } } private static class FromEntryConverter implements Function<Entry, BsonDocument> { @Override public BsonDocument apply(@Nonnull Entry from) { return new BsonDocumentBuilder() .append(NAME_FIELD, from.getCollectionName()) .append(OPTIONS_FIELD, from.getCollectionOptions().marshall() ) .build(); } } } }