001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.vmd.api.codegen;
042:
043: import org.netbeans.modules.vmd.api.model.Debug;
044: import org.netbeans.modules.vmd.api.model.DesignComponent;
045:
046: import java.util.*;
047:
048: /**
049: * @author David Kaspar
050: */
051: public final class InitCodeGenerator {
052:
053: private static final int PRICE_OF_REQUIRED_PARAM = 3;
054: private static final int PRICE_OF_DEFAULT_PARAM = -1;
055:
056: public static void generateInitializationCode(
057: MultiGuardedSection section, DesignComponent component) {
058: Collection<? extends CodeSetterPresenter> presenters = component
059: .getPresenters(CodeSetterPresenter.class);
060: HashMap<String, Parameter> parametersMap = new HashMap<String, Parameter>();
061: ArrayList<Setter> constructors = new ArrayList<Setter>();
062: ArrayList<Setter> setters = new ArrayList<Setter>();
063: HashSet<String> requiredToBeSet = new HashSet<String>();
064:
065: parametersMap.put(Parameter.PARAM_INDEX, Parameter.INDEX);
066:
067: for (CodeSetterPresenter presenter : presenters) {
068: for (Parameter parameter : presenter.getParameters()) {
069: String parameterName = parameter.getParameterName();
070: assert parameterName != null;
071: Parameter currentParameter = parametersMap
072: .get(parameterName);
073: if (currentParameter != null) {
074: int currentPriority = currentParameter
075: .getParameterPriority();
076: int priority = parameter.getParameterPriority();
077: if (currentPriority >= priority) {
078: if (currentPriority == priority)
079: Debug.warning("Duplicate parameter found",
080: component, parameterName); // NOI18N
081: continue;
082: }
083: requiredToBeSet.remove(parameterName);
084: }
085: parametersMap.put(parameterName, parameter);
086: if (parameter.isRequiredToBeSet(component))
087: requiredToBeSet.add(parameterName);
088: }
089: for (Setter setter : presenter.getSetters()) {
090: if (!setter.getVersionable().isAvailable(
091: component.getDocument()))
092: continue;
093: if (setter.isConstructor()) {
094: if (component.getType().equals(
095: setter.getConstructorRelatedTypeID()))
096: constructors.add(setter);
097: } else
098: setters.add(setter);
099: }
100: }
101:
102: HashSet<String> unusedParameters = new HashSet<String>(
103: parametersMap.keySet());
104:
105: for (Setter setter : constructors) {
106: for (String parameter : setter.getParameters()) {
107: unusedParameters.remove(parameter);
108: if (!parametersMap.containsKey(parameter))
109: Debug.warning("No setter parameter found",
110: component, setter.getSetterName(),
111: parameter); // NOI18N
112: }
113: }
114: for (Setter setter : setters) {
115: for (String parameter : setter.getParameters()) {
116: unusedParameters.remove(parameter);
117: if (!parametersMap.containsKey(parameter))
118: Debug.warning("No setter parameter found",
119: component, setter.getSetterName(),
120: parameter); // NOI18N
121: }
122: }
123: unusedParameters.remove(Parameter.PARAM_INDEX);
124: if (!unusedParameters.isEmpty())
125: Debug.warning("Unused parameters", component,
126: unusedParameters); // NOI18N
127:
128: // TODO - static instance of SetterComparator
129: Collections.sort(constructors, new SetterComparator());
130:
131: Setter setter = findSetter(constructors, requiredToBeSet, false);
132: if (setter == null) {
133: Debug.warning("No constructor found", component); // NOI18N
134: } else {
135: do {
136: for (String parameter : setter.getParameters())
137: requiredToBeSet.remove(parameter);
138: setter.generateSetterCode(section, component,
139: parametersMap);
140: setter = findSetter(setters, requiredToBeSet, true);
141: } while (setter != null
142: && !setter.getParameters().isEmpty());
143: }
144: }
145:
146: private static Setter findSetter(ArrayList<Setter> setters,
147: HashSet<String> requiredToBeSet,
148: boolean mustUseChangedProperty) {
149: Setter bestSetter = null;
150: int bestPrice = Integer.MIN_VALUE;
151:
152: for (Setter setter : setters) {
153: boolean usesChangedProperty = false;
154: int price = 0;
155:
156: for (String parameterName : setter.getParameters()) {
157: if (requiredToBeSet.contains(parameterName)) {
158: price += PRICE_OF_REQUIRED_PARAM;
159: usesChangedProperty = true;
160: } else {
161: price += PRICE_OF_DEFAULT_PARAM;
162: }
163: price += setter.getPriority();
164: }
165:
166: if (!mustUseChangedProperty || usesChangedProperty) {
167: if (price > bestPrice) {
168: bestSetter = setter;
169: bestPrice = price;
170: }
171: }
172: }
173:
174: return bestSetter;
175: }
176:
177: private static int compareStrings(String s1, String s2) {
178: if (s1 != null)
179: return s2 != null ? s1.compareTo(s2) : 1;
180: else
181: return s2 != null ? -1 : 0;
182: }
183:
184: // TODO - setter name for constructors have to be "null" - setting constructors as preferred
185: private static class SetterComparator implements Comparator<Setter> {
186:
187: public int compare(Setter setter1, Setter setter2) {
188: List<String> params1 = setter1.getParameters();
189: List<String> params2 = setter2.getParameters();
190: int diff;
191: diff = (params1 != null ? params1.size() : 0)
192: - (params2 != null ? params2.size() : 0);
193: if (diff != 0)
194: return diff;
195: diff = compareStrings(setter1.getSetterName(), setter2
196: .getSetterName());
197: if (diff != 0)
198: return diff;
199: if (params1 != null && params2 != null)
200: for (int a = 0; a < params1.size(); a++) {
201: diff = compareStrings(params1.get(a), params2
202: .get(a));
203: if (diff != 0)
204: return diff;
205: }
206: return 0;
207: }
208:
209: }
210:
211: }
|