001/* 002 * Copyright 2016 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.workflow.store; 017 018import java.util.ArrayList; 019import java.util.List; 020 021import javax.jcr.Node; 022import javax.jcr.Repository; 023import javax.jcr.RepositoryException; 024import javax.jcr.Session; 025 026import org.apache.cocoon.util.HashUtil; 027import org.apache.commons.lang.StringUtils; 028 029import org.ametys.plugins.workflow.support.WorkflowProvider; 030 031/** 032 * The generic workflow store. 033 * @see WorkflowProvider 034 */ 035public class GenericWorkflowStore extends AbstractJackrabbitWorkflowStore 036{ 037 /** Internal hash tree node type. */ 038 static final String __HTREE_NT = __NM_PREFIX + "hashSegment"; 039 040 /** 041 * Generic workflow store constructor 042 * @param repository The repository 043 */ 044 public GenericWorkflowStore(Repository repository) 045 { 046 super(repository); 047 } 048 049 @Override 050 public boolean shouldClearHistory() 051 { 052 return true; 053 } 054 055 @Override 056 protected void _createRootNode() throws RepositoryException 057 { 058 Session session = null; 059 try 060 { 061 session = _getSession(); 062 063 Node root = session.getRootNode(); 064 if (!root.hasNode(__ROOT_NODE)) 065 { 066 if (_log.isDebugEnabled()) 067 { 068 _log.debug("Creating osworkflow root node"); 069 } 070 071 root.addNode(__ROOT_NODE, __ROOT_NT); 072 073 session.save(); 074 } 075 else 076 { 077 if (_log.isDebugEnabled()) 078 { 079 _log.debug("Existing osworkflow root node, skipping creation."); 080 } 081 } 082 } 083 finally 084 { 085 _release(session); 086 } 087 } 088 089 @Override 090 protected Node _getRootNode(Session session) throws RepositoryException 091 { 092 return session.getRootNode().getNode(__ROOT_NODE); 093 } 094 /** 095 * Retrieve the hash used for an entry id. 096 * @param entryId the entry id. 097 * @return the hash parts. 098 */ 099 protected List<String> _getEntryHash(long entryId) 100 { 101 long hash = Math.abs(HashUtil.hash(String.valueOf(entryId))); 102 // Prepend 0 for having same length hash parts 103 String hashHexa = StringUtils.leftPad(Long.toString(hash, 16), 4, "0"); 104 105 List<String> hashSegments = new ArrayList<>(); 106 107 hashSegments.add(hashHexa.substring(0, 2)); 108 hashSegments.add(hashHexa.substring(2, 4)); 109 110 return hashSegments; 111 } 112 113 @Override 114 protected Node _getOrCreateParentEntryNode(Node root, long id) throws RepositoryException 115 { 116 // Balanced tree management 117 Node htree = root; 118 List<String> hashSegments = _getEntryHash(id); 119 for (String hashSegment : hashSegments) 120 { 121 if (htree.hasNode(hashSegment)) 122 { 123 // Go down to a leaf of the hash tree 124 htree = htree.getNode(hashSegment); 125 } 126 else 127 { 128 // Add a new leaf to the hash tree 129 htree = htree.addNode(hashSegment, __HTREE_NT); 130 } 131 } 132 133 return htree; 134 } 135}