com.google.appinventor.client.youngandroid.YoungAndroidFormUpgrader.java Source code

Java tutorial

Introduction

Here is the source code for com.google.appinventor.client.youngandroid.YoungAndroidFormUpgrader.java

Source

// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0

package com.google.appinventor.client.youngandroid;

import static com.google.appinventor.client.Ode.MESSAGES;

import java.util.Map;

import com.google.appinventor.client.editor.simple.SimpleComponentDatabase;
import com.google.appinventor.client.editor.simple.components.MockVisibleComponent;
import com.google.appinventor.client.output.OdeLog;
import com.google.appinventor.client.properties.json.ClientJsonString;
import com.google.appinventor.common.utils.StringUtils;
import com.google.appinventor.components.common.YaVersion;
import com.google.appinventor.shared.properties.json.JSONArray;
import com.google.appinventor.shared.properties.json.JSONValue;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.Window;

/**
 * A class that can upgrade a Young Android Form source file.
 *
 * @author lizlooney@google.com (Liz Looney)
 */
public final class YoungAndroidFormUpgrader {
    static class LoadException extends IllegalStateException {
        LoadException(String message) {
            super(message);
        }
    }

    private static final SimpleComponentDatabase COMPONENT_DATABASE = SimpleComponentDatabase.getInstance();

    private YoungAndroidFormUpgrader() {
    }

    /**
     * Upgrades the given sourceProperties if necessary.
     *
     * @param sourceProperties the properties from the source file
     * @return true if the sourceProperties was upgraded, false otherwise
     */
    public static boolean upgradeSourceProperties(Map<String, JSONValue> sourceProperties) {
        StringBuilder upgradeDetails = new StringBuilder();
        try {
            int srcYaVersion = getSrcYaVersion(sourceProperties);
            if (needToUpgrade(srcYaVersion)) {
                Map<String, JSONValue> formProperties = sourceProperties.get("Properties").asObject()
                        .getProperties();
                upgradeComponent(srcYaVersion, formProperties, upgradeDetails);
                // The sourceProperties were upgraded. Update the version number.
                setSrcYaVersion(sourceProperties);
                if (upgradeDetails.length() > 0) {
                    Window.alert(MESSAGES.projectWasUpgraded(upgradeDetails.toString()));
                }
                return true;
            }
        } catch (LoadException e) {
            // This shouldn't happen. If it does it's our fault, not the user's fault.
            Window.alert(MESSAGES.unexpectedProblem(e.getMessage()));
            OdeLog.xlog(e);
        }
        return false;
    }

    private static int getSrcYaVersion(Map<String, JSONValue> sourceProperties) {
        int srcYaVersion = 0;
        if (sourceProperties.containsKey("YaVersion")) {
            String version = sourceProperties.get("YaVersion").asString().getString();
            srcYaVersion = Integer.parseInt(version);
        }
        return srcYaVersion;
    }

    private static void setSrcYaVersion(Map<String, JSONValue> sourceProperties) {
        sourceProperties.put("YaVersion", new ClientJsonString("" + YaVersion.YOUNG_ANDROID_VERSION));
    }

    private static boolean needToUpgrade(int srcYaVersion) {
        // Compare the source file's YoungAndroid version with the system's YoungAndroid version.
        final int sysYaVersion = YaVersion.YOUNG_ANDROID_VERSION;
        if (srcYaVersion > sysYaVersion) {
            // The source file's version is newer than the system's version.
            // This can happen if the user is using (or in the past has used) a non-production version of
            // App Inventor.
            // This can also happen if the user is connected to a new version of App Inventor and then
            // later is connected to an old version of App Inventor.
            // We'll try to load the project but there may be compatibility issues if the project uses
            // future components or other features that the current system doesn't understand.
            Window.alert(MESSAGES.newerVersionProject());
            return false;
        }

        if (srcYaVersion == 0) {
            // The source file doesn't have a YoungAndroid version number.
            // There are two situations that cause this:
            // 1. The project may have been downloaded from alpha (androidblocks.googlelabs.com) and
            // uploaded to beta (appinventor.googlelabs.com), which is illegal.
            // 2. The project may have been created with beta (appinventor.googlelabs.com) before we
            // started putting version numbers into the source file, which is legal, and nothing
            // really changed between version 0 and version 1.
            //
            // For a limited time, we assume #2, show a warning, and proceed.
            // TODO(lizlooney) - after the limited time is up (when we think that all appinventor
            // projects have been upgraded), we may decide to refuse to load the project.
            Window.alert(MESSAGES.veryOldProject());
        }

        return (srcYaVersion < sysYaVersion);
    }

    /*
     * Parses the JSON properties and upgrades the component if necessary.
     * This method is called recursively for nested components.
     */
    private static void upgradeComponent(int srcYaVersion, Map<String, JSONValue> componentProperties,
            StringBuilder upgradeDetails) {

        String componentType = componentProperties.get("$Type").asString().getString();

        // Get the source component version from the componentProperties.
        int srcCompVersion = 0;
        if (componentProperties.containsKey("$Version")) {
            String version = componentProperties.get("$Version").asString().getString();
            srcCompVersion = Integer.parseInt(version);
        }

        if (srcYaVersion < 2) {
            // In YOUNG_ANDROID_VERSION 2, the Logger component was removed; Notifier should be used
            // instead.
            // Here we change the Logger component to a Notifier component automatically. Sweet!
            // (We need to do this upgrade here, not in the upgradeComponentProperties method. This is
            // because the code below calls COMPONENT_DATABASE.getComponentVersion() and that will fail
            // if componentType is "Logger" because "Logger" isn't a valid component type anymore.)
            if (componentType.equals("Logger")) {
                componentType = "Notifier";
                srcCompVersion = COMPONENT_DATABASE.getComponentVersion(componentType);
                componentProperties.put("$Type", new ClientJsonString(componentType));
                componentProperties.put("$Version", new ClientJsonString("" + srcCompVersion));
                upgradeDetails.append(MESSAGES.upgradeDetailLoggerReplacedWithNotifier(
                        componentProperties.get("$Name").asString().getString()));
            }
        }

        // Get the system component version from the component database.
        final int sysCompVersion;
        try {
            sysCompVersion = COMPONENT_DATABASE.getComponentVersion(componentType);
        } catch (IllegalArgumentException e) {
            OdeLog.wlog("Cound not find component of type = " + componentType
                    + " assuming it is an external component.");
            return; // This should be safe because external components don't have
                    // nested children
        }

        // Upgrade if necessary.
        upgradeComponentProperties(componentProperties, componentType, srcCompVersion, sysCompVersion);

        if (srcYaVersion < 26) {
            // Beginning with YOUNG_ANDROID_VERSION 26:
            // - In .scm files, values for asset, BluetoothClient, component, lego_nxt_sensor_port,
            // and string properties no longer contain leading and trailing quotes.
            unquotePropertyValues(componentProperties, componentType);
        }

        // Upgrade nested components
        if (componentProperties.containsKey("$Components")) {
            JSONArray componentsArray = componentProperties.get("$Components").asArray();
            for (JSONValue nestedComponent : componentsArray.getElements()) {
                upgradeComponent(srcYaVersion, nestedComponent.asObject().getProperties(), upgradeDetails);
            }
        }
    }

    private static void upgradeComponentProperties(Map<String, JSONValue> componentProperties, String componentType,
            int srcCompVersion, final int sysCompVersion) {
        // Compare the source file's component version with the system's component version.
        if (srcCompVersion == 0) {
            // The source file doesn't have a version number for this component.
            // There are two situations that cause this:
            // 1. The project may have been downloaded from alpha (androidblocks.googlelabs.com) and
            // uploaded to beta (appinventor.googlelabs.com), which is illegal.
            // 2. The project may have been created with beta (appinventor.googlelabs.com) before we
            // started putting version numbers into the source file, which is legal, and nothing
            // really changed between version 0 and version 1.
            //
            // For a limited time, we assume #2 and pretend that the source file said version 1.
            // TODO(lizlooney) - after the limited time is up (when we think that all appinventor
            // projects have been upgraded), we may decide to refuse to load the project.
            srcCompVersion = 1;
        }

        if (srcCompVersion > sysCompVersion) {
            // This shouldn't happen because we should have already detected that the project is a newer
            // version than the system and returned false in needToUpgrade.
            // NOTE(lizlooney,user) - we need to make sure that this situation does not happen by
            // incrementing YaVersion.YOUNG_ANDROID_VERSION each time a component's version number is
            // incremented.
            throw new LoadException(
                    MESSAGES.newerVersionComponentException(componentType, srcCompVersion, sysCompVersion));
        }

        if (srcCompVersion < sysCompVersion) {
            // NOTE(lizlooney,user) - when a component changes, increment the component's version
            // number in com.google.appinventor.components.common.YaVersion and add code here to upgrade
            // properties as necessary.
            if (componentType.equals("AccelerometerSensor")) {
                srcCompVersion = upgradeAccelerometerSensorProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("ActivityStarter")) {
                srcCompVersion = upgradeActivityStarterProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Ball")) {
                srcCompVersion = upgradeBallProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("BarcodeScanner")) {
                srcCompVersion = upgradeBarcodeScannerProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("BluetoothClient")) {
                srcCompVersion = upgradeBluetoothClientProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("BluetoothServer")) {
                srcCompVersion = upgradeBluetoothServerProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Slider")) {
                srcCompVersion = upgradeSliderProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("TextToSpeech")) {
                srcCompVersion = upgradeTextToSpeechProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Button")) {
                srcCompVersion = upgradeButtonProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Camera")) {
                srcCompVersion = upgradeCameraProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Canvas")) {
                srcCompVersion = upgradeCanvasProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("CheckBox")) {
                srcCompVersion = upgradeCheckBoxProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Clock")) {
                srcCompVersion = upgradeClockProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("ContactPicker")) {
                srcCompVersion = upgradeContactPickerProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("DatePicker")) {
                srcCompVersion = upgradeDatePickerProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("EmailPicker")) {
                srcCompVersion = upgradeEmailPickerProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("File")) {
                srcCompVersion = upgradeFileProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Form")) {
                srcCompVersion = upgradeFormProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("FusiontablesControl")) {
                srcCompVersion = upgradeFusiontablesControlProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("HorizontalArrangement")) {
                srcCompVersion = upgradeHorizontalArrangementProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Image")) {
                srcCompVersion = upgradeImageProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("ImagePicker")) {
                srcCompVersion = upgradeImagePickerProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("ImageSprite")) {
                srcCompVersion = upgradeImageSpriteProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Label")) {
                srcCompVersion = upgradeLabelProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("ListPicker")) {
                srcCompVersion = upgradeListPickerProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("ListView")) {
                srcCompVersion = upgradeListViewProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("LocationSensor")) {
                srcCompVersion = upgradeLocationSensorProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("OrientationSensor")) {
                srcCompVersion = upgradeOrientationSensorProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("PasswordTextBox")) {
                srcCompVersion = upgradePasswordTextBoxProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("PhoneCall")) {
                srcCompVersion = upgradePhoneCallProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("PhoneNumberPicker")) {
                srcCompVersion = upgradePhoneNumberPickerProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Player")) {
                srcCompVersion = upgradePlayerProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Sound")) {
                srcCompVersion = upgradeSoundProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("SoundRecorder")) {
                srcCompVersion = upgradeSoundRecorderProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("TimePicker")) {
                srcCompVersion = upgradeTimePickerProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("TinyWebDB")) {
                srcCompVersion = upgradeTinyWebDBProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("VerticalArrangement")) {
                srcCompVersion = upgradeVerticalArrangementProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("VideoPlayer")) {
                srcCompVersion = upgradeVideoPlayerProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("TextBox")) {
                srcCompVersion = upgradeTextBoxProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Texting")) {
                srcCompVersion = upgradeTextingProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Notifier")) {
                srcCompVersion = upgradeNotifierProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Twitter")) {
                srcCompVersion = upgradeTwitterProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("Web")) {
                srcCompVersion = upgradeWebProperties(componentProperties, srcCompVersion);

            } else if (componentType.equals("WebViewer")) {
                srcCompVersion = upgradeWebViewerProperties(componentProperties, srcCompVersion);
            } else if (componentType.equals("FirebaseDB")) {
                srcCompVersion = upgradeFirebaseDBProperties(componentProperties, srcCompVersion);
            } else if (componentType.equals("Pedometer")) {
                srcCompVersion = upgradePedometerProperties(componentProperties, srcCompVersion);
            }

            if (srcCompVersion < sysCompVersion) {
                // If we got here, a component needed to be upgraded, but nothing handled it.
                // NOTE(lizlooney,user) - we need to make sure that this situation does not happen by
                // adding the appropriate code above to handle all component upgrades.
                throw new LoadException(
                        MESSAGES.noUpgradeStrategyException(componentType, srcCompVersion, sysCompVersion));
            }

            // The component was upgraded. Update the $Version property.
            componentProperties.put("$Version", new ClientJsonString("" + srcCompVersion));

        }
    }

    private static void unquotePropertyValues(Map<String, JSONValue> componentProperties, String componentType) {
        // From the component database, get the map of property names and types for the component type.
        Map<String, String> propertyTypesByName = COMPONENT_DATABASE.getPropertyTypesByName(componentType);

        // Iterate through the component properties.
        for (String propertyName : componentProperties.keySet()) {
            // Get the property type.
            String propertyType = propertyTypesByName.get(propertyName);
            // In theory the check for propertyType == null shouldn't be necessary
            // but I have sometimes had a problem with it being null when running
            // with GWT debugging. Maybe it changes the timing somehow. Anyway,
            // this test for null should not hurt anything. -Sharon
            if (propertyType == null) {
                OdeLog.wlog("Couldn't find propertyType for property " + propertyName + " in component type "
                        + componentType);
                continue;
            }
            // If the property type is one that was previously quoted, unquote the value.
            if (propertyType.equals("asset") || propertyType.equals("BluetoothClient")
                    || propertyType.equals("component") || propertyType.equals("lego_nxt_sensor_port")
                    || propertyType.equals("string")) {
                // Unquote the property value.
                JSONValue propertyValue = componentProperties.get(propertyName);
                String propertyValueString = propertyValue.asString().getString();
                propertyValueString = StringUtils.unquote(propertyValueString);
                componentProperties.put(propertyName, new ClientJsonString(propertyValueString));
            }
        }
    }

    private static int upgradeAccelerometerSensorProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The AccelerometerSensor.MinimumInterval property was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The AccelerometerSensor.Sensitivity property was added.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradeActivityStarterProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The ActivityStarter.DataType, ActivityStarter.ResultType, and ActivityStarter.ResultUri
            // properties were added.
            // The ActivityStarter.ResolveActivity method was added.
            // The ActivityStarter.ActivityError event was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The ActivityStarter.ActivityError event was marked userVisible false and is no longer
            // used.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The ActivityStarter.StartActivity method was modified to provide the parent Form's
            // screen animation type.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // The ActivityStarter.ActivityCanceled event was added.
            // No properties need to be modified to upgrade to version 5.
            srcCompVersion = 5;
        }
        if (srcCompVersion < 6) {
            // Extras property was added to accept a list of key-value pairs to put to the intent
            String defaultValue = "";
            boolean sendWarning = false;

            if (componentProperties.containsKey("ExtraKey")) {
                String extraKeyValue = componentProperties.get("ExtraKey").asString().getString();
                if (!extraKeyValue.equals(defaultValue)) {
                    sendWarning = true;
                }
            }

            if (componentProperties.containsKey("ExtraValue")) {
                String extraValueValue = componentProperties.get("ExtraValue").asString().getString();
                if (!extraValueValue.equals(defaultValue)) {
                    sendWarning = true;
                }
            }

            if (sendWarning) {
                Window.alert(MESSAGES.extraKeyValueWarning());
            }

            srcCompVersion = 6;
        }
        return srcCompVersion;
    }

    private static int upgradeBallProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Heading property was changed from int to double
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The Z property was added
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The TouchUp, TouchDown, and Flung events were added. (for all sprites)
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // The callback parameters speed and heading were added to Flung.
            srcCompVersion = 5;
        }
        return srcCompVersion;
    }

    private static int upgradeBarcodeScannerProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The UseExternalScanner property was added.
            srcCompVersion = 2;
        }
        return srcCompVersion;
    }

    private static int upgradeBluetoothClientProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The BluetoothClient.Enabled property was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The BluetoothClient.BluetoothError event was marked userVisible false and is no longer
            // used.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The BluetoothClient.DelimiterByte property was added.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // The BluetoothClient.Secure property was added.
            // No properties need to be modified to upgrade to version 5.
            srcCompVersion = 5;
        }
        return srcCompVersion;
    }

    private static int upgradeBluetoothServerProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The BluetoothServer.Enabled property was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The BluetoothServer.BluetoothError event was marked userVisible false and is no longer
            // used.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The BluetoothServer.DelimiterByte property was added.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // The BluetoothServer.Secure property was added.
            // No properties need to be modified to upgrade to version 5.
            srcCompVersion = 5;
        }
        return srcCompVersion;
    }

    private static int upgradeSliderProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 1) {
            // Initial version. Placeholder for future upgrades
            srcCompVersion = 1;
        }
        if (srcCompVersion < 2) {
            // Added the property to allow for the removal of the Thumb Slider
            srcCompVersion = 2;
        }
        return srcCompVersion;
    }

    private static int upgradeTextToSpeechProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // Added speech pitch and rate
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The AvailableLanguages property was added
            // The AvailableCountires property was added
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // the Country designer property was changed to use a ChoicePropertyEditor
            // the Language designer property was changed to use a ChoicePropertyEditor
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // default value was added to the Country designer property
            // default value was added to the Language designer property
            srcCompVersion = 5;
        }
        return srcCompVersion;
    }

    private static int upgradeButtonProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Alignment property was renamed to TextAlignment.
            handlePropertyRename(componentProperties, "Alignment", "TextAlignment");
            // Properties related to this component have now been upgraded to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The LongClick event was added.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The Shape property was added.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // The ShowFeedback property was added.
            // No properties need to be modified to upgrade to version 5.
            srcCompVersion = 5;
        }
        if (srcCompVersion < 6) {
            // - Added TouchUp and TouchDown events
            // - FontSize, FontBold, FontItalic properties made visible in block editor
            // No properties need to be modified to upgrade to version 6.
            srcCompVersion = 6;
        }
        return srcCompVersion;
    }

    private static int upgradeCameraProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The UseFront property was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The UseFront property was removed, it isn't supported in
            // newer versions of Android
            if (componentProperties.containsKey("UseFront")) {
                componentProperties.remove("UseFront");
                upgradeWarnDialog(MESSAGES.useFrontDeprecated());
            }
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradeCanvasProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The LineWidth property was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The FontSize and TextAlignment properties and
            // the DrawText and DrawTextAtAngle methods were added.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // No properties need to be modified to upgrade to version 4.
            // The Save and SaveAs methods were added.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // No properties need to be modified to upgrade to version 5.
            // The methods GetBackgroundPixelColor, GetPixelColor, and
            // SetBackgroundPixelColor were added.
            srcCompVersion = 5;
        }
        if (srcCompVersion < 6) {
            // No properties need to be modified to upgrade to version 6.
            // The events TouchDown, TouchUp, and Flung were added.
            srcCompVersion = 6;
        }
        if (srcCompVersion < 7) {
            // The callback parameters speed and heading were added to Flung.
            srcCompVersion = 7;
        }
        if (srcCompVersion < 8) {
            // DrawCircle parameter names changed to centerx,centery, radius
            // Touched parameter touchedSprite name changed to touchedAnySprite
            // Dragged parameter draggedSprite name changed to draggedAnySprite
            srcCompVersion = 8;
        }
        if (srcCompVersion < 9) {
            // DrawCircle takes a new isFilled as fourth parameter.
            srcCompVersion = 9;
        }
        if (srcCompVersion < 10) {
            // TextAlignment default was changed to Component.ALIGNMENT_CENTER.
            // Previously the default was ALIGNMENT_NORMAL (left).
            int oldDefault = 0; // ALIGNMENT_NORMAL (left)
            JSONValue def = new ClientJsonString(Integer.toString(oldDefault));
            componentProperties.put("TextAlignment", def);
            srcCompVersion = 10;
        }
        return srcCompVersion;
    }

    private static int upgradeCheckBoxProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Value property was renamed to Checked.
            handlePropertyRename(componentProperties, "Value", "Checked");
            // Properties related to this component have now been upgraded to version 2.
            srcCompVersion = 2;
        }
        return srcCompVersion;
    }

    private static int upgradeClockProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 3) {
            // (2) The FormatDate and FormatDateTime methods were modified to take another parameter of pattern.
            // No properties need to be modified to upgrade to version 2.
            // (3) Duration Support was added
            // No properties need to be added to upgrade to version 3.
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradeContactPickerProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Alignment property was renamed to TextAlignment.
            handlePropertyRename(componentProperties, "Alignment", "TextAlignment");
            // Properties related to this component have now been upgraded to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The Open method was added.  No changes are needed.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The Shape property was added.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // The PhoneNumber, PhoneNumberList, and EmailAddressList properties were added.
            // For Eclair and up, we now use ContactsContract instead of the deprecated Contacts.
            srcCompVersion = 5;
        }
        if (srcCompVersion < 6) {
            // The ContactUri property was added.
            // No properties need to be modified to upgrade to version 6.
            srcCompVersion = 6;
        }
        return srcCompVersion;
    }

    private static int upgradeDatePickerProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The SetDateToDisplay and LaunchPicker methods were added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // SetDateToDisplayFromInstant, and Instant property are added.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradeEmailPickerProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Alignment property was renamed to TextAlignment.
            handlePropertyRename(componentProperties, "Alignment", "TextAlignment");
            // Properties related to this component have now been upgraded to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // RequestFocus function was added (via TextBoxBase)
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradeFileProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // File.AfterFileSaved event was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        return srcCompVersion;
    }

    private static int upgradeFormProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Screen.Scrollable property was added.
            // If the form contains a direct child component whose height is set to fill parent,
            // we set the Scrollable property value to false.
            if (componentProperties.containsKey("$Components")) {
                JSONArray componentsArray = componentProperties.get("$Components").asArray();
                for (JSONValue nestedComponent : componentsArray.getElements()) {
                    Map<String, JSONValue> nestedComponentProperties = nestedComponent.asObject().getProperties();
                    if (nestedComponentProperties.containsKey("Height")) {
                        JSONValue heightValue = nestedComponentProperties.get("Height");
                        String heightString = heightValue.asString().getString();
                        try {
                            int height = Integer.parseInt(heightString);
                            if (height == MockVisibleComponent.LENGTH_FILL_PARENT) {
                                // Set the Form's Scrollable property to false.
                                componentProperties.put("Scrollable", new ClientJsonString("False"));
                                break;
                            }
                        } catch (NumberFormatException e) {
                            // Ignore this. If we throw an exception here, the project is unrecoverable.
                        }
                    }
                }
            }
            // Properties related to this component have now been upgraded to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The Screen.Icon property was added.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The Screen.ErrorOccurred event was added.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // The Screen.ScreenOrientation property and Screen.ScreenOrientationChanged event were
            // added.
            // No properties need to be modified to upgrade to version 5.
            srcCompVersion = 5;
        }
        if (srcCompVersion < 6) {
            // The SwitchForm and SwitchFormWithArgs methods were removed and the OtherScreenClosed event
            // was added.
            srcCompVersion = 6;
        }
        if (srcCompVersion < 7) {
            // The VersionCode and VersionName properties were added. No properties need to be modified
            // to update to version 7.
            srcCompVersion = 7;
        }

        if (srcCompVersion < 8) {
            // The AlignHorizontal and AlignVertical properties were added. No blocks need to be modified
            // to upgrade to version 8.
            srcCompVersion = 8;
        }
        if (srcCompVersion < 9) {
            // The OpenScreenAnimation and CloseScreenAnimation properties were added. No blocks need
            // to be modified to upgrade to version 9.
            srcCompVersion = 9;
        }
        if (srcCompVersion < 10) {
            // The BackPressed event was added. No blocks need to be modified to upgrade to version 10.
            srcCompVersion = 10;
        }
        if (srcCompVersion < 11) {
            // OpenScreenAnimation and CloseScreenAnimation are now properties.
            srcCompVersion = 11;
        }
        if (srcCompVersion < 12) {
            // The AboutScreen property was added.
            srcCompVersion = 12;
        }
        if (srcCompVersion < 13) {
            // The Scrollable property was set to False by default.
            if (componentProperties.containsKey("Scrollable")) {
                String value = ((ClientJsonString) componentProperties.get("Scrollable")).getString();
                if (value.equals("False")) {
                    componentProperties.remove("Scrollable");
                }
            } else {
                componentProperties.put("Scrollable", new ClientJsonString("True"));
            }
            srcCompVersion = 13;
        }

        if (srcCompVersion < 15) {
            // The AppName property was added.
            // The Compatibility Mode property was added. No properties need to be modified to update to
            // version 7.
            srcCompVersion = 15;
        }
        if (srcCompVersion < 16) {
            // The ShowStatusBar property was added.
            // The TitleVisible property was added.
            srcCompVersion = 16;
        }
        if (srcCompVersion < 17) {
            // The CompatibilityMode property was added
            // When upgrading projects, turn on Compatbility Mode
            // NOTE: This change never saw production, but was on various
            // Test Instances
            componentProperties.put("CompatibilityMode", new ClientJsonString("True"));
            srcCompVersion = 17;
        }

        if (srcCompVersion < 18) {
            // Compatilibity Mode property turned into the Sizing property
            if (componentProperties.containsKey("CompatibilityMode")) {
                componentProperties.remove("CompatibilityMode");
            } else {
                componentProperties.put("Sizing", new ClientJsonString("Responsive"));
            }
            srcCompVersion = 18;
        }

        if (srcCompVersion < 19) {
            // Added HideKeyboard
            srcCompVersion = 19;
        }

        return srcCompVersion;
    }

    private static int upgradeFusiontablesControlProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // No properties need to be modified to upgrade to version 2.
            // The ApiKey property and the SendQuery and ForgetLogin methods were added.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // No properties need to be modified to upgrade to version 3.
            // GetRows, InsertRows and GetRowsWithConditions methods were added.
            // KeyFile, UseServiceAuthentication and ServiceAccountEmail properties
            // were added.
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradeHorizontalArrangementProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The AlignHorizontal and AlignVertical properties were added. No blocks need to be modified
            // to upgrqde to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // - Added background color & image
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradeImageProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The RotationAngle property was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // ScalePictureToFit was replaced by Scaling property
            // Note: We will do this upgrade in a future release (jis: 2/12/2016)
            // if (componentProperties.containsKey("ScalePictureToFit")) {
            //   JSONValue propValue = componentProperties.remove("ScalePictureToFit");
            //   if (propValue.asString().getString().equals("True")) {
            //     // 1 corresponds to Scale to fit
            //     componentProperties.put("Scaling", new ClientJsonString("1"));
            //   }
            // }
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradeImagePickerProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Alignment property was renamed to TextAlignment.
            handlePropertyRename(componentProperties, "Alignment", "TextAlignment");
            // Properties related to this component have now been upgraded to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The Open method was added.  No changes are needed.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The Shape property was added.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // The ImagePath property was renamed to Selection.
            handlePropertyRename(componentProperties, "ImagePath", "Selection");
            // Properties related to this component have now been upgraded to version 2.
            srcCompVersion = 5;
        }
        return srcCompVersion;
    }

    private static int upgradeImageSpriteProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The SpriteComponent.Rotates property was added
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The Heading property was changed from int to Double
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The Z property was added
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // The TouchUp, TouchDown, and Flung events were added. (for all sprites)
            // No properties need to be modified to upgrade to version 5.
            srcCompVersion = 5;
        }
        if (srcCompVersion < 6) {
            // The callback parameters speed and heading were added to Flung.
            srcCompVersion = 6;
        }
        return srcCompVersion;
    }

    private static int upgradeLabelProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Alignment property was renamed to TextAlignment.
            handlePropertyRename(componentProperties, "Alignment", "TextAlignment");
            // Properties related to this component have now been upgraded to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 4) {
            // The LabelFormat method was added.  No changes are needed. (3)
            // The HasMargins property was added. (4)
            componentProperties.put("HasMargins", new ClientJsonString("False"));
            srcCompVersion = 4;
        }
        return srcCompVersion;
    }

    private static int upgradeListPickerProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Alignment property was renamed to TextAlignment.
            handlePropertyRename(componentProperties, "Alignment", "TextAlignment");
            // Properties related to this component have now been upgraded to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The SelectionIndex property was added.  No changes are needed.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The Open method was added.  No changes are needed.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // The Shape property was added.
            // No properties need to be modified to upgrade to version 5.
            srcCompVersion = 5;
        }
        if (srcCompVersion < 6) {
            // The getIntent method was modified to add the parent Form's screen
            // animation type. No properties need to be modified to upgrade to
            // version 6.
            srcCompVersion = 6;
        }
        if (srcCompVersion < 7) {
            //  Added ShowFilterBar property
            srcCompVersion = 7;
        }
        if (srcCompVersion < 8) {
            //  Added title property
            srcCompVersion = 8;
        }
        if (srcCompVersion < 9) {
            // Added ItemTextColor, ItemBackgroundColor
            srcCompVersion = 9;
        }
        return srcCompVersion;
    }

    private static int upgradeListViewProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // Added the Elements property
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // Added the BackgroundColor property
            // Added the TextColor property
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // Added the TextSize property
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // Added the SelectionColor property
            srcCompVersion = 5;
        }
        return srcCompVersion;
    }

    private static int upgradeLocationSensorProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 3) {
            // Version 2:
            // The TimeInterval and DistanceInterval properties were added.
            // No properties need to be modified to upgrade to Version 2.
            // Version 3:
            // The speed parameter was added to the LocationChanged event
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradeOrientationSensorProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Yaw property was renamed to Azimuth.
            handlePropertyRename(componentProperties, "Yaw", "Azimuth");
            // Properties related to this component have now been upgraded to version 2.
            srcCompVersion = 2;
        }
        return srcCompVersion;
    }

    private static int upgradePasswordTextBoxProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Alignment property was renamed to TextAlignment.
            handlePropertyRename(componentProperties, "Alignment", "TextAlignment");
            // Properties related to this component have now been upgraded to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // Added RequestFocus Function (via TextBoxBase)
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradePhoneCallProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The PhoneCallStarted event was added.
            // The PhoneCallEnded event was added.
            // The IncomingCallAnswered event was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        return srcCompVersion;
    }

    private static int upgradePhoneNumberPickerProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Alignment property was renamed to TextAlignment.
            handlePropertyRename(componentProperties, "Alignment", "TextAlignment");
            // Properties related to this component have now been upgraded to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The Open method was added.  No changes are needed.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The Shape property was added.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        return srcCompVersion;
    }

    private static int upgradePlayerProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Player.PlayerError event was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The Player.PlayerError event was marked userVisible false and is no longer used.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The Looping and Volume properties were added.
            // The Completed Event was added.
            // The IsPlaying method was added.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // The IsPlaying method was renamed to Loop.
            handlePropertyRename(componentProperties, "IsLooping", "Loop");
            // Properties related to this component have now been upgraded to version  5.
            srcCompVersion = 5;
        }
        if (srcCompVersion < 6) {
            // The PlayInForeground method was added.
            // The OtherPlayerStarted event was added.
            // Properties related to this component have now been upgraded to version  6.
            srcCompVersion = 6;
        }
        return srcCompVersion;
    }

    private static int upgradeSoundProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The Sound.SoundError event was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The Sound.SoundError event was marked userVisible false and is no longer used.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradeSoundRecorderProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The SoundRecorder.RecordFile property was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        return srcCompVersion;
    }

    private static int upgradeTimePickerProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The SetTimeToDisplay and LaunchPicker methods were added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // SetTimeToDisplayFromInstant, and Instant property are added.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradeTinyWebDBProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The TinyWebDB.ShowAlert method was removed. Notifier.ShowAlert should be used instead.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        return srcCompVersion;
    }

    private static int upgradeVerticalArrangementProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The AlignHorizontal and AlignVertical properties were added. No blocks need to be modified
            // to upgrqde to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // - Added background color & image
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradeNotifierProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // A new boolean socket was added to allow canceling out of ShowChooseDialog
            // and ShowTextDialog
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The BackgroundColor, NotifierLength, and TextColor options were added.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // A new type of dialog was created, a ProgressDialog, and a method to
            // dismiss the dialog was also added.
            srcCompVersion = 4;
        }
        return srcCompVersion;
    }

    private static int upgradeVideoPlayerProperties(Map<String, JSONValue> componentProperties,
            int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The VideoPlayer.VideoPlayerError event was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The VideoPlayer.VideoPlayerError event was marked userVisible false and is no longer used.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The VideoPlayer.height and VideoPlayer.width getter and setters were marked as
            // visible to the user.
            // The FullScreen property was created.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // The Volume property (setter only) was created.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 5;
        }
        return srcCompVersion;
    }

    private static int upgradeTwitterProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The designer properties ConsumerKey and ConsumerSecret were added
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The designer property TwitPic_API_Key was added
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The designer property TwitPic_API_Key and functions are hidden and deprecated.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        return srcCompVersion;
    }

    private static int upgradeTextingProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The designer property GoogleVoiceEnabled was added
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            if (componentProperties.containsKey("ReceivingEnabled")) {
                JSONValue receivingEnabled = componentProperties.get("ReceivingEnabled");
                String receivingString = receivingEnabled.asString().getString();
                if (receivingString.equals("true")) {
                    componentProperties.put("ReceivingEnabled", new ClientJsonString("2"));
                } else {
                    componentProperties.put("ReceivingEnabled", new ClientJsonString("1"));
                }
            }
            srcCompVersion = 3;
        }

        return srcCompVersion;
    }

    private static int upgradeTextBoxProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The property (and designer property) TextBox.NumbersOnly was added
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The Alignment property was renamed to TextAlignment.
            handlePropertyRename(componentProperties, "Alignment", "TextAlignment");
            // Properties related to this component have now been upgraded to version 3.
            srcCompVersion = 3;
        }

        if (srcCompVersion < 4) {
            // The MultiLine property was added.
            // The default for Multiline from now on is false, but up until now,
            // all text boxes have been multiline.
            // We need to set the MultiLine to true when we upgrade old projects.
            componentProperties.put("MultiLine", new ClientJsonString("True"));
            // Properties related to this component have now been upgraded to version 4.
            srcCompVersion = 4;
        }
        if (srcCompVersion < 5) {
            // RequestFocus method was added
            srcCompVersion = 5;
        }
        return srcCompVersion;
    }

    private static int upgradeWebProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The RequestHeaders and AllowCookies properties were added.
            // The BuildPostData and ClearCookies methods were added.
            // The existing PostText method was renamed to PostTextWithEncoding, and a new PostText
            // method was added.
            // No properties need to be modified to upgrade to version 2.
            srcCompVersion = 2;
        }
        if (srcCompVersion < 3) {
            // The methods PutText, PutTextWithEncoding, PutFile and Delete were added.
            // The method BuildPostData was renamed to BuildRequestData.
            // No properties need to be modified to upgrade to version 3.
            srcCompVersion = 3;
        }
        if (srcCompVersion < 4) {
            // The XMLTextDecode method was added.
            // No properties need to be modified to upgrade to version 4.
            srcCompVersion = 4;
        }
        return srcCompVersion;
    }

    private static int upgradeWebViewerProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 6) {
            // The CanGoForward and CanGoBack methods were added.
            // No properties need to be modified to upgrade to version 2.
            // UsesLocation property added.
            // No properties need to be modified to upgrade to version 3.
            // WebViewString added
            // No properties need to be modified to upgrade to version 4.
            // IgnoreSslError property added (version 5)
            // ClearCaches method was added (version 6)
            srcCompVersion = 6;
        }
        return srcCompVersion;
    }

    private static int upgradeFirebaseDBProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 3) {
            // Version 2
            // Added AppendValue, RemoveFirst and FirstRemoved
            // Version 3
            // Added RemoveValue, GetTagList and Persist
            srcCompVersion = 3;
        }
        return srcCompVersion;
    }

    private static int upgradePedometerProperties(Map<String, JSONValue> componentProperties, int srcCompVersion) {
        if (srcCompVersion < 2) {
            // The step sensing algorithm was updated to be more accurate.
            // The GPS related functionality was removed.
            srcCompVersion = 2;
        }
        return srcCompVersion;
    }

    private static void handlePropertyRename(Map<String, JSONValue> componentProperties, String oldPropName,
            String newPropName) {
        if (componentProperties.containsKey(oldPropName)) {
            componentProperties.put(newPropName, componentProperties.remove(oldPropName));
        }
    }

    private static void handleSupplyValueForPreviouslyDefaultedProperty(Map<String, JSONValue> componentProperties,
            String PropName, JSONValue valueToSupply) {
        // if the property wasn't previously there as a key, the previous value was
        // the default value
        if (!(componentProperties.containsKey(PropName))) {
            componentProperties.put(PropName, valueToSupply);
        }
    }

    private static void upgradeWarnDialog(String aMessage) {
        final DialogBox dialogBox = new DialogBox(false, true);
        dialogBox.setStylePrimaryName("ode-DialogBox");
        dialogBox.setText(MESSAGES.warningDialogTitle());
        dialogBox.setGlassEnabled(true);
        dialogBox.setAnimationEnabled(true);
        final HTML message = new HTML(aMessage);
        message.setStyleName("DialogBox-message");
        VerticalPanel vPanel = new VerticalPanel();
        Button okButton = new Button("OK");
        okButton.addClickListener(new ClickListener() {
            @Override
            public void onClick(Widget sender) {
                dialogBox.hide();
            }
        });
        vPanel.add(message);
        vPanel.add(okButton);
        dialogBox.setWidget(vPanel);
        dialogBox.center();
        dialogBox.show();
    }

}