Coverage Report - org.kuali.rice.kew.doctype.service.impl.DocumentTypeServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
DocumentTypeServiceImpl
0%
0/163
0%
0/70
2.455
 
 1  
 /*
 2  
  * Copyright 2005-2007 The Kuali Foundation
 3  
  *
 4  
  *
 5  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  * http://www.opensource.org/licenses/ecl2.php
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.kuali.rice.kew.doctype.service.impl;
 18  
 
 19  
 import java.io.InputStream;
 20  
 import java.util.ArrayList;
 21  
 import java.util.Collection;
 22  
 import java.util.Iterator;
 23  
 import java.util.List;
 24  
 
 25  
 import org.jdom.Element;
 26  
 import org.kuali.rice.kew.doctype.bo.DocumentType;
 27  
 import org.kuali.rice.kew.doctype.dao.DocumentTypeDAO;
 28  
 import org.kuali.rice.kew.doctype.service.DocumentTypePermissionService;
 29  
 import org.kuali.rice.kew.doctype.service.DocumentTypeService;
 30  
 import org.kuali.rice.kew.dto.DTOConverter;
 31  
 import org.kuali.rice.kew.dto.DocumentTypeDTO;
 32  
 import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
 33  
 import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
 34  
 import org.kuali.rice.kew.export.ExportDataSet;
 35  
 import org.kuali.rice.kew.rule.bo.RuleAttribute;
 36  
 import org.kuali.rice.kew.service.KEWServiceLocator;
 37  
 import org.kuali.rice.kew.util.KEWConstants;
 38  
 import org.kuali.rice.kew.util.Utilities;
 39  
 import org.kuali.rice.kew.xml.DocumentTypeXmlParser;
 40  
 import org.kuali.rice.kew.xml.export.DocumentTypeXmlExporter;
 41  
 import org.kuali.rice.kns.util.ObjectUtils;
 42  
 
 43  
 
 44  
 /**
 45  
  * The standard implementation of the DocumentTypeService.
 46  
  *
 47  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 48  
  */
 49  0
 public class DocumentTypeServiceImpl implements DocumentTypeService {
 50  
 
 51  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentTypeServiceImpl.class);
 52  
     protected static final String XML_FILE_PARSE_ERROR = "general.error.parsexml";
 53  
 
 54  
     public static final String DOCUMENT_TYPE_ID_CACHE_GROUP = "DocumentTypeId";
 55  
     public static final String DOCUMENT_TYPE_NAME_CACHE_GROUP = "DocumentTypeName";
 56  
     public static final String DOCUMENT_TYPE_DTO_ID_CACHE_GROUP = "DocumentTypeDTOId";
 57  
     public static final String DOCUMENT_TYPE_DTO_NAME_CACHE_GROUP = "DocumentTypeDTOName";
 58  
 
 59  
     public static final String DOCUMENT_TYPE_ID_CACHE_PREFIX = DOCUMENT_TYPE_ID_CACHE_GROUP + ":";
 60  
     public static final String DOCUMENT_TYPE_NAME_CACHE_PREFIX = DOCUMENT_TYPE_NAME_CACHE_GROUP + ":";
 61  
     public static final String DOCUMENT_TYPE_DTO_ID_CACHE_PREFIX = DOCUMENT_TYPE_DTO_ID_CACHE_GROUP + ":";
 62  
     public static final String DOCUMENT_TYPE_DTO_NAME_CACHE_PREFIX = DOCUMENT_TYPE_DTO_NAME_CACHE_GROUP + ":";
 63  
     public static final String CURRENT_ROOTS_IN_CACHE_KEY = "DocumentType:CurrentRootsInCache";
 64  
 
 65  
 
 66  
     private DocumentTypeDAO documentTypeDAO;
 67  
 
 68  
     public Collection<DocumentType> find(DocumentType documentType, String docTypeParentName, boolean climbHierarchy) {
 69  0
         DocumentType docTypeParent = this.findByName(docTypeParentName);
 70  0
         Collection<DocumentType> documentTypes = getDocumentTypeDAO().find(documentType, docTypeParent, climbHierarchy);
 71  
         //since we're here put them in the cache
 72  0
         for (Object documentType1 : documentTypes)
 73  
         {
 74  0
             insertIntoCache((DocumentType) documentType1);
 75  
         }
 76  0
         return documentTypes;
 77  
     }
 78  
 
 79  
     public DocumentType findById(Long documentTypeId) {
 80  0
             if (documentTypeId == null) {
 81  0
                     return null;
 82  
             }
 83  0
             DocumentType documentType = fetchFromCacheById(documentTypeId);
 84  0
             if (documentType == null) {
 85  0
                     documentType = getDocumentTypeDAO().findByDocId(documentTypeId);
 86  0
                     insertIntoCache(documentType);
 87  
             }
 88  0
         return documentType;
 89  
     }
 90  
 
 91  
     public DocumentType findByDocumentId(Long documentId) {
 92  0
             if (documentId == null) {
 93  0
                     return null;
 94  
             }
 95  0
             Long documentTypeId = getDocumentTypeDAO().findDocumentTypeIdByDocumentId(documentId);
 96  0
             return findById(documentTypeId);
 97  
     }
 98  
 
 99  
     public DocumentType findByName(String name) {
 100  0
             return this.findByName(name, true, true);
 101  
     }
 102  
 
 103  
     public DocumentType findByNameCaseInsensitive(String name) {
 104  0
             return this.findByName(name, false,true);
 105  
     }
 106  
 
 107  
     /**
 108  
      * 
 109  
      * This method seaches for a DocumentType by document name.
 110  
      * 
 111  
      * @param name
 112  
      * @param caseSensitive
 113  
      * @deprecated Use findByName(String name, boolean caseSensitive, boolean checkCache)
 114  
      * @return
 115  
      */
 116  
     protected DocumentType findByName(String name, boolean caseSensitive) {
 117  0
             if (name == null) {
 118  0
                     return null;
 119  
             }
 120  0
             DocumentType documentType = fetchFromCacheByName(name);
 121  0
         if (documentType == null) {
 122  0
                 documentType = getDocumentTypeDAO().findByName(name, caseSensitive);
 123  0
                 insertIntoCache(documentType);
 124  
         }
 125  0
             return documentType;
 126  
     }
 127  
 
 128  
     /**
 129  
      * 
 130  
      * This method seaches for a DocumentType by document name.
 131  
      * 
 132  
      * @param name DocumentType name
 133  
      * @param caseSensitive If false, case will be ignored
 134  
      * @param checkCache if false the cache will not be checked.
 135  
      * @return
 136  
      */
 137  
     protected DocumentType findByName(String name, boolean caseSensitive, boolean checkCache) {
 138  0
             if (name == null) {
 139  0
                     return null;
 140  
             }
 141  
             
 142  0
             DocumentType documentType = null;
 143  0
             if(checkCache){
 144  0
                     documentType = fetchFromCacheByName(name);
 145  
             }
 146  0
         if (documentType == null) {
 147  0
                 documentType = getDocumentTypeDAO().findByName(name, caseSensitive);
 148  0
                 insertIntoCache(documentType);
 149  
         }
 150  0
             return documentType;
 151  
     }
 152  
 
 153  
     /**
 154  
      * Fetches the DocumentType from the cache with the given document type name.  If there is no entry in the cache for the given
 155  
      * document type name, null is returned.
 156  
      */
 157  
     protected DocumentType fetchFromCacheByName(String documentTypeName) {
 158  0
             return (DocumentType)KEWServiceLocator.getCacheAdministrator().getFromCache(getNameCacheKey(documentTypeName));
 159  
     }
 160  
 
 161  
     /**
 162  
      * Fetches the DocumentType from the cache with the given document type id.  If there is no entry in the cache for the given
 163  
      * document type id, null is returned.
 164  
      */
 165  
     protected DocumentType fetchFromCacheById(Long documentTypeId) {
 166  0
             return (DocumentType)KEWServiceLocator.getCacheAdministrator().getFromCache(getIdCacheKey(documentTypeId));
 167  
     }
 168  
 
 169  
     /**
 170  
      * Returns the cache key for the given document type ID.
 171  
      */
 172  
     protected String getIdCacheKey(Long documentTypeId) {
 173  0
             return DOCUMENT_TYPE_ID_CACHE_PREFIX + documentTypeId.toString();
 174  
     }
 175  
 
 176  
     /**
 177  
      * Returns the cache key for the given document type name.
 178  
      */
 179  
     protected String getNameCacheKey(String documentTypeName) {
 180  0
             return DOCUMENT_TYPE_NAME_CACHE_PREFIX + documentTypeName;
 181  
     }
 182  
 
 183  
     /**
 184  
      * Inserts the given DocumentType into the name and id caches.  If the DocumentType is already in the cache,
 185  
      * these entries should  be overwritten.
 186  
      *
 187  
      * <p>If the given DocumentType does not represent the current version of the DocumentType then it
 188  
      * should not be inserted into the name cache.  This is because different versions of DocumentTypes have
 189  
      * different IDs but they all have the same name.  We want only the most recent version of the DocumentType
 190  
      * to be cached by name.
 191  
      */
 192  
     protected void insertIntoCache(DocumentType documentType) {
 193  0
             if (documentType == null) {
 194  0
                     return;
 195  
             }
 196  
             //don't cache by name if this isn't the current version
 197  0
             if (documentType.getCurrentInd().booleanValue()) {
 198  0
                     KEWServiceLocator.getCacheAdministrator().putInCache(getNameCacheKey(documentType.getName()), documentType, DOCUMENT_TYPE_NAME_CACHE_GROUP);
 199  
             }
 200  
 
 201  0
             KEWServiceLocator.getCacheAdministrator().putInCache(getIdCacheKey(documentType.getDocumentTypeId()), documentType, DOCUMENT_TYPE_ID_CACHE_GROUP);
 202  0
     }
 203  
 
 204  
     /**
 205  
      * Fetches the DocumentType from the cache with the given document type name.  If there is no entry in the cache for the given
 206  
      * document type name, null is returned.
 207  
      */
 208  
     protected DocumentTypeDTO fetchDTOFromCacheByName(String documentTypeName) {
 209  0
             return (DocumentTypeDTO)KEWServiceLocator.getCacheAdministrator().getFromCache(getDTONameCacheKey(documentTypeName));
 210  
     }
 211  
 
 212  
     /**
 213  
      * Fetches the DocumentType from the cache with the given document type id.  If there is no entry in the cache for the given
 214  
      * document type id, null is returned.
 215  
      */
 216  
     protected DocumentTypeDTO fetchDTOFromCacheById(Long documentTypeId) {
 217  0
             return (DocumentTypeDTO)KEWServiceLocator.getCacheAdministrator().getFromCache(getDTOIdCacheKey(documentTypeId));
 218  
     }
 219  
 
 220  
     /**
 221  
      * Returns the cache key for the given document type ID.
 222  
      */
 223  
     protected String getDTOIdCacheKey(Long documentTypeId) {
 224  0
             return DOCUMENT_TYPE_DTO_ID_CACHE_PREFIX + documentTypeId.toString();
 225  
     }
 226  
 
 227  
     /**
 228  
      * Returns the cache key for the given document type name.
 229  
      */
 230  
     protected String getDTONameCacheKey(String documentTypeName) {
 231  0
             return DOCUMENT_TYPE_DTO_NAME_CACHE_PREFIX + documentTypeName;
 232  
     }
 233  
 
 234  
     /**
 235  
      * Inserts the given DocumentType into the name and id caches.  If the DocumentType is already in the cache,
 236  
      * these entries should  be overwritten.
 237  
      *
 238  
      * <p>If the given DocumentType does not represent the current version of the DocumentType then it
 239  
      * should not be inserted into the name cache.  This is because different versions of DocumentTypes have
 240  
      * different IDs but they all have the same name.  We want only the most recent version of the DocumentType
 241  
      * to be cached by name.
 242  
      */
 243  
     protected void insertDTOIntoCache(DocumentTypeDTO documentType) {
 244  0
             if (documentType == null) {
 245  0
                     return;
 246  
             }
 247  
             //don't cache by name if this isn't the current version
 248  0
             if ( documentType.getDocTypeCurrentInd().equals(KEWConstants.ACTIVE_CD) ) {
 249  0
                     KEWServiceLocator.getCacheAdministrator().putInCache(getDTONameCacheKey(documentType.getName()), documentType, DOCUMENT_TYPE_DTO_NAME_CACHE_GROUP);
 250  
             }
 251  
 
 252  0
             KEWServiceLocator.getCacheAdministrator().putInCache(getDTOIdCacheKey(documentType.getDocTypeId()), documentType, DOCUMENT_TYPE_DTO_ID_CACHE_GROUP);
 253  0
     }
 254  
 
 255  
     /**
 256  
      * Flushes all DocumentTypes from the cache.
 257  
      */
 258  
     public void flushCache() {
 259  
             // invalidate locally because if we're doing an upload of a document hierarchy we can't wait the 5 secs for this nodes cache
 260  
                 //to be accurate-the data going in the db depends on it being accurate now.  This means the cache will be cleared multiple times
 261  
             //over during an upload and the subsequent notification to this node.
 262  0
             LOG.info("clearing DocumentType cache because of local update");
 263  0
             KEWServiceLocator.getCacheAdministrator().flushGroup(DOCUMENT_TYPE_ID_CACHE_GROUP);
 264  0
             KEWServiceLocator.getCacheAdministrator().flushGroup(DOCUMENT_TYPE_NAME_CACHE_GROUP);
 265  0
             KEWServiceLocator.getCacheAdministrator().flushGroup(DOCUMENT_TYPE_DTO_ID_CACHE_GROUP);
 266  0
             KEWServiceLocator.getCacheAdministrator().flushGroup(DOCUMENT_TYPE_DTO_NAME_CACHE_GROUP);
 267  0
             KEWServiceLocator.getCacheAdministrator().flushGroup(DocumentTypePermissionService.DOC_TYPE_PERM_CACHE_GROUP);
 268  0
             KEWServiceLocator.getCacheAdministrator().flushEntry(CURRENT_ROOTS_IN_CACHE_KEY);
 269  0
     }
 270  
 
 271  
     public void clearCacheForAttributeUpdate(RuleAttribute ruleAttribute) {
 272  0
             List documentTypeAttributes = this.documentTypeDAO.findDocumentTypeAttributes(ruleAttribute);
 273  0
             if (documentTypeAttributes.size() != 0) {
 274  0
                     flushCache();
 275  
             }
 276  0
     }
 277  
 
 278  
     public void versionAndSave(DocumentType documentType) {
 279  
             try {
 280  
                     // at this point this save is designed to version the document type by creating an entire new record if this is going to be an update and
 281  
                     // not a create just throw and exception to be on the safe side
 282  0
                     if (documentType.getDocumentTypeId() != null && documentType.getVersionNumber() != null) {
 283  0
                             throw new RuntimeException("DocumentType configured for update and not versioning which we support");
 284  
                     }
 285  
 
 286  
                     // grab the old document. Don't Use Cached Version!
 287  0
                     DocumentType oldDocumentType = findByName(documentType.getName(), true, false);
 288  
                     // reset the children on the oldDocumentType
 289  
                     //oldDocumentType.resetChildren();
 290  0
                     Long existingDocTypeId = null;
 291  0
                     if (oldDocumentType != null) {
 292  0
                         existingDocTypeId = oldDocumentType.getDocumentTypeId();
 293  0
                         if (existingDocTypeId.longValue() > 0) {
 294  
                             // set version number on the new doc type using the max version from the database
 295  0
                             Integer maxVersionNumber = documentTypeDAO.getMaxVersionNumber(documentType.getName());
 296  0
                                 documentType.setVersion((maxVersionNumber != null) ? new Integer(maxVersionNumber.intValue() + 1) : new Integer(0));
 297  0
                                 oldDocumentType.setCurrentInd(Boolean.FALSE);
 298  0
                                 if ( LOG.isInfoEnabled() ) { 
 299  0
                                         LOG.info("Saving old document type Id " + oldDocumentType.getDocumentTypeId() + " name '" + oldDocumentType.getName() + "' (current = " + oldDocumentType.getCurrentInd() + ")");
 300  
                                 }
 301  0
                                 save(oldDocumentType, false);
 302  
                         }
 303  
                     }
 304  
                     // check to see that no current documents exist in database
 305  0
                     if (!Utilities.isEmpty(documentTypeDAO.findAllCurrentByName(documentType.getName()))) {
 306  0
                         String errorMsg = "Found invalid 'current' document with name '" + documentType.getName() + "'.  None should exist.";
 307  0
                         LOG.error(errorMsg);
 308  0
                         throw new RuntimeException(errorMsg);
 309  
                     }
 310  
             // set up the previous current doc type on the new doc type
 311  0
             documentType.setPreviousVersionId(existingDocTypeId);
 312  0
             documentType.setCurrentInd(Boolean.TRUE);
 313  0
                     save(documentType, false);
 314  0
                     if ( LOG.isInfoEnabled() ) { 
 315  0
                             LOG.info("Saved current document type Id " + documentType.getDocumentTypeId() + " name '" + documentType.getName() + "' (current = " + documentType.getCurrentInd() + ")");
 316  
                     }
 317  
                     //attach the children to this new parent.  cloning the children would probably be a better way to go here...
 318  0
                     if (ObjectUtils.isNotNull(existingDocTypeId)) {
 319  
                         // documentType.getPreviousVersion() should not be null at this point
 320  0
                 for (Iterator iterator = getChildDocumentTypes(existingDocTypeId).iterator(); iterator.hasNext();) {
 321  
 //                            for (Iterator iterator = oldDocumentType.getChildrenDocTypes().iterator(); iterator.hasNext();) {
 322  0
                                     DocumentType child = (DocumentType) iterator.next();
 323  0
                                     child.setDocTypeParentId(documentType.getDocumentTypeId());
 324  0
                                     save(child, false);
 325  0
                                     if ( LOG.isInfoEnabled() ) { 
 326  0
                                             LOG.info("Saved child document type Id " + child.getDocumentTypeId() + " name '" + child.getName() + "' (parent = " + child.getDocTypeParentId() + ", current = " + child.getCurrentInd() + ")");
 327  
                                     }
 328  0
                             }
 329  
                     }
 330  
                     // initiate a save of this document type's parent document type, this will force a
 331  
                     // version check which should reveal (via an optimistic lock exception) whether or
 332  
                     // not there is a concurrent transaction
 333  
                     // which has modified the parent (and therefore made it non-current)
 334  
                     // be sure to get the parent doc type directly from the db and not from the cache
 335  0
                     if (documentType.getDocTypeParentId() != null) {
 336  0
                             DocumentType parent = getDocumentTypeDAO().findByDocId(documentType.getDocTypeParentId());
 337  0
                             save(parent, false);
 338  0
                             if ( LOG.isInfoEnabled() ) { 
 339  0
                                     LOG.info("Saved parent document type Id " + parent.getDocumentTypeId() + " name '" + parent.getName() + "' (current = " + parent.getCurrentInd() + ")");
 340  
                             }
 341  
                     }
 342  
 
 343  
                     // finally, flush the cache and notify the rule cache of the DocumentType change
 344  0
                     flushCache();
 345  0
                     KEWServiceLocator.getRuleService().notifyCacheOfDocumentTypeChange(documentType);
 346  0
             } finally {
 347  
                     // the double flush here is necessary because of a series of events which occur inside of
 348  
                     // notifyCacheOfDocumentTypeChange, see the documentation inside that service method for
 349  
                     // more information on the problem.  Essentially, the method ends up invoking methods on
 350  
                     // this service which re-cache document types, however the document types that get
 351  
                     // re-cached are ones pulled from the OJB cache that don't have the proper children
 352  
                     // on them
 353  
                     //
 354  
                     // also we flush in the finally block because if an exception is thrown then it's still possible
 355  
                     // the the "oldDocumentType" which was fetched from the cache has had it's dbLockVerNbr incremented
 356  0
                     flushCache();
 357  0
             }
 358  0
     }
 359  
 
 360  
     public void save(DocumentType documentType, boolean flushCache) {
 361  0
             getDocumentTypeDAO().save(documentType);
 362  0
             if (flushCache) {
 363  
                     // always clear the entire cache
 364  0
                     flushCache();
 365  0
                 KEWServiceLocator.getRuleService().notifyCacheOfDocumentTypeChange(documentType);
 366  0
                 flushCache();
 367  
             }
 368  0
     }
 369  
 
 370  
     public void save(DocumentType documentType) {
 371  0
             save(documentType, true);
 372  0
     }
 373  
 
 374  
     public DocumentTypeDAO getDocumentTypeDAO() {
 375  0
         return documentTypeDAO;
 376  
     }
 377  
 
 378  
     public void setDocumentTypeDAO(DocumentTypeDAO documentTypeDAO) {
 379  0
         this.documentTypeDAO = documentTypeDAO;
 380  0
     }
 381  
 
 382  
     public DocumentTypeDTO getDocumentTypeVO(Long documentTypeId) {
 383  0
         DocumentTypeDTO dto = fetchDTOFromCacheById(documentTypeId);
 384  0
         if ( dto == null ) {
 385  0
             DocumentType docType = findById(documentTypeId);
 386  0
             if ( docType == null ) {
 387  0
                     return null;
 388  
             }
 389  0
                 dto = DTOConverter.convertDocumentType(docType);
 390  0
                 insertDTOIntoCache(dto);
 391  
         }
 392  
         
 393  0
         return dto;
 394  
     }
 395  
 
 396  
     public DocumentTypeDTO getDocumentTypeVO(String documentTypeName) {
 397  0
         DocumentTypeDTO dto = fetchDTOFromCacheByName(documentTypeName);
 398  0
         if ( dto == null ) {
 399  0
             DocumentType docType = findByName(documentTypeName);
 400  0
             if ( docType == null ) {
 401  0
                     return null;
 402  
             }
 403  0
                 dto = DTOConverter.convertDocumentType(docType);
 404  0
                 insertDTOIntoCache(dto);
 405  
         }
 406  0
         return dto;
 407  
     }
 408  
 
 409  
     public synchronized List findAllCurrentRootDocuments() {
 410  0
             List currentRootsInCache = (List) KEWServiceLocator.getCacheAdministrator().getFromCache(CURRENT_ROOTS_IN_CACHE_KEY);
 411  
             //we can do this because we whack the entire cache when a new document type comes into the picture.
 412  0
             if (currentRootsInCache == null) {
 413  0
                     currentRootsInCache = getDocumentTypeDAO().findAllCurrentRootDocuments();
 414  0
                     KEWServiceLocator.getCacheAdministrator().putInCache(CURRENT_ROOTS_IN_CACHE_KEY, currentRootsInCache);
 415  
             }
 416  0
             return currentRootsInCache;
 417  
     }
 418  
 
 419  
     public List findAllCurrent() {
 420  0
         return getDocumentTypeDAO().findAllCurrent();
 421  
     }
 422  
 
 423  
     public List<DocumentType> findPreviousInstances(String documentTypeName) {
 424  0
         return getDocumentTypeDAO().findPreviousInstances(documentTypeName);
 425  
     }
 426  
 
 427  
     public DocumentType findRootDocumentType(DocumentType docType) {
 428  0
         if (docType.getParentDocType() != null) {
 429  0
             return findRootDocumentType(docType.getParentDocType());
 430  
         } else {
 431  0
             return docType;
 432  
         }
 433  
     }
 434  
 
 435  
     public void loadXml(InputStream inputStream, String principalId) {
 436  0
         DocumentTypeXmlParser parser = new DocumentTypeXmlParser();
 437  
         try {
 438  0
             parser.parseDocumentTypes(inputStream);
 439  0
         } catch (Exception e) {
 440  0
             WorkflowServiceErrorException wsee = new WorkflowServiceErrorException("Error parsing documentType XML file", new WorkflowServiceErrorImpl("Error parsing documentType XML file", XML_FILE_PARSE_ERROR));
 441  0
             wsee.initCause(e);
 442  0
             throw wsee;
 443  0
         }
 444  0
     }
 445  
 
 446  
     public Element export(ExportDataSet dataSet) {
 447  0
         DocumentTypeXmlExporter exporter = new DocumentTypeXmlExporter();
 448  0
         return exporter.export(dataSet);
 449  
     }
 450  
 
 451  
     public List getChildDocumentTypes(Long documentTypeId) {
 452  0
             List childDocumentTypes = new ArrayList();
 453  0
             List childIds = getDocumentTypeDAO().getChildDocumentTypeIds(documentTypeId);
 454  0
             for (Iterator iter = childIds.iterator(); iter.hasNext();) {
 455  0
                         Long childDocumentTypeId = (Long) iter.next();
 456  0
                         childDocumentTypes.add(findById(childDocumentTypeId));
 457  0
                 }
 458  0
             return childDocumentTypes;
 459  
     }
 460  
 
 461  
 }