root/pl/PLObjectOutput.java

Revision 10 (checked in by rsz, 4 years ago)

Initial import

Line 
1 //
2 //      ===========================================================================
3 //
4 //      Title:          PLObjectOutput.java
5 //      Description:    PL ObjectOutput
6 //      Author:         Rapha‘l Szwarc http://alt.textdrive.com/pl/
7 //      Creation Date:  Thu Dec 09 2004
8 //      Legal:          Copyright (C) 2004 Rapha‘l Szwarc
9 //
10 //      This software is provided 'as-is', without any express or implied warranty.
11 //      In no event will the author be held liable for any damages arising from
12 //      the use of this software.
13 //
14 //      Permission is granted to anyone to use this software for any purpose,
15 //      including commercial applications, and to alter it and
16 //      redistribute it freely, subject to the following restrictions:
17 //
18 //      1. The origin of this software must not be misrepresented;
19 //      you must not claim that you wrote the original software.
20 //      If you use this software in a product, an acknowledgment
21 //      in the product documentation would be appreciated but is not required.
22 //
23 //      2. Altered source versions must be plainly marked as such,
24 //      and must not be misrepresented as being the original software.
25 //
26 //      3. This notice may not be removed or altered from any source distribution.
27 //
28 //      ---------------------------------------------------------------------------
29 //
30
31 package alt.dev.pl;
32
33 import java.io.ByteArrayOutputStream;
34 import java.io.OutputStream;
35 import java.io.ObjectOutput;
36 import java.io.IOException;
37
38 import java.util.List;
39 import java.util.ArrayList;
40 import java.util.Map;
41 import java.util.HashMap;
42
43 import java.util.logging.Logger;
44 import java.util.logging.Level;
45
46 public class PLObjectOutput extends Object implements ObjectOutput, PLWriter.Delegate
47 {
48
49 //      ===========================================================================
50 //      Constant(s)
51 //      ---------------------------------------------------------------------------
52
53         private static final Logger     Log = Logger.getLogger( PLObjectOutput.class.getName() );
54
55 //      ===========================================================================
56 //      Class variable(s)
57 //      ---------------------------------------------------------------------------
58
59 //      ===========================================================================
60 //      Instance variable(s)
61 //      ---------------------------------------------------------------------------
62
63         private OutputStream            _outputStream = null;
64         private PLObjectOutput          _parent = null;
65         private List                    _values = null;
66         private boolean                 _isTraversing = false;
67         private Map                     _userInfo = null;
68         private int                     _aliasID = 0;
69         private CountedSet              _aliasIDs = null;
70         private Map                     _aliases = null;
71        
72 //      ===========================================================================
73 //      Constructor method(s)
74 //      ---------------------------------------------------------------------------
75
76         public PLObjectOutput(final OutputStream anOutputStream)
77         {
78                 this();
79                
80                 this.setOutputStream( anOutputStream );
81         }
82
83         PLObjectOutput(final PLObjectOutput aParent)
84         {
85                 this();
86                
87                 this.setParent( aParent );
88         }
89        
90         PLObjectOutput()
91         {
92                 super();
93         }
94
95 //      ===========================================================================
96 //      Class method(s)
97 //      ---------------------------------------------------------------------------
98
99         public static String toString(final Object anObject)
100         {
101                 try
102                 {
103                         ByteArrayOutputStream   anOutputStream = new ByteArrayOutputStream();
104                         ObjectOutput            anObjectOutput = new PLObjectOutput( anOutputStream );
105                        
106                         anObjectOutput.writeObject( anObject );
107                         anObjectOutput.close();
108                        
109                         return new String( anOutputStream.toByteArray(), PLWriter.Encoding );
110                 }
111                 catch (Exception anException)
112                 {
113                         Log.log( Level.FINER, anException.getMessage(), anException );
114                         Log.info( "Couldn't convert '" + anObject + "'." );
115                 }
116                
117                 return null;
118         }
119
120 //      ===========================================================================
121 //      Instance method(s)
122 //      ---------------------------------------------------------------------------
123
124         private OutputStream outputStream()
125         {
126                 return _outputStream;
127         }
128        
129         private void setOutputStream(final OutputStream aValue)
130         {
131                 if ( aValue != null )
132                 {
133                         _outputStream = aValue;
134                        
135                         return;
136                 }
137                
138                 throw new IllegalArgumentException( "PLObjectOutput.setOutputStream: value" );
139         }
140        
141         private PLObjectOutput parent()
142         {
143                 return _parent;
144         }
145        
146         private void setParent(final PLObjectOutput aValue)
147         {
148                 if ( aValue != null )
149                 {
150                         _parent = aValue;
151                        
152                         return;
153                 }
154                
155                 throw new IllegalArgumentException( "PLObjectOutput.setOutputStream: value" );
156         }
157        
158         public List values()
159         {
160                 if ( _values == null )
161                 {
162                         this.setValues( new ArrayList() );
163                 }
164                
165                 return _values;
166         }
167        
168         private void setValues(final List aValue)
169         {
170                 _values = aValue;
171         }
172        
173         private boolean isTraversing()
174         {
175                 return _isTraversing;
176         }
177        
178         private void setIsTraversing(final boolean aValue)
179         {
180                 _isTraversing = aValue;
181         }
182        
183         public Map userInfo()
184         {
185                 if ( _userInfo == null )
186                 {
187                         _userInfo = new HashMap();
188                 }
189        
190                 return _userInfo;
191         }
192        
193 //      ===========================================================================
194 //      DataOutput method(s)
195 //      ---------------------------------------------------------------------------
196
197         public void write(final byte[] aValue) throws IOException
198         {
199                 this.values().add( aValue );
200         }
201
202         public void write(final byte[] aValue, final int anOffset, final int aLength) throws IOException
203         {
204                 byte[]  someBytes = new byte[ aLength ];
205                
206                 System.arraycopy( aValue, anOffset, someBytes, 0, aLength );
207                
208                 this.values().add( someBytes );
209         }
210
211         public void write(final int aValue) throws IOException
212         {
213                 byte[]  someBytes = { (byte) aValue };
214                
215                 this.values().add( someBytes );
216         }
217
218         public void writeBoolean(final boolean aValue) throws IOException
219         {
220                 String  aDescription = Boolean.TYPE.getName() + ":" + Boolean.toString( aValue );
221                
222                 this.values().add( aDescription );
223         }
224
225         public void writeByte(final int aValue) throws IOException
226         {
227                 byte[]  someBytes = { (byte) aValue };
228                
229                 this.values().add( someBytes );
230         }
231
232         public void writeBytes(final String aValue) throws IOException
233         {
234                 this.values().add( aValue.getBytes() );
235         }
236
237         public void writeChar(final int aValue) throws IOException
238         {
239                 String  aDescription = Character.toString( (char) aValue );
240                
241                 this.values().add( aDescription );
242         }
243
244         public void writeChars(final String aValue) throws IOException
245         {
246                 this.values().add( aValue );
247         }
248
249         public void writeDouble(final double aValue) throws IOException
250         {
251                 String  aDescription = Double.TYPE.getName() + ":" + Double.toString( aValue );
252                
253                 this.values().add( aDescription );
254         }
255
256         public void writeFloat(final float aValue) throws IOException
257         {
258                 String  aDescription = Float.TYPE.getName() + ":" + Float.toString( aValue );
259                
260                 this.values().add( aDescription );
261         }
262
263         public void writeInt(final int aValue) throws IOException
264         {
265                 String  aDescription = Integer.TYPE.getName() + ":" + Integer.toString( aValue );
266                
267                 this.values().add( aDescription );
268         }
269
270         public void writeLong(final long aValue) throws IOException
271         {
272                 String  aDescription = Long.TYPE.getName() + ":" + Long.toString( aValue );
273                
274                 this.values().add( aDescription );
275         }
276
277         public void writeShort(final int aValue) throws IOException
278         {
279                 String  aDescription = Short.TYPE.getName() + ":" + Short.toString( (short) aValue );
280                
281                 this.values().add( aDescription );
282         }
283
284         public void writeUTF(final String aValue) throws IOException
285         {
286                 List    someValues = this.values();
287                
288                 this.values().add( aValue );
289         }
290
291 //      ===========================================================================
292 //      ObjectOutput method(s)
293 //      ---------------------------------------------------------------------------
294
295         public void close() throws IOException
296         {
297                 if ( this.outputStream() != null )
298                 {
299                         this.outputStream().close();
300                 }
301         }
302
303         public void flush() throws IOException
304         {
305         }
306
307         public void writeObject(final Object anObject) throws IOException
308         {
309                 if ( this.parent() == null )
310                 {
311                         PLWriter      aWriter = new PLWriter( this.outputStream() );
312                        
313                         aWriter.setDelegate( this );
314                        
315                         this.setIsTraversing( true );
316                         PLObjectOutputWriter.writeObject( anObject, this );
317                         this.aliases().clear();
318                         this.setAliasID( 0 );
319                         this.setIsTraversing( false );
320
321                         aWriter.writeObject( anObject );
322                 }
323                 else
324                 {
325                         Object  anotherObject = PLObjectOutputWriter.writeObject( anObject, this );
326                
327                         this.values().add( anotherObject );
328                 }
329         }
330        
331 //      ===========================================================================
332 //      PLWriter.Delegate method(s)
333 //      ---------------------------------------------------------------------------
334
335         public Object valueForObject(final PLWriter aWriter, final Object anObject)
336         {
337                 return PLObjectOutputWriter.writeObject( anObject, this );
338         }
339
340 //      ===========================================================================
341 //      Aliases method(s)
342 //      ---------------------------------------------------------------------------
343
344         private Map aliases()
345         {
346                 if ( this.parent() == null )
347                 {
348                         if ( _aliases == null )
349                         {
350                                 _aliases = new HashMap();
351                         }
352                        
353                         return _aliases;
354                 }
355                
356                 return this.parent().aliases();
357         }
358
359         private int aliasID()
360         {
361                 if ( this.parent() == null )
362                 {
363                         return ( _aliasID += 1 );
364                 }
365                
366                 return this.parent().aliasID();
367         }
368        
369         private void setAliasID(final int aValue)
370         {
371                 if ( this.parent() == null )
372                 {
373                         _aliasID = aValue;
374                        
375                         return;
376                 }
377                
378                 this.parent().setAliasID( aValue );
379         }
380        
381         private CountedSet aliasIDs()
382         {
383                 if ( this.parent() == null )
384                 {
385                         if ( _aliasIDs == null )
386                         {
387                                 _aliasIDs = new CountedSet();
388                         }
389                
390                         return _aliasIDs;
391                 }
392                
393                 return this.parent().aliasIDs();
394         }
395        
396         public Object aliasID(final Object anObject)
397         {
398                 Object  aKey = this.aliasKey( anObject );
399                 int     aCount = this.aliasIDs().countForObject( aKey );
400                
401                 if ( aCount > 1 )
402                 {
403                         Object  anAlias = this.alias( anObject );
404                        
405                         return anAlias.toString();
406                 }
407                        
408                 return null;
409         }
410        
411         private Object aliasKey(final Object anObject)
412         {
413                 if ( anObject != null )
414                 {
415                         StringBuffer    aBuffer = new StringBuffer( 24 );
416                        
417                         aBuffer.append( anObject.getClass().hashCode() );
418                         aBuffer.append( '@' );
419                         aBuffer.append( System.identityHashCode( anObject ) );
420                        
421                         return aBuffer.toString();
422                 }
423                
424                 return null;
425         }
426
427         Object alias(final Object anObject)
428         {
429                 if ( ( anObject != null ) && ( ( anObject instanceof Alias ) == false ) )
430                 {
431                         Object  aKey = this.aliasKey( anObject );
432                         Map     someAliases = this.aliases();
433                         Object  anAlias = someAliases.get( aKey );
434                        
435                         if ( this.isTraversing() == true )
436                         {
437                                 this.aliasIDs().add( aKey );
438                         }
439                                
440                         if ( anAlias == null )
441                         {
442                                 anAlias = new Alias( this.aliasID() );
443                                
444                                 someAliases.put( aKey, anAlias );
445                         }
446                         else
447                         {
448                                 return anAlias;
449                         }
450                 }
451                
452                 return anObject;
453         }
454        
455 //      ===========================================================================
456 //      Alias method(s)
457 //      ---------------------------------------------------------------------------
458
459         static final class Alias extends Object
460         {
461        
462                 private int     _id = 0;
463        
464                 private Alias(final int anID)
465                 {
466                         super();
467                        
468                         _id = anID;
469                 }
470                
471                 public final String toString()
472                 {
473                         return Integer.toString( _id );
474                 }
475                
476         }
477
478 }
Note: See TracBrowser for help on using the browser.