I'm working on the same problem right now so I understand your confusion. You have a lot of questions, but I think they can be summed up into a singular question:
How does the Migrate module handle migrating a normalized database
into a Drupal installation?
It's definitely not straightforward, but here's my understanding of how it works. We'll start from the top (WineWineMigration) going down and ask questions as we go.
We start off by looking at the code at the top of the WineWineMigration
class.
...
$this->dependencies = array('WineVariety', 'WineRegion',
'WineBestWith', 'WineUser', 'WineProducer');
...
This tells the Migrate module that in order to migrate your Wine content, the dependent migrations - WineVariety, WineRegion, WineBestWith, WineUser, WineProduce - must be completed first.
So what we've learned here is that migrations can be dependent on other migrations.
Next we have the mapping between the table that currently holds the base wine info and the Drupal node:
$this->map = new MigrateSQLMap($this->machineName,
array(
'wineid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'description' => 'Wine ID',
'alias' => 'w',
)
),
MigrateDestinationNode::getKeySchema()
);
This is pretty straightforward so if you need clarification I will provide it.
I'm going to skip over some interim stuff that isn't really pertinent to hooking up the various categories and wine objects.
Now we get to the field mappings. Observe:
// Mapped fields
$this->addFieldMapping('title', 'name')
->description(t('Mapping wine name in source to node title'));
$this->addFieldMapping('uid', 'accountid')
->sourceMigration('WineUser')
->defaultValue(1);
// TIP: By default, term relationship are assumed to be passed by name.
// In this case, the source values are IDs, so we specify the relevant
// migration (so the tid can be looked up in the map), and tell the term
// field handler that it is receiving tids instead of names
$this->addFieldMapping('migrate_example_wine_varieties', 'variety')
->sourceMigration('WineVariety')
->arguments(array('source_type' => 'tid'));
$this->addFieldMapping('migrate_example_wine_regions', 'region')
->sourceMigration('WineRegion')
->arguments(array('source_type' => 'tid'));
$this->addFieldMapping('migrate_example_wine_best_with', 'best_with')
->separator(',')
->sourceMigration('WineBestWith')
->arguments(array('source_type' => 'tid'));
$this->addFieldMapping('field_migrate_example_wine_ratin', 'rating');
$this->addFieldMapping('field_migrate_example_top_vintag', 'best_vintages');
See where it says:
->sourceMigration(...)
This indicates to the migration that in order to map this field, another migration must be satisfied first. I believe this is the "secondary migration" that you spoke of. Let's use the region
field mapping as the example here. Breaking it down...
$this->addFieldMapping('migrate_example_wine_regions', 'region')
->sourceMigration('WineRegion')
->arguments(array('source_type' => 'tid'));
This says that the category region in the source database is mapped to a region vocabulary term. As the TIP comment states in the field mappings code chunk, it assumes that mappings are made based on field_names, but since we are dependent on a secondary migration as you put it, we need to specify the migration it is dependent on and instruct it to use tids instead of field names.
So pretty much for every normalized table you have in your source database, you're going to be specifying a migration for each, and then in the relevant field mappings that involve those tables, you'll be specifying dependent migrations in your field mapping calls, as well as the dependent migrations declaration at the beginning of each migration.
I hope this helps. I don't fully understand this myself so I used this question as an opportunity to enhance my understanding of how Migrate relates databases. As I learn a bit more I'll update my answer accordingly.