| // CountryModelCreator.java |
| package org.eclipse.stem.tests.util; |
| |
| /******************************************************************************* |
| * Copyright (c) 2006 IBM Corporation and others. |
| * 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| import java.io.BufferedWriter; |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.io.Writer; |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.stem.core.Constants; |
| import org.eclipse.stem.core.common.DublinCore; |
| import org.eclipse.stem.core.model.Model; |
| import org.eclipse.stem.core.model.ModelFactory; |
| import org.eclipse.stem.tests.util.CountryDirectoryUtilities.CountryCode; |
| import org.eclipse.stem.tests.util.CountryGraphCreator.DataType; |
| import org.eclipse.stem.tests.util.CountryGraphCreator.GraphRecord; |
| import org.eclipse.stem.tests.util.CountryGraphCreator.Record; |
| |
| /** |
| * This class is used to auotmate the generation of models in STEM. |
| */ |
| public class CountryModelCreator { |
| |
| /** |
| * This is the name of the directory under the |
| * {@link CountryGraphCreator#ROOT_OUTPUT_DIR} that contains the directories |
| * that contain the models that define the geographies and features of |
| * countries. |
| */ |
| public static final String MODEL_OUTPUT_DIR = "models"; |
| |
| /** |
| * This is the path to the country models directory |
| */ |
| public static final String COUNTRY_MODEL_PATH = CountryGraphCreator.ROOT_OUTPUT_DIR |
| + File.separator |
| + MODEL_OUTPUT_DIR |
| + File.separator |
| + CountryGraphCreator.COUNTRY_DIR; |
| |
| /** |
| * This is the id of the extension point extended by graphs that are plugged |
| * into STEM |
| */ |
| // public static final String ID_MODEL_EXTENSION_POINT = Constants.ID_ROOT |
| // + ".core.model"; |
| /** |
| * This is the id of the top-level STEM category for graphs |
| */ |
| public static final String ID_STEM_MODEL_CATEGORY = Constants.ID_ROOT |
| + ".core.model"; |
| |
| /** |
| * This is the id of the extension point extended by models with geographic |
| * information that are plugged into STEM |
| */ |
| public static final String ID_MODEL_GEOGRAPHY_CATEGORY = ID_STEM_MODEL_CATEGORY |
| + "." + CountryGraphCreator.GEOGRAPHY.toLowerCase(); |
| |
| /** |
| * This is the id of the extension point extended by models with geographic |
| * political information that are plugged into STEM |
| */ |
| public static final String ID_MODEL_POLITICAL_CATEGORY = ID_MODEL_GEOGRAPHY_CATEGORY |
| + "." + CountryGraphCreator.POLITICAL.toLowerCase(); |
| |
| /** |
| * This is the id of the extension point extended by models with geographic |
| * political information that are plugged into STEM |
| */ |
| public static final String ID_MODEL_COUNTRIES_CATEGORY = ID_MODEL_POLITICAL_CATEGORY |
| + "." + CountryGraphCreator.COUNTRIES.toLowerCase(); |
| |
| /** |
| * This is the format of the generated NLS keys for categories |
| */ |
| public static final String NLS_CATEGORY_KEY_FORMAT = "_UI_{0}_model_category"; |
| |
| /** |
| * @param args |
| */ |
| public static void main(String[] args) { |
| // Now create the graphs |
| final List<CountryCode> countryCodes = CountryDirectoryUtilities |
| .getAllCountryCodes(); |
| Collections.sort(countryCodes); |
| |
| final CountryModelCreator cmc = new CountryModelCreator(); |
| final Map<CountryCode, List<CountryModelRecord>> countryModels = cmc |
| .createCountryModels(); |
| try { |
| cmc.serializeCountryModels(countryModels, COUNTRY_MODEL_PATH); |
| |
| List<Map<CountryCode, List<CountryModelRecord>>> modelRecords = new ArrayList<Map<CountryCode, List<CountryModelRecord>>>(); |
| modelRecords.add(countryModels); |
| |
| int maxAdminLevel = 0; |
| maxAdminLevel = Math.max(maxAdminLevel, |
| getMaxAdminLevel(countryModels)); |
| |
| final File modelExtensionFile = new File(COUNTRY_MODEL_PATH |
| + CountryGraphCreator.GRAPH_EXTENSION_POINT_FILE_NAME); |
| final File modelPluginPropertiesFile = new File( |
| COUNTRY_MODEL_PATH |
| + CountryGraphCreator.GRAPH_PLUGIN_PROPERTIES_POINT_FILE_NAME); |
| |
| final BufferedWriter modelOut = new BufferedWriter(new FileWriter( |
| modelExtensionFile)); |
| |
| final BufferedWriter pluginOut = new BufferedWriter(new FileWriter( |
| modelPluginPropertiesFile)); |
| |
| // Create a snippet of xml that can be included in a plugin.xml file |
| // to plug into STEM the graphs we just serialized. |
| cmc.generateModelExtensionPointXML(modelRecords, countryCodes, |
| maxAdminLevel, modelOut, pluginOut); |
| } // try |
| catch (IOException e) { |
| e.printStackTrace(); |
| } |
| } // main |
| |
| /** |
| * @param models |
| * a map between country code and list of model records for the |
| * country |
| * @param uriPathString |
| * the path to the root of the folder to serialize the models to |
| * @throws IOException |
| */ |
| private void serializeCountryModels( |
| final Map<CountryCode, List<CountryModelRecord>> models, |
| final String uriPathString) throws IOException { |
| |
| for (CountryCode countryCode : models.keySet()) { |
| for (CountryModelRecord modelRecord : models.get(countryCode)) { |
| modelRecord.serialize(uriPathString); |
| } // for each model record for each country |
| } // for each country code |
| |
| // |
| // for (CountryCode countryCode : graphs.keySet()) { |
| // for (GraphRecord graphRecord : graphs.get(countryCode)) { |
| // graphRecord.serialize(uriPathString); |
| // } // for each graph record for each country |
| // } // for each country code |
| |
| } // serializeCountryModels |
| |
| /** |
| * @param countryNodeGraphs |
| * a list of maps of models of nodes for countries for each |
| * adminstration level |
| * @param modelOut |
| * the output writer for the plugin.xml file contents |
| * @param pluginOut |
| * the output writer for the plugin.properties file contents |
| */ |
| private void generateModelExtensionPointXML( |
| final List<Map<CountryCode, List<CountryModelRecord>>> modelRecords, |
| List<CountryCode> countryCodes, final int maxAdminLevel, |
| final Writer modelOut, final Writer pluginOut) { |
| |
| // The dublin core instances of the models likely share common |
| // attributes, we can avoid duplicate entries in the files we generate |
| // by finding the duplicate entries and only generating a single key for |
| // the generated plugins file content. |
| final Map<String, String> dcValueKeyMap = new HashMap<String, String>(); |
| |
| // We also don't want to generate duplicate country categories |
| final Map<String, String> countryCategories = new HashMap<String, String>(); |
| |
| try { |
| modelOut.write("<!-- Generated content. Do not modify -->\n"); |
| |
| modelOut.write(MessageFormat.format( |
| CountryGraphCreator.XML_EXTENSION_POINT_OPEN, |
| new Object[] { Constants.ID_MODEL_EXTENSION_POINT })); |
| modelOut.write("\n"); |
| |
| pluginOut |
| .write("#Model NLS Keys. Automatically generated, do not modify. " |
| + Calendar.getInstance().getTime() |
| + " " |
| + System.getProperty("user.name") + "\n"); |
| |
| // Output the categories that make up the hierarchy for the graph |
| // plugins (all except for the country categories which we output |
| // below) |
| final String[] levelCategoryId = outputCategories( |
| maxAdminLevel + 1, modelOut, pluginOut); |
| |
| for (CountryCode countryCode : countryCodes) { |
| for (Map<CountryCode, List<CountryModelRecord>> modelRecordMap : modelRecords) { |
| List<CountryModelRecord> foo = modelRecordMap |
| .get(countryCode); |
| // Anything in the list? |
| if (foo != null) { |
| // Yes |
| for (CountryModelRecord modelRecord : modelRecordMap |
| .get(countryCode)) { |
| outputModelRecord(modelRecord, dcValueKeyMap, |
| countryCategories, levelCategoryId, |
| modelOut, pluginOut); |
| } |
| } |
| |
| } // for each type of graph Record |
| } // for each country code |
| |
| modelOut.write(CountryGraphCreator.XML_EXTENSION_POINT_CLOSE); |
| modelOut.close(); |
| pluginOut.close(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| |
| }// generateModelExtensionPointXML |
| |
| /** |
| * @param numLevels |
| * the number of administration levels to generate categories for |
| * @param modelOut |
| * the output writer for the plugin.xml file contents |
| * @param pluginOut |
| * the output writer for the plugin.properties file contents |
| * @return an array indexed by administration level of the category ideas of |
| * the different administration levels |
| * @throws IOException |
| * if there is a problem writing to the output writers |
| */ |
| private String[] outputCategories(final int numLevels, |
| final Writer modelOut, final Writer pluginOut) throws IOException { |
| // The categories |
| // STEM |
| CountryGraphCreator.outputCategory(ID_STEM_MODEL_CATEGORY, |
| CountryGraphCreator.STEM, "/", NLS_CATEGORY_KEY_FORMAT, |
| modelOut, pluginOut); |
| |
| // Geography |
| CountryGraphCreator.outputCategory(ID_MODEL_GEOGRAPHY_CATEGORY, |
| CountryGraphCreator.GEOGRAPHY, ID_STEM_MODEL_CATEGORY, |
| NLS_CATEGORY_KEY_FORMAT, modelOut, pluginOut); |
| |
| // Political |
| CountryGraphCreator.outputCategory(ID_MODEL_POLITICAL_CATEGORY, |
| CountryGraphCreator.POLITICAL, ID_MODEL_GEOGRAPHY_CATEGORY, |
| NLS_CATEGORY_KEY_FORMAT, modelOut, pluginOut); |
| |
| // Country |
| CountryGraphCreator.outputCategory(ID_MODEL_COUNTRIES_CATEGORY, |
| CountryGraphCreator.COUNTRIES, ID_MODEL_POLITICAL_CATEGORY, |
| NLS_CATEGORY_KEY_FORMAT, modelOut, pluginOut); |
| |
| final String[] levelCategoryId = new String[numLevels]; |
| |
| // Level |
| for (int adminLevel = 0; adminLevel < numLevels; adminLevel++) { |
| // Level category |
| levelCategoryId[adminLevel] = ID_MODEL_COUNTRIES_CATEGORY + "." |
| + CountryGraphCreator.LEVEL.toLowerCase() + adminLevel; |
| |
| CountryGraphCreator.outputCategory(levelCategoryId[adminLevel], |
| CountryGraphCreator.LEVEL + adminLevel, |
| ID_MODEL_COUNTRIES_CATEGORY, NLS_CATEGORY_KEY_FORMAT, |
| modelOut, pluginOut); |
| } // for adminLevel |
| |
| modelOut.write("\n"); |
| pluginOut.write("\n"); |
| return levelCategoryId; |
| } // outputCategories |
| |
| /** |
| * @param modelRecord |
| * @param dcValueKeyMap |
| * @param countryCategories |
| * @param levelCategoryId |
| * @param modelOut |
| * @param pluginOut |
| * @throws IOException |
| */ |
| private void outputModelRecord(ModelRecord modelRecord, |
| Map<String, String> dcValueKeyMap, |
| Map<String, String> countryCategories, String[] levelCategoryId, |
| Writer modelOut, Writer pluginOut) throws IOException { |
| // Make everything come out in alphabetical order |
| |
| final String countryCodeString = modelRecord.getId().toLowerCase(); |
| final String countryCategoryId = levelCategoryId[modelRecord |
| .getMaxAdminLevel()] |
| + "." + countryCodeString; |
| |
| // Have we seen this country category id before? |
| if (countryCategories.get(countryCategoryId) == null) { |
| // No |
| // Create a category for the country |
| modelOut.write(MessageFormat.format( |
| CountryGraphCreator.XML_CATEGORY_ELEMENT_OPEN, |
| new Object[] { countryCategoryId, modelRecord.getId(), |
| levelCategoryId[modelRecord.getMaxAdminLevel()] })); |
| modelOut.write("\n"); |
| // ...and remember we did so we don't do it again |
| countryCategories.put(countryCategoryId, countryCategoryId); |
| } // if we haven't seen this category id before |
| |
| // pluginOut.write("# Dublin Core for " |
| // + graphRecord.getCountryCode().toString() + "\n"); |
| // // We don't NLS the ISO30166 alpha-3 codes |
| |
| CountryGraphCreator.outputDublinCore(modelRecord, countryCategoryId, |
| dcValueKeyMap, modelOut, pluginOut); |
| |
| } // outputModelRecord |
| |
| /** |
| * @return a mapping between country code and a list of the models for the |
| * country. The models are of mixed administration levels. |
| */ |
| public Map<CountryCode, List<CountryModelRecord>> createCountryModels() { |
| final Map<CountryCode, List<CountryModelRecord>> retValue = new HashMap<CountryCode, List<CountryModelRecord>>(); |
| |
| final List<CountryCode> countryCodes = CountryDirectoryUtilities |
| .getAllCountryCodes(); |
| Collections.sort(countryCodes); |
| |
| final CountryGraphCreator cgc = new CountryGraphCreator(); |
| |
| Map<CountryCode, List<GraphRecord>> nodeGraphs = cgc |
| .createGraphRecords(countryCodes, DataType.node); |
| |
| Map<CountryCode, List<GraphRecord>> areaGraphs = cgc |
| .createGraphRecords(countryCodes, DataType.area); |
| |
| for (CountryCode countryCode : countryCodes) { |
| List<GraphRecord> nodeGraphRecords = nodeGraphs.get(countryCode); |
| List<GraphRecord> areaGraphRecords = areaGraphs.get(countryCode); |
| |
| // Find the maximum adminstration level we're working with |
| final int maxNodeAdminLevel = nodeGraphRecords != null ? CountryGraphCreator |
| .getMaxAdminLevel(nodeGraphRecords) |
| : -1; |
| final int maxAreaAdminLevel = areaGraphRecords != null ? CountryGraphCreator |
| .getMaxAdminLevel(areaGraphRecords) |
| : -1; |
| int maxAdminLevel = Math.max(maxAreaAdminLevel, maxNodeAdminLevel); |
| |
| // Create one country model for each administration level |
| final List<CountryModelRecord> countryModels = new ArrayList<CountryModelRecord>(); |
| for (int adminLevel = 0; adminLevel < maxAdminLevel + 1; adminLevel++) { |
| |
| // Did we get nodes? |
| if (nodeGraphRecords == null) { |
| // No |
| System.out.println("Skipping country \"" |
| + countryCode.toString() + "\" at level \"" |
| + adminLevel + "\" because there are no nodes"); |
| continue; |
| } |
| // Did we get area labels? |
| if (areaGraphRecords == null) { |
| // No |
| System.out.println("Skipping country \"" |
| + countryCode.toString() + "\" at level \"" |
| + adminLevel |
| + "\" because there are no area labels"); |
| continue; |
| } |
| |
| final List<GraphRecord> modelRecords = new ArrayList<GraphRecord>(); |
| final GraphRecord nodeGraph = getByAdminLevel(adminLevel, |
| nodeGraphRecords); |
| final GraphRecord areaGraph = getByAdminLevel(adminLevel, |
| areaGraphRecords); |
| modelRecords.add(nodeGraph); |
| modelRecords.add(areaGraph); |
| countryModels.add(new CountryModelRecord(createModel( |
| countryCode, adminLevel, modelRecords, |
| CountryGraphCreator.GEOGRAPHY_FILE_URI_PREFIX), |
| countryCode, adminLevel)); |
| } // for adminLevel |
| |
| // Any country models created? |
| if (countryModels.size() > 0) { |
| // Yes |
| retValue.put(countryCode, countryModels); |
| } |
| |
| } // for each country code |
| |
| return retValue; |
| } // createCountryModels |
| |
| /** |
| * Create the country models, but organize them by administration level |
| * |
| * @return a list of lists of ModelRecord's, the 0'th element of the list |
| * contains a list of models at administration level 0 |
| */ |
| public List<List<CountryModelRecord>> createCountryModels2() { |
| final Map<CountryCode, List<CountryModelRecord>> countryModels = createCountryModels(); |
| |
| // Reorganize the models by administration level |
| final int maxAdminLevel = getMaxAdminLevel(countryModels); |
| List<List<CountryModelRecord>> retValue = new ArrayList<List<CountryModelRecord>>(); |
| for (int adminLevel = 0; adminLevel < maxAdminLevel + 1; adminLevel++) { |
| retValue.add(new ArrayList<CountryModelRecord>()); |
| } // for adminLevel |
| |
| for (Entry<CountryCode, List<CountryModelRecord>> entry : countryModels |
| .entrySet()) { |
| for (CountryModelRecord modelRecord : entry.getValue()) { |
| retValue.get(modelRecord.getMaxAdminLevel()).add(modelRecord); |
| } // foreach ModelRecord |
| } // foreach countryModels.entrySet |
| |
| return retValue; |
| } // createCountryModels2 |
| |
| /** |
| * @param countryCode |
| * @param adminLevel |
| * @param graphRecords |
| * @param dataFileURIPrefix |
| * @return a model with all of the graphs added |
| */ |
| @SuppressWarnings("unchecked") |
| private Model createModel(final CountryCode countryCode, |
| final int adminLevel, final List<GraphRecord> graphRecords, |
| final String dataFileURIPrefix) { |
| final Model retValue = ModelFactory.eINSTANCE.createModel(); |
| final DublinCore dc = retValue.getDublinCore(); |
| dc.populate(); |
| dc.setTitle(CountryDirectoryUtilities.getCountryName(countryCode) |
| + " Model (Level " + adminLevel + ", " + graphRecords.size() |
| + " graphs)"); |
| // dc.setSource(nonDataProperties.get(SOURCE_PROPERTY)); |
| |
| retValue.setURI(URI.createURI(MessageFormat.format( |
| CountryGraphCreator.IDENTIFIER_FORMAT, dataFileURIPrefix, |
| countryCode, countryCode.toString() + "_" |
| + Integer.toString(adminLevel), "model"))); |
| |
| for (GraphRecord modelRecord : graphRecords) { |
| // A null value? |
| if (modelRecord != null) { |
| // No |
| retValue.getGraphs().add(modelRecord.getGraph()); |
| } |
| } // for each node data |
| |
| return retValue; |
| } // createModel |
| |
| /** |
| * @param graphRecords |
| * a list of GraphRecords to search |
| * @return the first GraphRecord that matches the administration level or |
| * null if not found |
| */ |
| private GraphRecord getByAdminLevel(final int adminLevel, |
| List<GraphRecord> nodeGraphRecords) { |
| GraphRecord retValue = null; |
| for (GraphRecord record : nodeGraphRecords) { |
| // Is this at the right admin level? |
| if (record.getAdminLevel() == adminLevel) { |
| // Yes |
| retValue = record; |
| } |
| } |
| return retValue; |
| } // getByAdminLevel |
| |
| /** |
| * @param models |
| * @return the maximum administration level found |
| */ |
| public static int getMaxAdminLevel( |
| Map<CountryCode, List<CountryModelRecord>> models) { |
| int maxAdminLevel = 0; |
| for (List<CountryModelRecord> list : models.values()) { |
| maxAdminLevel = Math.max(maxAdminLevel, getMaxAdminLevel(list)); |
| } // for |
| return maxAdminLevel; |
| } // getMaxAdminLevel |
| |
| /** |
| * @param modelRecords |
| * @return the maximum administration level found in all of the model |
| * records |
| */ |
| public static int getMaxAdminLevel(List<CountryModelRecord> modelRecords) { |
| int maxAdminLevel = 0; |
| for (CountryModelRecord modelRecord : modelRecords) { |
| maxAdminLevel = Math.max(maxAdminLevel, modelRecord |
| .getMaxAdminLevel()); |
| } |
| return maxAdminLevel; |
| } // getMaxAdminLevel |
| |
| /** |
| * This class represents a model. |
| */ |
| abstract public static class ModelRecord extends Record { |
| |
| /** |
| * @param model |
| * the model |
| * @param id |
| * the id of the the model |
| * @param adminLevel |
| * the administration level of the contents of the model |
| */ |
| public ModelRecord(final Model model, final String id, |
| final int adminLevel) { |
| this(model, id, Collections.singletonList(Integer |
| .valueOf(adminLevel))); |
| } // ModelRecord |
| |
| /** |
| * @param model |
| * the model |
| * @param id |
| * the id of the the model |
| * @param adminLevels |
| * the administration level of the contents of the model |
| */ |
| public ModelRecord(final Model model, final String id, |
| final List<Integer> adminLevels) { |
| super(model, id, adminLevels); |
| } // ModelRecord |
| |
| /** |
| * @return the model |
| */ |
| public final Model getModel() { |
| return (Model) identifiable; |
| } // getModel |
| |
| /** |
| * @see org.eclipse.stem.data.geography.graph.CountryGraphCreator.Record#getOutputType() |
| */ |
| @Override |
| public String getOutputType() { |
| return "model"; |
| } |
| } // ModelRecord |
| |
| /** |
| * This class represents a model of a country and its details. |
| */ |
| public static class CountryModelRecord extends ModelRecord { |
| |
| /** |
| * @param model |
| * the model |
| * @param countryCode |
| * the code of the country the model represents |
| * @param adminLevel |
| * the administration level of the contents of the model |
| */ |
| public CountryModelRecord(final Model model, |
| final CountryCode countryCode, final int adminLevel) { |
| super(model, countryCode.toString(), adminLevel); |
| } // CountryModelRecord |
| |
| /** |
| * @see org.eclipse.stem.data.geography.graph.CountryGraphCreator.Record#getType() |
| */ |
| @Override |
| public String getType() { |
| return "country"; |
| } |
| |
| } // CountryModelRecord |
| |
| } // CountryModelCreator |