1/*******************************************************************************
2 * Copyright (c) 2011 Google, Inc.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *    Google, Inc. - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.wb.internal.core.editor.structure.property;
12
13import com.google.common.collect.Lists;
14
15import org.eclipse.wb.internal.core.model.property.Property;
16import org.eclipse.wb.internal.core.model.property.PropertyManager;
17
18import java.util.Iterator;
19import java.util.List;
20
21/**
22 * Helper for computing intersection of {@link Property} arrays.
23 *
24 * @author scheglov_ke
25 * @coverage core.editor.structure
26 */
27public final class PropertyListIntersector {
28  private List<PropertyGroup> m_intersection;
29
30  ////////////////////////////////////////////////////////////////////////////
31  //
32  // Access
33  //
34  ////////////////////////////////////////////////////////////////////////////
35  /**
36   * Updates intersection by intersecting with new given array.
37   */
38  public void intersect(Property[] properties) {
39    if (m_intersection == null) {
40      m_intersection = Lists.newArrayList();
41      for (int i = 0; i < properties.length; i++) {
42        Property property = properties[i];
43        m_intersection.add(new PropertyGroup(property));
44      }
45    } else {
46      for (Iterator<PropertyGroup> I = m_intersection.iterator(); I.hasNext();) {
47        PropertyGroup propertyGroup = I.next();
48        if (!propertyGroup.add(properties)) {
49          I.remove();
50        }
51      }
52    }
53  }
54
55  /**
56   * @return the array of matched composite {@link Property}'s.
57   */
58  public Property[] getProperties() {
59    List<Property> properties = Lists.newArrayList();
60    for (PropertyGroup propertyGroup : m_intersection) {
61      Property compositeProperty = propertyGroup.getCompositeProperty();
62      if (compositeProperty != null) {
63        properties.add(compositeProperty);
64      }
65    }
66    //
67    return properties.toArray(new Property[properties.size()]);
68  }
69
70  ////////////////////////////////////////////////////////////////////////////
71  //
72  // PropertyGroup
73  //
74  ////////////////////////////////////////////////////////////////////////////
75  /**
76   * The group of {@link Property}'s that match.
77   */
78  private static final class PropertyGroup {
79    private final List<Property> m_properties = Lists.newArrayList();
80
81    ////////////////////////////////////////////////////////////////////////////
82    //
83    // Constructor
84    //
85    ////////////////////////////////////////////////////////////////////////////
86    public PropertyGroup(Property property) {
87      m_properties.add(property);
88    }
89
90    ////////////////////////////////////////////////////////////////////////////
91    //
92    // Access
93    //
94    ////////////////////////////////////////////////////////////////////////////
95    /**
96     * @return <code>true</code> if new matched {@link Property} from given array was added.
97     */
98    public boolean add(Property[] properties) {
99      for (Property property : properties) {
100        if (add(property)) {
101          return true;
102        }
103      }
104      // no match
105      return false;
106    }
107
108    /**
109     * @return the composite {@link Property} for this group.
110     */
111    public Property getCompositeProperty() {
112      Property properties[] = m_properties.toArray(new Property[m_properties.size()]);
113      return properties[0].getComposite(properties);
114    }
115
116    ////////////////////////////////////////////////////////////////////////////
117    //
118    // Internal
119    //
120    ////////////////////////////////////////////////////////////////////////////
121    /**
122     * @return <code>true</code> if given {@link Property} matches and was added.
123     */
124    private boolean add(Property property) {
125      Property example = m_properties.get(0);
126      if (example.getClass() == property.getClass()
127          && example.getTitle().equals(property.getTitle())
128          && PropertyManager.getCategory(example) == PropertyManager.getCategory(property)) {
129        m_properties.add(property);
130        return true;
131      }
132      // no match
133      return false;
134    }
135  }
136}
137