Moving to root below branch label

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2005-12-08 07:13:07 +00:00
commit e1e6508fec
1095 changed files with 230566 additions and 0 deletions

View File

@@ -0,0 +1,229 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.domain.hibernate;
import org.alfresco.repo.domain.ChildAssoc;
import org.alfresco.repo.domain.Node;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.EqualsHelper;
/**
* @author Derek Hulley
*/
public class ChildAssocImpl implements ChildAssoc
{
private Long id;
private Node parent;
private Node child;
private QName typeQName;
private QName qName;
private boolean isPrimary;
private int index;
private transient ChildAssociationRef childAssocRef;
public ChildAssocImpl()
{
setIndex(Integer.MAX_VALUE); // comes last
}
public void buildAssociation(Node parentNode, Node childNode)
{
// add the forward associations
this.setParent(parentNode);
this.setChild(childNode);
// add the inverse associations
parentNode.getChildAssocs().add(this);
childNode.getParentAssocs().add(this);
}
public void removeAssociation()
{
// maintain inverse assoc from parent node to this instance
this.getParent().getChildAssocs().remove(this);
// maintain inverse assoc from child node to this instance
this.getChild().getParentAssocs().remove(this);
}
public synchronized ChildAssociationRef getChildAssocRef()
{
if (childAssocRef == null)
{
childAssocRef = new ChildAssociationRef(
this.typeQName,
getParent().getNodeRef(),
this.qName,
getChild().getNodeRef(),
this.isPrimary,
-1);
}
return childAssocRef;
}
public String toString()
{
StringBuffer sb = new StringBuffer(32);
sb.append("ChildAssoc")
.append("[ parent=").append(parent)
.append(", child=").append(child)
.append(", name=").append(getQname())
.append(", isPrimary=").append(isPrimary)
.append("]");
return sb.toString();
}
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
else if (obj == this)
{
return true;
}
else if (!(obj instanceof ChildAssoc))
{
return false;
}
ChildAssoc that = (ChildAssoc) obj;
return (this.getIsPrimary() == that.getIsPrimary()
&& EqualsHelper.nullSafeEquals(this.getTypeQName(), that.getTypeQName())
&& EqualsHelper.nullSafeEquals(this.getQname(), that.getQname())
&& EqualsHelper.nullSafeEquals(this.getParent(), that.getParent())
&& EqualsHelper.nullSafeEquals(this.getChild(), that.getChild()));
}
public int hashCode()
{
return (qName == null ? 0 : qName.hashCode());
}
/**
* Orders the child associations by ID. A smaller ID has a higher priority.
* This may change once we introduce a changeable index against which to order.
*/
public int compareTo(ChildAssoc another)
{
if (this == another)
{
return 0;
}
int thisIndex = this.getIndex();
int anotherIndex = another.getIndex();
Long thisId = this.getId();
Long anotherId = another.getId();
if (thisId == null) // this ID has not been set, make this instance greater
{
return -1;
}
else if (anotherId == null) // other ID has not been set, make this instance lesser
{
return 1;
}
else if (thisIndex == anotherIndex) // use the explicit index
{
return thisId.compareTo(anotherId);
}
else // fallback on order of creation
{
return (thisIndex > anotherIndex) ? 1 : -1; // a lower index, make this instance lesser
}
}
public Long getId()
{
return id;
}
/**
* For Hibernate use
*/
private void setId(Long id)
{
this.id = id;
}
public Node getParent()
{
return parent;
}
/**
* For Hibernate use
*/
private void setParent(Node parentNode)
{
this.parent = parentNode;
}
public Node getChild()
{
return child;
}
/**
* For Hibernate use
*/
private void setChild(Node node)
{
child = node;
}
public QName getTypeQName()
{
return typeQName;
}
public void setTypeQName(QName typeQName)
{
this.typeQName = typeQName;
}
public QName getQname()
{
return qName;
}
public void setQname(QName qname)
{
this.qName = qname;
}
public boolean getIsPrimary()
{
return isPrimary;
}
public void setIsPrimary(boolean isPrimary)
{
this.isPrimary = isPrimary;
}
public int getIndex()
{
return index;
}
public void setIndex(int index)
{
this.index = index;
}
}

View File

@@ -0,0 +1,465 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.domain.hibernate;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.domain.ChildAssoc;
import org.alfresco.repo.domain.Node;
import org.alfresco.repo.domain.NodeAssoc;
import org.alfresco.repo.domain.NodeKey;
import org.alfresco.repo.domain.NodeStatus;
import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.repo.domain.Store;
import org.alfresco.repo.domain.StoreKey;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.BaseSpringTest;
import org.alfresco.util.GUID;
/**
* Test persistence and retrieval of Hibernate-specific implementations of the
* {@link org.alfresco.repo.domain.Node} interface
*
* @author Derek Hulley
*/
public class HibernateNodeTest extends BaseSpringTest
{
private static final String TEST_NAMESPACE = "http://www.alfresco.org/test/HibernateNodeTest";
private Store store;
public HibernateNodeTest()
{
}
protected void onSetUpInTransaction() throws Exception
{
store = new StoreImpl();
StoreKey storeKey = new StoreKey(StoreRef.PROTOCOL_WORKSPACE,
"TestWorkspace@" + System.currentTimeMillis());
store.setKey(storeKey);
// persist so that it is present in the hibernate cache
getSession().save(store);
}
protected void onTearDownInTransaction()
{
// force a flush to ensure that the database updates succeed
getSession().flush();
getSession().clear();
}
public void testSetUp() throws Exception
{
assertNotNull("Workspace not initialised", store);
}
public void testGetStore() throws Exception
{
NodeKey key = new NodeKey("Random Protocol", "Random Identifier", "AAA");
// create the node status
NodeStatus nodeStatus = new NodeStatusImpl();
nodeStatus.setKey(key);
nodeStatus.setDeleted(false);
nodeStatus.setChangeTxnId("txn:123");
getSession().save(nodeStatus);
// create a new Node
Node node = new NodeImpl();
node.setKey(key);
node.setStore(store); // not meaningful as it contradicts the key
node.setTypeQName(ContentModel.TYPE_CONTAINER);
node.setStatus(nodeStatus);
// persist it
try
{
Serializable id = getSession().save(node);
fail("No store exists");
}
catch (Throwable e)
{
// expected
}
// this should not solve the problem
node.setStore(store);
// persist it
try
{
Serializable id = getSession().save(node);
fail("Setting store does not persist protocol and identifier attributes");
}
catch (Throwable e)
{
// expected
}
// fix the key
key = new NodeKey(store.getKey().getProtocol(), store.getKey().getIdentifier(), "AAA");
node.setKey(key);
// now it should work
Serializable id = getSession().save(node);
// throw the reference away and get the a new one for the id
node = (Node) getSession().load(NodeImpl.class, id);
assertNotNull("Node not found", node);
// check that the store has been loaded
Store loadedStore = node.getStore();
assertNotNull("Store not present on node", loadedStore);
assertEquals("Incorrect store key", store, loadedStore);
}
public void testNodeStatus()
{
NodeKey key = new NodeKey(store.getKey(), "AAA");
// create the node status
NodeStatus nodeStatus = new NodeStatusImpl();
nodeStatus.setKey(key);
nodeStatus.setDeleted(false);
nodeStatus.setChangeTxnId("txn:123");
getSession().save(nodeStatus);
// it must be able to exist without the node
flushAndClear();
// create a new Node
Node node = new NodeImpl();
node.setStore(store);
node.setKey(key);
node.setStore(store); // not meaningful as it contradicts the key
node.setTypeQName(ContentModel.TYPE_CONTAINER);
node.setStatus(nodeStatus);
Serializable id = getSession().save(node);
// flush
flushAndClear();
// is the status retrievable
node = (Node) getSession().get(NodeImpl.class, id);
nodeStatus = node.getStatus();
// change the values
nodeStatus.setChangeTxnId("txn:456");
nodeStatus.setDeleted(true);
// delete the node
getSession().delete(node);
// flush
flushAndClear();
}
/**
* Check that properties can be persisted and retrieved
*/
public void testProperties() throws Exception
{
NodeKey key = new NodeKey(store.getKey(), "AAA");
// create the node status
NodeStatus nodeStatus = new NodeStatusImpl();
nodeStatus.setKey(key);
nodeStatus.setDeleted(false);
nodeStatus.setChangeTxnId("txn:123");
getSession().save(nodeStatus);
// create a new Node
Node node = new NodeImpl();
node.setKey(key);
node.setTypeQName(ContentModel.TYPE_CONTAINER);
node.setStatus(nodeStatus);
// give it a property map
Map<QName, PropertyValue> propertyMap = new HashMap<QName, PropertyValue>(5);
QName propertyQName = QName.createQName("{}A");
PropertyValue propertyValue = new PropertyValue(DataTypeDefinition.TEXT, "AAA");
propertyMap.put(propertyQName, propertyValue);
node.getProperties().putAll(propertyMap);
// persist it
Serializable id = getSession().save(node);
// throw the reference away and get the a new one for the id
node = (Node) getSession().load(NodeImpl.class, id);
assertNotNull("Node not found", node);
// extract the Map
propertyMap = node.getProperties();
assertNotNull("Map not persisted", propertyMap);
// ensure that the value is present
assertNotNull("Property value not present in map", QName.createQName("{}A"));
}
/**
* Check that aspect qnames can be added and removed from a node and that they
* are persisted correctly
*/
public void testAspects() throws Exception
{
NodeKey key = new NodeKey(store.getKey(), GUID.generate());
// create the node status
NodeStatus nodeStatus = new NodeStatusImpl();
nodeStatus.setKey(key);
nodeStatus.setDeleted(false);
nodeStatus.setChangeTxnId("txn:123");
getSession().save(nodeStatus);
// make a real node
Node node = new NodeImpl();
node.setKey(key);
node.setStore(store);
node.setTypeQName(ContentModel.TYPE_CMOBJECT);
node.setStatus(nodeStatus);
// add some aspects
QName aspect1 = QName.createQName(TEST_NAMESPACE, "1");
QName aspect2 = QName.createQName(TEST_NAMESPACE, "2");
QName aspect3 = QName.createQName(TEST_NAMESPACE, "3");
QName aspect4 = QName.createQName(TEST_NAMESPACE, "4");
Set<QName> aspects = node.getAspects();
aspects.add(aspect1);
aspects.add(aspect2);
aspects.add(aspect3);
aspects.add(aspect4);
assertFalse("Set did not eliminate duplicate aspect qname", aspects.add(aspect4));
// persist
Serializable id = getSession().save(node);
// flush and clear
flushAndClear();
// get node and check aspects
node = (Node) getSession().get(NodeImpl.class, id);
assertNotNull("Node not persisted", node);
aspects = node.getAspects();
assertEquals("Not all aspects persisted", 4, aspects.size());
}
public void testNodeAssoc() throws Exception
{
NodeKey sourceKey = new NodeKey(store.getKey(), GUID.generate());
// make a source node
NodeStatus sourceNodeStatus = new NodeStatusImpl();
sourceNodeStatus.setKey(sourceKey);
sourceNodeStatus.setDeleted(false);
sourceNodeStatus.setChangeTxnId("txn:123");
getSession().save(sourceNodeStatus);
Node sourceNode = new NodeImpl();
sourceNode.setKey(sourceKey);
sourceNode.setStore(store);
sourceNode.setTypeQName(ContentModel.TYPE_CMOBJECT);
sourceNode.setStatus(sourceNodeStatus);
Serializable realNodeKey = getSession().save(sourceNode);
// make a container node
NodeKey targetKey = new NodeKey(store.getKey(), GUID.generate());
NodeStatus targetNodeStatus = new NodeStatusImpl();
targetNodeStatus.setKey(targetKey);
targetNodeStatus.setDeleted(false);
targetNodeStatus.setChangeTxnId("txn:123");
getSession().save(targetNodeStatus);
Node targetNode = new NodeImpl();
targetNode.setKey(targetKey);
targetNode.setStore(store);
targetNode.setTypeQName(ContentModel.TYPE_CONTAINER);
targetNode.setStatus(targetNodeStatus);
Serializable containerNodeKey = getSession().save(targetNode);
// create an association between them
NodeAssoc assoc = new NodeAssocImpl();
assoc.setTypeQName(QName.createQName("next"));
assoc.buildAssociation(sourceNode, targetNode);
getSession().save(assoc);
// make another association between the same two nodes
assoc = new NodeAssocImpl();
assoc.setTypeQName(QName.createQName("helper"));
assoc.buildAssociation(sourceNode, targetNode);
getSession().save(assoc);
// flush and clear the session
getSession().flush();
getSession().clear();
// reload the source
sourceNode = (Node) getSession().get(NodeImpl.class, sourceKey);
assertNotNull("Source node not found", sourceNode);
// check that the associations are present
assertEquals("Expected exactly 2 target assocs", 2, sourceNode.getTargetNodeAssocs().size());
// reload the target
targetNode = (Node) getSession().get(NodeImpl.class, targetKey);
assertNotNull("Target node not found", targetNode);
// check that the associations are present
assertEquals("Expected exactly 2 source assocs", 2, targetNode.getSourceNodeAssocs().size());
}
public void testChildAssoc() throws Exception
{
// make a content node
NodeKey key = new NodeKey(store.getKey(), GUID.generate());
NodeStatus contentNodeStatus = new NodeStatusImpl();
contentNodeStatus.setKey(key);
contentNodeStatus.setDeleted(false);
contentNodeStatus.setChangeTxnId("txn:123");
getSession().save(contentNodeStatus);
Node contentNode = new NodeImpl();
contentNode.setKey(key);
contentNode.setStore(store);
contentNode.setTypeQName(ContentModel.TYPE_CONTENT);
contentNode.setStatus(contentNodeStatus);
Serializable contentNodeKey = getSession().save(contentNode);
// make a container node
key = new NodeKey(store.getKey(), GUID.generate());
NodeStatus containerNodeStatus = new NodeStatusImpl();
containerNodeStatus.setKey(key);
containerNodeStatus.setDeleted(false);
containerNodeStatus.setChangeTxnId("txn:123");
getSession().save(containerNodeStatus);
Node containerNode = new NodeImpl();
containerNode.setKey(key);
containerNode.setStore(store);
containerNode.setTypeQName(ContentModel.TYPE_CONTAINER);
containerNode.setStatus(containerNodeStatus);
Serializable containerNodeKey = getSession().save(containerNode);
// create an association to the content
ChildAssoc assoc1 = new ChildAssocImpl();
assoc1.setIsPrimary(true);
assoc1.setTypeQName(QName.createQName(null, "type1"));
assoc1.setQname(QName.createQName(null, "number1"));
assoc1.buildAssociation(containerNode, contentNode);
getSession().save(assoc1);
// make another association between the same two parent and child nodes
ChildAssoc assoc2 = new ChildAssocImpl();
assoc2.setIsPrimary(true);
assoc2.setTypeQName(QName.createQName(null, "type1"));
assoc2.setQname(QName.createQName(null, "number2"));
assoc2.buildAssociation(containerNode, contentNode);
getSession().save(assoc2);
assertFalse("Hashcode incorrent", assoc2.hashCode() == 0);
assertNotSame("Assoc equals failure", assoc1, assoc2);
// flushAndClear();
// reload the container
containerNode = (Node) getSession().get(NodeImpl.class, containerNodeKey);
assertNotNull("Node not found", containerNode);
// check
assertEquals("Expected exactly 2 children", 2, containerNode.getChildAssocs().size());
for (Iterator iterator = containerNode.getChildAssocs().iterator(); iterator.hasNext(); /**/)
{
ChildAssoc assoc = (ChildAssoc) iterator.next();
// the node id must be known
assertNotNull("Node not populated on assoc", assoc.getChild());
assertEquals("Node key on child assoc is incorrect", contentNodeKey,
assoc.getChild().getKey());
}
// check that we can traverse the association from the child
Collection<ChildAssoc> parentAssocs = contentNode.getParentAssocs();
assertEquals("Expected exactly 2 parent assocs", 2, parentAssocs.size());
parentAssocs = new HashSet<ChildAssoc>(parentAssocs);
for (ChildAssoc assoc : parentAssocs)
{
// maintain inverse assoc sets
assoc.removeAssociation();
// remove the assoc
getSession().delete(assoc);
}
// check that the child now has zero parents
parentAssocs = contentNode.getParentAssocs();
assertEquals("Expected exactly 0 parent assocs", 0, parentAssocs.size());
}
/**
* Allows tracing of L2 cache
*/
public void testCaching() throws Exception
{
NodeKey key = new NodeKey(store.getKey(), GUID.generate());
// make a node
NodeStatus nodeStatus = new NodeStatusImpl();
nodeStatus.setKey(key);
nodeStatus.setDeleted(false);
nodeStatus.setChangeTxnId("txn:123");
getSession().save(nodeStatus);
Node node = new NodeImpl();
node.setKey(key);
node.setStore(store);
node.setTypeQName(ContentModel.TYPE_CONTENT);
node.setStatus(nodeStatus);
getSession().save(node);
// add some aspects to the node
Set<QName> aspects = node.getAspects();
aspects.add(ContentModel.ASPECT_AUDITABLE);
// add some properties
Map<QName, PropertyValue> properties = node.getProperties();
properties.put(ContentModel.PROP_NAME, new PropertyValue(DataTypeDefinition.TEXT, "ABC"));
// check that the session hands back the same instance
Node checkNode = (Node) getSession().get(NodeImpl.class, key);
assertNotNull(checkNode);
assertTrue("Node retrieved was not same instance", checkNode == node);
Set<QName> checkAspects = checkNode.getAspects();
assertTrue("Aspect set retrieved was not the same instance", checkAspects == aspects);
assertEquals("Incorrect number of aspects", 1, checkAspects.size());
QName checkQName = (QName) checkAspects.toArray()[0];
assertTrue("QName retrieved was not the same instance", checkQName == ContentModel.ASPECT_AUDITABLE);
Map<QName, PropertyValue> checkProperties = checkNode.getProperties();
assertTrue("Propery map retrieved was not the same instance", checkProperties == properties);
assertTrue("Property not found", checkProperties.containsKey(ContentModel.PROP_NAME));
// assertTrue("Property value instance retrieved not the same", checkProperties)
flushAndClear();
// commit the transaction
setComplete();
endTransaction();
TransactionService transactionService = (TransactionService) applicationContext.getBean("transactionComponent");
UserTransaction txn = transactionService.getUserTransaction();
try
{
txn.begin();
// check that the L2 cache hands back the same instance
checkNode = (Node) getSession().get(NodeImpl.class, key);
assertNotNull(checkNode);
checkAspects = checkNode.getAspects();
// assertTrue("Node retrieved was not same instance", checkNode == node);
txn.commit();
}
catch (Throwable e)
{
txn.rollback();
}
}
}

View File

@@ -0,0 +1,333 @@
<?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>
<typedef class="org.alfresco.repo.domain.hibernate.QNameUserType" name="QName" />
<class
name="org.alfresco.repo.domain.hibernate.NodeImpl"
proxy="org.alfresco.repo.domain.Node"
table="node"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
lazy="true"
optimistic-lock="version" >
<!-- composite PK -->
<composite-id name="key" class="org.alfresco.repo.domain.NodeKey">
<key-property name="protocol" length="50" />
<key-property name="identifier" length="100" />
<key-property name="guid" length="36"/>
</composite-id>
<property name="typeQName" column="type_qname" type="QName" length="255" not-null="true" />
<!-- forward assoc to node status -->
<one-to-one
name="status"
class="org.alfresco.repo.domain.hibernate.NodeStatusImpl"
constrained="true"
lazy="no-proxy"
fetch="select">
</one-to-one>
<!-- forward assoc to properties -->
<map
name="properties"
table="node_properties"
lazy="false"
fetch="join"
sort="unsorted"
inverse="false"
optimistic-lock="true"
cascade="delete" >
<key>
<column name="protocol" length="50" />
<column name="identifier" length="100" />
<column name="guid" length="36" />
</key>
<map-key column="qname" type="QName" length="128" />
<composite-element class="org.alfresco.repo.domain.PropertyValue" >
<property name="actualType" column="actual_type" type="string" length="15" not-null="true" />
<property name="multiValued" column="multi_valued" type="boolean" not-null="true" />
<property name="persistedType" column="persisted_type" type="string" length="15" not-null="true" />
<property name="booleanValue" column="boolean_value" type="boolean" />
<property name="longValue" column="long_value" type="long" />
<property name="floatValue" column="float_value" type="float" />
<property name="doubleValue" column="double_value" type="double" />
<property name="stringValue" column="string_value" type="string" length="1024"/>
<property name="serializableValue" column="serializable_value" type="serializable" length="16384"/>
</composite-element>
</map>
<!-- forward assoc to aspects -->
<set
name="aspects"
table="node_aspects"
lazy="true"
sort="unsorted"
inverse="false"
fetch="select"
optimistic-lock="true"
cascade="delete" >
<key>
<column name="protocol" length="50" />
<column name="identifier" length="100" />
<column name="guid" length="36" />
</key>
<element column="qname" type="QName" length="128"/>
</set>
<!-- forward assoc to store -->
<many-to-one
name="store"
class="org.alfresco.repo.domain.hibernate.StoreImpl"
not-null="true"
insert="false"
update="false"
lazy="no-proxy"
optimistic-lock="true"
fetch="select">
<column name="protocol" />
<column name="identifier" />
</many-to-one>
<!-- inverse assoc to parent childassocs -->
<bag
name="parentAssocs"
lazy="true"
inverse="true"
cascade="none"
optimistic-lock="true"
fetch="select" >
<key>
<column name="child_protocol" />
<column name="child_identifier" />
<column name="child_guid" length="36" />
</key>
<one-to-many class="org.alfresco.repo.domain.hibernate.ChildAssocImpl" />
</bag>
<!-- inverse assoc to child childassocs -->
<bag
name="childAssocs"
inverse="true"
lazy="true"
cascade="none"
optimistic-lock="true"
fetch="select" >
<key>
<column name="parent_protocol" />
<column name="parent_identifier" />
<column name="parent_guid" length="36" />
</key>
<one-to-many class="org.alfresco.repo.domain.hibernate.ChildAssocImpl" />
</bag>
<!-- inverse assoc to source nodeassocs -->
<bag
name="sourceNodeAssocs"
inverse="true"
cascade="none"
optimistic-lock="true" >
<key>
<column name="target_protocol" />
<column name="target_identifier" />
<column name="target_guid" length="36" />
</key>
<one-to-many class="org.alfresco.repo.domain.hibernate.NodeAssocImpl" />
</bag>
<!-- inverse assoc to target nodeassocs -->
<bag
name="targetNodeAssocs"
inverse="true"
cascade="none"
optimistic-lock="true" >
<key>
<column name="source_protocol" />
<column name="source_identifier" />
<column name="source_guid" length="36" />
</key>
<one-to-many class="org.alfresco.repo.domain.hibernate.NodeAssocImpl" />
</bag>
</class>
<class
name="org.alfresco.repo.domain.hibernate.NodeStatusImpl"
proxy="org.alfresco.repo.domain.NodeStatus"
table="node_status"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
lazy="true"
optimistic-lock="version" >
<!-- composite PK -->
<composite-id name="key" class="org.alfresco.repo.domain.NodeKey">
<key-property name="protocol" length="50" />
<key-property name="identifier" length="100" />
<key-property name="guid" length="36"/>
</composite-id>
<property name="changeTxnId" column="change_txn_id" type="string" length="56" not-null="true" />
<property name="deleted" column="deleted" type="boolean" not-null="true" />
</class>
<class
name="org.alfresco.repo.domain.hibernate.ChildAssocImpl"
proxy="org.alfresco.repo.domain.ChildAssoc"
dynamic-insert="false"
dynamic-update="false"
lazy="true"
optimistic-lock="version"
table="child_assoc" >
<id
name="id"
column="id"
type="long" >
<generator class="increment" />
</id>
<property name="typeQName" column="type_qname" type="QName" length="255" not-null="true" />
<property name="qname" column="qname" type="QName" length="255" not-null="true" />
<property name="isPrimary" />
<property name="index" column="assoc_index" />
<!-- forward assoc to parent node -->
<many-to-one
name="parent"
class="org.alfresco.repo.domain.hibernate.NodeImpl"
lazy="false"
fetch="join"
optimistic-lock="true"
not-null="true" >
<column name="parent_protocol" />
<column name="parent_identifier" />
<column name="parent_guid" length="36" />
</many-to-one>
<!-- forward assoc to child node -->
<many-to-one
name="child"
lazy="false"
fetch="join"
class="org.alfresco.repo.domain.hibernate.NodeImpl"
optimistic-lock="true"
not-null="true" >
<column name="child_protocol" />
<column name="child_identifier" />
<column name="child_guid" length="36" />
</many-to-one>
</class>
<class
name="org.alfresco.repo.domain.hibernate.NodeAssocImpl"
proxy="org.alfresco.repo.domain.NodeAssoc"
table="node_assoc" >
<id
name="id"
column="id"
type="long" >
<generator class="increment" />
</id>
<property name="typeQName" column="type_qname" type="QName" length="255" not-null="true" />
<!-- forward assoc to source node -->
<many-to-one
name="source"
class="org.alfresco.repo.domain.hibernate.NodeImpl"
not-null="true" >
<column name="source_protocol" />
<column name="source_identifier" />
<column name="source_guid" length="36" />
</many-to-one>
<!-- forward assoc to target node -->
<many-to-one
name="target"
class="org.alfresco.repo.domain.hibernate.NodeImpl"
not-null="true" >
<column name="target_protocol" />
<column name="target_identifier" />
<column name="target_guid" length="36" />
</many-to-one>
</class>
<query name="store.GetAllStores">
select
store
from
org.alfresco.repo.domain.hibernate.StoreImpl as store
</query>
<query name="node.GetNodeAssoc">
select
assoc
from
org.alfresco.repo.domain.hibernate.NodeImpl as source
join source.targetNodeAssocs as assoc
join assoc.target as target
where
source.key.protocol = :sourceKeyProtocol and
source.key.identifier = :sourceKeyIdentifier and
source.key.guid = :sourceKeyGuid and
assoc.typeQName = :assocTypeQName and
target.key.protocol = :targetKeyProtocol and
target.key.identifier = :targetKeyIdentifier and
target.key.guid = :targetKeyGuid
</query>
<query name="node.GetNodeAssocTargets">
select
target
from
org.alfresco.repo.domain.hibernate.NodeImpl as source
join source.targetNodeAssocs as assoc
join assoc.target as target
where
source.key.protocol = :sourceKeyProtocol and
source.key.identifier = :sourceKeyIdentifier and
source.key.guid = :sourceKeyGuid and
assoc.typeQName = :assocTypeQName
</query>
<query name="node.GetNodeAssocSources">
select
source
from
org.alfresco.repo.domain.hibernate.NodeImpl as target
join target.sourceNodeAssocs as assoc
join assoc.source as source
where
target.key.protocol = :targetKeyProtocol and
target.key.identifier = :targetKeyIdentifier and
target.key.guid = :targetKeyGuid and
assoc.typeQName = :assocTypeQName
</query>
<query name="node.GetNextChangeTxnIds">
select distinct
status.changeTxnId
from
org.alfresco.repo.domain.hibernate.NodeStatusImpl as status
where
status.changeTxnId > :currentTxnId
order by
status.changeTxnId
</query>
<query name="node.GetChangedNodeStatusesCount">
select
count(status.changeTxnId)
from
org.alfresco.repo.domain.hibernate.NodeStatusImpl as status
where
status.key.protocol = :storeProtocol and
status.key.identifier = :storeIdentifier and
status.deleted = :deleted and
status.changeTxnId = :changeTxnId
</query>
<query name="node.GetChangedNodeStatuses">
select
status
from
org.alfresco.repo.domain.hibernate.NodeStatusImpl as status
where
status.key.protocol = :storeProtocol and
status.key.identifier = :storeIdentifier and
status.deleted = :deleted and
status.changeTxnId = :changeTxnId
</query>
</hibernate-mapping>

View File

@@ -0,0 +1,155 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.domain.hibernate;
import org.alfresco.repo.domain.Node;
import org.alfresco.repo.domain.NodeAssoc;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.EqualsHelper;
/**
* Hibernate-specific implementation of the generic node association
*
* @author Derek Hulley
*/
public class NodeAssocImpl implements NodeAssoc
{
private long id;
private Node source;
private Node target;
private QName typeQName;
private transient AssociationRef nodeAssocRef;
public NodeAssocImpl()
{
}
public void buildAssociation(Node sourceNode, Node targetNode)
{
// add the forward associations
this.setTarget(targetNode);
this.setSource(sourceNode);
// add the inverse associations
sourceNode.getTargetNodeAssocs().add(this);
targetNode.getSourceNodeAssocs().add(this);
}
public void removeAssociation()
{
// maintain inverse assoc from source node to this instance
this.getSource().getTargetNodeAssocs().remove(this);
// maintain inverse assoc from target node to this instance
this.getTarget().getSourceNodeAssocs().remove(this);
}
public synchronized AssociationRef getNodeAssocRef()
{
if (nodeAssocRef == null)
{
nodeAssocRef = new AssociationRef(getSource().getNodeRef(),
this.typeQName,
getTarget().getNodeRef());
}
return nodeAssocRef;
}
public String toString()
{
StringBuffer sb = new StringBuffer(32);
sb.append("NodeAssoc")
.append("[ source=").append(source)
.append(", target=").append(target)
.append(", name=").append(getTypeQName())
.append("]");
return sb.toString();
}
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
else if (obj == this)
{
return true;
}
else if (!(obj instanceof NodeAssoc))
{
return false;
}
NodeAssoc that = (NodeAssoc) obj;
return (EqualsHelper.nullSafeEquals(this.getTypeQName(), that.getTypeQName())
&& EqualsHelper.nullSafeEquals(this.getTarget(), that.getTarget())
&& EqualsHelper.nullSafeEquals(this.getSource(), that.getSource()));
}
public int hashCode()
{
return (typeQName == null ? 0 : typeQName.hashCode());
}
public long getId()
{
return id;
}
/**
* For Hibernate use
*/
private void setId(long id)
{
this.id = id;
}
public Node getSource()
{
return source;
}
/**
* For internal use
*/
private void setSource(Node source)
{
this.source = source;
}
public Node getTarget()
{
return target;
}
/**
* For internal use
*/
private void setTarget(Node target)
{
this.target = target;
}
public QName getTypeQName()
{
return typeQName;
}
public void setTypeQName(QName typeQName)
{
this.typeQName = typeQName;
}
}

View File

@@ -0,0 +1,228 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.domain.hibernate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.alfresco.repo.domain.ChildAssoc;
import org.alfresco.repo.domain.Node;
import org.alfresco.repo.domain.NodeAssoc;
import org.alfresco.repo.domain.NodeKey;
import org.alfresco.repo.domain.NodeStatus;
import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.repo.domain.Store;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.hibernate.mapping.Bag;
/**
* Bean containing all the persistence data representing a <b>node</b>.
* <p>
* This implementation of the {@link org.alfresco.repo.domain.Node Node} interface is
* Hibernate specific.
*
* @author Derek Hulley
*/
public class NodeImpl implements Node
{
private NodeKey key;
private Store store;
private QName typeQName;
private NodeStatus status;
private Set<QName> aspects;
private Collection<NodeAssoc> sourceNodeAssocs;
private Collection<NodeAssoc> targetNodeAssocs;
private Collection<ChildAssoc> parentAssocs;
private Collection<ChildAssoc> childAssocs;
private Map<QName, PropertyValue> properties;
private transient NodeRef nodeRef;
public NodeImpl()
{
aspects = new HashSet<QName>(5);
sourceNodeAssocs = new ArrayList<NodeAssoc>(3);
targetNodeAssocs = new ArrayList<NodeAssoc>(3);
parentAssocs = new ArrayList<ChildAssoc>(3);
childAssocs = new ArrayList<ChildAssoc>(3);
properties = new HashMap<QName, PropertyValue>(5);
}
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
else if (obj == this)
{
return true;
}
else if (!(obj instanceof Node))
{
return false;
}
Node that = (Node) obj;
return (this.getKey().equals(that.getKey()));
}
public int hashCode()
{
return getKey().hashCode();
}
public NodeKey getKey() {
return key;
}
public void setKey(NodeKey key) {
this.key = key;
}
public Store getStore()
{
return store;
}
public synchronized void setStore(Store store)
{
this.store = store;
this.nodeRef = null;
}
public QName getTypeQName()
{
return typeQName;
}
public void setTypeQName(QName typeQName)
{
this.typeQName = typeQName;
}
public NodeStatus getStatus()
{
return status;
}
public void setStatus(NodeStatus status)
{
this.status = status;
}
public Set<QName> getAspects()
{
return aspects;
}
/**
* For Hibernate use
*/
private void setAspects(Set<QName> aspects)
{
this.aspects = aspects;
}
public Collection<NodeAssoc> getSourceNodeAssocs()
{
return sourceNodeAssocs;
}
/**
* For Hibernate use
*/
private void setSourceNodeAssocs(Collection<NodeAssoc> sourceNodeAssocs)
{
this.sourceNodeAssocs = sourceNodeAssocs;
}
public Collection<NodeAssoc> getTargetNodeAssocs()
{
return targetNodeAssocs;
}
/**
* For Hibernate use
*/
private void setTargetNodeAssocs(Collection<NodeAssoc> targetNodeAssocs)
{
this.targetNodeAssocs = targetNodeAssocs;
}
public Collection<ChildAssoc> getParentAssocs()
{
return parentAssocs;
}
/**
* For Hibernate use
*/
private void setParentAssocs(Collection<ChildAssoc> parentAssocs)
{
this.parentAssocs = parentAssocs;
}
public Collection<ChildAssoc> getChildAssocs()
{
return childAssocs;
}
/**
* For Hibernate use
*/
private void setChildAssocs(Collection<ChildAssoc> childAssocs)
{
this.childAssocs = childAssocs;
}
public Map<QName, PropertyValue> getProperties()
{
return properties;
}
/**
* For Hibernate use
*/
private void setProperties(Map<QName, PropertyValue> properties)
{
this.properties = properties;
}
/**
* Thread-safe caching of the reference is provided
*/
public synchronized NodeRef getNodeRef()
{
if (nodeRef == null && key != null)
{
nodeRef = new NodeRef(getStore().getStoreRef(), getKey().getGuid());
}
return nodeRef;
}
/**
* @see #getNodeRef()
*/
public String toString()
{
return getNodeRef().toString();
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.domain.hibernate;
import org.alfresco.repo.domain.NodeKey;
import org.alfresco.repo.domain.NodeStatus;
import org.alfresco.util.EqualsHelper;
/**
* Hibernate implementation of a <b>node status</b>
*
* @author Derek Hulley
*/
public class NodeStatusImpl implements NodeStatus
{
private NodeKey key;
private String changeTxnId;
private boolean deleted;
public int hashCode()
{
return (key == null) ? 0 : key.hashCode();
}
public boolean equals(Object obj)
{
if (obj == this)
return true;
else if (obj == null)
return false;
else if (!(obj instanceof NodeStatusImpl))
return false;
NodeStatus that = (NodeStatus) obj;
return (EqualsHelper.nullSafeEquals(this.key, that.getKey())) &&
(EqualsHelper.nullSafeEquals(this.changeTxnId, that.getChangeTxnId())) &&
(this.deleted == that.isDeleted());
}
public String toString()
{
StringBuilder sb = new StringBuilder(50);
sb.append("NodeStatus")
.append("[key=").append(key)
.append(", txn=").append(changeTxnId)
.append(", deleted=").append(deleted)
.append("]");
return sb.toString();
}
public NodeKey getKey()
{
return key;
}
public void setKey(NodeKey key)
{
this.key = key;
}
public String getChangeTxnId()
{
return changeTxnId;
}
public void setChangeTxnId(String txnId)
{
this.changeTxnId = txnId;
}
public boolean isDeleted()
{
return deleted;
}
public void setDeleted(boolean deleted)
{
this.deleted = deleted;
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.domain.hibernate;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.EqualsHelper;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
/**
* Custom type to hide the persistence of {@link org.alfresco.service.namespace.QName qname}
* instances.
*
* @author Derek Hulley
*/
public class QNameUserType implements UserType
{
private static int[] SQL_TYPES = new int[] {Types.VARCHAR};
public Class returnedClass()
{
return QName.class;
}
/**
* @see #SQL_TYPES
*/
public int[] sqlTypes()
{
return SQL_TYPES;
}
public boolean isMutable()
{
return false;
}
public boolean equals(Object x, Object y) throws HibernateException
{
return EqualsHelper.nullSafeEquals(x, y);
}
public int hashCode(Object x) throws HibernateException
{
return x.hashCode();
}
public Object deepCopy(Object value) throws HibernateException
{
// the qname is immutable
return value;
}
public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException
{
String qnameStr = rs.getString(names[0]);
if (qnameStr == null)
{
return null;
}
else
{
QName qname = QName.createQName(qnameStr);
return qname;
}
}
public void nullSafeSet(PreparedStatement stmt, Object value, int index) throws HibernateException, SQLException
{
// convert the qname to a string
stmt.setString(index, value.toString());
}
public Object replace(Object original, Object target, Object owner) throws HibernateException
{
// qname is immutable
return original;
}
public Object assemble(Serializable cached, Object owner) throws HibernateException
{
// qname is serializable
return cached;
}
public Serializable disassemble(Object value) throws HibernateException
{
// qname is serializable
return (QName) value;
}
}

View File

@@ -0,0 +1,35 @@
<?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>
<class
name="org.alfresco.repo.domain.hibernate.StoreImpl"
proxy="org.alfresco.repo.domain.Store"
table="store"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
optimistic-lock="version" >
<!-- composite PK -->
<composite-id name="key" class="org.alfresco.repo.domain.StoreKey">
<key-property name="protocol" length="100" />
<key-property name="identifier" length="100" />
</composite-id>
<!-- forward assoc to root node -->
<many-to-one
name="rootNode"
not-null="false"
lazy="false"
class="org.alfresco.repo.domain.hibernate.NodeImpl"
fetch="join" >
<column name="root_protocol" />
<column name="root_identifier" />
<column name="root_guid" />
</many-to-one>
</class>
</hibernate-mapping>

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.domain.hibernate;
import org.alfresco.repo.domain.Node;
import org.alfresco.repo.domain.Store;
import org.alfresco.repo.domain.StoreKey;
import org.alfresco.service.cmr.repository.StoreRef;
/**
* Hibernate-specific implementation of the domain entity <b>store</b>.
*
* @author Derek Hulley
*/
public class StoreImpl implements Store
{
private StoreKey key;
private Node rootNode;
private transient StoreRef storeRef;
public StoreImpl()
{
}
/**
* @see #getKey()
*/
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
else if (obj == this)
{
return true;
}
else if (!(obj instanceof Node))
{
return false;
}
Node that = (Node) obj;
return (this.getKey().equals(that.getKey()));
}
/**
* @see #getKey()
*/
public int hashCode()
{
return getKey().hashCode();
}
/**
* @see #getStoreRef()()
*/
public String toString()
{
return getStoreRef().toString();
}
public StoreKey getKey() {
return key;
}
public synchronized void setKey(StoreKey key) {
this.key = key;
this.storeRef = null;
}
public Node getRootNode()
{
return rootNode;
}
public void setRootNode(Node rootNode)
{
this.rootNode = rootNode;
}
/**
* Lazily constructs <code>StoreRef</code> instance referencing this entity
*/
public synchronized StoreRef getStoreRef()
{
if (storeRef == null && key != null)
{
storeRef = new StoreRef(key.getProtocol(), key.getIdentifier());
}
return storeRef;
}
}

View File

@@ -0,0 +1,25 @@
<?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>
<class
name="org.alfresco.repo.domain.hibernate.VersionCountImpl"
proxy="org.alfresco.repo.domain.VersionCount"
table="version_count"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
optimistic-lock="version" >
<!-- composite PK -->
<composite-id name="key" class="org.alfresco.repo.domain.StoreKey">
<key-property name="protocol" length="100" />
<key-property name="identifier" length="100" />
</composite-id>
<property name="versionCount" column="version_count" type="int" not-null="true" />
</class>
</hibernate-mapping>

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.domain.hibernate;
import org.alfresco.repo.domain.Node;
import org.alfresco.repo.domain.StoreKey;
import org.alfresco.repo.domain.VersionCount;
import org.alfresco.service.cmr.repository.StoreRef;
/**
* Hibernate-specific implementation of the domain entity <b>versioncounter</b>.
*
* @author Derek Hulley
*/
public class VersionCountImpl implements VersionCount
{
private StoreKey key;
private int versionCount;
private transient StoreRef storeRef;
public VersionCountImpl()
{
versionCount = 0;
}
/**
* @see #getKey()
*/
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
else if (obj == this)
{
return true;
}
else if (!(obj instanceof Node))
{
return false;
}
Node that = (Node) obj;
return (this.getKey().equals(that.getKey()));
}
/**
* @see #getKey()
*/
public int hashCode()
{
return getKey().hashCode();
}
/**
* @see #getKey()
*/
public String toString()
{
return getKey().toString();
}
public StoreKey getKey() {
return key;
}
public synchronized void setKey(StoreKey key) {
this.key = key;
this.storeRef = null;
}
/**
* For Hibernate use
*/
private void setVersionCount(int versionCount)
{
this.versionCount = versionCount;
}
public int incrementVersionCount()
{
return ++versionCount;
}
/**
* Reset back to 0
*/
public void resetVersionCount()
{
setVersionCount(0);
}
public int getVersionCount()
{
return versionCount;
}
}