blob: 4e524e6f68380054df962373bc54e47590473816 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2008 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0, which accompanies this distribution
* and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.gen.internal;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jpt.db.Table;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;
/**
* Build a GenTable for each db.Table passed in.
* Determine all the relations among the tables in the scope:
* many-to-many
* many-to-one
* one-to-many
* Make a first pass to determine each entity table's Java attribute names,
* because we will need them on subsequent passes.
*/
class GenScope {
private final EntityGenerator.Config entityConfig;
private final HashMap<Table, GenTable> genTables;
// ********** construction/initialization **********
GenScope(EntityGenerator.Config entityConfig, IProgressMonitor progressMonitor) {
super();
this.entityConfig = entityConfig;
this.genTables = new HashMap<Table, GenTable>(entityConfig.tablesSize());
SubMonitor sm = SubMonitor.convert(progressMonitor, JptGenMessages.GenScope_taskName, 4);
this.buildGenTables();
sm.worked(1);
this.checkCanceled(sm);
this.buildManyToManyRelations();
sm.worked(1);
this.checkCanceled(sm);
this.buildManyToOneRelations(); // this will also build the corresponding one-to-many relations
sm.worked(1);
this.checkCanceled(sm);
this.buildAttributeNames();
sm.worked(1);
this.checkCanceled(sm);
}
private void buildGenTables() {
for (Iterator<Table> stream = entityConfig.tables(); stream.hasNext(); ) {
Table table = stream.next();
this.genTables.put(table, new GenTable(this, table));
}
}
/**
* find all the "join" tables
*/
private void buildManyToManyRelations() {
for (Iterator<GenTable> stream = this.genTables(); stream.hasNext(); ) {
stream.next().buildJoinTableRelation();
}
// revert any "join" table that is referenced by another table back to an "entity" table
HashSet<GenTable> referencedGenTables = this.buildReferencedGenTables();
for (Iterator<GenTable> stream = this.joinGenTables(); stream.hasNext(); ) {
GenTable joinGenTable = stream.next();
if (referencedGenTables.contains(joinGenTable)) {
joinGenTable.clearJoinTableRelation();
}
}
}
/**
* find all the many-to-one and corresponding one-to-many relations
*/
private void buildManyToOneRelations() {
for (Iterator<GenTable> stream = this.entityGenTables(); stream.hasNext(); ) {
stream.next().buildManyToOneRelations();
}
}
/**
* determine all the Java attribute names up-front because we will
* need them for things like 'mappedBy' annotation elements
*/
private void buildAttributeNames() {
for (Iterator<GenTable> stream = this.entityGenTables(); stream.hasNext(); ) {
stream.next().buildAttributeNames();
}
}
// ********** package API **********
EntityGenerator.Config getEntityConfig() {
return this.entityConfig;
}
/**
* return only the gen tables that are suitable for generating
* entities (i.e. exclude the "join" tables)
*/
Iterator<GenTable> entityGenTables() {
return new FilteringIterator<GenTable, GenTable>(this.genTables()) {
@Override
protected boolean accept(GenTable genTable) {
return ! genTable.isJoinTable();
}
};
}
int entityTablesSize() {
return CollectionTools.size(this.entityGenTables());
}
/**
* return the gen table corresponding to the specified db table;
* return null if the gen table is not "in-scope" (e.g. a db foreign key
* might have a reference to a db table that was not included in the
* scope, so we won't have a corresponding gen table)
*/
GenTable getGenTable(Table table) {
return this.genTables.get(table);
}
// ********** internal methods **********
private Iterator<GenTable> genTables() {
return this.genTables.values().iterator();
}
private int genTablesSize() {
return this.genTables.size();
}
/**
* return only the "join" gen tables
*/
private Iterator<GenTable> joinGenTables() {
return new FilteringIterator<GenTable, GenTable>(this.genTables()) {
@Override
protected boolean accept(GenTable genTable) {
return genTable.isJoinTable();
}
};
}
/**
* build a set of the gen tables that are referenced by other gen tables
* in the scope
*/
private HashSet<GenTable> buildReferencedGenTables() {
HashSet<GenTable> referencedGenTables = new HashSet<GenTable>(this.genTablesSize());
for (Iterator<GenTable> stream = this.genTables(); stream.hasNext(); ) {
stream.next().addReferencedGenTablesTo(referencedGenTables);
}
return referencedGenTables;
}
private void checkCanceled(IProgressMonitor progressMonitor) {
if (progressMonitor.isCanceled()) {
throw new OperationCanceledException();
}
}
@Override
public String toString() {
return StringTools.buildToStringFor(this, this.genTables);
}
}