001package de.deepamehta.core.service;
002
003import de.deepamehta.core.Association;
004import de.deepamehta.core.AssociationType;
005import de.deepamehta.core.DeepaMehtaObject;
006import de.deepamehta.core.RelatedAssociation;
007import de.deepamehta.core.RelatedTopic;
008import de.deepamehta.core.Topic;
009import de.deepamehta.core.TopicType;
010import de.deepamehta.core.model.AssociationModel;
011import de.deepamehta.core.model.AssociationTypeModel;
012import de.deepamehta.core.model.SimpleValue;
013import de.deepamehta.core.model.TopicModel;
014import de.deepamehta.core.model.TopicTypeModel;
015import de.deepamehta.core.service.accesscontrol.AccessControl;
016import de.deepamehta.core.storage.spi.DeepaMehtaTransaction;
017
018import java.util.List;
019
020
021
022/**
023 * Specification of the DeepaMehta core service -- the heart of DeepaMehta.
024 * <p>
025 * The responsibility of the DeepaMehta core service is to orchestrate the control flow and allow plugins to hook in.
026 * The main duties of the DeepaMehta core service are to provide access to the storage layer and to dispatch events to
027 * the installed plugins. ### FIXDOC
028 * <p>
029 * The DeepaMehta core service is a realization of the <i>Inversion of Control</i> pattern.
030 * <p>
031 * The DeepaMehta core service provides methods to deal with topics, associations, types, and plugins.
032 * <p>
033 * Plugin developer notes: Inside the {@link PluginActivator} and {@link Migration} classes an instance of the
034 * DeepaMehta core service is available through the <code>dm4</code> object.
035 */
036public interface CoreService {
037
038
039
040    // === Topics ===
041
042    /**
043     * Accesses a topic by ID.
044     *
045     * @return  the topic.
046     *
047     * @throws  RuntimeException    if no such topic exists.
048     */
049    Topic getTopic(long topicId);
050
051    /**
052     * Accesses a topic by URI.
053     *
054     * @return  the topic, or <code>null</code> if no such topic exists.
055     */
056    Topic getTopicByUri(String uri);
057
058    /**
059     * Looks up a single topic by exact value.
060     * <p>
061     * Note: wildcards like "*" in String values are <i>not</i> interpreted. They are treated literally.
062     * Compare to {@link #getTopicsByValue(String,SimpleValue)}
063     * <p>
064     * IMPORTANT: Looking up a topic this way requires the corresponding type to be indexed with indexing mode
065     * <code>dm4.core.key</code>.
066     *
067     * @return  the topic, or <code>null</code> if no such topic exists.
068     *
069     * @throws  RuntimeException    If more than one topic is found.
070     */
071    Topic getTopicByValue(String key, SimpleValue value);
072
073    /**
074     * Looks up topics by key and value.
075     * <p>
076     * Wildcards like "*" in String values are interpreted.
077     * <p>
078     * IMPORTANT: Looking up topics this way requires the corresponding type to be indexed with indexing mode
079     * <code>dm4.core.key</code>.
080     */
081    List<Topic> getTopicsByValue(String key, SimpleValue value);
082
083    List<Topic> getTopicsByType(String topicTypeUri);
084
085    /**
086     * Performs a fulltext search.
087     * <p>
088     * IMPORTANT: Searching topics this way requires the corresponding type to be indexed with indexing mode
089     * <code>dm4.core.fulltext</code> or <code>dm4.core.fulltext_key</code>. ### FIXDOC
090     *
091     * @param   fieldUri    The URI of the data field to search. If null is provided all fields are searched. ### FIXDOC
092     *                      ### TODO: rename parameter to "key"?
093     */
094    List<Topic> searchTopics(String searchTerm, String fieldUri);
095
096    Iterable<Topic> getAllTopics();
097
098    // ---
099
100    Topic createTopic(TopicModel model);
101
102    void updateTopic(TopicModel newModel);
103
104    void deleteTopic(long topicId);
105
106
107
108    // === Associations ===
109
110    Association getAssociation(long assocId);
111
112    /**
113     * Looks up a single association by exact value.
114     * <p>
115     * Note: wildcards like "*" in String values are <i>not</i> interpreted. They are treated literally.
116     * Compare to {@link #getAssociationsByValue(String,SimpleValue)}
117     * <p>
118     * IMPORTANT: Looking up an association this way requires the corresponding type to be indexed with indexing mode
119     * <code>dm4.core.key</code>.
120     *
121     * @return  the association, or <code>null</code> if no such association exists.
122     *
123     * @throws  RuntimeException    If more than one association is found.
124     */
125    Association getAssociationByValue(String key, SimpleValue value);
126
127    /**
128     * Looks up associations by key and value.
129     * <p>
130     * Wildcards like "*" in String values <i>are</i> interpreted.
131     * <p>
132     * IMPORTANT: Looking up associations this way requires the corresponding type to be indexed with indexing mode
133     * <code>dm4.core.key</code>.
134     */
135    List<Association> getAssociationsByValue(String key, SimpleValue value);
136
137    /**
138     * Returns the association between two topics, qualified by association type and both role types.
139     * If no such association exists <code>null</code> is returned.
140     * If more than one association exist, a runtime exception is thrown.
141     *
142     * @param   assocTypeUri    Association type filter. Pass <code>null</code> to switch filter off.
143     */
144    Association getAssociation(String assocTypeUri, long topic1Id, long topic2Id,
145                                                    String roleTypeUri1, String roleTypeUri2);
146
147    Association getAssociationBetweenTopicAndAssociation(String assocTypeUri, long topicId, long assocId,
148                                                         String topicRoleTypeUri, String assocRoleTypeUri);
149
150    // ---
151
152    List<Association> getAssociationsByType(String assocTypeUri);
153
154    /**
155     * Returns all associations between two topics. If no such association exists an empty set is returned.
156     */
157    List<Association> getAssociations(long topic1Id, long topic2Id);
158
159    /**
160     * Returns the associations between two topics. If no such association exists an empty set is returned.
161     *
162     * @param   assocTypeUri    Association type filter. Pass <code>null</code> to switch filter off.
163     */
164    List<Association> getAssociations(long topic1Id, long topic2Id, String assocTypeUri);
165
166    // ---
167
168    Iterable<Association> getAllAssociations();
169
170    long[] getPlayerIds(long assocId);
171
172    // ---
173
174    Association createAssociation(AssociationModel model);
175
176    void updateAssociation(AssociationModel newModel);
177
178    void deleteAssociation(long assocId);
179
180
181
182    // === Topic Types ===
183
184    TopicType getTopicType(String topicTypeUri);
185
186    /**
187     * Acccesses a topic type while enforcing the <i>implicit READ permission</i>.
188     * A user has implicit READ permission for the topic type if she has READ permission for the given topic.
189     */
190    TopicType getTopicTypeImplicitly(long topicId);
191
192    // ---
193
194    List<TopicType> getAllTopicTypes();
195
196    // ---
197
198    TopicType createTopicType(TopicTypeModel model);
199
200    void updateTopicType(TopicTypeModel newModel);
201
202    void deleteTopicType(String topicTypeUri);
203
204
205
206    // === Association Types ===
207
208    AssociationType getAssociationType(String assocTypeUri);
209
210    /**
211     * Acccesses an association type while enforcing the <i>implicit READ permission</i>.
212     * A user has implicit READ permission for the association type if she has READ permission for the given
213     * association.
214     */
215    AssociationType getAssociationTypeImplicitly(long assocId);
216
217    // ---
218
219    List<AssociationType> getAllAssociationTypes();
220
221    // ---
222
223    AssociationType createAssociationType(AssociationTypeModel model);
224
225    void updateAssociationType(AssociationTypeModel newModel);
226
227    void deleteAssociationType(String assocTypeUri);
228
229
230
231    // === Role Types ===
232
233    Topic createRoleType(TopicModel model);
234
235
236
237    // === Generic Object ===
238
239    DeepaMehtaObject getObject(long id);
240
241
242
243    // === Plugins ===
244
245    Plugin getPlugin(String pluginUri);
246
247    List<PluginInfo> getPluginInfo();
248
249
250
251    // === Events ===
252
253    void fireEvent(DeepaMehtaEvent event, Object... params);
254
255    void dispatchEvent(String pluginUri, DeepaMehtaEvent event, Object... params);
256
257
258
259    // === Properties ===
260
261    /**
262     * Returns a topic's or association's property value associated with the given property URI.
263     * If there's no property value associated with the property URI an exception is thrown.
264     *
265     * @param   id  a topic ID, or an association ID
266     */
267    Object getProperty(long id, String propUri);
268
269    /**
270     * Checks whether for a given topic or association a property value is associated with a given property URI.
271     *
272     * @param   id  a topic ID, or an association ID
273     */
274    boolean hasProperty(long id, String propUri);
275
276    // Note: there is no setter here. If we want one we actually need 2 setters: one for topics, one for assocs.
277    // This is because the storage layer maintains separate indexes for topics and assocs.
278
279    // ---
280
281    List<Topic> getTopicsByProperty(String propUri, Object propValue);
282
283    List<Topic> getTopicsByPropertyRange(String propUri, Number from, Number to);
284
285    List<Association> getAssociationsByProperty(String propUri, Object propValue);
286
287    List<Association> getAssociationsByPropertyRange(String propUri, Number from, Number to);
288
289    // ---
290
291    void addTopicPropertyIndex(String propUri);
292
293    void addAssociationPropertyIndex(String propUri);
294
295
296
297    // === Misc ===
298
299    DeepaMehtaTransaction beginTx();
300
301    // ---
302
303    ModelFactory getModelFactory();
304
305    AccessControl getAccessControl();   // ### TODO: drop this
306
307    Object getDatabaseVendorObject();
308}