001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.modeshape.schematic; 017 018import java.util.Collection; 019import java.util.List; 020import org.modeshape.schematic.annotation.RequiresTransaction; 021import org.modeshape.schematic.document.Document; 022import org.modeshape.schematic.document.EditableDocument; 023 024/** 025 * A store for JSON documents and other binary content, plus a library of JSON Schema documents used to describe and validate the 026 * stored documents. 027 * 028 * @author Horia Chiorean <hchiorea@redhat.com> 029 * @since 5.0 030 */ 031public interface SchematicDb extends TransactionListener, Lifecycle, Lockable { 032 033 /** 034 * Returns a unique identifier for this schematic DB. 035 * <p> 036 * Implementations should make sure that the provided id is unique per storage instance. 037 * In other words, if two {@link SchematicDb} instances of the same type store data in two different places, they should 038 * return a different id. 039 * </p> 040 * 041 * @return a {@link String}, never {@code null} 042 */ 043 String id(); 044 045 /** 046 * Returns a set over all the keys present in the DB. 047 * <p> 048 * If this method is called within an existing transaction, it should take into account the transient transactional context 049 * (i.e. any local but not yet committed changes) 050 * </p> 051 * 052 * @return a {@link List} instance, never {@code null} 053 */ 054 List<String> keys(); 055 056 /** 057 * Get the document with the supplied key. This will represent the full {@link SchematicEntry} document if one exists. 058 * <p> 059 * If this method is called within an existing transaction, it should take into account the transient transactional context 060 * (i.e. any local but not yet committed changes) 061 * </p> 062 * 063 * @param key the key or identifier for the document 064 * @return the document, or null if there was no document with the supplied key 065 */ 066 Document get( String key ); 067 068 /** 069 * Loads a set of documents from the DB returning the corresponding schematic entries. 070 * 071 * <p> 072 * If this method is called within an existing transaction, it should <b>take into account</b> the transient transactional 073 * context (i.e. any local but not yet committed changes) and either use that (if it exists) or the persisted information. 074 * </p> 075 * 076 * @param keys an {@link Collection} of keys; never {@code null} 077 * @return a {@link List} of {@link SchematicEntry entries}; never {@code null} 078 */ 079 List<SchematicEntry> load(Collection<String> keys); 080 081 /** 082 * Stores the supplied schematic entry under the given key. If an entry already exists with the same key, it should be 083 * overwritten. 084 * @param key a schematic entry id, never {@code null} 085 * @param entry a {@link SchematicEntry} instance, never {@code null} 086 */ 087 @RequiresTransaction 088 void put(String key, SchematicEntry entry); 089 090 /** 091 * Get an editor for the content of the given entry with the supplied key. 092 * 093 * @param key the key or identifier for the document 094 * @param createIfMissing true if a new entry should be created and added to the database if an existing entry does not exist 095 * @return the content document, or null if there was no document with the supplied key and a new one could not be created 096 */ 097 @RequiresTransaction 098 EditableDocument editContent(String key, boolean createIfMissing); 099 100 /** 101 * Store the supplied content at the given key. 102 * 103 * <p> 104 * Depending on the actual implementation, this may or may not be thread-safe. ModeShape never assumes this is thread-safe 105 * when calling it. 106 * </p> 107 * 108 * @param key the key or identifier for the content 109 * @param content the content that is to be stored 110 * @return the existing entry for the supplied key, or null if there was no entry and the put was successful 111 */ 112 @RequiresTransaction 113 SchematicEntry putIfAbsent(String key, Document content); 114 115 /** 116 * Remove the existing document at the given key. 117 * 118 * @param key the key or identifier for the document 119 * @return {@code true} if the removal was successful, {@code false} otherwise 120 */ 121 @RequiresTransaction 122 boolean remove(String key); 123 124 /** 125 * Removes all the entries from this DB. 126 */ 127 @RequiresTransaction 128 void removeAll(); 129 130 /** 131 * Store the supplied content document at the given key. If a document already exists with the given key, this should 132 * overwrite the existing document. 133 * 134 * @param key the key or identifier for the document 135 * @param content the document that is to be stored 136 * @see #putIfAbsent(String, Document) 137 */ 138 @RequiresTransaction 139 default void put( String key, Document content ) { 140 put(key, SchematicEntry.create(key, content)); 141 } 142 143 @Override 144 @RequiresTransaction 145 default boolean lockForWriting( List<String> locks ) { 146 throw new UnsupportedOperationException(getClass() + " does not support exclusive locking"); 147 } 148 149 /** 150 * Get the entry with the supplied key. 151 * <p> 152 * If this method is called within an existing transaction, it should take into account the transient transactional context 153 * (i.e. any local but not yet committed changes) 154 * </p> 155 * 156 * @param key the key or identifier for the document 157 * @return the entry, or null if there was no document with the supplied key 158 */ 159 default SchematicEntry getEntry( String key) { 160 Document doc = get(key); 161 return doc != null ? () -> doc : null; 162 } 163 164 /** 165 * Determine whether the database contains an entry with the supplied key. 166 * <p> 167 * If this method is called within an existing transaction, it should take into account the transient transactional context 168 * (i.e. any local but not yet committed changes) 169 * </p> 170 * 171 * @param key the key or identifier for the document 172 * @return true if the database contains an entry with this key, or false otherwise 173 */ 174 default boolean containsKey( String key ) { 175 return get(key) != null; 176 } 177 178 /** 179 * Store the supplied document. This document is expected to be a full entry document, which contains both a "metadata" 180 * and "content" section. 181 * 182 * @param entryDocument the document that contains the metadata document and content document. 183 * @see #putIfAbsent(String, Document) 184 */ 185 @RequiresTransaction 186 default void putEntry(Document entryDocument) { 187 SchematicEntry entry = SchematicEntry.fromDocument(entryDocument); 188 put(entry.id(), entry); 189 } 190}