0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.beans.beaninfo;
0043:
0044: import java.io.IOException;
0045: import java.lang.reflect.InvocationTargetException;
0046: import java.util.ArrayList;
0047: import java.util.Iterator;
0048: import java.util.List;
0049: import java.util.Set;
0050: import java.util.StringTokenizer;
0051: import java.util.TreeSet;
0052: import javax.lang.model.element.ExecutableElement;
0053: import javax.lang.model.element.TypeElement;
0054: import javax.lang.model.type.ArrayType;
0055: import javax.lang.model.type.TypeKind;
0056: import javax.lang.model.type.TypeMirror;
0057: import javax.lang.model.util.ElementFilter;
0058: import javax.swing.SwingUtilities;
0059: import javax.swing.text.StyledDocument;
0060: import org.netbeans.api.java.source.CompilationInfo;
0061: import org.netbeans.api.java.source.ElementHandle;
0062: import org.netbeans.modules.beans.EventSetPattern;
0063: import org.netbeans.modules.beans.GenerateBeanException;
0064: import org.netbeans.modules.beans.IdxPropertyPattern;
0065: import org.netbeans.modules.beans.PatternAnalyser;
0066: import org.netbeans.modules.beans.PropertyPattern;
0067: import org.openide.DialogDisplayer;
0068: import org.openide.NotifyDescriptor;
0069: import org.openide.cookies.EditorCookie;
0070: import org.openide.loaders.DataObject;
0071: import org.openide.text.NbDocument;
0072: import org.openide.util.Exceptions;
0073: import org.openide.util.NbBundle;
0074:
0075: /** Analyses the ClassElement trying to find source code patterns i.e.
0076: * properties or event sets;
0077: *
0078: * @author Petr Hrebejk, Petr Suchomel
0079: */
0080:
0081: public final class BiAnalyser {
0082:
0083: private static final String TAB = " "; // NOI18N
0084: private static final String TABx2 = TAB + TAB;
0085: private static final String TABx3 = TAB + TABx2;
0086:
0087: private static final String NOI18N_COMMENT = " // NOI18N"; // NOI18N
0088:
0089: private static final String ICONNAME_C16 = "iconNameC16"; // NOI18N
0090: private static final String ICONNAME_C32 = "iconNameC32"; // NOI18N
0091: private static final String ICONNAME_M16 = "iconNameM16"; // NOI18N
0092: private static final String ICONNAME_M32 = "iconNameM32"; // NOI18N
0093:
0094: private static final String DEFAULT_PROPERTY_INDEX = "defaultPropertyIndex"; // NOI18N
0095: private static final String DEFAULT_EVENT_INDEX = "defaultEventIndex"; // NOI18N
0096:
0097: /** Holds Bean descriptor */
0098: List<BiFeature.Descriptor> descriptor;
0099:
0100: /** Holds all properties */
0101: List<BiFeature.Property> properties;
0102:
0103: /** Holds all indexed properties */
0104: List<BiFeature.IdxProperty> idxProperties;
0105:
0106: /** Holds all events sets */
0107: List<BiFeature.EventSet> eventSets;
0108:
0109: /** Holds all methods */
0110: List<BiFeature.Method> methods;
0111:
0112: /** Object representing source code of associated BeanInfo */
0113: BeanInfoSource bis;
0114:
0115: /** Should bean descriptor be obtained from introspection */
0116: private boolean nullDescriptor = false;
0117:
0118: /** Should properties be obtained from introspection */
0119: private boolean nullProperties = false;
0120:
0121: /** Should event sets be obtained from introspection */
0122: private boolean nullEventSets = false;
0123:
0124: /** Should methods be obtained from introspection */
0125: private boolean nullMethods = false;
0126:
0127: /** Should bean descriptor have lazy init */
0128: private boolean lazyDescriptor = true;
0129:
0130: /** Should properties have lazy init */
0131: private boolean lazyProperties = true;
0132:
0133: /** Should event sets have lazy init */
0134: private boolean lazyEventSets = true;
0135:
0136: /** Should methods have lazy init */
0137: private boolean lazyMethods = true;
0138:
0139: /** Is the version of BeanInfo generated by older beans module? */
0140: private final boolean olderVersion;
0141: /** Is the version of BeanInfo generated by new beans module with superclass? */
0142: private boolean super ClassVersion = true;
0143:
0144: /* Holds the class for which the bean info is generated */
0145: private String classfqn;
0146:
0147: private String iconC16;
0148: private String iconM16;
0149: private String iconC32;
0150: private String iconM32;
0151: private int defaultPropertyIndex = -1;
0152: private int defaultEventIndex = -1;
0153: private boolean useSuperClass = false;
0154: private boolean isModified = false;
0155: private boolean isUpdateMode;
0156:
0157: private int getIndexOfMethod(List<BiFeature.Method> al,
0158: ElementHandle<ExecutableElement> method) {
0159: if (method == null)
0160: return -1;
0161:
0162: int i = 0;
0163: for (BiFeature.Method bifMethod : al) {
0164: if (method.equals(bifMethod.getElement())) {
0165: return i;
0166: }
0167: ++i;
0168: }
0169:
0170: return -1;
0171: }
0172:
0173: /** Creates Bean Info analyser which contains all patterns from PatternAnalyser
0174: */
0175: BiAnalyser(PatternAnalyser pa, CompilationInfo javac)
0176: throws GenerateBeanException {
0177: int index;
0178:
0179: // Try to find and analyse existing bean info
0180: bis = new BeanInfoSource(pa.getFileObject());
0181: olderVersion = (bis.isNbBeanInfo() && bis.getMethodsSection() == null);
0182: super ClassVersion = (bis.isNbSuperclass() || !bis.exists());
0183:
0184: TypeElement classElement = pa.getClassElementHandle().resolve(
0185: javac);
0186: this .classfqn = classElement.getQualifiedName().toString();
0187:
0188: // Fill Descriptor list (only in case we have new templates)
0189: descriptor = new ArrayList<BiFeature.Descriptor>();
0190: descriptor.add(new BiFeature.Descriptor(classElement, this ));
0191:
0192: // Fill methods list (only in case we have new templates)
0193: methods = new ArrayList<BiFeature.Method>();
0194: if (!olderVersion) {
0195: for (ExecutableElement method : ElementFilter
0196: .methodsIn(classElement.getEnclosedElements())) {
0197: methods.add(new BiFeature.Method(method, pa, javac,
0198: this ));
0199: }
0200: }
0201:
0202: // Fill properties list
0203: List<PropertyPattern> propertyPatterns = pa
0204: .getPropertyPatterns();
0205: properties = new ArrayList<BiFeature.Property>(propertyPatterns
0206: .size());
0207: for (PropertyPattern pp : propertyPatterns) {
0208: properties.add(new BiFeature.Property(pp, javac, this ));
0209: for (int i = 0; i < methods.size(); i++) {
0210: if ((index = getIndexOfMethod(methods, pp
0211: .getGetterMethod())) != -1)
0212: methods.remove(index);
0213: if ((index = getIndexOfMethod(methods, pp
0214: .getSetterMethod())) != -1)
0215: methods.remove(index);
0216: }
0217: }
0218:
0219: // Fill indexed properties list
0220: List<IdxPropertyPattern> idxPropertyPatterns = pa
0221: .getIdxPropertyPatterns();
0222: idxProperties = new ArrayList<BiFeature.IdxProperty>(
0223: idxPropertyPatterns.size());
0224: for (IdxPropertyPattern ipp : idxPropertyPatterns) {
0225: TypeMirror type = ipp.getType().resolve(javac);
0226: TypeMirror idxtype = ipp.getIndexedType().resolve(javac);
0227: if (type.getKind() != TypeKind.ARRAY
0228: || !javac.getTypes().isSameType(
0229: ((ArrayType) type).getComponentType(),
0230: idxtype)) {
0231: continue;
0232: }
0233:
0234: idxProperties.add(new BiFeature.IdxProperty(ipp, javac,
0235: this ));
0236: if ((index = getIndexOfMethod(methods, ipp
0237: .getGetterMethod())) != -1)
0238: methods.remove(index);
0239: if ((index = getIndexOfMethod(methods, ipp
0240: .getSetterMethod())) != -1)
0241: methods.remove(index);
0242: if ((index = getIndexOfMethod(methods, ipp
0243: .getIndexedGetterMethod())) != -1)
0244: methods.remove(index);
0245: if ((index = getIndexOfMethod(methods, ipp
0246: .getIndexedSetterMethod())) != -1)
0247: methods.remove(index);
0248: }
0249:
0250: // Fill event sets list
0251: List<EventSetPattern> eventSetPatterns = pa
0252: .getEventSetPatterns();
0253: eventSets = new ArrayList<BiFeature.EventSet>(eventSetPatterns
0254: .size());
0255: for (EventSetPattern esp : eventSetPatterns) {
0256: eventSets.add(new BiFeature.EventSet(esp, javac, this ));
0257: if ((index = getIndexOfMethod(methods, esp
0258: .getRemoveListenerMethod())) != -1)
0259: methods.remove(index);
0260: if ((index = getIndexOfMethod(methods, esp
0261: .getAddListenerMethod())) != -1)
0262: methods.remove(index);
0263: }
0264:
0265: try {
0266: isUpdateMode = false;
0267: analyzeBeanInfoSource();
0268: } finally {
0269: isUpdateMode = true;
0270: }
0271:
0272: }
0273:
0274: List<BiFeature.Descriptor> getDescriptor() {
0275: return descriptor;
0276: }
0277:
0278: List<BiFeature.Property> getProperties() {
0279: return properties;
0280: }
0281:
0282: List<BiFeature.IdxProperty> getIdxProperties() {
0283: return idxProperties;
0284: }
0285:
0286: List<BiFeature.EventSet> getEventSets() {
0287: return eventSets;
0288: }
0289:
0290: List<BiFeature.Method> getMethods() {
0291: return methods;
0292: }
0293:
0294: public boolean isOlderVersion() {
0295: return olderVersion;
0296: }
0297:
0298: public boolean isSuperclassVersion() {
0299: return super ClassVersion;
0300: }
0301:
0302: public String getIconC16() {
0303: return iconC16;
0304: }
0305:
0306: public void setIconC16(String iconC16) {
0307: this .iconC16 = iconC16;
0308: setModified();
0309: }
0310:
0311: public String getIconM16() {
0312: return iconM16;
0313: }
0314:
0315: public void setIconM16(String iconM16) {
0316: this .iconM16 = iconM16;
0317: setModified();
0318: }
0319:
0320: public String getIconC32() {
0321: return iconC32;
0322: }
0323:
0324: public void setIconC32(String iconC32) {
0325: this .iconC32 = iconC32;
0326: setModified();
0327: }
0328:
0329: public String getIconM32() {
0330: return iconM32;
0331: }
0332:
0333: public void setIconM32(String iconM32) {
0334: this .iconM32 = iconM32;
0335: setModified();
0336: }
0337:
0338: public int getDefaultPropertyIndex() {
0339: return defaultPropertyIndex;
0340: }
0341:
0342: public void setDefaultPropertyIndex(int defaultPropertyIndex) {
0343: this .defaultPropertyIndex = defaultPropertyIndex;
0344: setModified();
0345: }
0346:
0347: public int getDefaultEventIndex() {
0348: return defaultEventIndex;
0349: }
0350:
0351: public void setDefaultEventIndex(int defaultEventIndex) {
0352: this .defaultEventIndex = defaultEventIndex;
0353: setModified();
0354: }
0355:
0356: /** Getter for property useSuperClass.
0357: * @return Value of property useSuperClass.
0358: */
0359: public boolean isUseSuperClass() {
0360: return this .useSuperClass;
0361: }
0362:
0363: /** Setter for property useSuperClass.
0364: * @param useSuperClass New value of property useSuperClass.
0365: */
0366: public void setUseSuperClass(boolean useSuperClass) {
0367: this .useSuperClass = useSuperClass;
0368: setModified();
0369: }
0370:
0371: boolean isNullDescriptor() {
0372: return nullDescriptor;
0373: }
0374:
0375: boolean isNullProperties() {
0376: return nullProperties;
0377: }
0378:
0379: boolean isNullMethods() {
0380: return nullMethods;
0381: }
0382:
0383: void setNullDescriptor(boolean nullDescriptor) {
0384: this .nullDescriptor = nullDescriptor;
0385: setModified();
0386: }
0387:
0388: void setNullProperties(boolean nullProperties) {
0389: this .nullProperties = nullProperties;
0390: setModified();
0391: }
0392:
0393: void setNullMethods(boolean nullMethods) {
0394: this .nullMethods = nullMethods;
0395: setModified();
0396: }
0397:
0398: boolean isNullEventSets() {
0399: return nullEventSets;
0400: }
0401:
0402: void setNullEventSets(boolean nullEventSets) {
0403: this .nullEventSets = nullEventSets;
0404: setModified();
0405: }
0406:
0407: public boolean isLazyDescriptor() {
0408: return lazyDescriptor;
0409: }
0410:
0411: public boolean isLazyProperties() {
0412: return lazyProperties;
0413: }
0414:
0415: public boolean isLazyMethods() {
0416: return lazyMethods;
0417: }
0418:
0419: public void setLazyDescriptor(boolean lazyDescriptor) {
0420: this .lazyDescriptor = lazyDescriptor;
0421: setModified();
0422: }
0423:
0424: public void setLazyProperties(boolean lazyProperties) {
0425: this .lazyProperties = lazyProperties;
0426: setModified();
0427: }
0428:
0429: public void setLazyMethods(boolean lazyMethods) {
0430: this .lazyMethods = lazyMethods;
0431: setModified();
0432: }
0433:
0434: public boolean isLazyEventSets() {
0435: return lazyEventSets;
0436: }
0437:
0438: public void setLazyEventSets(boolean lazyEventSets) {
0439: this .lazyEventSets = lazyEventSets;
0440: setModified();
0441: }
0442:
0443: void regenerateSource() {
0444: if (bis.exists() && !bis.isNbBeanInfo()) {
0445: throw new IllegalStateException();
0446: }
0447:
0448: DataObject dataObject = bis.getDataObject();
0449: EditorCookie editor = dataObject.getLookup().lookup(
0450: EditorCookie.class);
0451: final StyledDocument doc = editor.getDocument();
0452: Runnable task = new Runnable() {
0453:
0454: public void run() {
0455: regenerateSourceImpl(doc);
0456: }
0457: };
0458:
0459: if (SwingUtilities.isEventDispatchThread()) {
0460: task.run();
0461: } else {
0462: try {
0463: SwingUtilities.invokeAndWait(task);
0464: } catch (InterruptedException ex) {
0465: Exceptions.printStackTrace(ex);
0466: } catch (InvocationTargetException ex) {
0467: Exceptions.printStackTrace(ex);
0468: }
0469: }
0470: }
0471:
0472: void regenerateSourceImpl(StyledDocument doc) {
0473: NbDocument.runAtomic(doc, new Runnable() {
0474: public void run() {
0475: regenerateBeanDescriptor();
0476: regenerateProperties();
0477: regenerateEvents();
0478: if (!olderVersion) {
0479: regenerateMethods();
0480: }
0481: regenerateIcons();
0482: regenerateDefaultIdx();
0483: regenerateSuperclass();
0484: isModified = false;
0485: }
0486: });
0487: }
0488:
0489: void openSource() {
0490:
0491: if (bis.exists()) {
0492:
0493: if (!bis.isNbBeanInfo()) {
0494:
0495: String mssg = GenerateBeanInfoAction
0496: .getString("MSG_BeanInfoExists"); // NOI18N
0497: NotifyDescriptor nd = new NotifyDescriptor.Confirmation(
0498: mssg, NotifyDescriptor.YES_NO_OPTION);
0499: DialogDisplayer.getDefault().notify(nd);
0500: if (!nd.getValue().equals(NotifyDescriptor.YES_OPTION)) {
0501: return;
0502: }
0503:
0504: try {
0505: bis.delete();
0506: } catch (IOException e) {
0507: mssg = GenerateBeanInfoAction
0508: .getString("MSG_BeanInfoCantDelete"); // NOI18N
0509: nd = new NotifyDescriptor.Message(mssg);
0510: DialogDisplayer.getDefault().notify(nd);
0511: return;
0512: }
0513: bis.createFromTemplate(iconBlockRequired());
0514: regenerateSource();
0515: }
0516: } else {
0517: // notify user about missing beaninfo and ask if generate new one.
0518: String mssg = NbBundle.getMessage(BiAnalyser.class,
0519: "MSG_BeanInfoNotExists");
0520: NotifyDescriptor nd = new NotifyDescriptor.Confirmation(
0521: mssg, NotifyDescriptor.YES_NO_OPTION);
0522: DialogDisplayer.getDefault().notify(nd);
0523: if (!nd.getValue().equals(NotifyDescriptor.YES_OPTION)) {
0524: return;
0525: }
0526: bis.createFromTemplate(iconBlockRequired());
0527: regenerateSource();
0528:
0529: if (!bis.isNbBeanInfo()) {
0530: // XXX notify user about wrong template
0531: return;
0532: }
0533:
0534: }
0535:
0536: bis.open();
0537:
0538: }
0539:
0540: private void regenerateBeanDescriptor() {
0541: StringBuilder sb = new StringBuilder(512);
0542:
0543: if (nullDescriptor) {
0544: sb.append(TAB
0545: + GenerateBeanInfoAction
0546: .getString("COMMENT_NullDescriptor")); // NOI18N
0547: sb
0548: .append(TAB
0549: + "private static BeanDescriptor beanDescriptor = null;\n"); // NOI18N
0550: sb
0551: .append(TAB
0552: + "private static BeanDescriptor getBdescriptor(){\n\n"); // NOI18N
0553: bis.setDescriptorSection(sb.toString(), "\n" + TABx2
0554: + "return beanDescriptor;\n" + TAB + "}\n\n"); // NOI18N
0555: return;
0556: }
0557:
0558: for (BiFeature.Descriptor bif : getDescriptor()) {
0559: if (bif.isIncluded()) {
0560: sb.append(TAB
0561: + GenerateBeanInfoAction
0562: .getString("COMMENT_BeanDescriptor")); // NOI18N
0563: if (!lazyDescriptor) {
0564: //this code is used for static init
0565: sb
0566: .append(TAB
0567: + "private static BeanDescriptor beanDescriptor = "); // NOI18N
0568: sb.append(bif.getCreationString());
0569: sb.append(';');
0570: appendNoi18nText(sb);
0571: sb.append("\n\n"); // NOI18N
0572:
0573: sb
0574: .append(TAB
0575: + "private static BeanDescriptor getBdescriptor(){\n"); // NOI18N
0576: sb.append(TABx2 + "return beanDescriptor;\n" + TAB
0577: + "}\n\n"); // NOI18N
0578:
0579: sb.append(TAB + "static {\n"); // NOI18N
0580: } else {
0581: sb.append(TAB + "/*lazy BeanDescriptor*/\n"); // NOI18N
0582: sb
0583: .append(TAB
0584: + "private static BeanDescriptor getBdescriptor(){\n"); // NOI18N
0585: sb.append(TABx2
0586: + "BeanDescriptor beanDescriptor = "); // NOI18N
0587: sb.append(bif.getCreationString());
0588: sb.append(';');
0589: appendNoi18nText(sb);
0590: sb.append('\n'); // NOI18N
0591: }
0592:
0593: for (String line : bif.getCustomizationStrings()) {
0594: sb.append(TABx2 + "beanDescriptor."); // NOI18N
0595: sb.append(line).append(";\n"); // NOI18N
0596: }
0597: if (!lazyDescriptor) {
0598: bis.setDescriptorSection(sb.toString(), "}\n"); // NOI18N
0599: } else {
0600: bis.setDescriptorSection(sb.toString(), TABx2
0601: + "return beanDescriptor;\n" + TAB + "}\n"); // NOI18N
0602: }
0603: }
0604: }
0605: }
0606:
0607: /** Regenerates the property section of BeanInfo */
0608: private void regenerateProperties() {
0609: StringBuilder sb = new StringBuilder(512);
0610: int propertyCount = 0;
0611:
0612: if (nullProperties) {
0613: sb.append(TAB
0614: + GenerateBeanInfoAction
0615: .getString("COMMENT_NullProperties")); // NOI18N
0616: sb
0617: .append(TAB
0618: + "private static PropertyDescriptor[] properties = null;\n"); // NOI18N
0619: sb
0620: .append(TAB
0621: + "private static PropertyDescriptor[] getPdescriptor(){\n"); // NOI18N
0622: bis.setPropertiesSection(sb.toString(), TABx2
0623: + "return properties;\n" + TAB + "}\n\n"); // NOI18N
0624: return;
0625: }
0626:
0627: // Make common list of all properites
0628: Set<BiFeature.Property> allProperties = new TreeSet<BiFeature.Property>(
0629: getProperties());
0630: allProperties.addAll(getIdxProperties());
0631:
0632: sb.append(TAB
0633: + GenerateBeanInfoAction
0634: .getString("COMMENT_PropertyIdentifiers")); // NOI18N
0635:
0636: for (BiFeature.Property bif : allProperties) {
0637:
0638: if (bif.isIncluded()) {
0639: sb.append(TAB + "private static final int "); // NOI18N
0640: // This prefix MUST be consistent w/ BiFeature.IdxProperty analyser
0641: sb.append("PROPERTY_" + bif.getName()); // NOI18N
0642: sb.append(" = " + (propertyCount++) + ";"); // NOI18N
0643: sb.append("\n"); // NOI18N
0644: }
0645: }
0646:
0647: sb.append("\n"
0648: + TAB
0649: + GenerateBeanInfoAction
0650: .getString("COMMENT_PropertyArray")); // NOI18N
0651: if (!lazyProperties) {
0652: sb
0653: .append(TAB
0654: + "private static PropertyDescriptor[] properties = new PropertyDescriptor["
0655: + // NOI18N
0656: propertyCount + "];\n\n"); // NOI18N
0657: sb
0658: .append(TAB
0659: + "private static PropertyDescriptor[] getPdescriptor(){\n"); // NOI18N
0660: sb.append(TABx2 + "return properties;\n" + TAB + "}\n\n"); // NOI18N
0661: } else {
0662: //lazy init
0663: sb.append(TAB + "/*lazy PropertyDescriptor*/\n"); // NOI18N
0664: sb
0665: .append(TAB
0666: + "private static PropertyDescriptor[] getPdescriptor(){\n"); // NOI18N
0667: sb
0668: .append(TABx2
0669: + "PropertyDescriptor[] properties = new PropertyDescriptor["); // NOI18N
0670: sb.append(propertyCount);
0671: sb.append("];\n"); // NOI18N
0672: }
0673: if (propertyCount > 0) {
0674: if (!lazyProperties) {
0675: sb.append(TAB + "static {\n" + TABx2 + "try {\n"); // NOI18N
0676: } else {
0677: sb.append(TAB + "\n" + TABx2 + "try {\n"); // NOI18N
0678: }
0679: }
0680:
0681: for (BiFeature.Property bif : allProperties) {
0682:
0683: if (bif.isIncluded()) {
0684: sb.append(TABx3 + "properties[PROPERTY_").append(
0685: bif.getName()).append("] = "); // NOI18N
0686: sb.append(bif.getCreationString());
0687: sb.append(';');
0688: appendNoi18nText(sb);
0689: sb.append('\n');
0690:
0691: for (String line : bif.getCustomizationStrings()) {
0692: sb.append(TABx3 + "properties[PROPERTY_").append(
0693: bif.getName()).append("]."); // NOI18N
0694: sb.append(line).append(";\n"); // NOI18N
0695: }
0696: }
0697: }
0698:
0699: if (propertyCount > 0)
0700: sb.append(TABx2 + "}\n" + TABx2
0701: + "catch(IntrospectionException e) {\n" + TABx3
0702: + "e.printStackTrace();\n" + TABx2 + "}"); // NOI18N
0703:
0704: if (!lazyProperties) {
0705: bis.setPropertiesSection(sb.toString(),
0706: propertyCount > 0 ? "}\n" : " \n"); // NOI18N
0707: } else {
0708: bis.setPropertiesSection(sb.toString(), TABx2
0709: + "return properties;\n" + TAB + "}\n"); // NOI18N
0710: }
0711: }
0712:
0713: /** Regenerates the method section of BeanInfo */
0714: private void regenerateMethods() {
0715: StringBuilder sb = new StringBuilder(512);
0716: int methodCount = 0;
0717:
0718: if (nullMethods) {
0719: sb.append(TAB
0720: + GenerateBeanInfoAction
0721: .getString("COMMENT_NullMethods")); // NOI18N
0722: sb
0723: .append(TAB
0724: + "private static MethodDescriptor[] methods = null;\n"); // NOI18N
0725: sb
0726: .append(TAB
0727: + "private static MethodDescriptor[] getMdescriptor(){\n"); // NOI18N
0728: bis.setMethodsSection(sb.toString(), TABx2
0729: + "return methods;\n" + TAB + "}\n\n"); // NOI18N
0730: return;
0731: }
0732:
0733: // Make common list of all methods
0734: Set<BiFeature.Method> allMethods = new TreeSet<BiFeature.Method>(
0735: getMethods());
0736:
0737: sb.append(TAB
0738: + GenerateBeanInfoAction
0739: .getString("COMMENT_MethodIdentifiers")); // NOI18N
0740:
0741: for (BiFeature.Method bif : allMethods) {
0742: if (bif.isIncluded()) {
0743: sb.append(TAB + "private static final int "); // NOI18N
0744: sb.append("METHOD_" + bif.getName() + methodCount); // NOI18N
0745: sb.append(" = " + (methodCount++) + ";"); // NOI18N
0746: sb.append("\n"); // NOI18N
0747: }
0748: }
0749:
0750: sb.append("\n"
0751: + TAB
0752: + GenerateBeanInfoAction
0753: .getString("COMMENT_MethodArray")); // NOI18N
0754: if (!lazyMethods) {
0755: sb
0756: .append(TAB
0757: + "private static MethodDescriptor[] methods = new MethodDescriptor["
0758: + // NOI18N
0759: methodCount + "];\n\n"); // NOI18N
0760: sb
0761: .append(TAB
0762: + "private static MethodDescriptor[] getMdescriptor(){\n"); // NOI18N
0763: sb.append(TABx2 + "return methods;\n" + TAB + "}\n\n"); // NOI18N
0764: } else {
0765: //lazy init
0766: sb.append(TAB + "/*lazy MethodDescriptor*/\n"); // NOI18N
0767: sb
0768: .append(TAB
0769: + "private static MethodDescriptor[] getMdescriptor(){\n"); // NOI18N
0770: sb
0771: .append(TABx2
0772: + "MethodDescriptor[] methods = new MethodDescriptor["); // NOI18N
0773: sb.append(methodCount);
0774: sb.append("];\n"); // NOI18N
0775: }
0776:
0777: if (methodCount > 0) {
0778: if (!lazyMethods) {
0779: sb.append(TAB + "static {\n" + TABx2 + "try {\n"); // NOI18N
0780: } else {
0781: sb.append(TAB + "\n" + TABx2 + "try {\n"); // NOI18N
0782: }
0783: }
0784:
0785: Iterator<BiFeature.Method> it = allMethods.iterator();
0786:
0787: for (int i = 0, lCurMethodCount = 0; it.hasNext();) {
0788: BiFeature bif = it.next();
0789:
0790: if (bif.isIncluded()) {
0791: sb.append(TABx3 + "methods[METHOD_").append(
0792: bif.getName()).append(
0793: lCurMethodCount++ + "] = "); // NOI18N
0794: sb.append(bif.getCreationString());
0795: sb.append(';');
0796: appendNoi18nText(sb);
0797: sb.append('\n');
0798:
0799: for (String line : bif.getCustomizationStrings()) {
0800: sb.append(TABx3 + "methods[METHOD_").append(
0801: bif.getName()).append(i + "]."); // NOI18N
0802: sb.append(line).append(";\n"); // NOI18N
0803: }
0804: i++;
0805: }
0806: }
0807:
0808: if (methodCount > 0)
0809: sb.append(TABx2 + "}\n" + TABx2 + "catch( Exception e) {}"); // NOI18N
0810:
0811: if (!lazyMethods) {
0812: bis.setMethodsSection(sb.toString(),
0813: methodCount > 0 ? "}\n" : " \n"); // NOI18N
0814: } else {
0815: bis.setMethodsSection(sb.toString(), TABx2
0816: + "return methods;\n" + TAB + "}\n"); // NOI18N
0817: }
0818: }
0819:
0820: /** Regenerates the event set section of BeanInfo */
0821: private void regenerateEvents() {
0822: StringBuilder sb = new StringBuilder(512);
0823: int eventCount = 0;
0824:
0825: if (nullEventSets) {
0826: sb.append(TAB
0827: + GenerateBeanInfoAction
0828: .getString("COMMENT_NullEventSets")); // NOI18N
0829: sb
0830: .append(TAB
0831: + "private static EventSetDescriptor[] eventSets = null;\n"); // NOI18N
0832: sb
0833: .append(TAB
0834: + "private static EventSetDescriptor[] getEdescriptor(){\n"); // NOI18N
0835: bis.setEventSetsSection(sb.toString(), TABx2
0836: + "return eventSets;\n" + TAB + "}\n\n"); // NOI18N
0837: return;
0838: }
0839:
0840: sb.append(TAB
0841: + GenerateBeanInfoAction
0842: .getString("COMMENT_EventSetsIdentifiers")); // NOI18N
0843:
0844: Set<BiFeature.EventSet> events = new TreeSet<BiFeature.EventSet>(
0845: eventSets);
0846: for (BiFeature.EventSet bif : events) {
0847: if (bif.isIncluded()) {
0848: sb.append(TAB + "private static final int "); // NOI18N
0849: sb.append("EVENT_" + bif.getName()); // NOI18N
0850: sb.append(" = " + (eventCount++) + ";"); // NOI18N
0851: sb.append("\n"); // NOI18N
0852: }
0853: }
0854:
0855: sb.append("\n"
0856: + TAB
0857: + GenerateBeanInfoAction
0858: .getString("COMMENT_EventSetsArray"));
0859: if (!lazyEventSets) {
0860: sb
0861: .append(TAB
0862: + "private static EventSetDescriptor[] eventSets = new EventSetDescriptor["
0863: + // NOI18N
0864: eventCount + "];\n\n"); // NOI18N
0865: sb
0866: .append(TAB
0867: + "private static EventSetDescriptor[] getEdescriptor(){\n"); // NOI18N
0868: sb.append(TABx2 + "return eventSets;\n" + TAB + "}\n\n"); // NOI18N
0869: } else {
0870: //lazy init
0871: sb.append(TAB + "/*lazy EventSetDescriptor*/\n"); // NOI18N
0872: sb
0873: .append(TAB
0874: + "private static EventSetDescriptor[] getEdescriptor(){\n"); // NOI18N
0875: sb
0876: .append(TABx2
0877: + "EventSetDescriptor[] eventSets = new EventSetDescriptor["); // NOI18N
0878: sb.append(eventCount);
0879: sb.append("];\n"); // NOI18N
0880: }
0881:
0882: if (eventCount > 0) {
0883: if (!lazyEventSets) {
0884: sb.append(TAB + "static {\n" + TABx2 + "try {\n"); // NOI18N
0885: } else {
0886: sb.append(TAB + "\n" + TABx2 + "try {\n"); // NOI18N
0887: }
0888: }
0889:
0890: for (BiFeature.EventSet bif : events) {
0891: if (bif.isIncluded()) {
0892: // the index prefix MUST be consistent w/ BiFeature.EventSet analyser.
0893: sb.append(TABx3 + "eventSets[EVENT_").append(
0894: bif.getName()).append("] = "); // NOI18N
0895: sb.append(bif.getCreationString());
0896: sb.append(';');
0897: appendNoi18nText(sb);
0898: sb.append('\n');
0899:
0900: for (String line : bif.getCustomizationStrings()) {
0901: sb.append(TABx3 + "eventSets[EVENT_").append(
0902: bif.getName()).append("]."); // NOI18N
0903: sb.append(line).append(";\n"); // NOI18N
0904: }
0905: }
0906: }
0907:
0908: if (eventCount > 0)
0909: sb.append(TABx2 + "}\n" + TABx2
0910: + "catch(IntrospectionException e) {\n" + TABx3
0911: + "e.printStackTrace();\n" + TABx2 + "}"); // NOI18N
0912:
0913: if (!lazyEventSets) {
0914: bis.setEventSetsSection(sb.toString(),
0915: eventCount > 0 ? "}\n" : " \n"); // NOI18N
0916: } else {
0917: bis.setEventSetsSection(sb.toString(), TABx2
0918: + "return eventSets;\n" + TAB + "}\n"); // NOI18N
0919: }
0920: }
0921:
0922: /** Generate image icon section */
0923: private void regenerateIcons() {
0924: if (iconBlockRequired()) {
0925: StringBuilder sb = new StringBuilder(200);
0926:
0927: sb.append(getIconDeclaration(ICONNAME_C16, iconC16));
0928: sb.append(getIconDeclaration(ICONNAME_C32, iconC32));
0929: sb.append(getIconDeclaration(ICONNAME_M16, iconM16));
0930: sb.append(getIconDeclaration(ICONNAME_M32, iconM32));
0931:
0932: bis.setIconsSection(sb.toString());
0933: }
0934: }
0935:
0936: private boolean iconBlockRequired() {
0937: return (iconC16 != null | iconC32 != null | iconM16 != null | iconM32 != null);
0938: }
0939:
0940: private static String getIconDeclaration(String name,
0941: String resource) {
0942: StringBuilder sb = new StringBuilder(80);
0943:
0944: sb.append(TAB + "private static String ").append(name).append(
0945: " = "); // NOI18N
0946: if (resource == null || resource.trim().length() == 0)
0947: sb.append("null;\n"); // NOI18N
0948: else
0949: sb.append("\"").append(resource.trim()).append("\";\n"); // NOI18N
0950: return sb.toString();
0951: }
0952:
0953: private void regenerateDefaultIdx() {
0954: StringBuilder sb = new StringBuilder(100);
0955:
0956: sb.append(
0957: TAB + "private static final int "
0958: + DEFAULT_PROPERTY_INDEX + " = ").append(
0959: defaultPropertyIndex).append(";\n"); // NOI18N
0960: sb.append(
0961: TAB + "private static final int " + DEFAULT_EVENT_INDEX
0962: + " = ").append(defaultEventIndex)
0963: .append(";\n"); // NOI18N
0964:
0965: bis.setDefaultIdxSection(sb.toString());
0966: }
0967:
0968: private void regenerateSuperclass() {
0969: StringBuilder sb = new StringBuilder(100);
0970: if (this .isUseSuperClass()) {
0971: sb.append(TAB
0972: + "public BeanInfo[] getAdditionalBeanInfo() {\n"); // NOI18N
0973: sb.append(TABx2 + "Class superclass = " + classfqn
0974: + ".class.getSuperclass();\n"); // NOI18N
0975: sb.append(TABx2 + "BeanInfo sbi = null;\n"); // NOI18N
0976: sb.append(TABx2 + "try {\n"); // NOI18N
0977: sb.append(TABx2 + TAB
0978: + "sbi = Introspector.getBeanInfo(superclass);\n"); // NOI18N
0979:
0980: bis
0981: .setSuperclassSection(
0982: sb.toString(),
0983: TABx3
0984: + "}\ncatch(IntrospectionException ex) {\n}\n\nreturn new BeanInfo[] { sbi };\n}\n"); // NOI18N
0985: } else {
0986: bis.setSuperclassSection("\n", "\n"); // NOI18N
0987: }
0988: }
0989:
0990: /** Analyzes existing BeanInfo */
0991: private void analyzeBeanInfoSource() throws GenerateBeanException {
0992:
0993: if (!bis.isNbBeanInfo())
0994: return;
0995:
0996: String section = bis.getIconsSection();
0997: List<String> code = normalizeText(section);
0998: setIconsFromBeanInfo(code);
0999:
1000: section = bis.getDefaultIdxSection();
1001: code = normalizeText(section);
1002: setDefaultIdxFromBeanInfo(code);
1003:
1004: section = bis.getDescriptorSection();
1005: code = normalizeText(section);
1006: nullDescriptor = setPropertiesFromBeanInfo(descriptor, code,
1007: "BeanDescriptor"); // NOI18N
1008: if (!nullDescriptor) {
1009: setLazyDescriptor(isLazy(code, "BeanDescriptor")); // NOI18N
1010: }
1011:
1012: section = bis.getPropertiesSection();
1013: code = normalizeText(section);
1014: nullProperties = setPropertiesFromBeanInfo(properties, code,
1015: "PropertyDescriptor[]"); // NOI18N
1016: if (!nullProperties) {
1017: setLazyProperties(isLazy(code, "PropertyDescriptor")); // NOI18N
1018: setPropertiesFromBeanInfo(idxProperties, code,
1019: "PropertyDescriptor[]"); // NOI18N
1020: }
1021:
1022: section = bis.getMethodsSection();
1023: if (section == null) {
1024: DialogDisplayer.getDefault().notify(
1025: new NotifyDescriptor.Message(GenerateBeanInfoAction
1026: .getString("MSG_Old_Version"),
1027: NotifyDescriptor.WARNING_MESSAGE)); // NOI18N
1028: nullMethods = true;
1029: } else {
1030: code = normalizeText(section);
1031: nullMethods = setPropertiesFromBeanInfo(methods, code,
1032: "MethodDescriptor[]"); // NOI18N
1033: if (!nullMethods) {
1034: setLazyMethods(isLazy(code, "MethodDescriptor")); // NOI18N
1035: }
1036: }
1037:
1038: section = bis.getEventSetsSection();
1039: code = normalizeText(section);
1040: nullEventSets = setPropertiesFromBeanInfo(eventSets, code,
1041: "EventSetDescriptor[]"); // NOI18N
1042: if (!nullEventSets) {
1043: setLazyEventSets(isLazy(code, "EventSetDescriptor")); // NOI18N
1044: }
1045:
1046: section = bis.getSuperclassSection();
1047: code = normalizeText(section);
1048: setUseSuperClass(hasSuperClass(code));
1049: }
1050:
1051: /** "Normalizes" the JavaCode. Removes all unneeded whitespaces. Makes strings from
1052: * commands.
1053: * @param code String containg the java source code
1054: * @return Normalized code as collection of string.
1055: */
1056: static List<String> normalizeText(String code) {
1057:
1058: List<String> result = new ArrayList<String>();
1059: StringBuilder sb = new StringBuilder(100);
1060:
1061: final int IN_TEXT = 0;
1062: final int IN_WHITE = 1;
1063: int mode = IN_WHITE;
1064: final int noi18n_length = NOI18N_COMMENT.length();
1065: boolean eo_javaid = false;
1066: boolean guarded = false; //guarded beetwen ""
1067: boolean escape = false; //guarded beetwen ""
1068:
1069: for (int i = 0; code != null && i < code.length(); i++) {
1070: char ch = code.charAt(i);
1071:
1072: if (ch != '\"')
1073: escape = false;
1074:
1075: switch (mode) {
1076: case IN_TEXT:
1077: if (!Character.isWhitespace(ch)) {
1078: if (ch == ';') {
1079: sb.append(ch);
1080: // check if there is "NOI18N" comment appended
1081: if (i + noi18n_length < code.length()
1082: && NOI18N_COMMENT.equals(code
1083: .substring(i + 1, i + 1
1084: + noi18n_length))) {
1085: sb.append(NOI18N_COMMENT);
1086: i += noi18n_length;
1087: }
1088: result.add(sb.toString());
1089: sb.setLength(0);
1090: mode = IN_WHITE;
1091: eo_javaid = false;
1092: } else if (ch == '\\') {
1093: escape = true;
1094: sb.append(ch);
1095: } else if (ch == '\"') {
1096: if (!escape)
1097: guarded = !guarded;
1098: escape = false;
1099: sb.append(ch);
1100: } else
1101: sb.append(ch);
1102: } else {
1103: if (guarded)
1104: sb.append(ch);
1105: else {
1106: eo_javaid = Character.isJavaIdentifierPart(code
1107: .charAt(i - 1));
1108: mode = IN_WHITE;
1109: }
1110: }
1111: break;
1112: case IN_WHITE:
1113: if (!Character.isWhitespace(ch)) {
1114: if (eo_javaid
1115: && Character.isJavaIdentifierStart(ch))
1116: sb.append(' ');
1117: else if (ch == '\\') {
1118: escape = true;
1119: sb.append(ch);
1120: } else if (ch == '\"') {
1121: if (!escape)
1122: guarded = !guarded;
1123: escape = false;
1124: }
1125: sb.append(ch);
1126: mode = IN_TEXT;
1127: }
1128: break;
1129: }
1130: }
1131:
1132: if (sb.length() > 0)
1133: result.add(sb.toString());
1134:
1135: return result;
1136:
1137: }
1138:
1139: static String[] getParameters(String command) {
1140: String paramString;
1141:
1142: int beg = command.indexOf('(');
1143: int end = command.lastIndexOf(')');
1144:
1145: if (beg != -1 && end != -1 && (++beg < end))
1146: paramString = command.substring(beg, end);
1147: else
1148: return new String[0];
1149:
1150: StringTokenizer strTok = new StringTokenizer(paramString, ","); // NOI18N
1151:
1152: String[] resultStrs = new String[strTok.countTokens()];
1153:
1154: for (int i = 0; strTok.hasMoreTokens(); i++)
1155: resultStrs[i] = strTok.nextToken();
1156:
1157: return resultStrs;
1158: }
1159:
1160: static String getArgumentParameter(String command) {
1161: int beg = command.indexOf('(');
1162: int end = command.lastIndexOf(')');
1163:
1164: if (beg != -1 && end != -1 && (++beg < end))
1165: return command.substring(beg, end);
1166: else
1167: return null;
1168: }
1169:
1170: /** Gets the initializer */
1171: static String getInitializer(String command) {
1172:
1173: int beg = command.lastIndexOf('=');
1174: int end = command.lastIndexOf(';');
1175:
1176: if (beg != -1 && end != -1 && (++beg < end))
1177: return command.substring(beg, end).trim();
1178: else
1179: return null;
1180: }
1181:
1182: /** test if initializer is lazy */
1183: static boolean isLazy(List<String> code, String name) {
1184: for (String statement : code) {
1185: if (statement.indexOf(name) != -1) {
1186: if (statement.indexOf("/*lazy " + name + "*/") != -1) { // NOI18N
1187: return true;
1188: }
1189: }
1190: }
1191: return false;
1192: }
1193:
1194: static boolean hasSuperClass(List<String> code) {
1195: for (String statement : code) {
1196: //System.out.println(statement);
1197: if (statement
1198: .indexOf("public BeanInfo[] getAdditionalBeanInfo()") != -1) { // NOI18N
1199: return true;
1200: }
1201: }
1202: return false;
1203: }
1204:
1205: /** Removes Quotation marks */
1206: static String removeQuotation(String text) {
1207:
1208: int beg = text.indexOf('"');
1209: int end = text.lastIndexOf('"');
1210:
1211: if (beg != -1 && end != -1 && (++beg < end))
1212: return text.substring(beg, end);
1213: else
1214: return null;
1215: }
1216:
1217: /** Let's the collection of features check for it's properties in BeanInfo */
1218: boolean setPropertiesFromBeanInfo(
1219: List<? extends BiFeature> features, List<String> code,
1220: String name) throws GenerateBeanException {
1221: for (String statement : code) {
1222: if (statement.indexOf(name) != -1)
1223:
1224: if ("null".equals(getInitializer(statement))) { // NOI18N
1225: return true;
1226: } else
1227: break; //others f.e. null/*lazy*/
1228: }
1229:
1230: for (BiFeature bif : features) {
1231: bif.setBrackets(bif.getBrackets());
1232: bif.analyzeCustomization(code);
1233: }
1234:
1235: return false;
1236: }
1237:
1238: /** Analyze icons properties from bean info */
1239:
1240: void setIconsFromBeanInfo(List<String> code) {
1241: for (String statement : code) {
1242: if (statement.indexOf(ICONNAME_C16) != -1) {
1243: iconC16 = removeQuotation(getInitializer(statement));
1244: continue;
1245: }
1246: if (statement.indexOf(ICONNAME_C32) != -1) {
1247: iconC32 = removeQuotation(getInitializer(statement));
1248: continue;
1249: }
1250: if (statement.indexOf(ICONNAME_M16) != -1) {
1251: iconM16 = removeQuotation(getInitializer(statement));
1252: continue;
1253: }
1254: if (statement.indexOf(ICONNAME_M32) != -1) {
1255: iconM32 = removeQuotation(getInitializer(statement));
1256: continue;
1257: }
1258: }
1259: }
1260:
1261: /** Analyze default section */
1262:
1263: void setDefaultIdxFromBeanInfo(List<String> code) {
1264: for (String statement : code) {
1265: if (statement.indexOf(DEFAULT_PROPERTY_INDEX) != -1) {
1266: try {
1267: defaultPropertyIndex = Integer
1268: .parseInt(getInitializer(statement));
1269: } catch (java.lang.NumberFormatException e) {
1270: defaultPropertyIndex = -1;
1271: }
1272:
1273: continue;
1274: }
1275: if (statement.indexOf(DEFAULT_EVENT_INDEX) != -1) {
1276: try {
1277: defaultEventIndex = Integer
1278: .parseInt(getInitializer(statement));
1279: } catch (java.lang.NumberFormatException e) {
1280: defaultEventIndex = -1;
1281: }
1282:
1283: continue;
1284: }
1285:
1286: }
1287: }
1288:
1289: private void appendNoi18nText(StringBuilder sb) {
1290: sb.append(NOI18N_COMMENT);
1291: }
1292:
1293: void setModified() {
1294: if (isUpdateMode) {
1295: this .isModified = true;
1296: BIEditorSupport editor = this .bis.getDataObject()
1297: .getLookup().lookup(BIEditorSupport.class);
1298: editor.notifyModified();
1299: }
1300: }
1301:
1302: public boolean isModified() {
1303: return this.isModified;
1304: }
1305: }
|