Transferred from the Adobe Open Source Subversion Repository

Revision: 19257
Author:   matamel@adobe.com
Date:     2010-12-10T13:19:33.327544Z

Log Message:
-----------
In MultiTopicConsumer, when subscribe call is immediately followed by addSubscription call, there's a tiny window where subscribed flag is not turned to true yet but shouldSubscribed flag is true. In that case, MultiTopicConsumer#reSubscribe method was called to add the subscription, but the subscribe message was discarded because subscribed flag was false. Fixed the issue by sending the subscribe message even when the Consumer is not reporting subscribed/connected yet. The message will be queued if the Consumer is not connected yet, and sent when it's connected, or it'll be sent out if it is already connected, so it's safe either way.

QE notes: Please test the scenario mentioned in the bug.
Doc notes: None
Bugs: BLZ-593 - MultiTopicConsumer can silently drops subscriptions when latency is present
Reviewer: None
Tests run: None, no checkintests for MTC.
Is noteworthy for integration: Yes

Modified Paths:
--------------
/private/flex/sdk/branches/hero_private/frameworks/projects/rpc/src/mx/messaging/MultiTopicConsumer.as

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1273553 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/rpc/src/mx/messaging/MultiTopicConsumer.as
+++ frameworks/projects/rpc/src/mx/messaging/MultiTopicConsumer.as
@@ -12,473 +12,471 @@
 package mx.messaging
 {

-import flash.events.TimerEvent;
-import flash.utils.Timer;
-
-import mx.collections.ArrayCollection;
-import mx.core.mx_internal;
-import mx.events.CollectionEvent;
-import mx.events.PropertyChangeEvent;
-import mx.messaging.errors.MessagingError;
-import mx.messaging.events.MessageEvent;
-import mx.messaging.messages.CommandMessage;
-import mx.messaging.messages.IMessage;
-
-use namespace mx_internal;
-
-/**
- *  Dispatched when a message is received by the Consumer.
- *
- *  @eventType mx.messaging.events.MessageEvent.MESSAGE
- *
- *  @langversion 3.0
- *  @playerversion Flash 9
- *  @playerversion AIR 1.1
- *  @productversion BlazeDS 4
- *  @productversion LCDS 3
- */
-[Event(name="message", type="mx.messaging.events.MessageEvent")]
-
-/**
- *  Like a Consumer, a MultiTopicConsumer subscribes to a destination with a single
- *  clientId and delivers messages to a single event handler.  Unlike a Consumer
- *  it lets you register subscriptions for a list of subtopics and selector expressions
- *  at the same time from a single message handler.  Where Consumer has subtopic and selector properties,
- *  this component has an addSubscription(subtopic, selector) method you use to
- *  add a new subscription to the existing set of subscriptions.  Alternatively, you can
- *  populate the subscriptions property with a list of SubscriptionInfo instances that
- *  define the subscriptions for this destination.
- *

- *  Like the regular Consumer, the MultiTopicConsumer sends subscribe and unsubscribe
- *  messages which generate a MessageAckEvent or MessageFaultEvent depending upon whether the
- *  operation was successful or not.
- *  Once subscribed, a MultiTopicConsumer dispatches a MessageEvent for each message it receives.

- *  @mxml
- *

- *  The <mx:MultiTopicConsumer> tag has these properties:
- *

- *

- *   <mx:Consumer
- *    Properties
- *    subscriptions=""an empty ArrayCollection of SubscriptionInfo objects"
- *    resubscribeAttempts="5"
- *    resubscribeInterval="5000"
- *    timestamp="No default."
- *  />
- *

- *
- *  @langversion 3.0
- *  @playerversion Flash 9
- *  @playerversion AIR 1.1
- *  @productversion BlazeDS 4
- *  @productversion LCDS 3
- */
-public class MultiTopicConsumer extends AbstractConsumer
-{
-
-    //--------------------------------------------------------------------------
-    //
-    // Constructor
-    //
-    //--------------------------------------------------------------------------
+    import flash.events.TimerEvent;
+    import flash.utils.Timer;
+
+    import mx.collections.ArrayCollection;
+    import mx.core.mx_internal;
+    import mx.events.CollectionEvent;
+    import mx.events.PropertyChangeEvent;
+    import mx.messaging.errors.MessagingError;
+    import mx.messaging.events.MessageEvent;
+    import mx.messaging.messages.CommandMessage;
+    import mx.messaging.messages.IMessage;
+
+    use namespace mx_internal;

     /**
-     *  Constructor.
-     *
-     *
-     *  @example
-     *  <listing version="3.0">
-     *   function initConsumer():void
-     *   {
-     *       var consumer:Consumer = new MultiTopicConsumer();
-     *       consumer.destination = "NASDAQ";
-     *       consumer.addEventListener(MessageEvent.MESSAGE, messageHandler);
-     *       consumer.addSubscription("myStock1", "operation IN ('BID', 'Ask')");
-     *       consumer.addSubscription("myStock2", "operation IN ('BID', 'Ask')");
-     *       consumer.subscribe();
-     *   }
+     *  Dispatched when a message is received by the Consumer.
      *
-     *   function messageHandler(event:MessageEvent):void
-     *   {
-     *       var msg:IMessage = event.message;
-     *       var info:Object = msg.body;
-     *       trace("-App recieved message: " + msg.toString());
-     *   }
-     *   </listing>
-     *
+     *  @eventType mx.messaging.events.MessageEvent.MESSAGE
+     *
      *  @langversion 3.0
      *  @playerversion Flash 9
      *  @playerversion AIR 1.1
      *  @productversion BlazeDS 4
-     *  @productversion LCDS 3
+     *  @productversion LCDS 3
      */
-    public function MultiTopicConsumer()
-    {
-        super();
-
-        _subscriptions.addEventListener(CollectionEvent.COLLECTION_CHANGE, subscriptionsChangeHandler);
-    }
-
-
-    //--------------------------------------------------------------------------
-    //
-    // Properties
-    //
-    //--------------------------------------------------------------------------
+    [Event(name="message", type="mx.messaging.events.MessageEvent")]

     /**
-     *  @private
-     */
-    private var _subscriptions:ArrayCollection = new ArrayCollection();
-
-    /**
-     * This is a map where the keys are string names of the form subtopic + separator + selector
-     * registered with the boolean true.  When we generate a subscription message and
-     * send it to the server, we add/remove those subscriptions from this list.  Thus this
-     * list tracks the subscriptions we have sent to the server.
-     *
+     *  Like a Consumer, a MultiTopicConsumer subscribes to a destination with a single
+     *  clientId and delivers messages to a single event handler.  Unlike a Consumer
+     *  it lets you register subscriptions for a list of subtopics and selector expressions
+     *  at the same time from a single message handler.  Where Consumer has subtopic and selector properties,
+     *  this component has an addSubscription(subtopic, selector) method you use to
+     *  add a new subscription to the existing set of subscriptions.  Alternatively, you can
+     *  populate the subscriptions property with a list of SubscriptionInfo instances that
+     *  define the subscriptions for this destination.
+     *

+     *  Like the regular Consumer, the MultiTopicConsumer sends subscribe and unsubscribe
+     *  messages which generate a MessageAckEvent or MessageFaultEvent depending upon whether the
+     *  operation was successful or not.
+     *  Once subscribed, a MultiTopicConsumer dispatches a MessageEvent for each message it receives.

+     *  @mxml
+     *

+     *  The <mx:MultiTopicConsumer> tag has these properties:
+     *

+     *

+     *   <mx:Consumer
+     *    Properties
+     *    subscriptions=""an empty ArrayCollection of SubscriptionInfo objects"
+     *    resubscribeAttempts="5"
+     *    resubscribeInterval="5000"
+     *    timestamp="No default."
+     *  />
+     *

+     *
      *  @langversion 3.0
      *  @playerversion Flash 9
      *  @playerversion AIR 1.1
      *  @productversion BlazeDS 4
-     *  @productversion LCDS 3
+     *  @productversion LCDS 3
      */
-    private var _currentSubscriptions:Object = {};
-
-    /**
-     * Used when the subscriptions property changes so we batch all changes made in one
-     * frame into a single multi-subscription message
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 9
-     *  @playerversion AIR 1.1
-     *  @productversion BlazeDS 4
-     *  @productversion LCDS 3
-     */
-    private var _subchangeTimer:Timer = null;
-
-    [Bindable(event="propertyChange")]
-
-    [Inspectable(category="General", verbose="1")]
-    /**
-     *  Stores an Array of SubscriptionInfo objects.  Each subscription
-     *  contains a subtopic and a selector each of which can be null.
-     *  A subscription with a non-null subtopic restricts the subscription
-     *  to messages delivered with only that subtopic.
-     *  If a subtopic is null, it uses the selector with no subtopic.
-     *  If the selector and the subtopic is null, the subscription receives
-     *  any messages targeted at the destination with no subtopic.
-     *  The subtopic can contain a wildcard specification.
-     *
-     *
Before a call to the subscribe() method, this property
-     *  can be set with no side effects.
-     *  After the MultiTopicConsumer has subscribed to its destination, changing this
-     *  value has the side effect of updating the MultiTopicConsumer's subscription to
-     *  include any new subscriptions and remove any subscriptions you deleted from
-     *  the ArrayCollection.

-     *
-     *
The remote destination must understand the value of the selector
-     *  expression.

-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 9
-     *  @playerversion AIR 1.1
-     *  @productversion BlazeDS 4
-     *  @productversion LCDS 3
-     */
-    public function get subscriptions():ArrayCollection
+    public class MultiTopicConsumer extends AbstractConsumer
     {
-        return _subscriptions;
+
+        //--------------------------------------------------------------------------
+        //
+        // Constructor
+        //
+        //--------------------------------------------------------------------------
+
+        /**
+         *  Constructor.
+         *
+         *
+         *  @example
+         *  <listing version="3.0">
+         *   function initConsumer():void
+         *   {
+         *       var consumer:Consumer = new MultiTopicConsumer();
+         *       consumer.destination = "NASDAQ";
+         *       consumer.addEventListener(MessageEvent.MESSAGE, messageHandler);
+         *       consumer.addSubscription("myStock1", "operation IN ('BID', 'Ask')");
+         *       consumer.addSubscription("myStock2", "operation IN ('BID', 'Ask')");
+         *       consumer.subscribe();
+         *   }
+         *
+         *   function messageHandler(event:MessageEvent):void
+         *   {
+         *       var msg:IMessage = event.message;
+         *       var info:Object = msg.body;
+         *       trace("-App recieved message: " + msg.toString());
+         *   }
+         *   </listing>
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 9
+         *  @playerversion AIR 1.1
+         *  @productversion BlazeDS 4
+         *  @productversion LCDS 3
+         */
+        public function MultiTopicConsumer()
+        {
+            super();
+
+            _subscriptions.addEventListener(CollectionEvent.COLLECTION_CHANGE, subscriptionsChangeHandler);
+        }
+
+
+        //--------------------------------------------------------------------------
+        //
+        // Properties
+        //
+        //--------------------------------------------------------------------------
+
+        /**
+         *  @private
+         */
+        private var _subscriptions:ArrayCollection = new ArrayCollection();
+
+        /**
+         * This is a map where the keys are string names of the form subtopic + separator + selector
+         * registered with the boolean true.  When we generate a subscription message and
+         * send it to the server, we add/remove those subscriptions from this list.  Thus this
+         * list tracks the subscriptions we have sent to the server.
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 9
+         *  @playerversion AIR 1.1
+         *  @productversion BlazeDS 4
+         *  @productversion LCDS 3
+         */
+        private var _currentSubscriptions:Object = {};
+
+        /**
+         * Used when the subscriptions property changes so we batch all changes made in one
+         * frame into a single multi-subscription message
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 9
+         *  @playerversion AIR 1.1
+         *  @productversion BlazeDS 4
+         *  @productversion LCDS 3
+         */
+        private var _subchangeTimer:Timer = null;
+
+        [Bindable(event="propertyChange")]
+
+        [Inspectable(category="General", verbose="1")]
+        /**
+         *  Stores an Array of SubscriptionInfo objects.  Each subscription
+         *  contains a subtopic and a selector each of which can be null.
+         *  A subscription with a non-null subtopic restricts the subscription
+         *  to messages delivered with only that subtopic.
+         *  If a subtopic is null, it uses the selector with no subtopic.
+         *  If the selector and the subtopic is null, the subscription receives
+         *  any messages targeted at the destination with no subtopic.
+         *  The subtopic can contain a wildcard specification.
+         *
+         *
Before a call to the subscribe() method, this property
+         *  can be set with no side effects.
+         *  After the MultiTopicConsumer has subscribed to its destination, changing this
+         *  value has the side effect of updating the MultiTopicConsumer's subscription to
+         *  include any new subscriptions and remove any subscriptions you deleted from
+         *  the ArrayCollection.

+         *
+         *
The remote destination must understand the value of the selector
+         *  expression.

+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 9
+         *  @playerversion AIR 1.1
+         *  @productversion BlazeDS 4
+         *  @productversion LCDS 3
+         */
+        public function get subscriptions():ArrayCollection
+        {
+            return _subscriptions;
+        }
+
+        /**
+         * Provide a new subscriptions array collection.  This should be an ArrayCollection
+         * containing SubscriptionInfo instances which define message topics and selectors
+         * you want received by this consumer.
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 9
+         *  @playerversion AIR 1.1
+         *  @productversion BlazeDS 4
+         *  @productversion LCDS 3
+         */
+        public function set subscriptions(value:ArrayCollection):void
+        {
+            if (_subscriptions !== value)
+            {
+                var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "subscriptions", _subscriptions, value);
+
+                if (subscribed)
+                {
+                    unsubscribe();
+                    _shouldBeSubscribed = true;
+                }
+
+                if (_subscriptions != null)
+                    _subscriptions.removeEventListener(CollectionEvent.COLLECTION_CHANGE, subscriptionsChangeHandler);
+
+                _subscriptions = value;
+
+                if (_subscriptions != null)
+                    _subscriptions.addEventListener(CollectionEvent.COLLECTION_CHANGE, subscriptionsChangeHandler);
+
+                // Update an existing subscription to use the new selector.
+                if (_shouldBeSubscribed)
+                    subscribe(clientId);
+
+                dispatchEvent(event);
+            }
+        }
+
+        /**
+         * This is a convenience method for adding a new subscription.  It just creates
+         * a new SubscriptionInfo object and adds it to the subscriptions property.
+         * To call this method, you provide the
+         * subtopic and selector string for the new subscription.  If the subtopic is null,
+         * the subscription applies to messages which do not have a subtopic set in the
+         * producer.  If the selector string is null, all messages sent which match the
+         * subtopic string are received by this consumer.
+         *
+         * @param subtopic The subtopic for the new subscription.
+         *
+         * @param selector The selector for the new subscription.
+         *
+         * @param maxFrequency The maximum number of messages per second the Consumer wants
+         * to receive for the subscription. Note that this value overwrites the Consumer
+         * wide maxFrequency.
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 9
+         *  @playerversion AIR 1.1
+         *  @productversion BlazeDS 4
+         *  @productversion LCDS 3
+         */
+        public function addSubscription(subtopic:String = null, selector:String = null, maxFrequency:uint = 0):void
+        {
+            subscriptions.addItem(new SubscriptionInfo(subtopic, selector, maxFrequency));
+        }
+
+        /**
+         * This method removes the subscription specified by the subtopic
+         * and selector.
+         *
+         * @param subtopic The subtopic for the subscription.
+         *
+         * @param selector The selector for the subscription.
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 9
+         *  @playerversion AIR 1.1
+         *  @productversion BlazeDS 4
+         *  @productversion LCDS 3
+         */
+        public function removeSubscription(subtopic:String = null, selector:String = null):void
+        {
+            var n:int = subscriptions.length;
+            for (var i:int = 0; i < n; ++i)
+            {
+                var si:SubscriptionInfo = SubscriptionInfo(subscriptions.getItemAt(i));
+                if (si.subtopic == subtopic && si.selector == selector)
+                {
+                    subscriptions.removeItemAt(i);
+                    break;
+                }
+            }
+
+            if (n == subscriptions.length)
+                throw new MessagingError("Attempt to remove a subscription with subtopic: " +
+                    subtopic + " and selector: " + selector + " that this consumer does not have");
+        }
+
+        //--------------------------------------------------------------------------
+        //
+        // Protected Methods
+        //
+        //--------------------------------------------------------------------------
+
+        /**
+         * Returns a subscribe message.
+         *
+         * @return The subscribe CommandMessage.
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 9
+         *  @playerversion AIR 1.1
+         *  @productversion BlazeDS 4
+         *  @productversion LCDS 3
+         */
+        override protected function buildSubscribeMessage():CommandMessage
+        {
+            var msg:CommandMessage = super.buildSubscribeMessage();
+            msg.operation = CommandMessage.MULTI_SUBSCRIBE_OPERATION;
+
+            var subs:Object = getCurrentSubscriptions();
+            var toAdd:Array = [];
+            var toRemove:Array = [];
+
+            for (var s:String in subs)
+            {
+                if (_currentSubscriptions[s] == null)
+                    toAdd.push(s);
+            }
+            for (s in _currentSubscriptions)
+            {
+                if (subs[s] == null)
+                    toRemove.push(s);
+            }
+
+            if (toAdd.length > 0)
+                msg.headers[CommandMessage.ADD_SUBSCRIPTIONS] = toAdd;
+            if (toRemove.length > 0)
+                msg.headers[CommandMessage.REMOVE_SUBSCRIPTIONS] = toRemove;
+
+            _currentSubscriptions = subs;
+
+            // Tell the ack handler to mark this guy as unsubscribed after the request
+            if (_currentSubscriptions.length == 0)
+                msg.headers.DSlastUnsub = true;
+
+            return msg;
+        }
+
+        /**
+         * Returns an unsubscribe mesage.
+         *
+         * @param preserveDurable When true, durable JMS subscriptions are
+         * not destroyed, allowing consumers to later resubscribe and
+         * receive missed messages.
+         *
+         * @return The unsubscribe CommandMessage.
+         *
+         *  @langversion 3.0
+         *  @playerversion Flash 9
+         *  @playerversion AIR 1.1
+         *  @productversion BlazeDS 4
+         *  @productversion LCDS 3
+         */
+        override protected function buildUnsubscribeMessage(preserveDurable:Boolean):CommandMessage
+        {
+            var msg:CommandMessage = super.buildUnsubscribeMessage(preserveDurable);
+            msg.operation = CommandMessage.MULTI_SUBSCRIBE_OPERATION;
+
+            var toRemove:Array = [];
+
+            for (var s:String in _currentSubscriptions)
+            {
+                toRemove.push(s);
+            }
+            _currentSubscriptions = {};
+
+            if (toRemove.length > 0)
+                msg.headers[CommandMessage.REMOVE_SUBSCRIPTIONS] = toRemove;
+
+            msg.headers.DSlastUnsub = true;
+
+            return msg;
+        }
+
+        /**
+         * @private
+         */
+        override protected function internalSend(message:IMessage, waitForClientId:Boolean = true):void
+        {
+            // If there is nothing to do with this message, do not send it - instead throw
+            // an exception as this was an attempt to subscribe or unsubscribe with no
+            // subscriptions.
+            if (message.headers[CommandMessage.ADD_SUBSCRIPTIONS] != null ||
+                message.headers[CommandMessage.REMOVE_SUBSCRIPTIONS] != null)
+                super.internalSend(message, waitForClientId);
+            else
+            {
+                if (channelSet == null)
+                    initChannelSet(message);
+                // If we are disconnected and are trying to subscribe, we still need
+                // to send the message to force a reconnect
+                if (channelSet != null && !channelSet.connected &&
+                    message is CommandMessage &&
+                    CommandMessage(message).operation == CommandMessage.MULTI_SUBSCRIBE_OPERATION)
+                    super.internalSend(message, waitForClientId);
+                if (message.headers.DSlastUnsub != null)
+                    setSubscribed(false);
+                    // In this case, if we are not sending the message we can just say we are
+                    // subscribed but only if we are connected
+                else if (channelSet != null && channelSet.connected)
+                    setSubscribed(true);
+            }
+        }
+        /**
+         * @private
+         */
+        override protected function setSubscribed(value:Boolean):void
+        {
+            /*
+            * Whenenver we get marked as being unsubscribed (i.e. the server is
+            * disconnected), we clear out the subscriptions on the server.  The
+            * client will then resubscribe and send all subscriptions on the next
+            * connect.
+            *
+            *  @langversion 3.0
+            *  @playerversion Flash 9
+            *  @playerversion AIR 1.1
+            *  @productversion BlazeDS 4
+            *  @productversion LCDS 3
+            */
+            if (!value)
+                _currentSubscriptions = {};
+            super.setSubscribed(value);
+        }
+
+        //--------------------------------------------------------------------------
+        //
+        // Private Methods
+        //
+        //--------------------------------------------------------------------------
+
+        private function getCurrentSubscriptions():Object
+        {
+            var subs:Object = {};
+
+            for (var i:int = 0; i < subscriptions.length; i++)
+            {
+                var si:SubscriptionInfo = SubscriptionInfo(subscriptions.getItemAt(i));
+                var temp:String = (si.subtopic == null ? "" : si.subtopic) +
+                    CommandMessage.SUBTOPIC_SEPARATOR +
+                    (si.selector == null ? "" : si.selector);
+                // Add maxFrequency as another token.
+                if (si.maxFrequency > 0)
+                    temp += CommandMessage.SUBTOPIC_SEPARATOR + si.maxFrequency;
+
+                subs[temp] = true;
+            }
+            return subs;
+        }
+
+        private function subscriptionsChangeHandler(event:CollectionEvent):void
+        {
+            // process the changes on the next frame to be sure we are done with
+            // all subscriptions.  If we get a change event after we've subscribed
+            // but before we've gotten the ack, _shouldBeSubscribed is true but
+            // subscribed is only set when we have acked.
+            if ((_shouldBeSubscribed || subscribed) && _subchangeTimer == null)
+            {
+                _subchangeTimer = new Timer(0, 1);
+                _subchangeTimer.addEventListener(TimerEvent.TIMER, doResubscribe);
+                _subchangeTimer.start();
+            }
+        }
+
+        private function doResubscribe(event:TimerEvent):void
+        {
+            _subchangeTimer.removeEventListener(TimerEvent.TIMER, doResubscribe);
+            _subchangeTimer = null;
+
+            // If the Consumer is not connected yet, the subscribe message will be queued.
+            internalSend(buildSubscribeMessage());
+        }
+
+
     }

-    /**
-     * Provide a new subscriptions array collection.  This should be an ArrayCollection
-     * containing SubscriptionInfo instances which define message topics and selectors
-     * you want received by this consumer.
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 9
-     *  @playerversion AIR 1.1
-     *  @productversion BlazeDS 4
-     *  @productversion LCDS 3
-     */
-    public function set subscriptions(value:ArrayCollection):void
-    {
-        if (_subscriptions !== value)
-        {
-            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "subscriptions", _subscriptions, value);
-
-            if (subscribed)
-            {
-                unsubscribe();
-                _shouldBeSubscribed = true;
-            }
-
-            if (_subscriptions != null)
-                _subscriptions.removeEventListener(CollectionEvent.COLLECTION_CHANGE, subscriptionsChangeHandler);
-
-            _subscriptions = value;
-
-            if (_subscriptions != null)
-                _subscriptions.addEventListener(CollectionEvent.COLLECTION_CHANGE, subscriptionsChangeHandler);
-
-            // Update an existing subscription to use the new selector.
-            if (_shouldBeSubscribed)
-                subscribe(clientId);
-
-            dispatchEvent(event);
-        }
-    }
-
-    /**
-     * This is a convenience method for adding a new subscription.  It just creates
-     * a new SubscriptionInfo object and adds it to the subscriptions property.
-     * To call this method, you provide the
-     * subtopic and selector string for the new subscription.  If the subtopic is null,
-     * the subscription applies to messages which do not have a subtopic set in the
-     * producer.  If the selector string is null, all messages sent which match the
-     * subtopic string are received by this consumer.
-     *
-     * @param subtopic The subtopic for the new subscription.
-     *
-     * @param selector The selector for the new subscription.
-     *
-     * @param maxFrequency The maximum number of messages per second the Consumer wants
-     * to receive for the subscription. Note that this value overwrites the Consumer
-     * wide maxFrequency.
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 9
-     *  @playerversion AIR 1.1
-     *  @productversion BlazeDS 4
-     *  @productversion LCDS 3
-     */
-    public function addSubscription(subtopic:String = null, selector:String = null, maxFrequency:uint = 0):void
-    {
-        subscriptions.addItem(new SubscriptionInfo(subtopic, selector, maxFrequency));
-    }
-
-    /**
-     * This method removes the subscription specified by the subtopic
-     * and selector.
-     *
-     * @param subtopic The subtopic for the subscription.
-     *
-     * @param selector The selector for the subscription.
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 9
-     *  @playerversion AIR 1.1
-     *  @productversion BlazeDS 4
-     *  @productversion LCDS 3
-     */
-    public function removeSubscription(subtopic:String = null, selector:String = null):void
-    {
-        var n:int = subscriptions.length;
-        for (var i:int = 0; i < n; ++i)
-        {
-            var si:SubscriptionInfo = SubscriptionInfo(subscriptions.getItemAt(i));
-            if (si.subtopic == subtopic && si.selector == selector)
-            {
-                subscriptions.removeItemAt(i);
-                break;
-            }
-        }
-
-        if (n == subscriptions.length)
-            throw new MessagingError("Attempt to remove a subscription with subtopic: " +
-                subtopic + " and selector: " + selector + " that this consumer does not have");
-    }
-
-    //--------------------------------------------------------------------------
-    //
-    // Protected Methods
-    //
-    //--------------------------------------------------------------------------
-
-    /**
-     * Returns a subscribe message.
-     *
-     * @return The subscribe CommandMessage.
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 9
-     *  @playerversion AIR 1.1
-     *  @productversion BlazeDS 4
-     *  @productversion LCDS 3
-     */
-    override protected function buildSubscribeMessage():CommandMessage
-    {
-        var msg:CommandMessage = super.buildSubscribeMessage();
-        msg.operation = CommandMessage.MULTI_SUBSCRIBE_OPERATION;
-
-        var subs:Object = getCurrentSubscriptions();
-        var toAdd:Array = [];
-        var toRemove:Array = [];
-
-        for (var s:String in subs)
-        {
-            if (_currentSubscriptions[s] == null)
-                toAdd.push(s);
-        }
-        for (s in _currentSubscriptions)
-        {
-            if (subs[s] == null)
-                toRemove.push(s);
-        }
-
-        if (toAdd.length > 0)
-            msg.headers[CommandMessage.ADD_SUBSCRIPTIONS] = toAdd;
-        if (toRemove.length > 0)
-            msg.headers[CommandMessage.REMOVE_SUBSCRIPTIONS] = toRemove;
-
-        _currentSubscriptions = subs;
-
-        // Tell the ack handler to mark this guy as unsubscribed after the request
-        if (_currentSubscriptions.length == 0)
-            msg.headers.DSlastUnsub = true;
-
-        return msg;
-    }
-
-    /**
-     * Returns an unsubscribe mesage.
-     *
-     * @param preserveDurable When true, durable JMS subscriptions are
-     * not destroyed, allowing consumers to later resubscribe and
-     * receive missed messages.
-     *
-     * @return The unsubscribe CommandMessage.
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 9
-     *  @playerversion AIR 1.1
-     *  @productversion BlazeDS 4
-     *  @productversion LCDS 3
-     */
-    override protected function buildUnsubscribeMessage(preserveDurable:Boolean):CommandMessage
-    {
-        var msg:CommandMessage = super.buildUnsubscribeMessage(preserveDurable);
-        msg.operation = CommandMessage.MULTI_SUBSCRIBE_OPERATION;
-
-        var toRemove:Array = [];
-
-        for (var s:String in _currentSubscriptions)
-        {
-            toRemove.push(s);
-        }
-        _currentSubscriptions = {};
-
-        if (toRemove.length > 0)
-            msg.headers[CommandMessage.REMOVE_SUBSCRIPTIONS] = toRemove;
-
-        msg.headers.DSlastUnsub = true;
-
-        return msg;
-    }
-
-    /**
-     * @private
-     */
-    override protected function internalSend(message:IMessage, waitForClientId:Boolean = true):void
-    {
-        // If there is nothing to do with this message, do not send it - instead throw
-        // an exception as this was an attempt to subscribe or unsubscribe with no
-        // subscriptions.
-        if (message.headers[CommandMessage.ADD_SUBSCRIPTIONS] != null ||
-            message.headers[CommandMessage.REMOVE_SUBSCRIPTIONS] != null)
-            super.internalSend(message, waitForClientId);
-        else
-        {
-            if (channelSet == null)
-                initChannelSet(message);
-            // If we are disconnected and are trying to subscribe, we still need
-            // to send the message to force a reconnect
-            if (channelSet != null && !channelSet.connected &&
-                message is CommandMessage &&
-                CommandMessage(message).operation == CommandMessage.MULTI_SUBSCRIBE_OPERATION)
-                super.internalSend(message, waitForClientId);
-            if (message.headers.DSlastUnsub != null)
-                setSubscribed(false);
-            // In this case, if we are not sending the message we can just say we are
-            // subscribed but only if we are connected
-            else if (channelSet != null && channelSet.connected)
-                setSubscribed(true);
-        }
-    }
-    /**
-     * @private
-     */
-    override protected function setSubscribed(value:Boolean):void
-    {
-        /*
-         * Whenenver we get marked as being unsubscribed (i.e. the server is
-         * disconnected), we clear out the subscriptions on the server.  The
-         * client will then resubscribe and send all subscriptions on the next
-         * connect.
-         *
-         *  @langversion 3.0
-         *  @playerversion Flash 9
-         *  @playerversion AIR 1.1
-         *  @productversion BlazeDS 4
-         *  @productversion LCDS 3
-         */
-        if (!value)
-            _currentSubscriptions = {};
-        super.setSubscribed(value);
-    }
-
-    //--------------------------------------------------------------------------
-    //
-    // Private Methods
-    //
-    //--------------------------------------------------------------------------
-
-    private function getCurrentSubscriptions():Object
-    {
-        var subs:Object = {};
-
-        for (var i:int = 0; i < subscriptions.length; i++)
-        {
-            var si:SubscriptionInfo = SubscriptionInfo(subscriptions.getItemAt(i));
-            var temp:String = (si.subtopic == null ? "" : si.subtopic) +
-                                CommandMessage.SUBTOPIC_SEPARATOR +
-                                (si.selector == null ? "" : si.selector);
-            // Add maxFrequency as another token.
-            if (si.maxFrequency > 0)
-                temp += CommandMessage.SUBTOPIC_SEPARATOR + si.maxFrequency;
-
-            subs[temp] = true;
-        }
-        return subs;
-    }
-
-    private function subscriptionsChangeHandler(event:CollectionEvent):void
-    {
-        // process the changes on the next frame to be sure we are done with
-        // all subscriptions.  If we get a change event after we've subscribed
-        // but before we've gotten the ack, _shouldBeSubscribed is true but
-        // subscribed is only set when we have acked.
-        if ((_shouldBeSubscribed || subscribed) && _subchangeTimer == null)
-        {
-            _subchangeTimer = new Timer(0, 1);
-            _subchangeTimer.addEventListener(TimerEvent.TIMER, doResubscribe);
-            _subchangeTimer.start();
-        }
-    }
-
-    private function doResubscribe(event:TimerEvent):void
-    {
-        _subchangeTimer.removeEventListener(TimerEvent.TIMER, doResubscribe);
-        _subchangeTimer = null;
-
-        if (subscribed)
-        {
-            internalSend(buildSubscribeMessage());
-        }
-    }
-
-
-}
-
-}
+}


Transferred from the Adobe Open Source Subversion Repository

Revision: 12850
Author:   jimurphy@adobe.com
Date:     2009-12-11T14:57:14.623098Z

Log Message:
-----------
add 6 new DMV projects to the SDK:
automation
automation_air
automation_dmv
automation_flashflexkit
automation_spark
datavisualization

These projects are setup to build in an ant main call.  There are currently several warnings in the datavisualization project that will be cleaned up.  No checkintests exist for these projects as of yet.

I also modified the exisitng projects build files for easier management of the localization targets, bundle and fat-swc. If the projects that I updated:airframework,airspark,framework,playerglobal,rpc,and spark.  All the new projects have been implemented this same way.

QE notes: DMV folks should run through their tests
Doc notes: probably
Bugs: nope
Reviewer:
Tests run: ran the following targets: compile,checkintests,other.locales and doc
Is noteworthy for integration: no

Modified Paths:
--------------
1404 paths were modified

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1251213 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/automation/src/mx/automation/codec/ArrayPropertyCodec.as
+++ frameworks/projects/automation/src/mx/automation/codec/ArrayPropertyCodec.as
@@ -0,0 +1,169 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  ADOBE SYSTEMS INCORPORATED
+//  Copyright 2009 Adobe Systems Incorporated
+//  All Rights Reserved.
+//
+//  NOTICE: Adobe permits you to use, modify, and distribute this file
+//  in accordance with the terms of the license agreement accompanying it.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.automation.codec
+{
+
+	import mx.automation.Automation;
+	import mx.automation.qtp.QTPPropertyDescriptor;
+	import mx.automation.qtp.IQTPPropertyDescriptor;
+	import mx.automation.IAutomationManager;
+	import mx.automation.IAutomationObject;
+
+	/**
+	 * translates between internal Flex array and automation-friendly version
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	public class ArrayPropertyCodec extends DefaultPropertyCodec
+	{
+		private var arrayTypeCodec:IAutomationPropertyCodec;
+
+		/**
+		 * Constructor
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+
+		public function ArrayPropertyCodec(arrayTypeCodec:IAutomationPropertyCodec)
+		{
+			super();
+
+			this.arrayTypeCodec = arrayTypeCodec;
+		}
+
+		private function converIntVectorToArray(vectorObj:Vector.<int> ):Array
+		{
+			var arrayObj:Array = new Array();
+			var count:int = vectorObj.length;
+
+			for (var i:int = 0; i<count; i++)
+			{
+				arrayObj.push(vectorObj[i]);
+			}
+			return arrayObj;
+		}
+
+		private function converObjVectorToArray(vectorObj:Vector.<Object> ):Array
+		{
+			var arrayObj:Array = new Array();
+			var count:int = vectorObj.length;
+
+			for (var i:int = 0; i<count; i++)
+			{
+				arrayObj.push(vectorObj[i]);
+			}
+			return arrayObj;
+		}
+
+		override public function encode(automationManager:IAutomationManager,
+										obj:Object,
+										pd:IQTPPropertyDescriptor,
+										relativeParent:IAutomationObject):Object
+		{
+			var result:Array = [];
+			var value:Object = getMemberFromObject(automationManager, obj, pd);
+
+
+			if (value != null && (!(value is Array)))
+			{
+				if(value is Vector.<int>)
+					value = converIntVectorToArray(value as  Vector.<int>) ;
+				else if (value is Vector.<Object>)
+					value = converObjVectorToArray(value as  Vector.<Object>);
+			}
+
+
+			if (value != null && value is Array)
+			{
+				var arrayObj:Array = value as Array;
+				var n:int = arrayObj.length;
+
+				for (var i:int = 0; i <n ; ++i)
+				{
+					var arrayPropertyDescriptor:QTPPropertyDescriptor=
+						new QTPPropertyDescriptor(String(i),
+							pd.forDescription,
+							pd.forVerification,
+							"string",
+							pd.codecName);
+					var arrayItem:String = String(arrayTypeCodec.encode(automationManager,
+						arrayObj,
+						arrayPropertyDescriptor,
+						relativeParent));
+
+					arrayItem = arrayItem.replace(/;/g, ";");
+
+					result.push(arrayItem);
+				}
+			}
+
+
+
+			//Arrays are always returned as strings
+			return result.join(";");
+		}
+
+		override public function decode(automationManager:IAutomationManager,
+										obj:Object,
+										value:Object,
+										pd:IQTPPropertyDescriptor,
+										relativeParent:IAutomationObject):void
+		{
+			if (value != null && value.length != 0)
+			{
+				//since we override obj when calling the sub-codec
+				//make sure relativeParent is set
+				var delegate:IAutomationObject = obj as IAutomationObject;
+				if (relativeParent == null)
+					relativeParent = delegate;
+
+				var arrayObj:Array = [];
+				var arrayString:Array = String(value).split(";");
+
+				//note if the array members have extra spaces this code
+				//won't work, we would need to trim the members, but that could
+				//be a bad thing if the spaces are significant, so if we need to
+				//do this, then we should also entity encode spaces (which would be ugly)
+
+				var n:int = arrayString.length;
+				for (var i:int = 0; i < n; ++i)
+				{
+					arrayString[i] = arrayString[i].replace(/;/g, ";");
+					var arrayPropertyDescriptor:QTPPropertyDescriptor=
+						new QTPPropertyDescriptor(String(i),
+							pd.forDescription,
+							pd.forVerification,
+							"string",
+							pd.codecName);
+
+					arrayTypeCodec.decode(automationManager,
+						arrayString,
+						arrayString[i],
+						arrayPropertyDescriptor,
+						relativeParent);
+
+					arrayObj.push(arrayString[i]);
+				}
+
+				obj[pd.name] = arrayObj;
+
+			}
+		}
+	}
+
+}


Transferred from the Adobe Open Source Subversion Repository

Revision: 7836
Author:   chaase@adobe.com
Date:     2009-06-15T14:37:21.379918Z

Log Message:
-----------
PARB changes for effects. This includes various property renames, a couple of class renames, moving 3 classes to a sub-package, and various doc cleanups. This also includes changing a handful of Array properties to typed Vectors.

QE: This breaks Mustella due to the renames
Doc: Docs will need to be updated to reflect the changes as well
Bugs: None
Reviewer: Jason
Tests: checkintests, Thermo's transitionbug test

Modified Paths:
--------------
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/utils/BitmapUtil.as</path>
<path kind="file" copyfrom-path="/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/MotionPath.as" copyfrom-rev="7748" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/animation/MotionPath.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/easing/Power.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/easing/EasingFraction.as</path>
<path kind="file" action="D">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/KeyFrame.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/interpolation/RGBInterpolator.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/interpolation/HSBInterpolator.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/CallAction.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/AnimateColor.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/Animate.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/supportClasses/FadeInstance.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/animation/RepeatBehavior.as</path>
<path kind="file" copyfrom-path="/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/AnimateShaderTransition.as" copyfrom-rev="7748" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/AnimateTransitionShader.as</path>
<path kind="file" action="D">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/AnimateShaderTransition.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/spark-manifest.xml</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/components/supportClasses/Slider.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/interpolation/IInterpolator.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/interpolation/NumberInterpolator.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/components/supportClasses/ScrollBar.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/Rotate3D.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/Scale.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/supportClasses/CallActionInstance.as</path>
<path kind="file" action="D">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/SimpleMotionPath.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/supportClasses/AnimateColorInstance.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/supportClasses/AnimateInstance.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/animation/Animation.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/Rotate.as</path>
<path kind="file" action="D">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/supportClasses/AnimateShaderTransitionInstance.as</path>
<path kind="file" copyfrom-path="/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/supportClasses/AnimateShaderTransitionInstance.as" copyfrom-rev="7748" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/supportClasses/AnimateTransitionShaderInstance.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/Wipe.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/easing/Sine.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/Move.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/interpolation/ArrayInterpolator.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/CrossFade.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/AnimateTransform.as</path>
<path kind="file" copyfrom-path="/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/SimpleMotionPath.as" copyfrom-rev="7748" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/animation/SimpleMotionPath.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/utils/HSBColor.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/animation/IAnimationTarget.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/easing/Linear.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/supportClasses/ResizeInstance.as</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/animation/Keyframe.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/CrossFade.pbk</path>
<path kind="file" action="D">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/MotionPath.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/supportClasses/WipeInstance.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/effects/supportClasses/AnimateTransformInstance.as</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1284110 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/spark/src/spark/effects/interpolation/HSBInterpolator.as
+++ frameworks/projects/spark/src/spark/effects/interpolation/HSBInterpolator.as
@@ -65,9 +65,9 @@
     {
         super();
         if (startRGB != StyleManager.NOT_A_COLOR)
-            startHSB = HSBColor.RGBtoHSB(startRGB);
+            startHSB = HSBColor.convertRGBtoHSB(startRGB);
         if (endRGB != StyleManager.NOT_A_COLOR)
-            endHSB = HSBColor.RGBtoHSB(endRGB);
+            endHSB = HSBColor.convertRGBtoHSB(endRGB);
     }

     /**
@@ -90,20 +90,6 @@
         if (!theInstance)
             theInstance = new HSBInterpolator();
         return theInstance;
-    }
-
-    /**
-     *  The uint type, which is the type of
-     *  object interpolated by the HSBInterpolator class,
-     *
-     *  @langversion 3.0
-     *  @playerversion Flash 10
-     *  @playerversion AIR 1.5
-     *  @productversion Flex 4
-     */
-    public function get interpolatedType():Class
-    {
-        return uint;
     }

     /**
@@ -133,9 +119,9 @@
         // If we have not converted start/end values at construction time,
         // do so now
         if (!start)
-            start = HSBColor.RGBtoHSB(uint(startValue));
+            start = HSBColor.convertRGBtoHSB(uint(startValue));
         if (!end)
-            end = HSBColor.RGBtoHSB(uint(endValue));
+            end = HSBColor.convertRGBtoHSB(uint(endValue));
         var startH:Number = start.hue;
         var endH:Number = end.hue;
         var deltaH:Number;
@@ -166,7 +152,7 @@
             hue = startH;
         else
             hue = startH + deltaH * fraction;
-        var rgb:uint = HSBColor.HSBtoRGB(hue, saturation, brightness);
+        var rgb:uint = HSBColor.convertHSBtoRGB(hue, saturation, brightness);
         return rgb;
     }

@@ -178,8 +164,8 @@
     private function combine(baseValue:uint, deltaValue:uint,
         increment:Boolean):Object
     {
-        var start:HSBColor = HSBColor.RGBtoHSB(baseValue);
-        var delta:HSBColor = HSBColor.RGBtoHSB(deltaValue);
+        var start:HSBColor = HSBColor.convertRGBtoHSB(baseValue);
+        var delta:HSBColor = HSBColor.convertRGBtoHSB(deltaValue);
         var newH:Number, newS:Number, newB:Number;
         if (increment)
         {
@@ -193,7 +179,7 @@
             newS = Math.max(start.saturation - delta.saturation, 0);
             newB = Math.max(start.brightness - delta.brightness, 0);
         }
-        return HSBColor.HSBtoRGB(newH, newS, newB);
+        return HSBColor.convertHSBtoRGB(newH, newS, newB);
     }

     /**


Change 20081112-maxcarlson-j by maxcarlson@Bank.local on 2008-11-12 15:39:33 PST
    in /Users/maxcarlson/openlaszlo/trunk-clean
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: Fix sendInFrontOf() in swf9

Bugs Fixed: LPP-7321 - sendInFrontOf() works once well, and second wrong, third well, and so on...

Technical Reviewer: hminsky
QA Reviewer: promanik

Details: Test to make sure the sprite is behind the current one before bringing to the front.

Tests: See LPP-7321.

git-svn-id: d62bde4b5aa582fdf07c8d403e53e0399a7ed285@11752 fa20e4f9-1d0a-0410-b5f3-dc9c16b8b17c

--- WEB-INF/lps/lfc/kernel/swf9/LzSprite.as
+++ WEB-INF/lps/lfc/kernel/swf9/LzSprite.as
@@ -1207,7 +1207,8 @@
       public function sendInFrontOf( sprite ){
           if (!this.isroot) {
               var i = parent.getChildIndex(sprite);
-              parent.setChildIndex(this, i);
+              var j = parent.getChildIndex(this);
+              if (j < i) parent.setChildIndex(this, i);
           }
       }


Removed (again) nested "for each (var geom:* in geoms)" loop which was
the same loop as the outer "for (var iGeom..." loop.

Change-Id: Ieef3c860f39a38a6308691edc0ddc7c251aeae1f

--- WeaveUI/src/weave/utils/SpatialIndex.as
+++ WeaveUI/src/weave/utils/SpatialIndex.as
@@ -485,133 +485,66 @@

 					for (var iGeom:int = 0; iGeom < geoms.length; ++iGeom)
 					{
-						for each (var geom:Object in geoms)
+						var geom:Object = geoms[iGeom];
+						xDistance = geom.bounds.getXCenter() - xQueryCenter;
+						yDistance = geom.bounds.getYCenter() - yQueryCenter;
+						if (!isNaN(xPrecision) && xPrecision != 0)
+							xDistance = int(xDistance / xPrecision);
+						if (!isNaN(yPrecision) && yPrecision != 0)
+							yDistance = int(yDistance / yPrecision);
+						var geomDistance:Number = xDistance * xDistance + yDistance * yDistance;
+
+						if (geom is GeneralizedGeometry)
 						{
-							xDistance = geom.bounds.getXCenter() - xQueryCenter;
-							yDistance = geom.bounds.getYCenter() - yQueryCenter;
-							if (!isNaN(xPrecision) && xPrecision != 0)
-								xDistance = int(xDistance / xPrecision);
-							if (!isNaN(yPrecision) && yPrecision != 0)
-								yDistance = int(yDistance / yPrecision);
-							var geomDistance:Number = xDistance * xDistance + yDistance * yDistance;
+							var genGeom:GeneralizedGeometry = geom as GeneralizedGeometry;
+							var genGeomIsPoly:Boolean = genGeom.isPolygon();
+							var genGeomIsLine:Boolean = genGeom.isLine();
+							var genGeomIsPoint:Boolean = genGeom.isPoint();
+							var genGeomBounds:IBounds2D = genGeom.bounds;

-							if (geom is GeneralizedGeometry)
-							{
-								var genGeom:GeneralizedGeometry = geom as GeneralizedGeometry;
-								var genGeomIsPoly:Boolean = genGeom.isPolygon();
-								var genGeomIsLine:Boolean = genGeom.isLine();
-								var genGeomIsPoint:Boolean = genGeom.isPoint();
-								var genGeomBounds:IBounds2D = genGeom.bounds;
+							var simplifiedGeom:Vector.<Vector.<BLGNode>> = (geom as GeneralizedGeometry).getSimplifiedGeometry(importance, bounds);
+
+							for (var i:int = 0; i < simplifiedGeom.length; ++i)
+							{
+								var part:Vector.<BLGNode> = simplifiedGeom[i];

-								var simplifiedGeom:Vector.<Vector.<BLGNode>> = (geom as GeneralizedGeometry).getSimplifiedGeometry(importance, bounds);
-
-								for (var i:int = 0; i < simplifiedGeom.length; ++i)
-								{
-									var part:Vector.<BLGNode> = simplifiedGeom[i];
-
-									if (genGeomIsPoly)
-									{
-										// if the polygon contains the point, this key is probably what we want
-										if (ComputationalGeometryUtils.polygonOverlapsPoint(part, xQueryCenter, yQueryCenter))
-										{
-											distanceSq = 0;
-											overlapsQueryCenter = true;
-										}
-										else
-										{
-											distanceSq = geomDistance;
-											overlapsQueryCenter = false;
-										}
-									}
-									else if (genGeomIsLine)
-									{
-										distanceSq = getMinimumUnscaledDistanceFromPolyLine(part, xQueryCenter, yQueryCenter);
-
-										if (distanceSq <= Number.MIN_VALUE)
-											overlapsQueryCenter = true;
-										else
-											overlapsQueryCenter = false;
-									}
-									else if (genGeomIsPoint)
-									{
-										distanceSq = getMinimumUnscaledDistanceFromPolyPoint(part, xQueryCenter, yQueryCenter);
-										if (distanceSq <= Number.MIN_VALUE)
-											overlapsQueryCenter = true;
-										else
-											overlapsQueryCenter = false;
-									}
-
-									// Consider all keys until we have found one that overlaps the query center.
-									// Consider lines and points because although they may not overlap, it's very likely that no points or lines
-									// will overlap. If we consider all of them, we can still find the closest.
-									// After that, only consider keys that overlap query center.
-									if (!foundQueryCenterOverlap || overlapsQueryCenter || geom.isLine() || geom.isPoint())
-									{
-										// if this is the first record that overlaps the query center, reset the list of keys
-										if (!foundQueryCenterOverlap && overlapsQueryCenter)
-										{
-											resultCount = 0;
-											closestDistanceSq = Infinity;
-											foundQueryCenterOverlap = true;
-										}
-										// if this distance is closer than any previous distance, clear all previous keys
-										if (distanceSq < closestDistanceSq)
-										{
-											// clear previous result and update closest distance
-											resultCount = 0;
-											closestDistanceSq = distanceSq;
-										}
-										// add keys to the result if they are the closest so far
-										if (distanceSq == closestDistanceSq && (resultCount == 0 || result[resultCount - 1] != key))
-											result[resultCount++] = key;
-									}
-								}
-							}
-							else
-							{
-								var simpleGeom:ISimpleGeometry = geom as ISimpleGeometry;
-								var simpleGeomIsPoly:Boolean = simpleGeom.isPolygon();
-								var simpleGeomIsLine:Boolean = simpleGeom.isLine();
-								var simpleGeomIsPoint:Boolean = simpleGeom.isPoint();
-								var vertices:Array = simpleGeom.getVertices();
-
-								// calculate the distanceSq and overlapsQueryCenter
-								if (simpleGeomIsPoly)
-								{
-									if (ComputationalGeometryUtils.polygonOverlapsPoint(
-										vertices, xQueryCenter, yQueryCenter))
+								if (genGeomIsPoly)
+								{
+									// if the polygon contains the point, this key is probably what we want
+									if (ComputationalGeometryUtils.polygonOverlapsPoint(part, xQueryCenter, yQueryCenter))
 									{
 										distanceSq = 0;
 										overlapsQueryCenter = true;
 									}
-									else
+									else
 									{
 										distanceSq = geomDistance;
 										overlapsQueryCenter = false;
 									}
 								}
-								else if (simpleGeomIsLine)
-								{
-									distanceSq = getMinimumUnscaledDistanceFromPolyLine(vertices, xQueryCenter, yQueryCenter);
+								else if (genGeomIsLine)
+								{
+									distanceSq = getMinimumUnscaledDistanceFromPolyLine(part, xQueryCenter, yQueryCenter);
+
 									if (distanceSq <= Number.MIN_VALUE)
 										overlapsQueryCenter = true;
 									else
 										overlapsQueryCenter = false;
 								}
-								else if (simpleGeomIsPoint)
-								{
-									distanceSq = getMinimumUnscaledDistanceFromPolyPoint(vertices, xQueryCenter, yQueryCenter);
+								else if (genGeomIsPoint)
+								{
+									distanceSq = getMinimumUnscaledDistanceFromPolyPoint(part, xQueryCenter, yQueryCenter);
 									if (distanceSq <= Number.MIN_VALUE)
 										overlapsQueryCenter = true;
 									else
-										overlapsQueryCenter = false;
+										overlapsQueryCenter = false;
 								}

 								// Consider all keys until we have found one that overlaps the query center.
 								// Consider lines and points because although they may not overlap, it's very likely that no points or lines
 								// will overlap. If we consider all of them, we can still find the closest.
 								// After that, only consider keys that overlap query center.
-								if (!foundQueryCenterOverlap || overlapsQueryCenter || simpleGeom.isLine() || simpleGeom.isPoint())
+								if (!foundQueryCenterOverlap || overlapsQueryCenter || geom.isLine() || geom.isPoint())
 								{
 									// if this is the first record that overlaps the query center, reset the list of keys
 									if (!foundQueryCenterOverlap && overlapsQueryCenter)
@@ -631,6 +564,71 @@
 									if (distanceSq == closestDistanceSq && (resultCount == 0 || result[resultCount - 1] != key))
 										result[resultCount++] = key;
 								}
+							}
+						}
+						else
+						{
+							var simpleGeom:ISimpleGeometry = geom as ISimpleGeometry;
+							var simpleGeomIsPoly:Boolean = simpleGeom.isPolygon();
+							var simpleGeomIsLine:Boolean = simpleGeom.isLine();
+							var simpleGeomIsPoint:Boolean = simpleGeom.isPoint();
+							var vertices:Array = simpleGeom.getVertices();
+
+							// calculate the distanceSq and overlapsQueryCenter
+							if (simpleGeomIsPoly)
+							{
+								if (ComputationalGeometryUtils.polygonOverlapsPoint(
+									vertices, xQueryCenter, yQueryCenter))
+								{
+									distanceSq = 0;
+									overlapsQueryCenter = true;
+								}
+								else
+								{
+									distanceSq = geomDistance;
+									overlapsQueryCenter = false;
+								}
+							}
+							else if (simpleGeomIsLine)
+							{
+								distanceSq = getMinimumUnscaledDistanceFromPolyLine(vertices, xQueryCenter, yQueryCenter);
+								if (distanceSq <= Number.MIN_VALUE)
+									overlapsQueryCenter = true;
+								else
+									overlapsQueryCenter = false;
+							}
+							else if (simpleGeomIsPoint)
+							{
+								distanceSq = getMinimumUnscaledDistanceFromPolyPoint(vertices, xQueryCenter, yQueryCenter);
+								if (distanceSq <= Number.MIN_VALUE)
+									overlapsQueryCenter = true;
+								else
+									overlapsQueryCenter = false;
+							}
+
+							// Consider all keys until we have found one that overlaps the query center.
+							// Consider lines and points because although they may not overlap, it's very likely that no points or lines
+							// will overlap. If we consider all of them, we can still find the closest.
+							// After that, only consider keys that overlap query center.
+							if (!foundQueryCenterOverlap || overlapsQueryCenter || simpleGeom.isLine() || simpleGeom.isPoint())
+							{
+								// if this is the first record that overlaps the query center, reset the list of keys
+								if (!foundQueryCenterOverlap && overlapsQueryCenter)
+								{
+									resultCount = 0;
+									closestDistanceSq = Infinity;
+									foundQueryCenterOverlap = true;
+								}
+								// if this distance is closer than any previous distance, clear all previous keys
+								if (distanceSq < closestDistanceSq)
+								{
+									// clear previous result and update closest distance
+									resultCount = 0;
+									closestDistanceSq = distanceSq;
+								}
+								// add keys to the result if they are the closest so far
+								if (distanceSq == closestDistanceSq && (resultCount == 0 || result[resultCount - 1] != key))
+									result[resultCount++] = key;
 							}
 						}
 					} // geomLoop


Transferred from the Adobe Open Source Subversion Repository

Revision: 23246
Author:   cframpto@adobe.com
Date:     2011-12-20T17:40:08.069454Z

Log Message:
-----------
Rollback 23243.  If comment followed header it was stripped as well.

Modified Paths:
--------------
2361 paths were modified

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1258569 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/framework/src/mx/binding/XMLWatcher.as
+++ frameworks/projects/framework/src/mx/binding/XMLWatcher.as
@@ -1,3 +1,13 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  ADOBE SYSTEMS INCORPORATED
+//  Copyright 2005-2007 Adobe Systems Incorporated
+//  All Rights Reserved.
+//
+//  NOTICE: Adobe permits you to use, modify, and distribute this file
+//  in accordance with the terms of the license agreement accompanying it.
+//
+////////////////////////////////////////////////////////////////////////////////

 package mx.binding
 {


Transferred from the Adobe Open Source Subversion Repository

Revision: 16773
Author:   aharui@adobe.com
Date:     2010-07-01T17:13:49.870714Z

Log Message:
-----------
If the URI is not decodable, gamble that it is still valid.

QE notes: none
Doc notes: none
Bugs: SDK-26294
Reviewer: Corey
Tests run: checkintests mustella/components/Image
Is noteworthy for integration:

Modified Paths:
--------------
/private/flex/sdk/branches/hero_private/frameworks/projects/framework/src/mx/controls/SWFLoader.as

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1258908 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/framework/src/mx/controls/SWFLoader.as
+++ frameworks/projects/framework/src/mx/controls/SWFLoader.as
@@ -1942,7 +1942,15 @@
      **/
     private function OSToPlayerURI(url:String, local:Boolean):String
     {
-        url = decodeURI(url);
+		try
+		{
+        	url = decodeURI(url);
+		}
+		catch (e:Error)
+		{
+			// malformed url, but some are legal on the file system
+			return url;
+		}

         if (local && flash.system.Capabilities.playerType == "ActiveX")
             return url;


Transferred from the Adobe Open Source Subversion Repository

Revision: 8595
Author:   mhorn@adobe.com
Date:     2009-07-15T20:04:01.318991Z

Log Message:
-----------
asdoc bug fix

Modified Paths:
--------------
/flex/sdk/trunk/frameworks/projects/framework/src/mx/styles/CSSSelector.as

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1262488 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/framework/src/mx/styles/CSSSelector.as
+++ frameworks/projects/framework/src/mx/styles/CSSSelector.as
@@ -35,9 +35,10 @@
      *  Constructor.
      *
      *  @param subject The plain representation of this selector without
-     *  conditions or ancestors.
-     *
-     *  @param conditions  An optional Array of type CSSCondition that is used to match a
+     *  conditions or ancestors. This is typically a fully-qualified class name; for example,
+     *  "spark.components.Button".
+     *
+     *  @param conditions  An optional Array of objects of type CSSCondition that is used to match a
      *  subset of component instances. Currently only a single or a pair of
      *  conditions are supported.
      *


Transferred from the Adobe Open Source Subversion Repository

Revision: 23247
Author:   cframpto@adobe.com
Date:     2011-12-20T19:21:13.134833Z

Log Message:
-----------
Remove ADOBE SYSTEMS license and replace with Apache license in headers - frameworks.  A 2nd pass will be needed to get the files not handled up by the scripts.

Modified Paths:
--------------
4959 paths were modified

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1278470 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/spark/src/spark/components/CheckBox.as
+++ frameworks/projects/spark/src/spark/components/CheckBox.as
@@ -1,11 +1,19 @@
 ////////////////////////////////////////////////////////////////////////////////
 //
-//  ADOBE SYSTEMS INCORPORATED
-//  Copyright 2008 Adobe Systems Incorporated
-//  All Rights Reserved.
-//
-//  NOTICE: Adobe permits you to use, modify, and distribute this file
-//  in accordance with the terms of the license agreement accompanying it.
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
 //
 ////////////////////////////////////////////////////////////////////////////////


Transferred from the Adobe Open Source Subversion Repository

Revision: 18548
Author:   rfrishbe@adobe.com
Date:     2010-11-11T22:05:22.380108Z

Log Message:
-----------
Just fixing up some ASDocs around touchDelay.

QE notes:
Doc notes:
Bugs: -
Reviewer:
Tests run:
Is noteworthy for integration: No

Modified Paths:
--------------
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/Scroller.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/SkinnableContainer.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/List.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/supportClasses/ButtonBase.as</path>
<path kind="file" action="M">/private/flex/sdk/branches/hero_private/frameworks/projects/spark/src/spark/components/supportClasses/GroupBase.as</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1280492 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/spark/src/spark/components/Scroller.as
+++ frameworks/projects/spark/src/spark/components/Scroller.as
@@ -166,20 +166,10 @@
 [Style(name="symbolColor", type="uint", format="Color", inherit="yes", theme="spark, mobile")]

 /**
- *  When in touch interaction mode, the number of milliseconds to wait before showing the
- *  component in a visually down state.
- *
- *
The reason for this delay is because when a user initiates a scroll gesture, we don't want
- *  components to flicker as they touch the screen.  By having a reasonable delay, we make
- *  sure that the user still gets feedback when they press down on a component, but that the
- *  feedback doesn't come too quickly that it gets displayed during a scroll gesture
- *  operation.

- *
- *
If the mobile theme is applied, the default value for this style is 100 ms for
- *  components inside of a Scroller and 0 ms for components outside of a Scroller.

+ *  @copy spark.components.supportClasses.GroupBase#style:touchDelay
  *
  *  @langversion 3.0
- *  @playerversion Flash 10
+ *  @playerversion Flash 10.1
  *  @playerversion AIR 2.5
  *  @productversion Flex 4.5
  */