import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;

/**
 * Example on how one might use hibernate annotations to create a many to many
 * relationship
 * 
 * @author Jake Carr &lt;resume@dawley-carr.org&gt;
 * 
 * @version 2007-01-03
 */

public class NToM {

    @Entity
    @Table(name = "foo")
    public static class Foo {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "foo_id")
        protected Long id;

        @ManyToMany
        @JoinTable(name = "foo_bar_relation", joinColumns = { @JoinColumn(name = "foo_id") }, inverseJoinColumns = { @JoinColumn(name = "bar_id") })
        protected Set<Bar> barSet;
    }

    @Entity
    @Table(name = "bar")
    public static class Bar {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "bar_id")
        protected Long id;

        @ManyToMany(mappedBy = "barSet")
        protected Set<Foo> fooSet;
    }

    private static final Logger log = Logger.getLogger(NToM.class);

    public static void dumpSchema() throws Exception {

        BasicConfigurator.configure();
        Logger.getRootLogger().setLevel(Level.INFO);

        File file = File.createTempFile("tmp.", ".tmp");
        file.deleteOnExit();

        Configuration configuration = getConfiguration();

        SchemaExport export = new SchemaExport(configuration);

        export.setDelimiter(";");
        export.setFormat(true);
        export.setOutputFile(file.getAbsolutePath());
        export.execute(false, false, false, true);

        Reader rawReader = new FileReader(file);
        BufferedReader reader = new BufferedReader(rawReader);

        String line;

        while ((line = reader.readLine()) != null) {

            log.info(line);
        }
        reader.close();
    }

    public static Configuration getConfiguration() {

        AnnotationConfiguration configuration = new AnnotationConfiguration();

        configuration.addAnnotatedClass(Foo.class);
        configuration.addAnnotatedClass(Bar.class);

        configuration.setProperty("hibernate.dialect",
                "org.hibernate.dialect.HSQLDialect");

        return configuration;
    }

    public static void main(String[] argv) throws Exception {

        dumpSchema();
    }
}
