View Javadoc

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 }