1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 package com.sun.star.wizards.common; 24 25 import com.sun.star.lang.XMultiServiceFactory; 26 import com.sun.star.util.DateTime; 27 import com.sun.star.beans.PropertyValue; 28 import java.util.*; 29 import java.io.File; 30 31 import com.sun.star.lib.util.UrlToFileMapper; 32 import java.io.IOException; 33 import java.net.MalformedURLException; 34 import java.net.URL; 35 36 /** 37 * 38 * @author bc93774 39 */ 40 public class JavaTools 41 { 42 43 /** Creates a new instance of JavaTools */ JavaTools()44 public JavaTools() 45 { 46 } 47 48 /* 49 public static void main(String args[]) 50 { 51 String sPath = PropertyNames.EMPTY_STRING; 52 DateTime oDateTime = null; 53 long n; 54 String ConnectStr = "uno:socket,host=localhost,port=8100;urp,negotiate=0,forcesynchronous=1;StarOffice.NamingService"; //localhost ;Lo-1.Germany.sun.com; 10.16.65.155 55 try 56 { 57 XMultiServiceFactory xLocMSF = com.sun.star.wizards.common.Desktop.connect(ConnectStr); 58 if (xLocMSF != null) 59 { 60 System.out.println("Connected to " + ConnectStr); 61 oDateTime = getDateTime(9500000); 62 sPath = convertfromURLNotation("file:///E:/trash/Web%20Wizard.xcu"); 63 n = getMillis(oDateTime); 64 int a = 1; 65 } 66 } 67 catch (Exception exception) 68 { 69 exception.printStackTrace(System.out); 70 } 71 } 72 */ copyStringArray(String[] FirstArray)73 public static String[] copyStringArray(String[] FirstArray) 74 { 75 if (FirstArray != null) 76 { 77 String[] SecondArray = new String[FirstArray.length]; 78 System.arraycopy(FirstArray, 0, SecondArray, 0, FirstArray.length); 79 return SecondArray; 80 } 81 else 82 { 83 return null; 84 } 85 } 86 initializeArray(Object[] olist, Object ovalue)87 public static Object[] initializeArray(Object[] olist, Object ovalue) 88 { 89 for (int i = 0; i < olist.length; i++) 90 { 91 olist[i] = ovalue; 92 } 93 return olist; 94 } 95 initializeMultiDimArray(Object[][] olist, Object[] ovalue)96 public static Object[][] initializeMultiDimArray(Object[][] olist, Object[] ovalue) 97 { 98 for (int i = 0; i < olist.length; i++) 99 { 100 olist[i] = ovalue; 101 } 102 return olist; 103 } 104 ArrayOutOfMultiDimArray(String _sMultiDimArray[][], int _index)105 public static String[] ArrayOutOfMultiDimArray(String _sMultiDimArray[][], int _index) 106 { 107 String[] sRetArray = null; 108 if (_sMultiDimArray != null) 109 { 110 sRetArray = new String[_sMultiDimArray.length]; 111 for (int i = 0; i < _sMultiDimArray.length; i++) 112 { 113 sRetArray[i] = _sMultiDimArray[i][_index]; 114 } 115 } 116 return sRetArray; 117 } 118 initializeintArray(int FieldCount, int nValue)119 public static int[] initializeintArray(int FieldCount, int nValue) 120 { 121 int[] LocintArray = new int[FieldCount]; 122 for (int i = 0; i < LocintArray.length; i++) 123 { 124 LocintArray[i] = nValue; 125 } 126 return LocintArray; 127 } 128 129 /**converts a list of Integer values included in an Integer vector to a list of int values 130 * 131 * 132 * @param _aIntegerVector 133 * @return 134 */ IntegerTointList(Vector<Integer> _aIntegerVector)135 public static int[] IntegerTointList(Vector<Integer> _aIntegerVector) 136 { 137 try 138 { 139 Integer[] nIntegerValues = new Integer[_aIntegerVector.size()]; 140 int[] nintValues = new int[_aIntegerVector.size()]; 141 _aIntegerVector.toArray(nIntegerValues); 142 for (int i = 0; i < nIntegerValues.length; i++) 143 { 144 nintValues[i] = nIntegerValues[i].intValue(); 145 } 146 return nintValues; 147 } 148 catch (RuntimeException e) 149 { 150 e.printStackTrace(System.out); 151 return null; 152 } 153 } 154 155 /**converts a list of Boolean values included in a Boolean vector to a list of boolean values 156 * 157 * 158 * @param _aBooleanVector 159 * @return 160 */ BooleanTobooleanList(Vector<Boolean> _aBooleanVector)161 public static boolean[] BooleanTobooleanList(Vector<Boolean> _aBooleanVector) 162 { 163 try 164 { 165 Boolean[] bBooleanValues = new Boolean[_aBooleanVector.size()]; 166 boolean[] bbooleanValues = new boolean[_aBooleanVector.size()]; 167 _aBooleanVector.toArray(bBooleanValues); 168 for (int i = 0; i < bBooleanValues.length; i++) 169 { 170 bbooleanValues[i] = bBooleanValues[i].booleanValue(); 171 } 172 return bbooleanValues; 173 } 174 catch (RuntimeException e) 175 { 176 e.printStackTrace(System.out); 177 return null; 178 } 179 } 180 multiDimListToArray(String[][] multidimlist)181 public static String[] multiDimListToArray(String[][] multidimlist) 182 { 183 String[] retlist = new String[] 184 { 185 }; 186 retlist = new String[multidimlist.length]; 187 for (int i = 0; i < multidimlist.length; i++) 188 { 189 retlist[i] = multidimlist[i][0]; 190 } 191 return retlist; 192 } 193 getlongestArrayItem(String[] StringArray)194 public static String getlongestArrayItem(String[] StringArray) 195 { 196 String sLongestItem = PropertyNames.EMPTY_STRING; 197 int FieldCount = StringArray.length; 198 int iOldLength = 0; 199 int iCurLength = 0; 200 for (int i = 0; i < FieldCount; i++) 201 { 202 iCurLength = StringArray[i].length(); 203 if (iCurLength > iOldLength) 204 { 205 iOldLength = iCurLength; 206 sLongestItem = StringArray[i]; 207 } 208 } 209 return sLongestItem; 210 } 211 ArraytoString(String[] LocArray)212 public static String ArraytoString(String[] LocArray) 213 { 214 StringBuilder ResultString = new StringBuilder(PropertyNames.EMPTY_STRING); 215 int iLen = LocArray.length; 216 for (int i = 0; i < iLen; i++) 217 { 218 ResultString.append(LocArray[i]); 219 if (i < iLen - 1) 220 { 221 ResultString.append(PropertyNames.SEMI_COLON); 222 } 223 } 224 return ResultString.toString(); 225 } 226 227 /** 228 * @author bc93774 229 * @param SearchList 230 * @param SearchString 231 * @return the index of the field that contains the string 'SearchString' or '-1' if not it is 232 * not contained within the array 233 */ FieldInList(String[] SearchList, String SearchString)234 public static int FieldInList(String[] SearchList, String SearchString) 235 { 236 int FieldLen = SearchList.length; 237 int retvalue = -1; 238 for (int i = 0; i < FieldLen; i++) 239 { 240 if (SearchList[i].compareTo(SearchString) == 0) 241 { 242 retvalue = i; 243 break; 244 } 245 } 246 return retvalue; 247 } 248 FieldInList(String[] SearchList, String SearchString, int StartIndex)249 public static int FieldInList(String[] SearchList, String SearchString, int StartIndex) 250 { 251 int FieldLen = SearchList.length; 252 int retvalue = -1; 253 if (StartIndex < FieldLen) 254 { 255 for (int i = StartIndex; i < FieldLen; i++) 256 { 257 if (SearchList[i].compareTo(SearchString) == 0) 258 { 259 retvalue = i; 260 break; 261 } 262 } 263 } 264 return retvalue; 265 } 266 FieldInTable(String[][] SearchList, String SearchString)267 public static int FieldInTable(String[][] SearchList, String SearchString) 268 { 269 int retvalue; 270 if (SearchList.length > 0) 271 { 272 int FieldLen = SearchList.length; 273 retvalue = -1; 274 for (int i = 0; i < FieldLen; i++) 275 { 276 if (SearchList[i][0] != null) 277 { 278 if (SearchList[i][0].compareTo(SearchString) == 0) 279 { 280 retvalue = i; 281 break; 282 } 283 } 284 } 285 } 286 else 287 { 288 retvalue = -1; 289 } 290 return retvalue; 291 } 292 FieldInIntTable(int[][] SearchList, int SearchValue)293 public static int FieldInIntTable(int[][] SearchList, int SearchValue) 294 { 295 int retvalue = -1; 296 for (int i = 0; i < SearchList.length; i++) 297 { 298 if (SearchList[i][0] == SearchValue) 299 { 300 retvalue = i; 301 break; 302 } 303 } 304 return retvalue; 305 } 306 FieldInIntTable(int[] SearchList, int SearchValue, int _startindex)307 public static int FieldInIntTable(int[] SearchList, int SearchValue, int _startindex) 308 { 309 int retvalue = -1; 310 for (int i = _startindex; i < SearchList.length; i++) 311 { 312 if (SearchList[i] == SearchValue) 313 { 314 retvalue = i; 315 break; 316 } 317 } 318 return retvalue; 319 } 320 FieldInIntTable(int[] SearchList, int SearchValue)321 public static int FieldInIntTable(int[] SearchList, int SearchValue) 322 { 323 return FieldInIntTable(SearchList, SearchValue, 0); 324 } 325 getArraylength(Object[] MyArray)326 public static int getArraylength(Object[] MyArray) 327 { 328 int FieldCount = 0; 329 if (MyArray != null) 330 { 331 FieldCount = MyArray.length; 332 } 333 return FieldCount; 334 } 335 336 /** 337 * @author bc93774 338 * This function bubble sorts an array of with 2 dimensions. 339 * The default sorting order is the first dimension 340 * Only if sort2ndValue is True the second dimension is the relevant for the sorting order 341 */ bubblesortList(String[][] SortList)342 public static String[][] bubblesortList(String[][] SortList) 343 { 344 String DisplayDummy; 345 int SortCount = SortList[0].length; 346 int DimCount = SortList.length; 347 for (int s = 0; s < SortCount; s++) 348 { 349 for (int t = 0; t < SortCount - s - 1; t++) 350 { 351 if (SortList[0][t].compareTo(SortList[0][t + 1]) > 0) 352 { 353 for (int k = 0; k < DimCount; k++) 354 { 355 DisplayDummy = SortList[k][t]; 356 SortList[k][t] = SortList[k][t + 1]; 357 SortList[k][t + 1] = DisplayDummy; 358 } 359 } 360 } 361 } 362 return SortList; 363 } 364 365 /** 366 * @param MainString 367 * @param Token 368 * @return 369 */ ArrayoutofString(String MainString, String Token)370 public static String[] ArrayoutofString(String MainString, String Token) 371 { 372 String[] StringArray; 373 if (!MainString.equals(PropertyNames.EMPTY_STRING)) 374 { 375 Vector StringVector = new Vector(); 376 String LocString = null; 377 int iIndex; 378 do 379 { 380 iIndex = MainString.indexOf(Token); 381 if (iIndex < 0) 382 { 383 StringVector.addElement(MainString); 384 } 385 else 386 { 387 StringVector.addElement(MainString.substring(0, iIndex)); 388 MainString = MainString.substring(iIndex + 1, MainString.length()); 389 } 390 } 391 while (iIndex >= 0); 392 int FieldCount = StringVector.size(); 393 StringArray = new String[FieldCount]; 394 StringVector.copyInto(StringArray); 395 } 396 else 397 { 398 StringArray = new String[0]; 399 } 400 return StringArray; 401 } 402 replaceSubString(String MainString, String NewSubString, String OldSubString)403 public static String replaceSubString(String MainString, String NewSubString, String OldSubString) 404 { 405 try 406 { 407 int NewIndex = 0; 408 int OldIndex = 0; 409 int NewSubLen = NewSubString.length(); 410 int OldSubLen = OldSubString.length(); 411 while (NewIndex != -1) 412 { 413 NewIndex = MainString.indexOf(OldSubString, OldIndex); 414 if (NewIndex != -1) 415 { 416 MainString = MainString.substring(0, NewIndex) + NewSubString + MainString.substring(NewIndex + OldSubLen); 417 OldIndex = NewIndex + NewSubLen; 418 } 419 } 420 return MainString; 421 } 422 catch (Exception exception) 423 { 424 exception.printStackTrace(System.out); 425 return null; 426 } 427 } 428 getFilenameOutOfPath(String sPath)429 public static String getFilenameOutOfPath(String sPath) 430 { 431 String[] Hierarchy = ArrayoutofString(sPath, "/"); 432 return Hierarchy[Hierarchy.length - 1]; 433 } 434 getFileDescription(String sPath)435 public static String getFileDescription(String sPath) 436 { 437 String sFilename = getFilenameOutOfPath(sPath); 438 String[] FilenameList = ArrayoutofString(sFilename, "."); 439 StringBuilder FileDescription = new StringBuilder(PropertyNames.EMPTY_STRING); 440 for (int i = 0; i < FilenameList.length - 1; i++) 441 { 442 FileDescription.append(FilenameList[i]); 443 } 444 return FileDescription.toString(); 445 } 446 convertfromURLNotation(String _sURLPath)447 public static String convertfromURLNotation(String _sURLPath) 448 { 449 String sPath = PropertyNames.EMPTY_STRING; 450 try 451 { 452 URL oJavaURL = new URL(_sURLPath); 453 File oFile = UrlToFileMapper.mapUrlToFile(oJavaURL); 454 sPath = oFile.getAbsolutePath(); 455 } 456 catch (MalformedURLException e) 457 { 458 e.printStackTrace(System.out); 459 } 460 catch (IOException e) 461 { 462 e.printStackTrace(System.out); 463 } 464 return sPath; 465 } 466 getDateTime(long timeMillis)467 public static DateTime getDateTime(long timeMillis) 468 { 469 java.util.Calendar cal = java.util.Calendar.getInstance(); 470 setTimeInMillis(cal, timeMillis); 471 DateTime dt = new DateTime(); 472 dt.Year = (short) cal.get(Calendar.YEAR); 473 dt.Day = (short) cal.get(Calendar.DAY_OF_MONTH); 474 dt.Month = (short) (cal.get(Calendar.MONTH) + 1); 475 dt.Hours = (short) cal.get(Calendar.HOUR); 476 dt.Minutes = (short) cal.get(Calendar.MINUTE); 477 dt.Seconds = (short) cal.get(Calendar.SECOND); 478 dt.HundredthSeconds = (short) cal.get(Calendar.MILLISECOND); 479 return dt; 480 } 481 getTimeInMillis(Calendar _calendar)482 public static long getTimeInMillis(Calendar _calendar) 483 { 484 java.util.Date dDate = _calendar.getTime(); 485 return dDate.getTime(); 486 } 487 setTimeInMillis(Calendar _calendar, long _timemillis)488 public static void setTimeInMillis(Calendar _calendar, long _timemillis) 489 { 490 java.util.Date dDate = new java.util.Date(); 491 dDate.setTime(_timemillis); 492 _calendar.setTime(dDate); 493 } 494 getMillis(DateTime time)495 public static long getMillis(DateTime time) 496 { 497 java.util.Calendar cal = java.util.Calendar.getInstance(); 498 cal.set(time.Year, time.Month, time.Day, time.Hours, time.Minutes, time.Seconds); 499 return getTimeInMillis(cal); 500 } 501 removeOutdatedFields(String[] baselist, String[] _complist)502 public static String[] removeOutdatedFields(String[] baselist, String[] _complist) 503 { 504 String[] retarray = new String[] 505 { 506 }; 507 if ((baselist != null) && (_complist != null)) 508 { 509 Vector retvector = new Vector(); 510 // String[] orderedcomplist = new String[_complist.length]; 511 // System.arraycopy(_complist, 0, orderedcomplist, 0, _complist.length); 512 for (int i = 0; i < baselist.length; i++) 513 // if (Arrays.binarySearch(orderedcomplist, baselist[i]) != -1) 514 { 515 if (FieldInList(_complist, baselist[i]) > -1) 516 { 517 retvector.add(baselist[i]); 518 // else 519 // here you could call the method of a defined interface to notify the calling method 520 // } 521 } 522 } 523 retarray = new String[retvector.size()]; 524 retvector.toArray(retarray); 525 } 526 return (retarray); 527 } 528 removeOutdatedFields(String[][] baselist, String[] _complist, int _compindex)529 public static String[][] removeOutdatedFields(String[][] baselist, String[] _complist, int _compindex) 530 { 531 String[][] retarray = new String[][] {}; 532 if ((baselist != null) && (_complist != null)) 533 { 534 if (baselist.length > 0) 535 { 536 Vector retvector = new Vector(); 537 for (int i = 0; i < baselist.length; i++) 538 { 539 String sValue = baselist[i][_compindex]; 540 if (FieldInList(_complist, sValue) != -1) 541 { 542 retvector.add(baselist[i]); 543 // else 544 // here you could call the method of a defined interface to notify the calling method 545 } 546 } 547 retarray = new String[retvector.size()][2]; 548 retvector.toArray(retarray); 549 } 550 } 551 return (retarray); 552 } 553 removeOutdatedFields(String[][] baselist, String[] _complist)554 public static String[][] removeOutdatedFields(String[][] baselist, String[] _complist) 555 { 556 return removeOutdatedFields(baselist, _complist, 0); 557 } 558 removeOutdatedFields(PropertyValue[][] baselist, String[] _complist)559 public static PropertyValue[][] removeOutdatedFields(PropertyValue[][] baselist, String[] _complist) 560 { 561 if ((baselist != null) && (_complist != null)) 562 { 563 ArrayList<PropertyValue[]> firstdimvector = new ArrayList<PropertyValue[]>(); 564 for (int n = 0; n < baselist.length; n++) 565 { 566 ArrayList<PropertyValue> secdimvector = new ArrayList<PropertyValue>(); 567 for (int m = 0; m < baselist[n].length; m++) 568 { 569 if (FieldInList(_complist, baselist[n][m].Name) > -1) 570 { 571 secdimvector.add(baselist[n][m]); 572 } 573 } 574 if (!secdimvector.isEmpty()) 575 { 576 PropertyValue[] internalArray = new PropertyValue[secdimvector.size()]; 577 secdimvector.toArray(internalArray); 578 firstdimvector.add(internalArray); 579 } 580 } 581 PropertyValue[][] retarray = new PropertyValue[firstdimvector.size()][]; 582 return firstdimvector.toArray(retarray); 583 } 584 return new PropertyValue[][] 585 { 586 }; 587 } 588 589 /** 590 * searches a multidimensional array for duplicate fields. According to the following example 591 * SlaveFieldName1 ;SlaveFieldName2; SlaveFieldName3 592 * MasterFieldName1;MasterFieldName2;MasterFieldName3 593 * The entries SlaveFieldNameX and MasterFieldNameX are grouped together and then the created groups are compared 594 * If a group is duplicate the entry of the second group is returned. 595 * @param _scomplist 596 * @return 597 */ getDuplicateFieldIndex(String[][] _scomplist)598 public static int getDuplicateFieldIndex(String[][] _scomplist) 599 { 600 int retvalue = -1; 601 if (_scomplist.length > 0) 602 { 603 int fieldcount = _scomplist[0].length; 604 String[] sDescList = new String[fieldcount]; 605 for (int m = 0; m < fieldcount; m++) 606 { 607 for (int n = 0; n < _scomplist.length; n++) 608 { 609 if (n == 0) 610 { 611 sDescList[m] = ""; 612 } 613 sDescList[m] += _scomplist[n][m]; 614 } 615 } 616 return getDuplicateFieldIndex(sDescList); 617 } 618 return retvalue; 619 } 620 621 /** 622 * not tested!!!!! 623 * @param scomplist 624 * @return 625 */ getDuplicateFieldIndex(String[] scomplist)626 public static int getDuplicateFieldIndex(String[] scomplist) 627 { 628 for (int n = 0; n < scomplist.length; n++) 629 { 630 String scurvalue = scomplist[n]; 631 for (int m = n; m < scomplist.length; m++) 632 { 633 if (m != n) 634 { 635 if (scurvalue.equals(scomplist[m])) 636 { 637 return m; 638 } 639 } 640 } 641 } 642 return -1; 643 } 644 getDuplicateFieldIndex(String[] _scomplist, String _fieldname)645 public static int getDuplicateFieldIndex(String[] _scomplist, String _fieldname) 646 { 647 int iduplicate = 0; 648 for (int n = 0; n < _scomplist.length; n++) 649 { 650 if (_scomplist[n].equals(_fieldname)) 651 { 652 iduplicate++; 653 if (iduplicate == 2) 654 { 655 return n; 656 } 657 } 658 } 659 return -1; 660 } 661 isEqual(PropertyValue firstPropValue, PropertyValue secPropValue)662 public static boolean isEqual(PropertyValue firstPropValue, PropertyValue secPropValue) 663 { 664 if (!firstPropValue.Name.equals(secPropValue.Name)) 665 { 666 return false; 667 //TODO replace 'equals' with AnyConverter.getType(firstpropValue).equals(secPropValue) to check content and Type 668 } 669 if (!firstPropValue.Value.equals(secPropValue.Value)) 670 { 671 return false; 672 } 673 return (firstPropValue.Handle == secPropValue.Handle); 674 } 675 getDuplicateFieldIndex(PropertyValue[][] ocomplist)676 public static int[] getDuplicateFieldIndex(PropertyValue[][] ocomplist) 677 { 678 for (int n = 0; n < ocomplist.length; n++) 679 { 680 PropertyValue[] ocurValue = ocomplist[n]; 681 for (int m = n; m < ocurValue.length; m++) 682 { 683 PropertyValue odetValue = ocurValue[m]; 684 for (int s = 0; s < ocurValue.length; s++) 685 { 686 if (s != m) 687 { 688 if (isEqual(odetValue, ocurValue[s])) 689 { 690 return new int[] 691 { 692 n, s 693 }; 694 } 695 } 696 } 697 } 698 } 699 return new int[] 700 { 701 -1, -1 702 }; 703 } 704 getSuffixNumber(String _sbasestring)705 public static String getSuffixNumber(String _sbasestring) 706 { 707 int suffixcharcount = 0; 708 for (int i = _sbasestring.length() - 1; i >= 0; i--) 709 { 710 char b = _sbasestring.charAt(i); 711 if ((b >= '0') && (b <= '9')) 712 { 713 suffixcharcount++; 714 } 715 else 716 { 717 break; 718 } 719 } 720 int istart = _sbasestring.length() - suffixcharcount; 721 return _sbasestring.substring(istart, _sbasestring.length()); 722 } 723 removefromList(String[] _sbaselist, String[] _sdellist)724 public static String[] removefromList(String[] _sbaselist, String[] _sdellist) 725 { 726 Vector tempbaselist = new Vector(); 727 for (int i = 0; i < _sbaselist.length; i++) 728 { 729 if (FieldInList(_sdellist, _sbaselist[i]) == -1) 730 { 731 tempbaselist.add(_sbaselist[i]); 732 } 733 } 734 String[] sretlist = new String[tempbaselist.size()]; 735 tempbaselist.toArray(sretlist); 736 return sretlist; 737 } 738 739 /** 740 * compares two strings. If one of them is empty and the other one is null it also returns true 741 * @param sFirstString 742 * @param sSecondString 743 * @return 744 */ isSame(String sFirstString, String sSecondString)745 public static boolean isSame(String sFirstString, String sSecondString) 746 { 747 boolean bissame = false; 748 if (sFirstString == null) 749 { 750 if (sSecondString != null) 751 { 752 bissame = sSecondString.equals(PropertyNames.EMPTY_STRING); 753 } 754 else 755 { 756 bissame = true; 757 } 758 } 759 else 760 { 761 if (sFirstString.equals(PropertyNames.EMPTY_STRING)) 762 { 763 bissame = (sSecondString == null); 764 } 765 else if (sSecondString != null) 766 { 767 bissame = sFirstString.equals(sSecondString); 768 } 769 } 770 return bissame; 771 } 772 } 773