View Javadoc

1   //Copyright 2007-2008, by the California Institute of Technology.
2   //ALL RIGHTS RESERVED. United States Government Sponsorship acknowledged.
3   //Any commercial use must be negotiated with the Office of Technology Transfer
4   //at the California Institute of Technology.
5   //
6   //This software is subject to U. S. export control laws and regulations
7   //(22 C.F.R. 120-130 and 15 C.F.R. 730-774). To the extent that the software
8   //is subject to U.S. export control laws and regulations, the recipient has
9   //the responsibility to obtain export licenses or other export authority as
10  //may be required before exporting such information to foreign countries or
11  //providing access to foreign nationals.
12  
13  package gov.nasa.pds.ltdt.label.reformat;
14  
15  import gov.nasa.pds.ltdt.label.statement.PrettyAttributeStatement;
16  import gov.nasa.pds.ltdt.label.statement.PrettyCommentStatement;
17  import gov.nasa.pds.ltdt.label.statement.PrettyGroupStatement;
18  import gov.nasa.pds.ltdt.label.statement.PrettyObjectStatement;
19  import gov.nasa.pds.ltdt.label.statement.PrettyStatement;
20  import gov.nasa.pds.ltdt.parser.ParserLite;
21  
22  import java.io.ByteArrayOutputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.util.ArrayList;
26  import java.util.Iterator;
27  import java.util.List;
28  
29  /***
30   * Class to reformat a PDS label so that it will have the 
31   * following characteristics:
32   * <ul>
33   *   <li>The position of the '=' will be two characters past the longest
34   *   element name up to a maximum predefined position. Default is position
35   *   40.</li>
36   *   <li>Lines within objects and groups are indented</li>
37   *   <li>Every line ends with a \<CR\>\<LF\></li>
38   *   <li>Lines will be wrapped at position 78 with subsequent lines of a 
39   *   wrapped value being indented 2 positions.</li>
40   * </ul>
41   * 
42   * 
43   * @author mcayanan
44   *
45   */
46  public class LabelReformatter {
47  	
48  	private static int DEFAULT_MAX_EQUALS = 40;
49  	private static String NEWLINE = Character.toString((char)0x0d) + Character.toString((char)0x0a);
50  	
51  	public LabelReformatter() {}
52  	
53  	/***
54  	 * Return a stream representation of a reformatted PDS label, where
55  	 * the max position of the '=' will be up to a default position of
56  	 * 40.
57  	 * 
58  	 * @param label A stream representation of the PDS label.
59  	 * 
60  	 * @return A stream representation of a reformatted PDS label.
61  	 * @throws IOException
62  	 */
63  	public ByteArrayOutputStream reformat(InputStream label) throws IOException {
64  		return reformat(label, DEFAULT_MAX_EQUALS);
65  	}
66  	
67  	/***
68       * Return a stream that contains a reformatted label, where all
69       * equals sign are aligned and all groups and objects are indented.
70       * The '=' will be one character past the longest element name up to
71       * the given maximum predefined position.
72       * 
73  	 * @param label A stream representation of the PDS label.
74  	 * @param maxEquals The maximum position of the '='.
75  	 * 
76  	 * @return A stream representation of the PDS label.
77  	 * @throws IOException 
78  	 */
79  	public ByteArrayOutputStream reformat(InputStream label, int maxEquals) 
80  	                               throws IOException {
81  		short indent = 0;
82  		ByteArrayOutputStream output = new ByteArrayOutputStream();
83  		List statements = new ArrayList();
84  		ParserLite parser = new ParserLite();
85  		statements = parser.parse(label);
86  		
87  		//Maximum position of the equals will be 2 spaces past the
88  		//longest identifier length found.
89  		int maxLength = getMaxIdentifierLength(statements, (short) 0) + 2;
90  		int maxValue = Math.min(maxLength, maxEquals) + 1;
91  		
92  		for(Iterator i=statements.iterator(); i.hasNext();) {
93  			Object object = i.next();
94  			try {
95  				PrettyStatement s = (PrettyStatement) object;
96  				String line = new String(s.toString(indent, maxValue)) + NEWLINE;
97  				output.write(line.getBytes());			
98  			} catch(ClassCastException ce) {
99  				String line = new String(object.toString()) + NEWLINE;
100 				output.write(line.getBytes());
101 			} catch(IllegalArgumentException ae) {
102 				//We've encountered a comment if this exception was thrown.
103 				PrettyCommentStatement cs = (PrettyCommentStatement) object;
104 				String line = new String(cs.toString(indent)) + NEWLINE;
105 				output.write(line.getBytes());
106 			}
107 		}
108 		return output;
109 	}
110 	
111 	/***
112 	 * Get the longest identifier length out of the given list of statements.
113 	 * 
114 	 * @param prettyStatements The list of PrettyStatement objects.
115 	 * @param indent The number of spaces that the statement will be indented.
116 	 *
117 	 * @return The value of the longest identifier length, including
118 	 * the indentation.
119 	 */
120 	public int getMaxIdentifierLength(List prettyStatements, short indent) {
121 		int maxValue = 0;
122 		
123 		for(Iterator i=prettyStatements.iterator(); i.hasNext();) {
124 			int length = 0;
125 			try {
126 				PrettyStatement s = (PrettyStatement) i.next();
127 				if(s instanceof PrettyAttributeStatement) {
128 					PrettyAttributeStatement ps = (PrettyAttributeStatement) s;
129 					length = ps.getIdentifier().length() + indent;
130 				}
131 				else if(s instanceof PrettyObjectStatement) {
132 					PrettyObjectStatement o = (PrettyObjectStatement) s;
133 					length = getMaxIdentifierLength(o.getStatements(), (short)(indent + 2));
134 				}
135 				else if(s instanceof PrettyGroupStatement) {
136 					PrettyGroupStatement g = (PrettyGroupStatement) s;
137 					length = getMaxIdentifierLength(g.getStatements(), (short)(indent + 2));
138 				}
139 				maxValue = Math.max(length, maxValue);
140 			} catch(ClassCastException c) {
141 				//Don't do anything.
142 			}
143 		}
144 		return maxValue;
145 	}
146 }