001/** 002 * Copyright 2005-2018 The Kuali Foundation 003 * 004 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php 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.kuali.rice.krad.util; 017 018import org.kuali.rice.kew.api.KewApiServiceLocator; 019import org.kuali.rice.krad.UserSession; 020import org.kuali.rice.krad.data.KradDataServiceLocator; 021import org.kuali.rice.krad.datadictionary.DocumentEntry; 022import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 023 024import java.util.concurrent.Callable; 025 026/** 027 * Exposes legacy detection functionality statically. 028 * 029 * @author Kuali Rice Team (rice.collab@kuali.org) 030 */ 031public final class LegacyUtils { 032 033 private static LegacyDetector ld = new LegacyDetector(KradDataServiceLocator.getMetadataRepository(), 034 KRADServiceLocatorWeb.getDataDictionaryService()); 035 036 private LegacyUtils() { 037 throw new UnsupportedOperationException(LegacyUtils.class + " should not be constructed"); 038 } 039 040 /** 041 * Indicates whether the given type is managed by the legacy data framework. Note that it's possible for a given 042 * type to managed by both the legacy and the non-legacy data framework, in which case this method will return true 043 * as well. 044 * 045 * @param type the type to check 046 * @return true if managed by the legacy framework, false otherwise 047 */ 048 public static boolean isLegacyManaged(Class<?> type) { 049 return ld.isLegacyManaged(type); 050 } 051 052 /** 053 * Indicates whether the given type is managed by the non-legacy data framework. Note that it's possible for a given 054 * type to managed by both the legacy and the non-legacy data framework, in which case this method will return true 055 * as well. 056 * 057 * @param type the type to check 058 * @return true if managed by the non-legacy krad-data framework, false otherwise 059 */ 060 public static boolean isKradDataManaged(Class<?> type) { 061 return ld.isKradDataManaged(type); 062 } 063 064 /** 065 * Indicates whether or not the given DocumentEntry represents a legacy KNS document entry. 066 * 067 * @param documentEntry the document entry to check 068 * @return true if the given entry is a KNS entry, false otherwise 069 */ 070 public static boolean isKnsDocumentEntry(DocumentEntry documentEntry) { 071 return "org.kuali.rice.kns.datadictionary".equals(documentEntry.getClass().getPackage().getName()); 072 } 073 074 public static boolean isKnsEnabled() { 075 return ld.isKnsEnabled(); 076 } 077 078 /** 079 * Return whether the legacy data framework is enabled 080 * @return whether the legacy data framework is enabled 081 */ 082 public static boolean isLegacyDataFrameworkEnabled() { 083 return ld.isLegacyDataFrameworkEnabled(); 084 } 085 086 /** 087 * Return whether objects of the given class should be handled via the legacy data framework 088 * @param dataObjectClass the data object class 089 * @return whether objects of the given class should be handled via the legacy data framework 090 */ 091 public static boolean useLegacy(Class<?> dataObjectClass) { 092 return ld.useLegacy(dataObjectClass); 093 } 094 095 /** 096 * Return whether the object should be handled via the legacy data framework 097 * @param dataObject the data object 098 * @return whether the object should be handled via the legacy data framework 099 */ 100 public static boolean useLegacyForObject(Object dataObject) { 101 return ld.useLegacyForObject(dataObject); 102 } 103 104 /** 105 * @return whether we are currently in a legacy calling context 106 */ 107 public static boolean isInLegacyContext() { 108 return ld.isInLegacyContext(); 109 } 110 111 public static void beginLegacyContext() { 112 ld.beginLegacyContext(); 113 } 114 115 public static void endLegacyContext() { 116 ld.endLegacyContext(); 117 } 118 119 /** 120 * Performs the specified {@link Callable} inside of the legacy context. 121 * 122 * @param callable the method to call inside of the new contexts 123 * @param <T> the return type of the callable 124 * @return the result of the callable 125 * @throws Exception any exception thrown during the execution of the context 126 */ 127 public static <T> T doInLegacyContext(Callable<T> callable) throws Exception { 128 beginLegacyContext(); 129 try { 130 return callable.call(); 131 } finally { 132 endLegacyContext(); 133 } 134 } 135 136 /** 137 * Performs the specified {@link Callable} inside of both the legacy context (if necessary as dependent on the 138 * {@code documentId}) and in new {@link GlobalVariables} as specified by the given {@code userSession}. 139 * 140 * @param documentId id of the document for which to establish the data context 141 * @param userSession the new user session to establish 142 * @param callable the method to call inside of the new contexts 143 * @param <T> the return type of the callable 144 * @return the result of the callable 145 * @throws Exception any exception thrown during the execution of the context 146 */ 147 public static <T> T doInLegacyContext(String documentId, UserSession userSession, Callable<T> callable) throws Exception { 148 boolean inLegacyContext = establishLegacyDataContextIfNecessary(documentId); 149 try { 150 return GlobalVariables.doInNewGlobalVariables(userSession, callable); 151 } finally { 152 clearLegacyDataContextIfExists(inLegacyContext); 153 } 154 } 155 156 /** 157 * Establish a legacy data context if it deems that it's necessary to do so for the document being processed. 158 * Unfortunately for us here, there is really no easy way to tell if the original document was submitted from a 159 * legacy context (i.e. KNS + OJB) or if it was submitted from a non-legacy context. 160 * 161 * <p>This is really only a problem for us if the data object happens to be mapped and configured in both the legacy 162 * and non-legacy data frameworks (which may be the case while a conversion is in-progress). In the case that the 163 * document or the maintainable happens to be configured for both legacy and non-legacy data frameworks, the best we 164 * can do is use the non-legacy framework by default. We will, however, ensure that the document entry is not one of 165 * the KNS subclasses, as that will tell us that they have, in fact, converted the document over from KNS to KRAD. 166 * </p> 167 * 168 * @param documentId id of the document for which to establish the data context 169 * @return true if a legacy data context was established, false otherwise 170 */ 171 private static boolean establishLegacyDataContextIfNecessary(String documentId) { 172 String documentTypeName = KewApiServiceLocator.getWorkflowDocumentService().getDocumentTypeName(documentId); 173 DocumentEntry documentEntry = KRADServiceLocatorWeb.getDocumentDictionaryService().getDocumentEntry(documentTypeName); 174 175 if (isKnsDocumentEntry(documentEntry)) { 176 beginLegacyContext(); 177 178 return true; 179 } 180 181 return false; 182 } 183 184 /** 185 * If the given boolean is true, will end any existing legacy data context. 186 * 187 * @param inLegacyContext whether or not the legacy data context has been established 188 */ 189 private static void clearLegacyDataContextIfExists(boolean inLegacyContext) { 190 if (inLegacyContext) { 191 endLegacyContext(); 192 } 193 } 194 195}