View Javadoc

1   /***
2    * Cecilia ADL Compiler
3    * Copyright (C) 2008 STMicroelectronics
4    *
5    * This library is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU Lesser General Public
7    * License as published by the Free Software Foundation; either
8    * version 2 of the License, or (at your option) any later version.
9    *
10   * This library is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   * Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public
16   * License along with this library; if not, write to the Free Software
17   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   *
19   * Contact: fractal@objectweb.org
20   *
21   * Author: Matthieu Leclercq
22   */
23  
24  package org.objectweb.fractal.cecilia.adl.components;
25  
26  import java.util.ArrayList;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.SortedMap;
30  import java.util.TreeMap;
31  
32  import org.objectweb.fractal.adl.ADLException;
33  import org.objectweb.fractal.adl.AbstractLoader;
34  import org.objectweb.fractal.adl.Definition;
35  import org.objectweb.fractal.adl.components.Component;
36  import org.objectweb.fractal.adl.components.ComponentContainer;
37  
38  /**
39   * Reorder {@link Component} nodes according to their
40   * {@link ExtendedComponent#getStartOrder() startOrder} attributes. This
41   * supposes that components will be actually started at runtime in the same
42   * order as they are defined in the {@link ComponentContainer}.
43   */
44  public class StartOrderLoader extends AbstractLoader {
45  
46    public Definition load(final String name, final Map<Object, Object> context)
47        throws ADLException {
48      final Definition d = clientLoader.load(name, context);
49      if (d instanceof ComponentContainer) checkOrder((ComponentContainer) d);
50  
51      return d;
52    }
53  
54    protected void checkOrder(final ComponentContainer container)
55        throws ADLException {
56      // In most cases, no component node will contain a 'startOrder' attribute.
57      // In other words, most of the time, this method has nothing to do. So avoid
58      // the creation of data structure unless it is actually necessary.
59      SortedMap<Integer, List<Component>> sortedComps = null;
60      final Component[] components = container.getComponents();
61      for (final Component component : components) {
62        checkOrder(component);
63        final int startOrder;
64        try {
65          startOrder = ComponentHelper.getStartOrder(component);
66        } catch (final NumberFormatException e) {
67          throw new ADLException(ComponentErrors.INVALID_START_ORDER, component);
68        }
69        if (startOrder < 0) {
70          throw new ADLException(ComponentErrors.INVALID_NEGATIVE_START_ORDER,
71              component);
72        } else if (startOrder != Integer.MAX_VALUE) {
73          if (sortedComps == null)
74            sortedComps = new TreeMap<Integer, List<Component>>();
75          List<Component> comps = sortedComps.get(startOrder);
76          if (comps == null) {
77            comps = new ArrayList<Component>();
78            sortedComps.put(startOrder, comps);
79          }
80          comps.add(component);
81        }
82      }
83  
84      if (sortedComps != null) {
85        // If at least one component node specify a start order,
86        // remove every component nodes from the container and re-add them in the
87        // correct order.
88        final List<Component> unsortedComps = new ArrayList<Component>(
89            components.length - sortedComps.size());
90        for (final Component component : components) {
91          if (ComponentHelper.getStartOrder(component) == Integer.MAX_VALUE)
92            unsortedComps.add(component);
93  
94          container.removeComponent(component);
95        }
96        for (final List<Component> comps : sortedComps.values()) {
97          for (final Component component : comps) {
98            container.addComponent(component);
99          }
100       }
101       for (final Component component : unsortedComps) {
102         container.addComponent(component);
103       }
104     }
105   }
106 }