001    /*
002     * Copyright (C) 2006-2007 the original author or authors.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.codehaus.gmaven.runtime.support.stubgen.render;
018    
019    import org.codehaus.gmaven.runtime.support.stubgen.model.ClassDef;
020    import org.codehaus.gmaven.runtime.support.stubgen.model.ConstructorDef;
021    import org.codehaus.gmaven.runtime.support.stubgen.model.EnumConstantDef;
022    import org.codehaus.gmaven.runtime.support.stubgen.model.EnumDef;
023    import org.codehaus.gmaven.runtime.support.stubgen.model.FieldDef;
024    import org.codehaus.gmaven.runtime.support.stubgen.model.ImportDef;
025    import org.codehaus.gmaven.runtime.support.stubgen.model.JavaDocAware;
026    import org.codehaus.gmaven.runtime.support.stubgen.model.JavaDocDef;
027    import org.codehaus.gmaven.runtime.support.stubgen.model.MethodDef;
028    import org.codehaus.gmaven.runtime.support.stubgen.model.ModifiersAware;
029    import org.codehaus.gmaven.runtime.support.stubgen.model.ModifiersDef;
030    import org.codehaus.gmaven.runtime.support.stubgen.model.PackageDef;
031    import org.codehaus.gmaven.runtime.support.stubgen.model.ParameterDef;
032    import org.codehaus.gmaven.runtime.support.stubgen.model.SuperParameterDef;
033    import org.codehaus.gmaven.runtime.support.stubgen.model.TagDef;
034    import org.codehaus.gmaven.runtime.support.stubgen.model.TypeDef;
035    
036    import java.io.BufferedReader;
037    import java.io.IOException;
038    import java.io.PrintWriter;
039    import java.io.StringReader;
040    import java.io.Writer;
041    import java.util.HashMap;
042    import java.util.Iterator;
043    import java.util.Map;
044    import java.util.Set;
045    
046    /**
047     * Provides support for {@link Renderer} implementations.
048     *
049     * @version $Id: RendererSupport.java 18 2009-07-16 09:39:40Z user57 $
050     * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
051     */
052    public class RendererSupport
053        implements Renderer
054    {
055        protected final ClassDef clazz;
056    
057        protected final Map importAliases = new HashMap();
058    
059        protected final Map definedMethods = new HashMap();
060    
061        protected RendererSupport(final ClassDef clazz) {
062            assert clazz != null;
063    
064            this.clazz = clazz;
065    
066            assert clazz.getParent() != null;
067    
068            // Create a map of method signatures for quick lookup resolution
069            Iterator iter = clazz.getMethods().iterator();
070            while (iter.hasNext()) {
071                MethodDef method = (MethodDef)iter.next();
072    
073                definedMethods.put(method.signature(), method);
074            }
075        }
076    
077        public void render(final Writer writer) throws IOException {
078            assert writer != null;
079    
080            PrintWriter out = new PrintWriter(writer);
081    
082            renderHeader(out);
083    
084            renderPackage(out);
085    
086            renderImports(out);
087    
088            renderClass(out);
089    
090            out.flush();
091        }
092    
093        public String getName() {
094            return clazz.getName();
095        }
096    
097        public String getPackage() {
098            PackageDef pkg = clazz.getPackage();
099            if (pkg != null) {
100                return pkg.getName();
101            }
102            return null;
103        }
104    
105        //
106        // Rendering
107        //
108    
109        protected void renderHeader(final PrintWriter out) {
110            assert out != null;
111    
112            // TODO: Should try to include the legal headers from the source here if we can parse them out
113    
114            out.println("//");
115            out.println("// Generated stub from " + clazz.getParent().getUrl());
116            out.println("//");
117            out.println();
118        }
119    
120        protected void renderPackage(final PrintWriter out) {
121            assert out != null;
122    
123            PackageDef def = clazz.getPackage();
124    
125            if (def != null) {
126                out.print("package ");
127                out.print(def.getName());
128                out.println(";");
129            }
130            else {
131                out.println("// Default package");
132            }
133    
134            out.println();
135        }
136    
137        protected void renderImports(final PrintWriter out) {
138            assert out != null;
139    
140            Set imports = clazz.getImports();
141            assert imports != null;
142    
143            if (!imports.isEmpty()) {
144                Iterator iter = imports.iterator();
145    
146                while (iter.hasNext()) {
147                    ImportDef def = (ImportDef)iter.next();
148    
149                    renderImport(out, def);
150                }
151    
152                out.println();
153            }
154        }
155    
156        protected void renderImport(final PrintWriter out, final ImportDef def) {
157            assert out != null;
158            assert def != null;
159    
160            // If the import is an alias (import as) then add to the mapping and omit rendering import
161            // will use the fully qualified name of the type when the alias is encoutnered
162    
163            String alias = def.getAlias();
164            if (alias != null) {
165                importAliases.put(alias, def);
166    
167                out.print("// Import alias '");
168                out.print(alias);
169                out.print("' will resolve to the full-qualified name: ");
170                out.println(def.getQualifiedName());
171    
172                return;
173            }
174    
175            out.print("import ");
176    
177            if (def.isStatic()) {
178                out.print("static ");
179            }
180    
181            out.print(def.getQualifiedName());
182    
183            if (def.isWildcard()) {
184                out.print(".*");
185            }
186    
187            out.println(";");
188        }
189    
190        protected void renderType(final PrintWriter out, TypeDef def) {
191            assert out != null;
192            assert def != null;
193    
194            String name = def.getName();
195    
196            if (name == null) {
197                name = TypeDef.OBJECT;
198            }
199            else {
200                ImportDef alias = (ImportDef)importAliases.get(name);
201    
202                if (alias != null) {
203                    name = alias.getQualifiedName();
204                }
205            }
206    
207            out.print(name);
208    
209            int dimensions = def.getDimensions();
210    
211            for (int i=0; i < dimensions; i++) {
212                out.print("[]");
213            }
214        }
215    
216        protected void renderTypeSet(final PrintWriter out, final Set types) {
217            assert out != null;
218            assert types != null;
219    
220            Iterator iter = types.iterator();
221    
222            while (iter.hasNext()) {
223                TypeDef def = (TypeDef)iter.next();
224                renderType(out, def);
225    
226                if (iter.hasNext()) {
227                    out.print(", ");
228                }
229            }
230        }
231    
232        protected void renderModifiers(final PrintWriter out, final ModifiersAware source) {
233            assert out != null;
234            assert source != null;
235    
236            ModifiersDef modifiers = source.getModifiers();
237            assert modifiers != null;
238    
239            Set values = modifiers.getValues();
240    
241            if (!values.isEmpty()) {
242                Iterator iter = values.iterator();
243    
244                while (iter.hasNext()) {
245                    String modifier = (String)iter.next();
246    
247                    out.print(modifier);
248    
249                    if (iter.hasNext()) {
250                        out.print(" ");
251                    }
252                }
253    
254                out.print(" ");
255            }
256        }
257    
258        protected void renderJavaDoc(final PrintWriter out, final JavaDocAware source, final String indent) {
259            assert out != null;
260            assert source != null;
261            assert indent != null;
262    
263            JavaDocDef def = source.getJavaDoc();
264    
265            if (def != null) {
266                out.print(indent);
267                out.println("/**");
268    
269                String comment = def.getComment();
270    
271                if (comment != null) {
272                    comment = comment.trim();
273    
274                    if (comment.length() > 0) {
275                        BufferedReader reader = new BufferedReader(new StringReader(comment));
276    
277                        String line;
278                        try {
279                            while ((line = reader.readLine()) != null) {
280                                out.print(indent);
281                                out.print(" * ");
282                                out.println(line);
283                            }
284                        }
285                        catch (IOException e) {
286                            throw new InternalError("Failed to process JavaDoc comment string: " + comment); // Should never happen
287                        }
288                    }
289                }
290    
291                Set tags = def.getTags();
292                assert tags != null;
293    
294                if (!tags.isEmpty()) {
295                    // Add blank if we have a coment
296                    if (comment != null && comment.length() > 0) {
297                        out.print(indent);
298                        out.println(" *");
299                    }
300    
301                    Iterator iter = tags.iterator();
302    
303                    while (iter.hasNext()) {
304                        TagDef tag = (TagDef)iter.next();
305    
306                        out.print(indent);
307                        out.print(" * @");
308                        out.print(tag.getName());
309    
310                        String value = tag.getValue();
311                        if (value != null && value.length() > 0) {
312                            out.print(" ");
313                            out.print(value);
314                        }
315    
316                        out.println();
317                    }
318                }
319    
320                out.print(indent);
321                out.println(" */");
322            }
323        }
324    
325        protected void renderClass(final PrintWriter out) {
326            assert out != null;
327    
328            renderJavaDoc(out, clazz, "");
329    
330            // TODO: May want to clone the modifiers to prevent augmenting the model
331    
332            ModifiersDef modifiers = clazz.getModifiers();
333            if (!modifiers.hasAccessModifiers()) {
334                modifiers.add(ModifiersDef.PUBLIC);
335            }
336    
337            renderModifiers(out, clazz);
338    
339            ClassDef.Type type = clazz.getType();
340            assert type != null;
341    
342            out.print(type);
343            out.print(" ");
344            out.println(clazz.getName());
345    
346            switch (type.code) {
347    
348                case ClassDef.Type.CLASS_CODE:
349                case ClassDef.Type.ENUM_CODE:
350                {
351                    TypeDef superClass = clazz.getSuperClass();
352                    if (superClass != null) {
353                        out.print("    extends ");
354                        renderType(out, superClass);
355                        out.println();
356                    }
357    
358                    Set implementz = clazz.getImplements();
359                    assert implementz != null;
360    
361                    if (!implementz.isEmpty()) {
362                        out.print("    implements ");
363                        renderTypeSet(out, implementz);
364                        out.println();
365                    }
366                }
367                break;
368    
369                case ClassDef.Type.INTERFACE_CODE:
370                case ClassDef.Type.ANNOTATION_CODE:
371                {
372                    Set implementz = clazz.getImplements();
373                    assert implementz != null;
374    
375                    if (!implementz.isEmpty()) {
376                        out.print("    extends ");
377                        renderTypeSet(out, implementz);
378                        out.println();
379                    }
380                }
381                break;
382    
383                default:
384                    throw new InternalError("Invalid class type: " + type); // Should never happen
385            }
386    
387            out.println("{");
388    
389            if (type.code == ClassDef.Type.ENUM_CODE) {
390                renderEnumConstants(out);
391            }
392    
393            renderFields(out);
394    
395            // Seperator only if we have both fields and methods
396            if (!clazz.getFields().isEmpty() && !clazz.getMethods().isEmpty()) {
397                out.println();
398            }
399    
400            renderMethods(out);
401    
402            // TODO: See when we need to set this and when it could be harmful?
403    
404            // Render synthetic methods
405            if (!clazz.isInterface() && !clazz.isAnnotation()) {
406                // Seperator if we have fields or methods
407                if (!clazz.getFields().isEmpty() || !clazz.getMethods().isEmpty()) {
408                    out.println();
409                }
410    
411                renderSyntheticMethods(out);
412            }
413    
414            out.println("}");
415        }
416    
417        protected void renderEnumConstants(final PrintWriter out) {
418            assert out != null;
419    
420            Set constants = ((EnumDef)clazz).getConstants();
421            assert constants != null;
422    
423            if (!constants.isEmpty()) {
424                out.print("    ");
425                
426                Iterator iter = constants.iterator();
427    
428                while (iter.hasNext()) {
429                    EnumConstantDef def = (EnumConstantDef)iter.next();
430    
431                    // TODO: Javadocs?
432    
433                    out.print(def.getName());
434    
435                    //
436                    // TODO: Need to render initalizers
437                    //
438    
439                    if (iter.hasNext()) {
440                        out.print(", ");
441                    }
442                }
443    
444                out.println(";");
445                out.println();
446            }
447        }
448    
449        protected void renderFields(final PrintWriter out) {
450            assert out != null;
451    
452            Set fields = clazz.getFields();
453            assert fields != null;
454    
455            if (!fields.isEmpty()) {
456                Iterator iter = fields.iterator();
457    
458                while (iter.hasNext()) {
459                    FieldDef def = (FieldDef)iter.next();
460    
461                    if (def.isProperty()) {
462                        renderProperty(out, def);
463                    }
464                    else {
465                        renderField(out, def);
466                    }
467    
468                    if (iter.hasNext()) {
469                        out.println();
470                    }
471                }
472            }
473        }
474    
475        protected void renderField(final PrintWriter out, final FieldDef def) {
476            assert out != null;
477            assert def != null;
478    
479            renderJavaDoc(out, def, "    ");
480    
481            out.print("    ");
482    
483            if (!def.getParent().isInterface()) {
484                renderModifiers(out, def);
485            }
486    
487            TypeDef type = def.getType();
488    
489            renderType(out, type);
490    
491            out.print(" ");
492    
493            out.print(def.getName());
494    
495            // TODO: See when we need to set this and when it could be harmful?
496    
497            out.print(" = ");
498            out.print(type.getDefaultValue());
499    
500            out.println(";");
501        }
502    
503        protected void renderProperty(final PrintWriter out, final FieldDef def) {
504            assert out != null;
505            assert def != null;
506            assert def.isProperty();
507    
508            // Render private field, w/original javadocs
509            FieldDef field = new FieldDef();
510            field.setParent(def.getParent());
511            field.setJavaDoc(def.getJavaDoc());
512            field.setType(def.getType());
513            field.setName(def.getName());
514            field.getModifiers().merge(def.getModifiers()).add(ModifiersDef.PRIVATE);
515            renderField(out, field);
516    
517            String name = capitalize(def.getName());
518    
519            // Setup the modifiers for property methods
520            ModifiersDef modifiers = def.getModifiers();
521            modifiers.add(ModifiersDef.PUBLIC);
522            modifiers.remove(ModifiersDef.TRANSIENT).remove(ModifiersDef.VOLATILE);
523    
524            MethodDef getter = new MethodDef();
525            getter.setParent(def.getParent());
526            getter.setName("get" + name);
527            getter.setReturns(def.getType());
528            getter.getModifiers().merge(modifiers);
529    
530            if (!definedMethods.containsKey(getter.signature())) {
531                renderMethod(out, getter);
532            }
533    
534            if (def.getType().isBoolean()) {
535                MethodDef isser = new MethodDef();
536                isser.setParent(def.getParent());
537                isser.setName("is" + name);
538                isser.setReturns(def.getType());
539                isser.getModifiers().merge(modifiers);
540    
541                if (!definedMethods.containsKey(isser.signature())) {
542                    renderMethod(out, isser);
543                }
544            }
545    
546            if (!def.getModifiers().isFinal()) {
547                MethodDef setter = new MethodDef();
548                setter.setParent(def.getParent());
549                setter.setName("set" + name);
550                setter.setReturns(TypeDef.VOID);
551                setter.addParameter(def.getType(), "value");
552                setter.getModifiers().merge(modifiers);
553    
554                if (!definedMethods.containsKey(setter.signature())) {
555                    renderMethod(out, setter);
556                }
557            }
558        }
559    
560        protected String capitalize(final String string) {
561            assert string != null;
562    
563            int length = string.length();
564    
565            if (length == 0) {
566                return string;
567            }
568            else if (length == 1) {
569                return string.toUpperCase();
570            }
571            else {
572                return (Character.toUpperCase(string.charAt(0)) + string.substring(1));
573            }
574        }
575    
576        protected void renderSyntheticMethods(final PrintWriter out) {
577            assert out != null;
578    
579            MethodDef def;
580    
581            //
582            // FIXME: Should these already be configured in the model, since every Class must implement GroovyObject?
583            //
584    
585            /*
586            java.lang.Object invokeMethod(java.lang.String s, java.lang.Object o);
587    
588            java.lang.Object getProperty(java.lang.String s);
589    
590            void setProperty(java.lang.String s, java.lang.Object o);
591    
592            groovy.lang.MetaClass getMetaClass();
593    
594            void setMetaClass(groovy.lang.MetaClass metaClass);
595            */
596    
597            def = new MethodDef();
598            def.setParent(clazz);
599            def.getModifiers().add(ModifiersDef.PUBLIC);
600            def.setReturns("groovy.lang.MetaClass");
601            def.setName("getMetaClass");
602    
603            if (!definedMethods.containsKey(def.signature())) {
604                renderMethod(out, def);
605                out.println();
606            }
607    
608            def = new MethodDef();
609            def.setParent(clazz);
610            def.getModifiers().add(ModifiersDef.PUBLIC);
611            def.setReturns(TypeDef.VOID);
612            def.setName("setMetaClass");
613            def.addParameter("groovy.lang.MetaClass", "metaClass");
614    
615            if (!definedMethods.containsKey(def.signature())) {
616                renderMethod(out, def);
617                out.println();
618            }
619    
620            def = new MethodDef();
621            def.setParent(clazz);
622            def.getModifiers().add(ModifiersDef.PUBLIC);
623            def.setReturns(TypeDef.OBJECT);
624            def.setName("invokeMethod");
625            def.addParameter(TypeDef.STRING, "name");
626            def.addParameter(TypeDef.OBJECT, "args");
627    
628            if (!definedMethods.containsKey(def.signature())) {
629                renderMethod(out, def);
630                out.println();
631            }
632    
633            def = new MethodDef();
634            def.setParent(clazz);
635            def.getModifiers().add(ModifiersDef.PUBLIC);
636            def.setReturns(TypeDef.OBJECT);
637            def.setName("getProperty");
638            def.addParameter(TypeDef.STRING, "name");
639    
640            if (!definedMethods.containsKey(def.signature())) {
641                renderMethod(out, def);
642                out.println();
643            }
644    
645            def = new MethodDef();
646            def.setParent(clazz);
647            def.getModifiers().add(ModifiersDef.PUBLIC);
648            def.setReturns(TypeDef.VOID);
649            def.setName("setProperty");
650            def.addParameter(TypeDef.STRING, "name");
651            def.addParameter(TypeDef.OBJECT, "value");
652    
653            if (!definedMethods.containsKey(def.signature())) {
654                renderMethod(out, def);
655            }
656        }
657    
658        protected void renderMethods(final PrintWriter out) {
659            assert out != null;
660    
661            if (!clazz.isInterface()) {
662                renderMagicConstructors(out);
663            }
664    
665            Set methods = clazz.getMethods();
666            assert methods != null;
667    
668            if (!methods.isEmpty()) {
669                Iterator iter = methods.iterator();
670    
671                while (iter.hasNext()) {
672                    MethodDef def = (MethodDef)iter.next();
673                    renderMethod(out, def);
674    
675                    if (iter.hasNext()) {
676                        out.println();
677                    }
678                }
679            }
680        }
681    
682        protected ConstructorDef createMagicConstructor() {
683            ConstructorDef def = new ConstructorDef(true);
684            def.setParent(clazz);
685            def.getModifiers().add(ModifiersDef.PRIVATE);
686            def.setJavaDoc("Magic constructor");
687    
688            // Add insane params which no one would ever use... :-(
689            def.addParameter("java.lang.Void", "void0");
690            def.addParameter("java.lang.Void", "void1");
691            def.addParameter("java.lang.Void", "void2");
692    
693            //
694            // NOTE: This must match up with what is invoked in {@link #renderMagicConstructorInvoke}
695            //
696    
697            return def;
698        }
699    
700        protected void renderMagicConstructorInvoke(final PrintWriter out, final ConstructorDef def) {
701            assert out != null;
702            assert def != null;
703    
704            out.print("        this((java.lang.Void)null, (java.lang.Void)null, (java.lang.Void)null");
705    
706            // If the given constructor declares throwables, then invoke correct magic constructor
707            Iterator iter = def.getThrows().iterator();
708            while (iter.hasNext()) {
709                TypeDef type = (TypeDef)iter.next();
710                out.print(", ");
711                out.print("(");
712                out.print(type.getName());
713                out.print(")null");
714            }
715    
716            out.println(");");
717        }
718        
719        protected void renderMagicConstructors(final PrintWriter out) {
720            assert out != null;
721    
722            // Only render magic constructors if there are other constructors defined
723            if (!clazz.getConstructors().isEmpty()) {
724                int count=0;
725    
726                // Generate magic constructor for constructors with a throws clauses.
727                Iterator iter = clazz.getConstructors().iterator();
728                while (iter.hasNext()) {
729                    ConstructorDef ctor = (ConstructorDef)iter.next();
730                    if (!ctor.getThrows().isEmpty()) {
731                        // Add a magic constructor based on the default, adding a parameter for each throwable in the list
732                        Iterator iter2 = ctor.getThrows().iterator();
733                        ConstructorDef def = createMagicConstructor();
734                        def.getThrows().addAll(ctor.getThrows());
735    
736                        int i=0;
737                        while (iter2.hasNext()) {
738                            TypeDef type = (TypeDef)iter2.next();
739                            def.addParameter(type.getName(), "cause" + i++);
740                        }
741    
742                        renderMethod(out, def);
743                        out.println();
744    
745                        count++;
746                    }
747                }
748    
749                // Generate the default magic constructor, if we didn't generate any others
750                if (count == 0) {
751                    renderMethod(out, createMagicConstructor());
752                    out.println();
753                }
754            }
755        }
756    
757        protected void renderMethod(final PrintWriter out, final MethodDef def) {
758            assert out != null;
759            assert def != null;
760    
761            MethodDef.Type type = def.getType();
762    
763            renderJavaDoc(out, def, "    ");
764    
765            out.print("    ");
766    
767            if (!def.getParent().isInterface()) {
768                // TODO: May want to clone the modifiers to prevent augmenting the model
769    
770                ModifiersDef modifiers = def.getModifiers();
771                if (!modifiers.hasAccessModifiers()) {
772                    modifiers.add(ModifiersDef.PUBLIC);
773                }
774    
775                renderModifiers(out, def);
776            }
777    
778            if (type == MethodDef.Type.METHOD) {
779                renderType(out, def.getReturns());
780                out.print(" ");
781            }
782    
783            out.print(def.getName());
784    
785            out.print("(");
786    
787            renderParameters(out, def.getParameters());
788    
789            out.print(")");
790    
791            Set throwz = def.getThrows();
792            assert throwz != null;
793    
794            if (!throwz.isEmpty()) {
795                out.print(" throws ");
796                renderTypeSet(out, throwz);
797            }
798    
799            if (def.getParent().isAnnotation()) {
800                //
801                // TODO: Render default muck
802                //
803                
804                out.println(";");
805            }
806            else if (def.getParent().isInterface() || def.getModifiers().isAbstract() || def.getModifiers().isNative()) {
807                out.println(";");
808            }
809            else {
810                out.println(" {");
811    
812                if (def.isConstructor()) {
813                    assert def instanceof ConstructorDef;
814    
815                    ConstructorDef ctor = (ConstructorDef)def;
816    
817                    if (ctor.isMagic()) {
818                        renderMagicConstructorSuper(out, ctor);
819                    }
820                    else {
821                        renderMagicConstructorInvoke(out, ctor);
822                    }
823                }
824    
825                out.println("        throw new InternalError(\"Stubbed method\");");
826    
827                out.println("    }");
828            }
829        }
830    
831        protected void renderMagicConstructorSuper(final PrintWriter out, final ConstructorDef def) {
832            assert out != null;
833            assert def != null;
834    
835            Set parameters = selectMagicConstructorSuperParameters(def);
836    
837            if (parameters != null) {
838                out.print("        super");
839                out.print("(");
840    
841                if (!parameters.isEmpty()) {
842                    Iterator iter = parameters.iterator();
843    
844                    while (iter.hasNext()) {
845                        SuperParameterDef param = (SuperParameterDef)iter.next();
846                        renderSuperParameter(out, param);
847    
848                        if (iter.hasNext()) {
849                            out.print(", ");
850                        }
851                    }
852                }
853    
854                out.println(");");
855                out.println();
856            }
857        }
858    
859        protected Set selectMagicConstructorSuperParameters(final ConstructorDef target) {
860            assert target != null;
861    
862            Iterator iter = target.getParent().getConstructors().iterator();
863    
864            //
865            // TODO: If we can't find one that is fully typed, perhaps we should pick the next best?
866            //
867            
868        FIND_MAGIC_CTOR:
869    
870            while (iter.hasNext()) {
871                ConstructorDef def = (ConstructorDef)iter.next();
872    
873                if (!def.isMagic() && "super".equals(def.getSuperType())) {
874                    Set parameters = def.getSuperParameters();
875    
876                    if (parameters != null && !parameters.isEmpty()) {
877                        Iterator iter2 = parameters.iterator();
878    
879                        while (iter2.hasNext()) {
880                            SuperParameterDef param = (SuperParameterDef)iter2.next();
881    
882                            if (param.getType() == null) {
883                                continue FIND_MAGIC_CTOR;
884                            }
885                        }
886    
887                        return parameters;
888                    }
889                }
890            }
891    
892            return null;
893        }
894    
895        protected void renderSuperParameters(final PrintWriter out, final ConstructorDef def) {
896            assert out != null;
897            assert def != null;
898    
899            String superType = def.getSuperType();
900    
901            if (superType != null) {
902    
903                out.print("        ");
904                out.print(superType);
905                out.print("(");
906    
907                Set params = def.getSuperParameters();
908    
909                if (!params.isEmpty()) {
910                    Iterator iter = params.iterator();
911    
912                    while (iter.hasNext()) {
913                        SuperParameterDef param = (SuperParameterDef)iter.next();
914                        renderSuperParameter(out, param);
915    
916                        if (iter.hasNext()) {
917                            out.print(", ");
918                        }
919                    }
920                }
921    
922                out.println(");");
923                out.println();
924            }
925        }
926    
927        protected void renderSuperParameter(final PrintWriter out, final SuperParameterDef def) {
928            assert out != null;
929            assert def != null;
930    
931            TypeDef type = def.getType();
932            if (type == null) {
933                // This is probably this, null or some dot expression, which needs to be handled better
934                out.print(TypeDef.NULL);
935            }
936            else {
937                out.print("(");
938                renderType(out, type);
939                out.print(")");
940                out.print(type.getDefaultValue());
941            }
942        }
943    
944        protected void renderParameters(final PrintWriter out, final Set parameters) {
945            assert out != null;
946            assert parameters != null;
947    
948            Iterator iter = parameters.iterator();
949    
950            while (iter.hasNext()) {
951                ParameterDef def = (ParameterDef)iter.next();
952    
953                renderParameter(out, def);
954    
955                if (iter.hasNext()) {
956                    out.print(", ");
957                }
958            }
959        }
960    
961        protected void renderParameter(final PrintWriter out, final ParameterDef def) {
962            assert out != null;
963            assert def != null;
964    
965            if (!def.getParent().getParent().isInterface()) {
966                renderModifiers(out, def);
967            }
968    
969            renderType(out, def.getType());
970    
971            out.print(" ");
972    
973            out.print(def.getName());
974        }
975    }