DBA Data[Home] [Help]

PACKAGE BODY: APPS.HR_MESSAGE

Source


1 PACKAGE BODY HR_MESSAGE AS
2 /* $Header: hrmesage.pkb 115.4 99/07/17 16:42:53 porting ship $ */
3 
4 --
5 -- ----------------------------------------------------------------------------
6 -- |                    Global Record Type Specification                      |
7 -- ----------------------------------------------------------------------------
8 --
9 TYPE g_error_info_type IS RECORD
10   (
11    sqlcode	NUMBER := 0,
12    sqlerrm	VARCHAR2(2000) := '',
13    encoded_error_text   VARCHAR2(2000) := '',
14    last_message_name	VARCHAR2(2000) := '',
15    last_message_app	VARCHAR2(2000) := '',
16    last_message_data    VARCHAR2(2000) := '');
17 
18 --
19 -- ----------------------------------------------------------------------------
20 -- |                         Global Definitions                               |
21 -- ----------------------------------------------------------------------------
22 --
23 
24 g_error_rec g_error_info_type;
25 
26 --
27 -- ----------------------------------------------------------------------------
28 -- |                         Global Package Name                              |
29 -- ----------------------------------------------------------------------------
30 --
31 
32 g_package varchar2(33) := '  hr_message_pkg.';
33 
34 function get_separator_string(p_encoded_error in varchar2) return varchar2 is
35 
36 -- This function works out what AOL are using as the separator between the
37 -- data in the encoded data string.  As of August 1998, the encoded error
38 -- message had the form:
39 --
40 -- MSG_APP||(sep)||MSG_NAME||(sep)||MSG_DATA
41 --
42 -- The length is determined by finding the start of the MSG_NAME, and
43 -- subtracting the length of the message application short name (PER, PAY
44 -- etc.)
45 --
46 -- The separator is then determined by substr starting at the position
47 -- one character past the length of the message application, and continuing
48 -- for the length just determined.  This function protects us a little bit
49 -- from changes in the AOL encoding string when we are trying to determine
50 -- the token values.
51 --
52 
53 l_sep_length NUMBER(4);
54 l_sep_string VARCHAR2(2000);
55 
56 begin
57 
58 l_sep_length:=to_number(INSTR(p_encoded_error,g_error_rec.last_message_name)
59                           -  LENGTH(g_error_rec.last_message_app) - 1);
60 
61 l_sep_string:=substr(p_encoded_error,length(g_error_rec.last_message_app)+1,
62                                    l_sep_length);
63 
64 return l_sep_string;
65 
66 end get_separator_string;
67 
68 procedure provide_error is
69 
70 -- This is the main procedure, which makes calls to the FND_MESSAGE package
71 -- to populate the global record structure with the name of the last message
72 -- application, and the last message name.  The other data supplied in
73 -- the encoded error message string is token information, and is not used
74 -- until a call to get_token_value is made.
75 
76 l_encoded_error	VARCHAR2(2000);
77 l_hr_error_app  VARCHAR2(2000);
78 l_hr_error_name VARCHAR2(2000);
79 l_sep_string VARCHAR2(2000) :='';
80 
81 begin
82 
83 -- Set up global variables with error information
84 
85 g_error_rec.sqlcode := sqlcode;
86 g_error_rec.sqlerrm := sqlerrm;
87 
88 if ((g_error_rec.sqlcode = -20001) or (g_error_rec.sqlcode = -20002)) then
89 
90 -- An error has been raised by APPS code - populate other global variables
91 
92     l_encoded_error := fnd_message.get_encoded;
93     g_error_rec.encoded_error_text := l_encoded_error;
94 
95     if (l_encoded_error is not null) then
96 
97 -- FND MESSAGE still knows which message we are talking about
98 -- Reset the message, so that the FND_MESSAGE state is not altered by
99 -- this procedure
100 
101      fnd_message.set_encoded(l_encoded_error);
102 
103 -- Now decode the encoded error message into required components
104 
105      fnd_message.parse_encoded(encoded_message => l_encoded_error,
106                            app_short_name => g_error_rec.last_message_app,
107                            message_name => g_error_rec.last_message_name);
108 
109        g_error_rec.last_message_data := '';
110 
111    else
112 --
113 --  We can't find anything out from FND_MESSAGE.  Perhaps the
114 --  message text has been retrieved, or some other call has
115 --  reset the global state.  Treat as non-APP error.
116 --
117     g_error_rec.last_message_name := '';
118     g_error_rec.last_message_app := '';
119     g_error_rec.last_message_data := '';
120     g_error_rec.encoded_error_text := '';
121 --
122    end if; -- l_encoded_error is null
123 else
124 
125 -- This was not an error raised by an application procedure -
126 -- set global definitions to NULL
127 
128     g_error_rec.last_message_name := '';
129     g_error_rec.last_message_app := '';
130     g_error_rec.last_message_data := '';
131     g_error_rec.encoded_error_text := '';
132 
133 end if;  -- Check for error raised by APPS
134 
135 end provide_error;
136 
137 procedure parse_encoded(p_encoded_error in varchar2) is
138 
139 -- This procedure assumes that the calling procedure already
140 -- has knowledge of the encoded error message (e.g.
141 -- as in the case of the flexfield server validation
142 -- routines.).  The string passed in must be in the same
143 -- format as the encoded string in FND_MESSAGE. I.e. it should
144 -- have been retrieved with a call to FND_MESSAGE.get_encoded.
145 
146 begin
147 
148 -- Use the FND routine to parse the encoded error message into
149 -- the global variables to make them available to the APIS,
150 -- forms, other packages etc. in a way consistent with provide_error
151 -- Do not reset the error message on the FND_MESSAGE stack, since
152 -- this would alter the state of that package.
153 
154    fnd_message.parse_encoded(encoded_message => p_encoded_error,
155                            app_short_name => g_error_rec.last_message_app,
156                            message_name => g_error_rec.last_message_name);
157 
158     g_error_rec.encoded_error_text := p_encoded_error;
159     g_error_rec.last_message_data := '';
160 
161 
162 end;
163 --
164 function last_message_number return varchar2 is
165 
166 -- A call to this function will return the message error code in
167 -- the following format:
168 --
169    l_error_code_text VARCHAR2(30) := 'APP-MSGNUM';
170    l_message_num VARCHAR2(10);
171 --
172 -- If you wish to change the format, change the default assignment above,
173 -- noting that the (sub) string MSGNUM will be replaced with the
174 -- message number.
175 --
176 begin
177 --
178 -- Check to see if we have a valid message on the stack
179 --
180    if (g_error_rec.last_message_name is not null) then
181 --
182 -- Have a valid message.  Lets form the number by assuming a form
183 -- for the message name of the following:
184 --   HR_(MSGNUM)_ERROR_MESSAGE_DESCR
185 --
186      l_message_num := substr(g_error_rec.last_message_name,
187                       (instr(g_error_rec.last_message_name,'_')+1),
188                       (instr(g_error_rec.last_message_name,'_',1,2) -
189                        instr(g_error_rec.last_message_name,'_')-1));
190 --
191      if (translate(l_message_num,'A0123456789','A') is null) then
192 --
193 -- substr above worked correctly - we have a message number, can output
194 -- a valid message code.
195 --
196             l_error_code_text := replace(l_error_code_text,'MSGNUM',
197                                                         l_message_num);
198 --
199      else
200 --
201 -- substr failed.  Should return NULL
202 --
203            l_error_code_text := '';
204 --
205      end if;
206 --
207    else
208 --
209 --
210 -- We don't have a valid message on the stack, therefore I should return
211 -- null for this.
212 --
213      l_error_code_text := '';
214 --
215    end if;
216 --
217    return l_error_code_text;
218 --
219 end last_message_number;
220 --
221 function last_message_name return varchar2 is
222 
223 -- A call to this function simply returns whatever is contained
224 -- in the current global variable record structure for the last
225 -- message name raised.
226 
227 begin
228 
229 return g_error_rec.last_message_name;
230 
231 end;
232 
233 function last_message_app return varchar2 is
234 
235 -- A call to this function simply returns whatever is contained
236 -- in the current global variable record structure for the last
237 -- app that raised a message followed by a call to provide_error.
238 
239 begin
240 
241 return g_error_rec.last_message_app;
242 
243 end;
244 
245 function get_token_value(p_token_name in varchar2
246                         ) return varchar2 is
247 
248 -- This function uses the MSG_DATA component of the encoded error string
249 -- to determine the value of a given token.
250 -- The message data has the following structure:
251 --
252 -- MSG_DATA = TKN_TRANSLATE||(sep)||TKN_NAME||(sep)||TKN_VALUE||(sep)
253 --
254 -- and so on for each token set with this message.  (sep) is the
255 -- encoding separator used beforehand.
256 
257 l_sep_string   VARCHAR2(2000);
258 l_msg_data_start NUMBER(4);
259 l_data_start	NUMBER(4);
260 l_data_end	NUMBER(4);
261 l_token_value	VARCHAR2(2000);
262 
263 
264 begin
265 
266 -- To be able to return the token values, we need to assume something about
267 -- the encoded nature of the message - this is a big assumption, and we
268 -- shouldn't really do it.  It would be better if the get_encoded returned
269 -- this along with the other data shown above - but it does not.  This is
270 -- therefore, unsupported (by AOL) code
271 
272 -- Use the function described above to work out what the format of the
273 -- message data separator.
274 
275      l_sep_string := get_separator_string(p_encoded_error =>
276                                    g_error_rec.encoded_error_text);
277 
278 -- The compete encoded message data has structure:
279 --
280 -- MSG_APP||(sep)||MSG_NAME||(sep)||MSG_DATA
281 --
282 -- so the message data starts at the character past the second
283 -- instance of the encoded string separator character.
284 
285      l_msg_data_start := INSTR(g_error_rec.encoded_error_text,
286                                                 l_sep_string,1,2)+1;
287 
288      g_error_rec.last_message_data := substr(g_error_rec.encoded_error_text,
289                                                     l_msg_data_start);
290 --
291 -- First check to see whether there is information on tokens available,
292 -- and that information exists for the token requested.  If not, return
293 -- a NULL value.
294 --
295 -- Note:  We will cause an error if the value of a token is
296 -- also a valid token name.  We should introduce a check on
297 -- the number of separator strings to ensure that we have a
298 -- valid token value.
299 --
300 if ((g_error_rec.last_message_data is null) or
301     (INSTR(g_error_rec.last_message_data,p_token_name)=0)) then
302 
303   return null;
304 
305 else
306 
307 -- The starting position (in the string) of the value for the given token
308 -- can be found using the standard character functions.  From the structure
309 -- seen above for MSG_DATA, it can be found by finding the position of the
310 -- token name, then adding the length of the token name, and the length of
311 -- the separator string.
312 
313   l_data_start := INSTR(g_error_rec.last_message_data,p_token_name)
314                       +length(p_token_name)
315                       +length(l_sep_string);
316 
317 -- The end of the token value corresponds to the next instance of the
318 -- separator string starting from the start of the token value.
319 
320   l_data_end := INSTR(substr(g_error_rec.last_message_data,l_data_start)
321                      ,l_sep_string);
322 
323   if(l_data_end>0) then
324 
325 -- If the data end variable contains a value larger than zero, it means
326 -- that another separator string was found.  Thus another token record
327 -- exists, and we should make sure that we only return the part of the
328 -- string between data_start and data_end, which will be the token value
329 
330      l_token_value := substr(g_error_rec.last_message_data,l_data_start,
331                       (l_data_end-1));
332 
333   else
334 
335 -- This token value was the last information in the MSG_DATA record.
336 -- The valid value is the whole string starting at the data_start
337 
338      l_token_value := substr(g_error_rec.last_message_data,l_data_start);
339 
340   end if;
341 
342   return l_token_value;
343 end if;
344 
345 end;
346 
347 function get_message_text return varchar2 is
348 
349 -- Call this function to retrieve the message text corresponding
350 -- to the message information held in the error information structure -
351 -- i.e. the last message after which provide_error was called.  If that
352 -- structure contains no information, the error is not likely to have been
353 -- raised by an application, hence just sqlerrm is returned in this case.
354 
355 l_message_text varchar2(2000);
356 
357 begin
358 
359 if (g_error_rec.encoded_error_text is null) then
360 
361 -- This message is not known about inside FND_MESSAGE, either the FND_MESSAGE
362 -- globals have been reset - in which case, no message text can be retrieved,
363 -- or this was not an APP error.  In either case, return the SQL error message
364 -- as this is the only place we can obtain the error message
365 
366    return sqlerrm;
367 
368 else
369 
370 -- The message text has not been asked for by any application yet - we can get
371 -- the message text straight from FND_MESSAGE, and reset the FND_MESSAGE
372 -- package state by reinitiating the message, so that this call does not disturb
373 -- the global environment
374 
375   l_message_text := FND_MESSAGE.get;
376 
377   FND_MESSAGE.set_encoded(ENCODED_MESSAGE => g_error_rec.encoded_error_text);
378 
379   return l_message_text;
380 
381 end if;
382 
383 end;
384 
385 END HR_MESSAGE;