001: /* ========================================================================
002: * JCommon : a free general purpose class library for the Java(tm) platform
003: * ========================================================================
004: *
005: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006: *
007: * Project Info: http://www.jfree.org/jcommon/index.html
008: *
009: * This library is free software; you can redistribute it and/or modify it
010: * under the terms of the GNU Lesser General Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but
015: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017: * License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022: * USA.
023: *
024: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025: * in the United States and other countries.]
026: *
027: * -------------------------
028: * SplittingModelWriter.java
029: * -------------------------
030: * (C)opyright 2003, by Thomas Morgner and Contributors.
031: *
032: * Original Author: Thomas Morgner;
033: * Contributor(s): David Gilbert (for Object Refinery Limited);
034: *
035: * $Id: SplittingModelWriter.java,v 1.2 2005/10/18 13:32:20 mungady Exp $
036: *
037: * Changes
038: * -------------------------
039: * 12.11.2003 : Initial version
040: *
041: */
042:
043: package org.jfree.xml.generator;
044:
045: import java.io.BufferedWriter;
046: import java.io.File;
047: import java.io.FileOutputStream;
048: import java.io.IOException;
049: import java.io.OutputStreamWriter;
050: import java.util.ArrayList;
051: import java.util.Arrays;
052: import java.util.Iterator;
053:
054: import org.jfree.io.IOUtils;
055: import org.jfree.util.HashNMap;
056: import org.jfree.util.Log;
057: import org.jfree.xml.generator.model.ClassDescription;
058: import org.jfree.xml.generator.model.DescriptionModel;
059: import org.jfree.xml.generator.model.ManualMappingInfo;
060: import org.jfree.xml.generator.model.MappingModel;
061: import org.jfree.xml.generator.model.MultiplexMappingInfo;
062: import org.jfree.xml.util.ClassModelTags;
063:
064: /**
065: * A model writer that writes to multiple files.
066: */
067: public class SplittingModelWriter extends ModelWriter {
068:
069: /** ??. */
070: private HashNMap classDescriptionByPackage;
071:
072: /** The sources. */
073: private ArrayList sources;
074:
075: /** The target file. */
076: private File targetFile;
077:
078: /** The file extension. */
079: private String extension;
080:
081: /** The plain file name. */
082: private String plainFileName;
083:
084: /** ??. */
085: private HashNMap manualMappingByPackage;
086:
087: /** ??. */
088: private HashNMap multiplexMappingByPackage;
089:
090: /**
091: * Creates a new instance.
092: */
093: public SplittingModelWriter() {
094: super ();
095: }
096:
097: /**
098: * Writes the model to the specified target.
099: *
100: * @param target the target file name.
101: *
102: * @throws IOException if there is an I/O problem.
103: */
104: public synchronized void write(final String target)
105: throws IOException {
106:
107: final DescriptionModel model = getModel();
108: this .sources = new ArrayList(Arrays.asList(model.getSources()));
109: this .targetFile = new File(target);
110: this .plainFileName = IOUtils.getInstance().stripFileExtension(
111: this .targetFile.getName());
112: this .extension = IOUtils.getInstance().getFileExtension(target);
113:
114: // split into classDescriptionByPackage ...
115: this .classDescriptionByPackage = new HashNMap();
116: for (int i = 0; i < model.size(); i++) {
117: final ClassDescription cd = model.get(i);
118: if (cd.getSource() == null) {
119: final String packageName = getPackage(cd
120: .getObjectClass());
121: final String includeFileName = this .plainFileName + "-"
122: + packageName + this .extension;
123: this .classDescriptionByPackage.add(includeFileName, cd);
124: } else {
125: this .classDescriptionByPackage.add(cd.getSource(), cd);
126: }
127: }
128:
129: final MappingModel mappingModel = model.getMappingModel();
130:
131: // split manual mappings into packages ...
132: final ManualMappingInfo[] manualMappings = mappingModel
133: .getManualMapping();
134: this .manualMappingByPackage = new HashNMap();
135: for (int i = 0; i < manualMappings.length; i++) {
136: final ManualMappingInfo mapping = manualMappings[i];
137: if (mapping.getSource() == null) {
138: this .manualMappingByPackage.add("", mapping);
139: } else {
140: this .manualMappingByPackage.add(mapping.getSource(),
141: mapping);
142: }
143: }
144:
145: // split manual mappings into packages ...
146: final MultiplexMappingInfo[] multiplexMappings = mappingModel
147: .getMultiplexMapping();
148: this .multiplexMappingByPackage = new HashNMap();
149: for (int i = 0; i < multiplexMappings.length; i++) {
150: final MultiplexMappingInfo mapping = multiplexMappings[i];
151: if (mapping.getSource() == null) {
152: this .multiplexMappingByPackage.add("", mapping);
153: } else {
154: this .multiplexMappingByPackage.add(mapping.getSource(),
155: mapping);
156: }
157: }
158:
159: final Object[] keys = this .classDescriptionByPackage.keySet()
160: .toArray();
161: for (int i = 0; i < keys.length; i++) {
162:
163: final String includeFileName = (String) keys[i];
164: // write if not contained in the master file ...
165: if (!includeFileName.equals("")) {
166: writePackageFile(includeFileName);
167: }
168: }
169:
170: writeMasterFile();
171:
172: this .manualMappingByPackage = null;
173: this .multiplexMappingByPackage = null;
174: this .classDescriptionByPackage = null;
175: this .sources = null;
176: }
177:
178: /**
179: * Writes a file for a package.
180: *
181: * @param includeFileName the name of the file.
182: *
183: * @throws IOException if there is an I/O problem.
184: */
185: private void writePackageFile(final String includeFileName)
186: throws IOException {
187:
188: final Iterator values = this .classDescriptionByPackage
189: .getAll(includeFileName);
190: final Iterator manualMappings = this .manualMappingByPackage
191: .getAll(includeFileName);
192: final Iterator multiplexMappings = this .multiplexMappingByPackage
193: .getAll(includeFileName);
194: if (!values.hasNext() && !manualMappings.hasNext()
195: && !multiplexMappings.hasNext()) {
196: return;
197: }
198:
199: Log.debug("Writing included file: " + includeFileName);
200: // the current file need no longer be included manually ...
201: this .sources.remove(includeFileName);
202:
203: final BufferedWriter writer = new BufferedWriter(
204: new OutputStreamWriter(new FileOutputStream(new File(
205: this .targetFile.getParentFile(),
206: includeFileName)), "UTF-8"));
207:
208: writeXMLHeader(writer);
209: writeStandardComment(writer, getModel().getModelComments());
210: getWriterSupport().writeTag(writer, ClassModelTags.OBJECTS_TAG);
211:
212: while (values.hasNext()) {
213: final ClassDescription cd = (ClassDescription) values
214: .next();
215: writeClassDescription(writer, cd);
216: }
217:
218: while (manualMappings.hasNext()) {
219: final ManualMappingInfo mi = (ManualMappingInfo) manualMappings
220: .next();
221: writeManualMapping(writer, mi);
222: }
223:
224: while (multiplexMappings.hasNext()) {
225: final MultiplexMappingInfo mi = (MultiplexMappingInfo) multiplexMappings
226: .next();
227: writeMultiplexMapping(writer, mi);
228: }
229:
230: writeCloseComment(writer, getModel().getModelComments());
231: getWriterSupport().writeCloseTag(writer,
232: ClassModelTags.OBJECTS_TAG);
233: writer.close();
234: }
235:
236: /**
237: * Returns the name of the package for the given class. This is a
238: * workaround for the classloader behaviour of JDK1.2.2 where no
239: * package objects are created.
240: *
241: * @param c the class for which we search the package.
242: *
243: * @return the name of the package, never null.
244: */
245: public static String getPackage(final Class c) {
246: final String className = c.getName();
247: final int idx = className.lastIndexOf('.');
248: if (idx <= 0) {
249: // the default package
250: return "";
251: } else {
252: return className.substring(0, idx);
253: }
254: }
255:
256: /**
257: * Writes the master file.
258: *
259: * @throws IOException if there is an I/O problem.
260: */
261: private void writeMasterFile() throws IOException {
262:
263: Log.debug("Writing master file: " + this .targetFile);
264:
265: final BufferedWriter writer = new BufferedWriter(
266: new OutputStreamWriter(new FileOutputStream(
267: this .targetFile), "UTF-8"));
268:
269: writeXMLHeader(writer);
270: writeStandardComment(writer, getModel().getModelComments());
271: getWriterSupport().writeTag(writer, ClassModelTags.OBJECTS_TAG);
272:
273: for (int i = 0; i < this .sources.size(); i++) {
274: final String includeFileName = (String) this .sources.get(i);
275: if (!includeFileName.equals("")) {
276: writeTag(writer, ClassModelTags.INCLUDE_TAG,
277: ClassModelTags.SOURCE_ATTR, includeFileName,
278: getModel().getIncludeComment(includeFileName));
279: }
280: }
281:
282: final Object[] keys = this .classDescriptionByPackage.keySet()
283: .toArray();
284: Arrays.sort(keys);
285: for (int i = 0; i < keys.length; i++) {
286: final String includeFileName = (String) keys[i];
287: if (!includeFileName.equals("")) {
288: writeTag(writer, ClassModelTags.INCLUDE_TAG,
289: ClassModelTags.SOURCE_ATTR, includeFileName,
290: getModel().getIncludeComment(includeFileName));
291: }
292: }
293:
294: final Iterator values = this .classDescriptionByPackage
295: .getAll("");
296: while (values.hasNext()) {
297: final ClassDescription cd = (ClassDescription) values
298: .next();
299: writeClassDescription(writer, cd);
300: }
301:
302: final Iterator manualMappings = this .manualMappingByPackage
303: .getAll("");
304: while (manualMappings.hasNext()) {
305: final ManualMappingInfo mi = (ManualMappingInfo) manualMappings
306: .next();
307: writeManualMapping(writer, mi);
308: }
309:
310: final Iterator multiplexMappings = this .multiplexMappingByPackage
311: .getAll("");
312: while (multiplexMappings.hasNext()) {
313: final MultiplexMappingInfo mi = (MultiplexMappingInfo) multiplexMappings
314: .next();
315: writeMultiplexMapping(writer, mi);
316: }
317:
318: writeCloseComment(writer, getModel().getModelComments());
319: getWriterSupport().writeCloseTag(writer,
320: ClassModelTags.OBJECTS_TAG);
321: writer.close();
322: }
323:
324: }
|