001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.openimaj.rdf.owl2java;
031
032import java.io.File;
033import java.io.FileNotFoundException;
034import java.io.PrintStream;
035import java.io.UnsupportedEncodingException;
036import java.util.Arrays;
037import java.util.HashMap;
038import java.util.HashSet;
039import java.util.Iterator;
040import java.util.Map;
041import java.util.Set;
042
043import org.apache.commons.lang.WordUtils;
044import org.joda.time.DateTime;
045import org.openimaj.rdf.owl2java.Generator.GeneratorOptions;
046import org.openrdf.model.URI;
047import org.openrdf.model.Value;
048import org.openrdf.query.BindingSet;
049import org.openrdf.query.MalformedQueryException;
050import org.openrdf.query.QueryEvaluationException;
051import org.openrdf.query.QueryLanguage;
052import org.openrdf.query.TupleQuery;
053import org.openrdf.query.TupleQueryResult;
054import org.openrdf.repository.RepositoryConnection;
055import org.openrdf.repository.RepositoryException;
056import org.openrdf.sail.memory.model.MemBNode;
057import org.openrdf.sail.memory.model.MemLiteral;
058import org.openrdf.sail.memory.model.MemStatement;
059import org.openrdf.sail.memory.model.MemStatementList;
060
061/**
062 * Represents the definition of an ontology class.
063 * 
064 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
065 * @author David Dupplaw (dpd@ecs.soton.ac.uk)
066 * @created 29 Oct 2012
067 * @version $Author$, $Revision$, $Date$
068 */
069public class ClassDef
070{
071        /** The description of the class from the RDF comment */
072        protected String comment;
073
074        /** The URI of the class */
075        protected URI uri;
076
077        /**
078         * List of the all the ancestral superclasses to each of the direct
079         * superclasses
080         */
081        protected Map<URI, Set<URI>> allSuperclasses;
082
083        /** A list of the direct superclasses of this class */
084        protected Set<URI> directSuperclasses;
085
086        /** List of the properties in this class */
087        protected Set<PropertyDef> properties;
088
089        /**
090         * Outputs the Java class definition for this class def
091         * 
092         * {@inheritDoc}
093         * 
094         * @see java.lang.Object#toString()
095         */
096        @Override
097        public String toString()
098        {
099                return "class " + this.uri.getLocalName() + " extends " +
100                                this.allSuperclasses + " {\n" + "\t" + this.properties + "\n}\n";
101        }
102
103        /**
104         * Loads all the class definitions from the given repository
105         * 
106         * @param conn
107         *            The repository connection from where to get the classes
108         * @param go
109         * @return a Map that maps class URIs to ClassDef objects
110         * @throws RepositoryException
111         * @throws MalformedQueryException
112         * @throws QueryEvaluationException
113         */
114        public static Map<URI, ClassDef> loadClasses(final GeneratorOptions go, final RepositoryConnection conn)
115                        throws RepositoryException, MalformedQueryException, QueryEvaluationException
116        {
117                final HashMap<URI, ClassDef> classes = new HashMap<URI, ClassDef>();
118
119                // This is the types we'll look for
120                // We'll look for both OWL and RDF classes
121                final String[] clzTypes = {
122                                "<http://www.w3.org/2002/07/owl#Class>",
123                                "rdfs:Class"
124                };
125
126                // Loop over the namespaces
127                for (final String clzType : clzTypes)
128                {
129                        // Create a query to get the classes
130                        final String query = "SELECT Class, Comment "
131                                        + "FROM {Class} rdf:type {" + clzType + "}; "
132                                        + " [ rdfs:comment {Comment} ]";
133
134                        // Prepare the query...
135                        final TupleQuery preparedQuery = conn.prepareTupleQuery(
136                                        QueryLanguage.SERQL, query);
137
138                        // Run the query...
139                        final TupleQueryResult res = preparedQuery.evaluate();
140
141                        // Loop over the results
142                        while (res.hasNext())
143                        {
144                                final BindingSet bindingSet = res.next();
145
146                                // If we have a class with a URI...
147                                if (bindingSet.getValue("Class") instanceof URI)
148                                {
149                                        // Create a new class definition for it
150                                        final ClassDef clz = new ClassDef();
151
152                                        // Get the comment, if there is one.
153                                        if (bindingSet.getValue("Comment") != null)
154                                        {
155                                                final MemLiteral lit = (MemLiteral)
156                                                                bindingSet.getValue("Comment");
157                                                clz.comment = lit.stringValue();
158                                        }
159
160                                        clz.uri = (URI) bindingSet.getValue("Class");
161                                        clz.directSuperclasses = ClassDef.getSuperclasses(clz.uri, conn);
162                                        clz.properties = PropertyDef.loadProperties(go, clz.uri, conn);
163
164                                        // Check whether there are any other classes
165                                        ClassDef.getEquivalentClasses(clz, conn);
166
167                                        // Get all the superclasses in the tree
168                                        clz.allSuperclasses = clz.getAllSuperclasses(conn);
169
170                                        classes.put(clz.uri, clz);
171                                }
172                        }
173                }
174                return classes;
175        }
176
177        /**
178         * Checks for owl:equivalentClass and updates the class definition based on
179         * whats found.
180         * 
181         * @param clz
182         *            the class definition
183         * @param conn
184         *            The connection to the repository
185         */
186        private static void getEquivalentClasses(final ClassDef clz, final RepositoryConnection conn)
187        {
188                try
189                {
190                        final String sparql = "prefix owl: <http://www.w3.org/2002/07/owl#> " +
191                                        "SELECT ?clazz WHERE " +
192                                        "{ <" + clz.uri + "> owl:equivalentClass ?clazz . }";
193
194                        // System.out.println( sparql );
195
196                        // Prepare the query...
197                        final TupleQuery preparedQuery = conn.prepareTupleQuery(
198                                        QueryLanguage.SPARQL, sparql);
199
200                        // Run the query...
201                        final TupleQueryResult res = preparedQuery.evaluate();
202
203                        // Loop through the results (if any)
204                        while (res.hasNext())
205                        {
206                                final BindingSet bs = res.next();
207
208                                final Value clazz = bs.getBinding("clazz").getValue();
209
210                                // If it's an equivalent then we'll simply make this class
211                                // a subclass of the equivalent class.
212                                // TODO: There is a possibility that we could end up with a
213                                // cycle here
214                                // and the resulting code would not compile.
215                                if (clazz instanceof URI)
216                                        clz.directSuperclasses.add((URI) clazz);
217                                else
218                                // If it's a BNode, then the BNode defines the equivalence.
219                                if (clazz instanceof MemBNode)
220                                {
221                                        final MemBNode b = (MemBNode) clazz;
222                                        final MemStatementList sl = b.getSubjectStatementList();
223
224                                        for (int i = 0; i < sl.size(); i++)
225                                        {
226                                                final MemStatement x = sl.get(i);
227                                                System.out.println("    -> " + x);
228                                        }
229                                }
230                        }
231
232                        res.close();
233                } catch (final RepositoryException e)
234                {
235                        e.printStackTrace();
236                } catch (final MalformedQueryException e)
237                {
238                        e.printStackTrace();
239                } catch (final QueryEvaluationException e)
240                {
241                        e.printStackTrace();
242                }
243        }
244
245        /**
246         * Retrieves the superclass list for the given class URI using the given
247         * repository
248         * 
249         * @param uri
250         *            The URI of the class to find the allSuperclasses of
251         * @param conn
252         *            The respository
253         * @return A list of URIs of allSuperclasses
254         * 
255         * @throws RepositoryException
256         * @throws MalformedQueryException
257         * @throws QueryEvaluationException
258         */
259        private static Set<URI> getSuperclasses(final URI uri, final RepositoryConnection conn)
260                        throws RepositoryException, MalformedQueryException, QueryEvaluationException
261        {
262                // SPARQL query to get the allSuperclasses
263                final String query = "SELECT ?superclass WHERE { " +
264                                "<" + uri.stringValue() + "> " +
265                                "<http://www.w3.org/2000/01/rdf-schema#subClassOf> " +
266                                "?superclass. }";
267
268                final TupleQuery preparedQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
269                final TupleQueryResult res = preparedQuery.evaluate();
270
271                final Set<URI> superclasses = new HashSet<URI>();
272                while (res.hasNext()) {
273                        final BindingSet bindingSet = res.next();
274
275                        if (bindingSet.getValue("superclass") instanceof URI) {
276                                superclasses.add((URI) bindingSet.getValue("superclass"));
277                        }
278                }
279
280                return superclasses;
281        }
282
283        /**
284         * Generates a Java file in the target directory
285         * 
286         * @param targetDir
287         *            The target directory
288         * @param pkgs
289         *            A map of package mappings to class URIs
290         * @param classes
291         *            A map of class URIs to ClassDefs
292         * @param flattenClassStructure
293         *            Whether to flatten the class structure
294         * @param generateAnnotations
295         *            Whether to generate OpenIMAJ RDF annotations for the
296         *            properties
297         * @param separateImplementations
298         * @throws FileNotFoundException
299         */
300        public void generateClass(final File targetDir, final Map<URI, String> pkgs,
301                        final Map<URI, ClassDef> classes, final boolean flattenClassStructure,
302                        final boolean generateAnnotations, final boolean separateImplementations) throws FileNotFoundException
303        {
304                // We don't need to generate an implementation file if there are no
305                // properties to get/set
306                // if (this.properties.size() == 0)
307                // return;
308
309                // Generate the filename for the output file
310                final File path = new File(targetDir.getAbsolutePath() + File.separator +
311                                pkgs.get(this.uri).replace(".", File.separator) +
312                                (separateImplementations ? File.separator + "impl" : ""));
313                path.mkdirs();
314                PrintStream ps;
315                try
316                {
317                        ps = new PrintStream(new File(path.getAbsolutePath()
318                                        + File.separator + Generator.getTypeName(this.uri) + "Impl.java"),
319                                        "UTF-8");
320                } catch (final UnsupportedEncodingException e)
321                {
322                        e.printStackTrace();
323                        return;
324                }
325
326                // Output the package definition
327                ps.println("package " + pkgs.get(this.uri) +
328                                (separateImplementations ? ".impl" : "") + ";");
329                ps.println();
330
331                // Output the imports
332                ps.println("import org.openimaj.rdf.owl2java.Something;");
333                if (separateImplementations)
334                        ps.println("import " + pkgs.get(this.uri) + ".*;");
335                if (generateAnnotations)
336                {
337                        ps.println("import org.openimaj.rdf.serialize.Predicate;\n");
338                        ps.println("import org.openimaj.rdf.serialize.RDFType;\n");
339                }
340                this.printImports(ps, pkgs, false, classes, true);
341                ps.println();
342
343                // Output the comment at the top of the class
344                this.printClassComment(ps);
345
346                // Output the class
347                ps.print("@RDFType(\"" + this.uri + "\")\n");
348                ps.print("public class " + Generator.getTypeName(this.uri) + "Impl ");
349                ps.print("extends Something ");
350
351                // It will implement the interface that defines it
352                ps.print("implements " + Generator.getTypeName(this.uri));
353
354                // if (this.superclasses.size() > 0)
355                // {
356                // // ...and any of the super class interfaces
357                // for( final URI superclass : this.superclasses )
358                // {
359                // ps.print(", ");
360                // ps.print( Generator.getTypeName( superclass ) );
361                // }
362                // }
363                ps.println("\n{");
364
365                // Output the definition of the class
366                this.printClassPropertyDefinitions(ps, classes,
367                                flattenClassStructure, generateAnnotations);
368
369                ps.println("}\n");
370        }
371
372        /**
373         * Generates a Java interface file in the target directory
374         * 
375         * @param targetDir
376         *            The target directory
377         * @param pkgs
378         *            A list of package mappings to class URIs
379         * @param classes
380         *            The URI to class definition map.
381         * @throws FileNotFoundException
382         */
383        public void generateInterface(final File targetDir, final Map<URI, String> pkgs,
384                        final Map<URI, ClassDef> classes) throws FileNotFoundException
385        {
386                final File path = new File(targetDir.getAbsolutePath() + File.separator +
387                                pkgs.get(this.uri).replace(".", File.separator));
388                path.mkdirs();
389                PrintStream ps;
390                try
391                {
392                        ps = new PrintStream(new File(path.getAbsolutePath()
393                                        + File.separator + Generator.getTypeName(this.uri) + ".java"),
394                                        "UTF-8");
395                } catch (final UnsupportedEncodingException e)
396                {
397                        e.printStackTrace();
398                        return;
399                }
400
401                ps.println("package " + pkgs.get(this.uri) + ";");
402                ps.println();
403                this.printImports(ps, pkgs, true, classes, false);
404                ps.println();
405
406                this.printClassComment(ps);
407
408                ps.print("public interface " + Generator.getTypeName(this.uri) + " ");
409                if (this.allSuperclasses.size() > 0)
410                {
411                        ps.print("\n\textends ");
412                        boolean first = true;
413                        for (final URI superClassURI : this.directSuperclasses)
414                        {
415                                if (!first)
416                                        ps.print(", ");
417                                ps.print(Generator.getTypeName(superClassURI));
418                                first = false;
419                        }
420                }
421
422                ps.println("\n{");
423                this.printInterfacePropertyDefinitions(ps);
424                ps.println("\tpublic String getURI();\n");
425                ps.println("}\n");
426        }
427
428        /**
429         * Prints the comment at the top of the file for this class.
430         * 
431         * @param ps
432         *            The stream to print the comment to.
433         */
434        private void printClassComment(final PrintStream ps)
435        {
436                ps.println("/**");
437                if (this.comment == null) {
438                        ps.println(" * " + this.uri);
439                } else {
440                        final String cmt = WordUtils.wrap(" * " +
441                                        this.comment.replaceAll("\\r?\\n", " "), 80, "\n * ", false);
442                        ps.println(" " + cmt);
443                }
444
445                ps.println(" *");
446                ps.println(" *\t@created " + new DateTime());
447                ps.println(" *\t@generated by owl2java from OpenIMAJ");
448                ps.println(" */");
449        }
450
451        /**
452         * Outputs the list of imports necessary for this class.
453         * 
454         * @param ps
455         *            The stream to print the imports to
456         * @param pkgs
457         *            The list of package mappings for all the known classes
458         * @param allSuperclasses
459         *            Whether to print imports for allSuperclasses
460         */
461        private void printImports(final PrintStream ps, final Map<URI, String> pkgs,
462                        final boolean superclasses, final Map<URI, ClassDef> classes,
463                        final boolean implementations)
464        {
465                final Set<String> imports = new HashSet<String>();
466
467                final Map<PropertyDef, String> pd = new HashMap<PropertyDef, String>();
468                final Map<String, String> instanceNameMap = new HashMap<String, String>();
469                this.getFullPropertyList(pd, instanceNameMap, classes);
470
471                for (final PropertyDef p : pd.keySet())
472                        if (implementations || pd.get(p).equals("this"))
473                                if (p.needsImport(implementations) != null)
474                                        imports.addAll(p.needsImport(implementations));
475
476                if (superclasses)
477                {
478                        for (final URI u : this.directSuperclasses) {
479                                imports.add(pkgs.get(u) + ".");
480                                // TODO - impl package should depend on configuration
481                                imports.add(pkgs.get(u) + ".impl.");
482                        }
483                }
484
485                imports.remove(pkgs.get(this.uri) + ".");
486
487                final String[] sortedImports = imports.toArray(new String[imports.size()]);
488                Arrays.sort(sortedImports);
489
490                for (final String imp : sortedImports) {
491                        if (imp.endsWith("."))
492                                ps.println("import " + imp + "*;");
493                        else
494                                ps.println("import " + imp + ";");
495                }
496        }
497
498        /**
499         * Outputs all the properties into the class definition.
500         * 
501         * @param ps
502         *            The stream to print to.
503         */
504        private void printInterfacePropertyDefinitions(final PrintStream ps)
505        {
506                for (final PropertyDef p : this.properties)
507                        ps.println(p.toSettersAndGetters("\t", false, null, false));
508        }
509
510        /**
511         * Outputs all the properties into the class definition.
512         * 
513         * @param ps
514         *            The stream to print to.
515         * @param classes
516         *            A map of class URIs to ClassDefs
517         * @param flattenClassStructure
518         *            Whether to combine all the properties from all the
519         *            allSuperclasses into this class (TRUE), or whether to use
520         *            instance pointers to classes of that type (FALSE)
521         * @param generateAnnotations
522         */
523        private void printClassPropertyDefinitions(final PrintStream ps,
524                        final Map<URI, ClassDef> classes, final boolean flattenClassStructure,
525                        final boolean generateAnnotations)
526        {
527                // Remember which ones we've output already
528                final HashSet<URI> alreadyDone = new HashSet<URI>();
529
530                if (flattenClassStructure)
531                {
532                        // TODO: Check this still works after the change in properties list
533                        // Work out all the properties to output
534                        final Set<PropertyDef> pd = new HashSet<PropertyDef>();
535                        pd.addAll(this.properties);
536                        for (final Set<URI> superclassList : this.allSuperclasses.values())
537                        {
538                                for (final URI superclass : superclassList)
539                                {
540                                        if (!alreadyDone.contains(superclass))
541                                        {
542                                                pd.addAll(classes.get(superclass).properties);
543                                                alreadyDone.add(superclass);
544                                        }
545                                }
546                        }
547
548                        // Output all the property definitions for this class.
549                        for (final PropertyDef p : pd)
550                                ps.println(p.toJavaDefinition("\t", generateAnnotations));
551                        ps.println();
552                        // Output all the getters and setters for this class.
553                        for (final PropertyDef p : pd)
554                                ps.println(p.toSettersAndGetters("\t", true, null, false));
555                }
556                else
557                {
558                        System.out.println("=======================================");
559                        System.out.println(this.uri);
560                        System.out.println("=======================================");
561                        System.out.println("Direct superclasses: " + this.directSuperclasses);
562
563                        // Output all the property definitions for this class.
564                        for (final PropertyDef p : this.properties)
565                                ps.println(p.toJavaDefinition("\t", generateAnnotations));
566                        ps.println();
567
568                        // Now we need to output the links to other objects from which
569                        // this class inherits. While we do that, we'll also remember which
570                        // properties we need to delegate to the other objects.
571                        final HashMap<PropertyDef, String> pd = new HashMap<PropertyDef, String>();
572                        final HashMap<String, String> entityNameMap = new HashMap<String, String>();
573                        this.getFullPropertyList(pd, entityNameMap, classes);
574
575                        // Check whether there are any delegation members to output
576                        // We do this by removing "this" from the map and seeing what's
577                        // left.
578                        final Map<PropertyDef, String> xx = new HashMap<PropertyDef, String>();
579                        xx.putAll(pd);
580                        final HashSet<String> delegatesToOutput = new HashSet<String>();
581                        final Iterator<String> i = xx.values().iterator();
582                        String xxx = null;
583                        while (i.hasNext())
584                                if (!(xxx = i.next()).equals("this"))
585                                {
586                                        delegatesToOutput.add(xxx);
587                                }
588                        System.out.println(xx);
589                        System.out.println(entityNameMap);
590                        System.out.println(delegatesToOutput);
591                        if (delegatesToOutput.size() > 0)
592                        {
593                                for (final String instanceName : delegatesToOutput)
594                                {
595                                        final String typeName = entityNameMap.get(instanceName);
596                                        ps.println("\t/** " + typeName + " superclass instance */");
597                                        ps.println("\tprivate " + typeName + " " + instanceName + " = new " + typeName + "Impl();\n");
598                                }
599                        }
600
601                        // Now output the delegated getters and setters for this class
602                        for (final PropertyDef pp : pd.keySet())
603                        {
604                                final String instanceName = pd.get(pp);
605                                ps.println("\n\t// From class " + instanceName + "\n\n");
606                                ps.println(pp.toSettersAndGetters("\t", true, instanceName, false));
607                        }
608                }
609        }
610
611        /**
612         * Traverses up the tree from this class to find all ancestor
613         * allSuperclasses.
614         * 
615         * @param conn
616         *            A connection to a triple-store repository
617         * @return A list of URIs representing the superclass ancestors of this
618         *         class
619         */
620        public Map<URI, Set<URI>> getAllSuperclasses(final RepositoryConnection conn)
621        {
622                final HashMap<URI, Set<URI>> map = new HashMap<URI, Set<URI>>();
623                for (final URI uri : this.directSuperclasses)
624                {
625                        final HashSet<URI> uris = new HashSet<URI>();
626                        ClassDef.getAllSuperclasses(uri, conn, uris);
627                        map.put(uri, uris);
628                }
629
630                return map;
631        }
632
633        /**
634         * For the given URI, will query the repository and fill the list of URIs
635         * with the URIs of all the ancestor allSuperclasses to the given URI.
636         * 
637         * @param uri
638         *            The URI of the class to find the ancestors of
639         * @param conn
640         *            A connection to a triple-store repository.
641         * @param uris
642         *            The list where classes are to be added
643         */
644        private static void getAllSuperclasses(final URI uri,
645                        final RepositoryConnection conn, final Set<URI> uris)
646        {
647                try
648                {
649                        final Set<URI> superclassesOf = ClassDef.getSuperclasses(uri, conn);
650                        uris.addAll(superclassesOf);
651                        for (final URI u : superclassesOf)
652                                ClassDef.getAllSuperclasses(u, conn, uris);
653                } catch (final RepositoryException e)
654                {
655                        e.printStackTrace();
656                } catch (final MalformedQueryException e)
657                {
658                        e.printStackTrace();
659                } catch (final QueryEvaluationException e)
660                {
661                        e.printStackTrace();
662                }
663        }
664
665        /**
666         * Returns a full list of all the properties for all the classes in the
667         * tree.
668         * 
669         * @param pd
670         *            The set of property definitions (linked to instance name) to
671         *            fill
672         * @param instanceNameMap
673         *            The list of property to instance name map
674         * @param classes
675         *            The definition of all the classes in the ontology
676         */
677        private void getFullPropertyList(final Map<PropertyDef, String> pd,
678                        final Map<String, String> instanceNameMap, final Map<URI, ClassDef> classes)
679        {
680                for (final PropertyDef pp : this.properties)
681                        pd.put(pp, "this");
682
683                for (final URI superclass : this.directSuperclasses)
684                {
685                        final String instanceName =
686                                        superclass.getLocalName().substring(0, 1).toLowerCase() +
687                                                        superclass.getLocalName().substring(1);
688
689                        for (final PropertyDef pp : classes.get(superclass).properties)
690                                pd.put(pp, instanceName);
691
692                        // map all the properties of the ancestors of this direct subclass
693                        // to the instance name of the direct superclass. This will make all
694                        // the getters and setters use the superclass instance to access the
695                        // ancestor properties.
696                        for (final URI ancestorURI : this.allSuperclasses.get(superclass))
697                        {
698                                for (final PropertyDef pp : classes.get(ancestorURI).properties)
699                                        pd.put(pp, instanceName);
700                        }
701
702                        // We don't need the instance variable if we're not inheriting
703                        // any properties from the superclasses.
704                        if (pd.keySet().size() == 0)
705                                continue;
706
707                        // Check we've not already got a delegation for that instance
708                        if (instanceNameMap.get(instanceName) == null)
709                        {
710                                instanceNameMap.put(instanceName,
711                                                /* Generator.getPackageName(superclass) + "." + */
712                                                Generator.getTypeName(superclass));
713                        }
714                }
715        }
716}