formatting
[jalview.git] / src / jalview / structure / StructureSelectionManager.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10  * 
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.structure;
19
20 import java.io.*;
21 import java.util.*;
22
23 import MCview.*;
24 import jalview.analysis.*;
25 import jalview.api.AlignmentViewPanel;
26 import jalview.api.StructureSelectionManagerProvider;
27 import jalview.datamodel.*;
28
29 public class StructureSelectionManager
30 {
31   static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
32
33   StructureMapping[] mappings;
34
35   /**
36    * debug function - write all mappings to stdout
37    */
38   public void reportMapping()
39   {
40     if (mappings == null)
41     {
42       System.err.println("reportMapping: No PDB/Sequence mappings.");
43     }
44     else
45     {
46       System.err.println("reportMapping: There are " + mappings.length
47               + " mappings.");
48       for (int m = 0; m < mappings.length; m++)
49       {
50         System.err.println("mapping " + m + " : " + mappings[m].pdbfile);
51       }
52     }
53   }
54
55   Hashtable mappingData = new Hashtable();
56
57   public static StructureSelectionManager getStructureSelectionManager(
58           StructureSelectionManagerProvider context)
59   {
60     if (instances == null)
61     {
62       instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
63     }
64     StructureSelectionManager instance = instances.get(context);
65     if (instance == null)
66     {
67       instances.put(context, instance = new StructureSelectionManager());
68     }
69     return instance;
70   }
71
72   /**
73    * flag controlling whether SeqMappings are relayed from received sequence
74    * mouse over events to other sequences
75    */
76   boolean relaySeqMappings = true;
77
78   /**
79    * Enable or disable relay of seqMapping events to other sequences. You might
80    * want to do this if there are many sequence mappings and the host computer
81    * is slow
82    * 
83    * @param relay
84    */
85   public void setRelaySeqMappings(boolean relay)
86   {
87     relaySeqMappings = relay;
88   }
89
90   /**
91    * get the state of the relay seqMappings flag.
92    * 
93    * @return true if sequence mouse overs are being relayed to other mapped
94    *         sequences
95    */
96   public boolean isRelaySeqMappingsEnabled()
97   {
98     return relaySeqMappings;
99   }
100
101   Vector listeners = new Vector();
102
103   /**
104    * register a listener for alignment sequence mouseover events
105    * 
106    * @param svl
107    */
108   public void addStructureViewerListener(Object svl)
109   {
110     if (!listeners.contains(svl))
111     {
112       listeners.addElement(svl);
113     }
114   }
115
116   public String alreadyMappedToFile(String pdbid)
117   {
118     if (mappings != null)
119     {
120       for (int i = 0; i < mappings.length; i++)
121       {
122         if (mappings[i].getPdbId().equals(pdbid))
123         {
124           return mappings[i].pdbfile;
125         }
126       }
127     }
128     return null;
129   }
130
131   /**
132    * create sequence structure mappings between each sequence and the given
133    * pdbFile (retrieved via the given protocol).
134    * 
135    * @param sequence
136    *          - one or more sequences to be mapped to pdbFile
137    * @param targetChains
138    *          - optional chain specification for mapping each sequence to pdb
139    *          (may be nill, individual elements may be nill)
140    * @param pdbFile
141    *          - structure data resource
142    * @param protocol
143    *          - how to resolve data from resource
144    * @return null or the structure data parsed as a pdb file
145    */
146   synchronized public MCview.PDBfile setMapping(SequenceI[] sequence,
147           String[] targetChains, String pdbFile, String protocol)
148   {
149     /*
150      * There will be better ways of doing this in the future, for now we'll use
151      * the tried and tested MCview pdb mapping
152      */
153     MCview.PDBfile pdb = null;
154     try
155     {
156       pdb = new MCview.PDBfile(pdbFile, protocol);
157     } catch (Exception ex)
158     {
159       ex.printStackTrace();
160       return null;
161     }
162
163     String targetChain;
164     for (int s = 0; s < sequence.length; s++)
165     {
166       boolean infChain = true;
167       if (targetChains != null && targetChains[s] != null)
168       {
169         infChain = false;
170         targetChain = targetChains[s];
171       }
172       else if (sequence[s].getName().indexOf("|") > -1)
173       {
174         targetChain = sequence[s].getName().substring(
175                 sequence[s].getName().lastIndexOf("|") + 1);
176         if (targetChain.length() > 1)
177         {
178           if (targetChain.trim().length() == 0)
179           {
180             targetChain = " ";
181           }
182           else
183           {
184             // not a valid chain identifier
185             targetChain = "";
186           }
187         }
188       }
189       else
190         targetChain = "";
191
192       int max = -10;
193       AlignSeq maxAlignseq = null;
194       String maxChainId = " ";
195       PDBChain maxChain = null;
196       boolean first = true;
197       for (int i = 0; i < pdb.chains.size(); i++)
198       {
199         PDBChain chain = ((PDBChain) pdb.chains.elementAt(i));
200         if (targetChain.length() > 0 && !targetChain.equals(chain.id)
201                 && !infChain)
202         {
203           continue; // don't try to map chains don't match.
204         }
205         // TODO: correctly determine sequence type for mixed na/peptide
206         // structures
207         AlignSeq as = new AlignSeq(sequence[s],
208                 ((PDBChain) pdb.chains.elementAt(i)).sequence,
209                 ((PDBChain) pdb.chains.elementAt(i)).isNa ? AlignSeq.DNA
210                         : AlignSeq.PEP);
211         as.calcScoreMatrix();
212         as.traceAlignment();
213
214         if (first || as.maxscore > max
215                 || (as.maxscore == max && chain.id.equals(targetChain)))
216         {
217           first = false;
218           maxChain = chain;
219           max = as.maxscore;
220           maxAlignseq = as;
221           maxChainId = chain.id;
222         }
223       }
224       if (maxChain == null)
225       {
226         continue;
227       }
228       final StringBuffer mappingDetails = new StringBuffer();
229       mappingDetails.append("\n\nPDB Sequence is :\nSequence = "
230               + maxChain.sequence.getSequenceAsString());
231       mappingDetails.append("\nNo of residues = "
232               + maxChain.residues.size() + "\n\n");
233       PrintStream ps = new PrintStream(System.out)
234       {
235         public void print(String x)
236         {
237           mappingDetails.append(x);
238         }
239
240         public void println()
241         {
242           mappingDetails.append("\n");
243         }
244       };
245
246       maxAlignseq.printAlignment(ps);
247
248       mappingDetails.append("\nPDB start/end " + maxAlignseq.seq2start
249               + " " + maxAlignseq.seq2end);
250       mappingDetails.append("\nSEQ start/end "
251               + (maxAlignseq.seq1start + sequence[s].getStart() - 1) + " "
252               + (maxAlignseq.seq1end + sequence[s].getEnd() - 1));
253
254       maxChain.makeExactMapping(maxAlignseq, sequence[s]);
255
256       maxChain.transferRESNUMFeatures(sequence[s], null);
257
258       // allocate enough slots to store the mapping from positions in
259       // sequence[s] to the associated chain
260       int[][] mapping = new int[sequence[s].findPosition(sequence[s]
261               .getLength()) + 2][2];
262       int resNum = -10000;
263       int index = 0;
264
265       do
266       {
267         Atom tmp = (Atom) maxChain.atoms.elementAt(index);
268         if (resNum != tmp.resNumber && tmp.alignmentMapping != -1)
269         {
270           resNum = tmp.resNumber;
271           mapping[tmp.alignmentMapping + 1][0] = tmp.resNumber;
272           mapping[tmp.alignmentMapping + 1][1] = tmp.atomIndex;
273         }
274
275         index++;
276       } while (index < maxChain.atoms.size());
277
278       if (mappings == null)
279       {
280         mappings = new StructureMapping[1];
281       }
282       else
283       {
284         StructureMapping[] tmp = new StructureMapping[mappings.length + 1];
285         System.arraycopy(mappings, 0, tmp, 0, mappings.length);
286         mappings = tmp;
287       }
288
289       if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
290         pdbFile = "INLINE" + pdb.id;
291
292       mappings[mappings.length - 1] = new StructureMapping(sequence[s],
293               pdbFile, pdb.id, maxChainId, mapping,
294               mappingDetails.toString());
295       maxChain.transferResidueAnnotation(mappings[mappings.length - 1]);
296     }
297     // ///////
298
299     return pdb;
300   }
301
302   public void removeStructureViewerListener(Object svl, String[] pdbfiles)
303   {
304     listeners.removeElement(svl);
305     if (svl instanceof SequenceListener)
306     {
307       for (int i = 0; i < listeners.size(); i++)
308       {
309         if (listeners.elementAt(i) instanceof StructureListener)
310         {
311           ((StructureListener) listeners.elementAt(i))
312                   .releaseReferences(svl);
313         }
314       }
315     }
316
317     if (pdbfiles == null)
318     {
319       return;
320     }
321     boolean removeMapping = true;
322     String[] handlepdbs;
323     Vector pdbs = new Vector();
324     for (int i = 0; i < pdbfiles.length; pdbs.addElement(pdbfiles[i++]))
325       ;
326     StructureListener sl;
327     for (int i = 0; i < listeners.size(); i++)
328     {
329       if (listeners.elementAt(i) instanceof StructureListener)
330       {
331         sl = (StructureListener) listeners.elementAt(i);
332         handlepdbs = sl.getPdbFile();
333         for (int j = 0; j < handlepdbs.length; j++)
334         {
335           if (pdbs.contains(handlepdbs[j]))
336           {
337             pdbs.removeElement(handlepdbs[j]);
338           }
339         }
340
341       }
342     }
343
344     if (pdbs.size() > 0 && mappings != null)
345     {
346       Vector tmp = new Vector();
347       for (int i = 0; i < mappings.length; i++)
348       {
349         if (!pdbs.contains(mappings[i].pdbfile))
350         {
351           tmp.addElement(mappings[i]);
352         }
353       }
354
355       mappings = new StructureMapping[tmp.size()];
356       tmp.copyInto(mappings);
357     }
358   }
359
360   public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
361   {
362     if (listeners == null)
363     {
364       // old or prematurely sent event
365       return;
366     }
367     boolean hasSequenceListeners = handlingVamsasMo || seqmappings != null;
368     SearchResults results = null;
369     SequenceI lastseq = null;
370     int lastipos = -1, indexpos;
371     for (int i = 0; i < listeners.size(); i++)
372     {
373       if (listeners.elementAt(i) instanceof SequenceListener)
374       {
375         if (results == null)
376         {
377           results = new SearchResults();
378         }
379         if (mappings != null)
380         {
381           for (int j = 0; j < mappings.length; j++)
382           {
383             if (mappings[j].pdbfile.equals(pdbfile)
384                     && mappings[j].pdbchain.equals(chain))
385             {
386               indexpos = mappings[j].getSeqPos(pdbResNum);
387               if (lastipos != indexpos && lastseq != mappings[j].sequence)
388               {
389                 results.addResult(mappings[j].sequence, indexpos, indexpos);
390                 lastipos = indexpos;
391                 lastseq = mappings[j].sequence;
392                 // construct highlighted sequence list
393                 if (seqmappings != null)
394                 {
395
396                   Enumeration e = seqmappings.elements();
397                   while (e.hasMoreElements())
398
399                   {
400                     ((AlignedCodonFrame) e.nextElement()).markMappedRegion(
401                             mappings[j].sequence, indexpos, results);
402                   }
403                 }
404               }
405
406             }
407           }
408         }
409       }
410     }
411     if (results != null)
412     {
413       for (int i = 0; i < listeners.size(); i++)
414       {
415         Object li = listeners.elementAt(i);
416         if (li instanceof SequenceListener)
417           ((SequenceListener) li).highlightSequence(results);
418       }
419     }
420   }
421
422   Vector seqmappings = null; // should be a simpler list of mapped seuqence
423
424   /**
425    * highlight regions associated with a position (indexpos) in seq
426    * 
427    * @param seq
428    *          the sequeence that the mouse over occured on
429    * @param indexpos
430    *          the absolute position being mouseovered in seq (0 to seq.length())
431    * @param index
432    *          the sequence position (if -1, seq.findPosition is called to
433    *          resolve the residue number)
434    */
435   public void mouseOverSequence(SequenceI seq, int indexpos, int index,
436           VamsasSource source)
437   {
438     boolean hasSequenceListeners = handlingVamsasMo || seqmappings != null;
439     SearchResults results = null;
440     if (index == -1)
441       index = seq.findPosition(indexpos);
442     StructureListener sl;
443     int atomNo = 0;
444     for (int i = 0; i < listeners.size(); i++)
445     {
446       Object listener = listeners.elementAt(i);
447       if (listener == source)
448       {
449         continue;
450       }
451       if (listener instanceof StructureListener)
452       {
453         sl = (StructureListener) listener;
454         if (mappings == null)
455         {
456           continue;
457         }
458         for (int j = 0; j < mappings.length; j++)
459         {
460           if (mappings[j].sequence == seq
461                   || mappings[j].sequence == seq.getDatasetSequence())
462           {
463             atomNo = mappings[j].getAtomNum(index);
464
465             if (atomNo > 0)
466             {
467               sl.highlightAtom(atomNo, mappings[j].getPDBResNum(index),
468                       mappings[j].pdbchain, mappings[j].pdbfile);
469             }
470           }
471         }
472       }
473       else
474       {
475         if (relaySeqMappings && hasSequenceListeners
476                 && listener instanceof SequenceListener)
477         {
478           // DEBUG
479           // System.err.println("relay Seq " + seq.getDisplayId(false) + " " +
480           // index);
481
482           if (results == null)
483           {
484             results = new SearchResults();
485             if (index >= seq.getStart() && index <= seq.getEnd())
486             {
487               // construct highlighted sequence list
488
489               if (seqmappings != null)
490               {
491                 Enumeration e = seqmappings.elements();
492                 while (e.hasMoreElements())
493
494                 {
495                   ((AlignedCodonFrame) e.nextElement()).markMappedRegion(
496                           seq, index, results);
497                 }
498               }
499               // hasSequenceListeners = results.getSize() > 0;
500               if (handlingVamsasMo)
501               {
502                 // maybe have to resolve seq to a dataset seqeunce...
503                 // add in additional direct sequence and/or dataset sequence
504                 // highlighting
505                 results.addResult(seq, index, index);
506               }
507             }
508           }
509           if (hasSequenceListeners)
510           {
511             ((SequenceListener) listener).highlightSequence(results);
512           }
513         }
514         else if (listener instanceof VamsasListener && !handlingVamsasMo)
515         {
516           // DEBUG
517           // System.err.println("Vamsas from Seq " + seq.getDisplayId(false) + "
518           // " +
519           // index);
520           // pass the mouse over and absolute position onto the
521           // VamsasListener(s)
522           ((VamsasListener) listener).mouseOver(seq, indexpos, source);
523         }
524         else if (listener instanceof SecondaryStructureListener)
525         {
526           ((SecondaryStructureListener) listener).mouseOverSequence(seq,
527                   indexpos);
528         }
529       }
530     }
531   }
532
533   /**
534    * true if a mouse over event from an external (ie Vamsas) source is being
535    * handled
536    */
537   boolean handlingVamsasMo = false;
538
539   long lastmsg = 0;
540
541   /**
542    * as mouseOverSequence but only route event to SequenceListeners
543    * 
544    * @param sequenceI
545    * @param position
546    *          in an alignment sequence
547    */
548   public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
549           VamsasSource source)
550   {
551     handlingVamsasMo = true;
552     long msg = sequenceI.hashCode() * (1 + position);
553     if (lastmsg != msg)
554     {
555       lastmsg = msg;
556       mouseOverSequence(sequenceI, position, -1, source);
557     }
558     handlingVamsasMo = false;
559   }
560
561   public Annotation[] colourSequenceFromStructure(SequenceI seq,
562           String pdbid)
563   {
564     return null;
565     // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
566     // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
567     /*
568      * Annotation [] annotations = new Annotation[seq.getLength()];
569      * 
570      * StructureListener sl; int atomNo = 0; for (int i = 0; i <
571      * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
572      * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
573      * 
574      * for (int j = 0; j < mappings.length; j++) {
575      * 
576      * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
577      * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
578      * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
579      * "+mappings[j].pdbfile);
580      * 
581      * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
582      * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
583      * 
584      * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
585      * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
586      * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
587      * mappings[j].pdbfile); }
588      * 
589      * annotations[index] = new Annotation("X",null,' ',0,col); } return
590      * annotations; } } } }
591      * 
592      * return annotations;
593      */
594   }
595
596   public void structureSelectionChanged()
597   {
598   }
599
600   public void sequenceSelectionChanged()
601   {
602   }
603
604   public void sequenceColoursChanged(Object source)
605   {
606     StructureListener sl;
607     for (int i = 0; i < listeners.size(); i++)
608     {
609       if (listeners.elementAt(i) instanceof StructureListener)
610       {
611         sl = (StructureListener) listeners.elementAt(i);
612         sl.updateColours(source);
613       }
614     }
615   }
616
617   public StructureMapping[] getMapping(String pdbfile)
618   {
619     Vector tmp = new Vector();
620     if (mappings != null)
621     {
622       for (int i = 0; i < mappings.length; i++)
623       {
624         if (mappings[i].pdbfile.equals(pdbfile))
625         {
626           tmp.addElement(mappings[i]);
627         }
628       }
629     }
630     StructureMapping[] ret = new StructureMapping[tmp.size()];
631     for (int i = 0; i < tmp.size(); i++)
632     {
633       ret[i] = (StructureMapping) tmp.elementAt(i);
634     }
635
636     return ret;
637   }
638
639   public String printMapping(String pdbfile)
640   {
641     StringBuffer sb = new StringBuffer();
642     for (int i = 0; i < mappings.length; i++)
643     {
644       if (mappings[i].pdbfile.equals(pdbfile))
645       {
646         sb.append(mappings[i].mappingDetails);
647       }
648     }
649
650     return sb.toString();
651   }
652
653   private int[] seqmappingrefs = null; // refcount for seqmappings elements
654
655   private synchronized void modifySeqMappingList(boolean add,
656           AlignedCodonFrame[] codonFrames)
657   {
658     if (!add && (seqmappings == null || seqmappings.size() == 0))
659       return;
660     if (seqmappings == null)
661       seqmappings = new Vector();
662     if (codonFrames != null && codonFrames.length > 0)
663     {
664       for (int cf = 0; cf < codonFrames.length; cf++)
665       {
666         if (seqmappings.contains(codonFrames[cf]))
667         {
668           if (add)
669           {
670             seqmappingrefs[seqmappings.indexOf(codonFrames[cf])]++;
671           }
672           else
673           {
674             if (--seqmappingrefs[seqmappings.indexOf(codonFrames[cf])] <= 0)
675             {
676               int pos = seqmappings.indexOf(codonFrames[cf]);
677               int[] nr = new int[seqmappingrefs.length - 1];
678               if (pos > 0)
679               {
680                 System.arraycopy(seqmappingrefs, 0, nr, 0, pos);
681               }
682               if (pos < seqmappingrefs.length - 1)
683               {
684                 System.arraycopy(seqmappingrefs, pos + 1, nr, 0,
685                         seqmappingrefs.length - pos - 2);
686               }
687             }
688           }
689         }
690         else
691         {
692           if (add)
693           {
694             seqmappings.addElement(codonFrames[cf]);
695
696             int[] nsr = new int[(seqmappingrefs == null) ? 1
697                     : seqmappingrefs.length + 1];
698             if (seqmappingrefs != null && seqmappingrefs.length > 0)
699               System.arraycopy(seqmappingrefs, 0, nsr, 0,
700                       seqmappingrefs.length);
701             nsr[(seqmappingrefs == null) ? 0 : seqmappingrefs.length] = 1;
702             seqmappingrefs = nsr;
703           }
704         }
705       }
706     }
707   }
708
709   public void removeMappings(AlignedCodonFrame[] codonFrames)
710   {
711     modifySeqMappingList(false, codonFrames);
712   }
713
714   public void addMappings(AlignedCodonFrame[] codonFrames)
715   {
716     modifySeqMappingList(true, codonFrames);
717   }
718
719   Vector<SelectionListener> sel_listeners = new Vector<SelectionListener>();
720
721   public void addSelectionListener(SelectionListener selecter)
722   {
723     if (!sel_listeners.contains(selecter))
724     {
725       sel_listeners.addElement(selecter);
726     }
727   }
728
729   public void removeSelectionListener(SelectionListener toremove)
730   {
731     if (sel_listeners.contains(toremove))
732     {
733       sel_listeners.removeElement(toremove);
734     }
735   }
736
737   public synchronized void sendSelection(
738           jalview.datamodel.SequenceGroup selection,
739           jalview.datamodel.ColumnSelection colsel, SelectionSource source)
740   {
741     if (sel_listeners != null && sel_listeners.size() > 0)
742     {
743       Enumeration listeners = sel_listeners.elements();
744       while (listeners.hasMoreElements())
745       {
746         SelectionListener slis = ((SelectionListener) listeners
747                 .nextElement());
748         if (slis != source)
749         {
750           slis.selection(selection, colsel, source);
751         }
752         ;
753       }
754     }
755   }
756
757   Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
758
759   public synchronized void sendViewPosition(
760           jalview.api.AlignmentViewPanel source, int startRes, int endRes,
761           int startSeq, int endSeq)
762   {
763
764     if (view_listeners != null && view_listeners.size() > 0)
765     {
766       Enumeration<AlignmentViewPanelListener> listeners = view_listeners
767               .elements();
768       while (listeners.hasMoreElements())
769       {
770         AlignmentViewPanelListener slis = listeners.nextElement();
771         if (slis != source)
772         {
773           slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
774         }
775         ;
776       }
777     }
778   }
779
780   public void finalize() throws Throwable
781   {
782     if (listeners != null)
783     {
784       listeners.clear();
785       listeners = null;
786     }
787     if (mappingData != null)
788     {
789       mappingData.clear();
790       mappingData = null;
791     }
792     if (sel_listeners != null)
793     {
794       sel_listeners.clear();
795       sel_listeners = null;
796     }
797     if (view_listeners != null)
798     {
799       view_listeners.clear();
800       view_listeners = null;
801     }
802     mappings = null;
803     seqmappingrefs = null;
804   }
805
806   /**
807    * release all references associated with this manager provider
808    * 
809    * @param jalviewLite
810    */
811   public static void release(StructureSelectionManagerProvider jalviewLite)
812   {
813     // synchronized (instances)
814     {
815       if (instances == null)
816       {
817         return;
818       }
819       StructureSelectionManager mnger = (instances.get(jalviewLite));
820       if (mnger != null)
821       {
822         instances.remove(jalviewLite);
823         try
824         {
825           mnger.finalize();
826         } catch (Throwable x)
827         {
828         }
829         ;
830       }
831     }
832   }
833
834 }