View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.util;
17  
18  import org.kuali.rice.kew.api.KewApiServiceLocator;
19  import org.kuali.rice.krad.UserSession;
20  import org.kuali.rice.krad.data.KradDataServiceLocator;
21  import org.kuali.rice.krad.datadictionary.DocumentEntry;
22  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
23  
24  import java.util.concurrent.Callable;
25  
26  /**
27   * Exposes legacy detection functionality statically.
28   *
29   * @author Kuali Rice Team (rice.collab@kuali.org)
30   */
31  public final class LegacyUtils {
32  
33      private static LegacyDetector ld = new LegacyDetector(KradDataServiceLocator.getMetadataRepository(),
34              KRADServiceLocatorWeb.getDataDictionaryService());
35  
36      private LegacyUtils() {
37          throw new UnsupportedOperationException(LegacyUtils.class + " should not be constructed");
38      }
39  
40      /**
41       * Indicates whether the given type is managed by the legacy data framework. Note that it's possible for a given
42       * type to managed by both the legacy and the non-legacy data framework, in which case this method will return true
43       * as well.
44       *
45       * @param type the type to check
46       * @return true if managed by the legacy framework, false otherwise
47       */
48      public static boolean isLegacyManaged(Class<?> type) {
49          return ld.isLegacyManaged(type);
50      }
51  
52      /**
53       * Indicates whether the given type is managed by the non-legacy data framework. Note that it's possible for a given
54       * type to managed by both the legacy and the non-legacy data framework, in which case this method will return true
55       * as well.
56       *
57       * @param type the type to check
58       * @return true if managed by the non-legacy krad-data framework, false otherwise
59       */
60      public static boolean isKradDataManaged(Class<?> type) {
61          return ld.isKradDataManaged(type);
62      }
63  
64      /**
65       * Indicates whether or not the given DocumentEntry represents a legacy KNS document entry.
66       *
67       * @param documentEntry the document entry to check
68       * @return true if the given entry is a KNS entry, false otherwise
69       */
70      public static boolean isKnsDocumentEntry(DocumentEntry documentEntry) {
71          return "org.kuali.rice.kns.datadictionary".equals(documentEntry.getClass().getPackage().getName());
72      }
73  
74      public static boolean isKnsEnabled() {
75          return ld.isKnsEnabled();
76      }
77  
78      /**
79       * Return whether the legacy data framework is enabled
80       * @return whether the legacy data framework is enabled
81       */
82      public static boolean isLegacyDataFrameworkEnabled() {
83          return ld.isLegacyDataFrameworkEnabled();
84      }
85  
86      /**
87       * Return whether objects of the given class should be handled via the legacy data framework
88       * @param dataObjectClass the data object class
89       * @return whether objects of the given class should be handled via the legacy data framework
90       */
91      public static boolean useLegacy(Class<?> dataObjectClass) {
92          return ld.useLegacy(dataObjectClass);
93      }
94  
95      /**
96       * Return whether the object should be handled via the legacy data framework
97       * @param dataObject the data object
98       * @return whether the object should be handled via the legacy data framework
99       */
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 }