1 /*
2 * ModeShape (http://www.modeshape.org)
3 * See the COPYRIGHT.txt file distributed with this work for information
4 * regarding copyright ownership. Some portions may be licensed
5 * to Red Hat, Inc. under one or more contributor license agreements.
6 * See the AUTHORS.txt file in the distribution for a full listing of
7 * individual contributors.
8 *
9 * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10 * is licensed to you under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * ModeShape is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this software; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23 */
24 package org.modeshape.connector.store.jpa.model.simple;
25
26 import org.hibernate.ejb.Ejb3Configuration;
27 import org.modeshape.connector.store.jpa.JpaConnectorI18n;
28 import org.modeshape.connector.store.jpa.JpaSource;
29 import org.modeshape.connector.store.jpa.Model;
30 import org.modeshape.connector.store.jpa.model.common.NamespaceEntity;
31 import org.modeshape.connector.store.jpa.model.common.WorkspaceEntity;
32 import org.modeshape.graph.connector.RepositoryConnection;
33 import org.modeshape.graph.request.CopyBranchRequest;
34 import org.modeshape.graph.request.DeleteBranchRequest;
35 import org.modeshape.graph.request.MoveBranchRequest;
36 import org.modeshape.graph.request.ReadBranchRequest;
37
38 /**
39 * Database model that stores each node (transparently) and its properties (opaquely) in a single row. Large property values are
40 * stored separately and can be shared between nodes.
41 * <p>
42 * The set of tables used in this model includes:
43 * <ul>
44 * <li>Namespaces - the set of namespace URIs used in paths, property names, and property values.</li>
45 * <li>Nodes - each node along with its name, seralized properties, parent, UUID, and position within its parent. This approach
46 * makes it possible to efficiently work with nodes containing large numbers of children, where adding and removing child nodes is
47 * largely independent of the number of children. Also, working with properties is also completely independent of the number of
48 * child nodes.</li>
49 * <li>Large values - property values larger than a certain size will be broken out into this table, where they are tracked by
50 * their SHA-1 hash and shared by all properties that have that same value. The values are stored in a binary (and optionally
51 * compressed) form.</li>
52 * <li>ReferenceChanges - the references from one node to another</li>
53 * <li>Subgraph - a working area for efficiently computing the space of a subgraph; see below</li>
54 * <li>Change log - a record of the changes that have been made to the repository. This is used to distribute change events across
55 * multiple distributed processes, and to allow a recently-connected client to identify the set of changes that have been made
56 * since a particular time or date. Changes are serialized into a binary, compressed format.</i></li>
57 * <li>Options - the parameters for this store's configuration (common to all models)</li>
58 * </ul>
59 * </p>
60 * <h3>Subgraph queries</h3>
61 * <p>
62 * This database model contains two tables that are used in an efficient mechanism to find all of the nodes in the subgraph below
63 * a certain node. This process starts by creating a record for the subgraph query, and then proceeds by executing a join to find
64 * all the children of the top-level node, and inserting them into the database (in a working area associated with the subgraph
65 * query). Then, another join finds all the children of those children and inserts them into the same working area. This continues
66 * until the maximum depth has been reached, or until there are no more children (whichever comes first). All of the nodes in the
67 * subgraph are then represented by records in the working area, and can be used to quickly and efficient work with the subgraph
68 * nodes. When finished, the mechanism deletes the records in the working area associated with the subgraph query.
69 * </p>
70 * <p>
71 * This subgraph query mechanism is extremely efficient, performing one join/insert statement <i>per level of the subgraph</i>,
72 * and is completely independent of the number of nodes in the subgraph. For example, consider a subgraph of node A, where A has
73 * 10 children, and each child contains 10 children, and each grandchild contains 10 children. This subgraph has a total of 1111
74 * nodes (1 root + 10 children + 10*10 grandchildren + 10*10*10 great-grandchildren). Finding the nodes in this subgraph would
75 * normally require 1 query per node (in other words, 1111 queries). But with this subgraph query mechanism, all of the nodes in
76 * the subgraph can be found with 1 insert plus 4 additional join/inserts.
77 * </p>
78 * <p>
79 * This mechanism has the added benefit that the set of nodes in the subgraph are kept in a working area in the database, meaning
80 * they don't have to be pulled into memory.
81 * </p>
82 * <p>
83 * Subgraph queries are used to efficiently process a number of different requests, including {@link ReadBranchRequest},
84 * {@link DeleteBranchRequest}, {@link MoveBranchRequest}, and {@link CopyBranchRequest}. Processing each of these kinds of
85 * requests requires knowledge of the subgraph, and in fact all but the <code>ReadBranchRequest</code> need to know the complete
86 * subgraph.
87 * </p>
88 */
89 public class SimpleModel extends Model {
90
91 public SimpleModel() {
92 super("Simple", JpaConnectorI18n.simpleModelDescription);
93 }
94
95 /**
96 * Configure the entity class that will be used by JPA to store information in the database.
97 *
98 * @param configurator the Hibernate {@link Ejb3Configuration} component; never null
99 */
100 @Override
101 public void configure( Ejb3Configuration configurator ) {
102 // Add the annotated classes ...
103 configurator.addAnnotatedClass(WorkspaceEntity.class);
104 configurator.addAnnotatedClass(NamespaceEntity.class);
105 configurator.addAnnotatedClass(LargeValueEntity.class);
106 configurator.addAnnotatedClass(NodeEntity.class);
107 configurator.addAnnotatedClass(SubgraphNodeEntity.class);
108 configurator.addAnnotatedClass(SubgraphQueryEntity.class);
109 }
110
111 @Override
112 public RepositoryConnection createConnection( JpaSource source ) {
113 return new SimpleJpaConnection(source);
114 }
115 }