289 lines
10 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="org.alfresco.repo.avm">
<!-- AVMNodeBean is the abstract base for filesystem like objects.
We're using the one table per class hierarchy strategy to implement
polymorphism. -->
<class table="avm_nodes" abstract="true"
name="AVMNodeImpl"
proxy="AVMNode"
optimistic-lock="version"
lazy="true">
<cache usage="read-write"/>
<!-- The id is set programmatically using an Issuer. See below. -->
<id name="id"
column="id"
type="long"/>
<!-- I suppose this would be more efficient to encode type by an int.
We'll see if using a string makes a difference. -->
<discriminator column="class_type"
type="string"
length="20"/>
<!-- We're using hibernate's own versioning scheme for concurrency control.
I don't know how well that will play with a full Spring-JTA stack. -->
<version column="vers"
name="vers"
type="long"/>
<!-- This should really be not null, but I haven't figured out
the right way to build the relation so that nullability constraints
won't cause violations in the db during saves. -->
<many-to-one name="repository" column="repository"
class="RepositoryImpl"/>
<property name="versionID" type="int" column="version_id"
not-null="true"/>
<property name="isNew" column="is_new" type="boolean"
not-null="true"/>
<component name="basicAttributes" class="BasicAttributesImpl">
<property name="creator" type="string" not-null="true"/>
<property name="owner" type="string" not-null="true"/>
<property name="lastModifier" type="string" not-null="true"/>
<property name="createDate" type="long" not-null="true"/>
<property name="modDate" type="long" not-null="true"/>
<property name="accessDate" type="long" not-null="true"/>
</component>
<property name="isRoot" column="is_root" type="boolean"/>
<!-- Directories, two flavors. -->
<subclass name="DirectoryNodeImpl"
proxy="DirectoryNode"
abstract="true"
lazy="true">
<!-- A Layered Directory is our smart symlink thingy. -->
<subclass name="LayeredDirectoryNodeImpl"
proxy="LayeredDirectoryNode"
discriminator-value="layereddirectory" lazy="true">
<!-- The layer id is an implementation trick to disambiguate
exactly what layer is being refered to in various circumstances. -->
<property name="layerID" column="layer_id" type="long"/>
<!-- The is the moral equivalent of the value of a symlink. -->
<property name="indirection" column="indirection"
type="string" length="511" />
<!-- This marks a layered directory as either knowing itself what
it points at (true) or inheriting what it points at from its
container (false). -->
<property name="primaryIndirection"
column="primary_indirection" type="boolean"/>
<!-- Map of names to DirectoryEntries. -->
</subclass>
<!-- Just plain directories. -->
<subclass name="PlainDirectoryNodeImpl"
discriminator-value="plaindirectory" proxy="PlainDirectoryNode" lazy="true">
<!-- For reference count based garbage collection of purged nodes
to work we need to specially mark the root directory of
a Repository as special so that its absence of parents will
not cause it to be vacuumed away. TODO: for ease of queries,
this probably wants to be in the base class. -->
<!-- A map of names to DirectoryEntries. In the AVM world, it makes sense
that nodes don't know there own names, only their containers do. -->
</subclass>
</subclass>
<!-- There are two kinds of files, plain and symlinky. -->
<subclass name="FileNodeImpl"
proxy="FileNode"
abstract="true"
lazy="false">
<!-- Plain files just have a reference to a Content object. -->
<subclass discriminator-value="plainfile"
name="PlainFileNodeImpl" proxy="PlainFileNode" lazy="true">
<many-to-one name="content" column="content_id"
class="FileContentImpl" fetch="join" cascade="save-update">
</many-to-one>
</subclass>
<!-- Layered files are almost exactly copy on write symlinks. -->
<subclass name="LayeredFileNodeImpl"
discriminator-value="layeredfile" proxy="LayeredFileNode" lazy="true">
<property name="indirection" type="string" length="511"
column="indirection" />
</subclass>
</subclass>
</class>
<!-- Contents are objects to hang actual bytestreams off. They are explicitly reference
counted. -->
<class table="contents" name="FileContentImpl" proxy="FileContent"
optimistic-lock="version">
<cache usage="read-write" />
<id name="id" column="id" type="long"/>
<version name="vers" column="vers" type="long"/>
<!-- The reference count. Contents are explicitly reference counted for now,
however it make sense to fold this into a generalized garbage collection
scheme. -->
<property name="refCount" column="ref_count" type="int"
not-null="true"/>
</class>
<!-- A Repository is the what we used to call a virtual repository.
Each Repository has it's own branch ids and layer ids but shares node ids
with other repositories. The physical repository is structured this way
for better scaling. -->
<class table="repositories" name="RepositoryImpl"
proxy="Repository" optimistic-lock="version">
<cache usage="read-write"/>
<id name="name" column="name" type="string"/>
<version name="vers" column="vers" type="long"/>
<property type="int" name="nextVersionID"
column="next_version_id" not-null="true"/>
<property type="string" name="creator" column="creator" not-null="true"/>
<property type="long" name="createDate" column="create_date" not-null="true"/>
<!-- Every Repository has a root directory that is the current root directory. -->
<!-- This should be not-null but hibernate (or my own idiocy) makes that difficult. -->
<many-to-one name="root" class="DirectoryNodeImpl"
column="current_root_id" unique="true" cascade="save-update">
</many-to-one>
</class>
<class name="VersionRootImpl" proxy="VersionRoot" table="version_roots">
<!-- <cache usage="read-write"/> -->
<id column="id" type="long">
<generator class="native"></generator>
</id>
<property name="versionID" type="int" not-null="true"
column="version_id" index="version_roots_version_id_index">
</property>
<property name="createDate" type="long" not-null="true" column="create_date">
</property>
<property name="creator" type="string" column="creator"
not-null="true">
</property>
<many-to-one name="repository" column="repository_id"
class="RepositoryImpl" not-null="true">
</many-to-one>
<many-to-one name="root" class="DirectoryNodeImpl"
column="root_id" not-null="true">
</many-to-one>
</class>
<class name="ChildEntryImpl" proxy="ChildEntry" table="child_entries" optimistic-lock="version">
<cache usage="read-write"/>
<composite-id>
<key-property name="name" type="string" column="name">
</key-property>
<key-many-to-one name="parent" column="parent_id" class="DirectoryNodeImpl">
</key-many-to-one>
</composite-id>
<version name="vers" column="vers" type="long"/>
<many-to-one name="child" column="child_id" class="AVMNodeImpl"
not-null="true">
</many-to-one>
</class>
<class table="deleted_children" name="DeletedChildImpl" proxy="DeletedChild">
<cache usage="read-write"/>
<composite-id>
<key-property name="name" column="name" type="string"/>
<key-many-to-one name="parent" class="LayeredDirectoryNodeImpl"
column="parent_id"/>
</composite-id>
</class>
<class name="HistoryLinkImpl" proxy="HistoryLink" table="history_links">
<composite-id>
<key-many-to-one name="ancestor" class="AVMNodeImpl" column="ancestor"/>
<key-many-to-one name="descendent" class="AVMNodeImpl" column="descendent"/>
</composite-id>
</class>
<class name="MergeLinkImpl" proxy="MergeLink" table="merge_links">
<composite-id>
<key-many-to-one name="mfrom" class="AVMNodeImpl" column="mfrom"/>
<key-many-to-one name="mto" class="AVMNodeImpl" column="mto"/>
</composite-id>
</class>
<query name="ChildEntry.ByNameParent">
<![CDATA[
from ChildEntryImpl ce
where
ce.name = :name and ce.parent = :parent
]]>
</query>
<query name="ChildEntry.ByParent">
<![CDATA[
from ChildEntryImpl ce
where
ce.parent = :parent
]]>
</query>
<query name="ChildEntry.ByParentChild">
<![CDATA[
from ChildEntryImpl ce
where
ce.child = :child and ce.parent = :parent
]]>
</query>
<query name="ChildEntry.DeleteByParent">
<![CDATA[
delete ChildEntryImpl ce
where ce.parent = :parent
]]>
</query>
<query name="AVMNode.ByNewInRepo">
<![CDATA[
from AVMNodeImpl a
where
a.repository = :repo and a.isNew = true
]]>
</query>
<query name="AVMNode.GetDescendents">
<![CDATA[
select hl.descendent
from HistoryLinkImpl hl
where hl.ancestor = :node
]]>
</query>
<query name="HistoryLink.ByAncestor">
<![CDATA[
from HistoryLinkImpl hl
where hl.ancestor = :node
]]>
</query>
<query name="AVMNode.GetMergedTo">
<![CDATA[
select ml.mto
from MergeLinkImpl ml
where ml.mfrom = :merged
]]>
</query>
<query name="MergeLink.ByFrom">
<![CDATA[
from MergeLinkImpl ml
where ml.mfrom = :merged
]]>
</query>
<query name="VersionRoot.GetVersionRoot">
<![CDATA[
select v.root
from VersionRootImpl v
where
v.repository = :rep and v.versionID = :version
]]>
</query>
<query name="VersionRoot.VersionByID">
<![CDATA[
from VersionRootImpl v
where
v.repository = :rep and v.versionID = :version
]]>
</query>
<query name="DeletedChild.ByNameParent">
<![CDATA[
from DeletedChildImpl dc
where
dc.parent = :parent and dc.name = :name
]]>
</query>
<query name="DeletedChild.ByParent">
<![CDATA[
from DeletedChildImpl dc
where
dc.parent = :parent
]]>
</query>
<query name="DeletedChild.DeleteByParent">
<![CDATA[
delete DeletedChildImpl dc
where dc.parent = :parent
]]>
</query>
<query name="FindOrphans">
<![CDATA[
from AVMNodeImpl an
where
an not in ( select ce.child
from ChildEntryImpl ce )
and an.isRoot = false
]]>
</query>
</hibernate-mapping>