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.spring.beans.editor;
042:
043: import java.io.File;
044: import java.io.IOException;
045: import java.util.ArrayList;
046: import java.util.Collections;
047: import java.util.HashSet;
048: import java.util.Iterator;
049: import java.util.List;
050: import java.util.Set;
051: import java.util.logging.Level;
052: import java.util.logging.Logger;
053: import javax.lang.model.element.Element;
054: import javax.lang.model.element.ElementKind;
055: import javax.lang.model.element.ExecutableElement;
056: import javax.lang.model.element.Modifier;
057: import javax.lang.model.element.PackageElement;
058: import javax.lang.model.element.TypeElement;
059: import javax.lang.model.type.DeclaredType;
060: import javax.lang.model.type.TypeKind;
061: import javax.lang.model.type.TypeMirror;
062: import javax.lang.model.util.ElementFilter;
063: import javax.lang.model.util.SimpleElementVisitor6;
064: import javax.swing.text.BadLocationException;
065: import javax.swing.text.Document;
066: import javax.swing.text.StyledDocument;
067: import org.netbeans.api.java.project.JavaProjectConstants;
068: import org.netbeans.api.java.source.ClasspathInfo;
069: import org.netbeans.api.java.source.CompilationController;
070: import org.netbeans.api.java.source.ElementHandle;
071: import org.netbeans.api.java.source.ElementUtilities;
072: import org.netbeans.api.java.source.JavaSource;
073: import org.netbeans.api.java.source.JavaSource.Phase;
074: import org.netbeans.api.java.source.Task;
075: import org.netbeans.api.java.source.ui.ElementOpen;
076: import org.netbeans.api.project.FileOwnerQuery;
077: import org.netbeans.api.project.Project;
078: import org.netbeans.api.project.ProjectUtils;
079: import org.netbeans.api.project.SourceGroup;
080: import org.netbeans.editor.BaseDocument;
081: import org.netbeans.editor.TokenItem;
082: import org.netbeans.modules.editor.NbEditorUtilities;
083: import org.netbeans.modules.spring.api.Action;
084: import org.netbeans.modules.spring.api.beans.model.Location;
085: import org.netbeans.modules.spring.api.beans.model.SpringBean;
086: import org.netbeans.modules.spring.api.beans.model.SpringBeans;
087: import org.netbeans.modules.spring.api.beans.model.SpringConfigModel;
088: import org.netbeans.modules.spring.beans.utils.StringUtils;
089: import org.netbeans.modules.xml.text.syntax.SyntaxElement;
090: import org.netbeans.modules.xml.text.syntax.XMLSyntaxSupport;
091: import org.netbeans.modules.xml.text.syntax.dom.EmptyTag;
092: import org.netbeans.modules.xml.text.syntax.dom.StartTag;
093: import org.netbeans.modules.xml.text.syntax.dom.Tag;
094: import org.openide.awt.StatusDisplayer;
095: import org.openide.cookies.EditorCookie;
096: import org.openide.cookies.LineCookie;
097: import org.openide.cookies.OpenCookie;
098: import org.openide.filesystems.FileObject;
099: import org.openide.filesystems.FileUtil;
100: import org.openide.loaders.DataObject;
101: import org.openide.text.Line;
102: import org.openide.text.NbDocument;
103: import org.openide.util.Exceptions;
104: import org.openide.util.NbBundle;
105: import org.w3c.dom.NamedNodeMap;
106: import org.w3c.dom.Node;
107:
108: /**
109: * Utility methods for Spring XML configuration file editor
110: *
111: * Inspired by BeansEditorUtils class from SpringIDE
112: *
113: * @author Rohan Ranade (Rohan.Ranade@Sun.COM)
114: */
115: public final class SpringXMLConfigEditorUtils {
116:
117: public static final String BEAN_NAME_DELIMITERS = ",; "; // NOI18N
118:
119: public enum Public {
120: YES, NO, DONT_CARE
121: };
122:
123: public enum Static {
124: YES, NO, DONT_CARE
125: };
126:
127: private SpringXMLConfigEditorUtils() {
128: }
129:
130: public static String getBeanPropertySetterName(String property) {
131: char[] buffer = property.toCharArray();
132: buffer[0] = Character.toUpperCase(buffer[0]);
133:
134: return "set" + String.valueOf(buffer); // NOI18N
135: }
136:
137: public static String getBeanFactoryMethod(Tag tag) {
138: Node bean = getBean(tag);
139: if (bean != null) {
140: NamedNodeMap attribs = bean.getAttributes();
141: if (attribs != null
142: && attribs.getNamedItem("factory-method") != null) { // NOI18N
143: return attribs.getNamedItem("factory-method")
144: .getNodeValue(); // NOI18N
145: }
146: }
147:
148: return null;
149: }
150:
151: public static TypeElement findClassElementByBinaryName(
152: final String binaryName, CompilationController cc) {
153: if (!binaryName.contains("$")) { // NOI18N
154: // fast search based on fqn
155: return cc.getElements().getTypeElement(binaryName);
156: } else {
157: // get containing package
158: String packageName = ""; // NOI18N
159: int dotIndex = binaryName.lastIndexOf("."); // NOI18N
160: if (dotIndex != -1) {
161: packageName = binaryName.substring(0, dotIndex);
162: }
163: PackageElement packElem = cc.getElements()
164: .getPackageElement(packageName);
165: if (packElem == null) {
166: return null;
167: }
168:
169: // scan for element matching the binaryName
170: return new BinaryNameTypeScanner().visit(packElem,
171: binaryName);
172: }
173: }
174:
175: private static class BinaryNameTypeScanner extends
176: SimpleElementVisitor6<TypeElement, String> {
177:
178: @Override
179: public TypeElement visitPackage(PackageElement packElem,
180: String binaryName) {
181: for (Element e : packElem.getEnclosedElements()) {
182: if (e.getKind().isClass()) {
183: TypeElement ret = e.accept(this , binaryName);
184: if (ret != null) {
185: return ret;
186: }
187: }
188: }
189:
190: return null;
191: }
192:
193: @Override
194: public TypeElement visitType(TypeElement typeElement,
195: String binaryName) {
196: String bName = ElementUtilities.getBinaryName(typeElement);
197: if (binaryName.equals(bName)) {
198: return typeElement;
199: } else if (binaryName.startsWith(bName)) {
200: for (Element child : typeElement.getEnclosedElements()) {
201: if (!child.getKind().isClass()) {
202: continue;
203: }
204:
205: TypeElement retVal = child.accept(this , binaryName);
206: if (retVal != null) {
207: return retVal;
208: }
209: }
210: }
211:
212: return null;
213: }
214:
215: }
216:
217: public static Node getBean(Node tag) {
218: if (tag == null) {
219: return null;
220: }
221:
222: if (tag.getNodeName().equals("bean")) { // NOI18N
223: return tag;
224: }
225:
226: if (tag.getNodeName().equals("lookup-method")
227: || tag.getNodeName().equals("replaced-method")
228: || tag.getNodeName().equals("property")) { // NOI18N
229: Node parent = tag.getParentNode();
230: if (parent.getNodeName().equals("bean")) { // NOI18N
231: return parent;
232: } else {
233: return null;
234: }
235: }
236:
237: return null;
238:
239: }
240:
241: public static String getBeanClassName(Node tag) {
242: Node bean = getBean(tag);
243: if (bean != null) {
244: NamedNodeMap attribs = bean.getAttributes();
245: if (attribs != null
246: && attribs.getNamedItem("class") != null) { // NOI18N
247: return attribs.getNamedItem("class").getNodeValue(); // NOI18N
248: }
249: }
250:
251: return null;
252: }
253:
254: public static JavaSource getJavaSource(Document doc) {
255: FileObject fileObject = NbEditorUtilities.getFileObject(doc);
256: if (fileObject == null) {
257: return null;
258: }
259: Project project = FileOwnerQuery.getOwner(fileObject);
260: if (project == null) {
261: return null;
262: }
263: // XXX this only works correctly with projects with a single sourcepath,
264: // but we don't plan to support another kind of projects anyway (what about Maven?).
265: SourceGroup[] sourceGroups = ProjectUtils
266: .getSources(project)
267: .getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
268: for (SourceGroup sourceGroup : sourceGroups) {
269: return JavaSource.create(ClasspathInfo.create(sourceGroup
270: .getRootFolder()));
271: }
272: return null;
273: }
274:
275: public static void findAndOpenJavaClass(
276: final String classBinaryName, Document doc) {
277: final JavaSource js = getJavaSource(doc);
278: if (js != null) {
279: try {
280: js.runUserActionTask(new Task<CompilationController>() {
281: public void run(CompilationController cc)
282: throws Exception {
283: boolean opened = false;
284: TypeElement element = findClassElementByBinaryName(
285: classBinaryName, cc);
286: if (element != null) {
287: opened = ElementOpen.open(js
288: .getClasspathInfo(), element);
289: }
290: if (!opened) {
291: String msg = NbBundle.getMessage(
292: SpringXMLConfigEditorUtils.class,
293: "LBL_SourceNotFound",
294: classBinaryName);
295: StatusDisplayer.getDefault().setStatusText(
296: msg);
297: }
298: }
299: }, false);
300: } catch (IOException ex) {
301: Logger.getLogger("global").log(Level.SEVERE,
302: ex.getMessage(), ex);
303: }
304: }
305: }
306:
307: public static ElementHandle<ExecutableElement> findMethod(
308: Document doc, final String classBinName,
309: final String methodName, int argCount, Public publicFlag,
310: Static staticFlag) {
311: JavaSource js = getJavaSource(doc);
312: if (js != null) {
313: try {
314: MethodFinder methodFinder = new MethodFinder(
315: classBinName, methodName, argCount, publicFlag,
316: staticFlag);
317: js.runUserActionTask(methodFinder, false);
318: return methodFinder.getMethodHandle();
319: } catch (IOException ex) {
320: Logger.getLogger("global").log(Level.SEVERE,
321: ex.getMessage(), ex);
322: }
323: }
324:
325: return null;
326: }
327:
328: /**
329: * Open the specified method of the specified class in the editor
330: *
331: * @param doc The document on from which the java model context is to be created
332: * @param classBinName binary name of the class whose method is to be opened in the editor
333: * @param methodName name of the method
334: * @param argCount number of arguments that the method has (-1 if caller doesn't care)
335: * @param publicFlag YES if the method is public, NO if not, DONT_CARE if caller doesn't care
336: * @param staticFlag YES if the method is static, NO if not, DONT_CARE if caller doesn't care
337: */
338: public static void openMethodInEditor(Document doc,
339: final String classBinName, final String methodName,
340: int argCount, Public publicFlag, Static staticFlag) {
341: if (classBinName == null || methodName == null || doc == null) {
342: return;
343: }
344:
345: final JavaSource js = getJavaSource(doc);
346: if (js == null) {
347: return;
348: }
349:
350: final ElementHandle<ExecutableElement> eh = findMethod(doc,
351: classBinName, methodName, argCount, publicFlag,
352: staticFlag);
353: if (eh != null) {
354: try {
355: js.runUserActionTask(new Task<CompilationController>() {
356:
357: public void run(CompilationController cc)
358: throws Exception {
359: ExecutableElement ee = eh.resolve(cc);
360: ElementOpen.open(js.getClasspathInfo(), ee);
361: }
362: }, false);
363: } catch (IOException ex) {
364: Logger.getLogger("global").log(Level.SEVERE,
365: ex.getMessage(), ex);
366: }
367: }
368: }
369:
370: public static final Tag getDocumentRoot(Document doc) {
371: Tag retTag = null;
372: try {
373: XMLSyntaxSupport syntaxSupport = (XMLSyntaxSupport) ((BaseDocument) doc)
374: .getSyntaxSupport();
375: TokenItem tok = syntaxSupport.getTokenChain(0, 1);
376: if (tok != null) {
377: while (!ContextUtilities.isTagToken(tok)) {
378: tok = tok.getNext();
379: }
380: SyntaxElement element = syntaxSupport
381: .getElementChain(tok.getOffset()
382: + tok.getImage().length());
383: if (element instanceof StartTag
384: || element instanceof EmptyTag) {
385: Tag tag = (Tag) element;
386: if (tag.getParentNode() instanceof org.w3c.dom.Document) {
387: return tag;
388: }
389: }
390: }
391: } catch (BadLocationException ex) {
392: // No context support available in this case
393: }
394:
395: return retTag;
396: }
397:
398: public static final boolean hasAttribute(Node node,
399: String attributeName) {
400: return (node != null && node.getAttributes() != null && node
401: .getAttributes().getNamedItem(attributeName) != null);
402: }
403:
404: public static final String getAttribute(Node node,
405: String attributeName) {
406: if (hasAttribute(node, attributeName)) {
407: return node.getAttributes().getNamedItem(attributeName)
408: .getNodeValue();
409: }
410: return null;
411: }
412:
413: public static boolean openFile(File file, int offset) {
414: FileObject fo = FileUtil.toFileObject(file);
415: if (fo != null) {
416: return openFile(fo, offset);
417: }
418: return false;
419: }
420:
421: public static boolean openFile(FileObject fo, int offset) {
422: DataObject dataObject;
423: boolean opened = false;
424: try {
425: dataObject = DataObject.find(fo);
426: if (offset > 0) {
427: opened = openFileAtOffset(dataObject, offset);
428: }
429: } catch (IOException e) {
430: Exceptions.printStackTrace(e);
431: return false;
432: }
433: if (opened) {
434: return true;
435: } else {
436: OpenCookie oc = dataObject
437: .getCookie(org.openide.cookies.OpenCookie.class);
438: if (oc != null) {
439: oc.open();
440: return true;
441: }
442: }
443: return false;
444: }
445:
446: private static boolean openFileAtOffset(DataObject dataObject,
447: int offset) throws IOException {
448: EditorCookie ec = dataObject.getCookie(EditorCookie.class);
449: LineCookie lc = dataObject.getCookie(LineCookie.class);
450: if (ec != null && lc != null) {
451: StyledDocument doc = ec.openDocument();
452: if (doc != null) {
453: int lineNumber = NbDocument.findLineNumber(doc, offset);
454: if (lineNumber != -1) {
455: Line line = lc.getLineSet().getCurrent(lineNumber);
456: if (line != null) {
457: int lineOffset = NbDocument.findLineOffset(doc,
458: lineNumber);
459: int column = offset - lineOffset;
460: line.show(Line.SHOW_GOTO, column);
461: return true;
462: }
463: }
464: }
465: }
466: return false;
467: }
468:
469: public static String getPropertyNameFromMethodName(String methodName) {
470: if (methodName.length() < 4) {
471: return null;
472: }
473: char[] propertyName = methodName.substring(3).toCharArray();
474: propertyName[0] = Character.toLowerCase(propertyName[0]);
475: return String.valueOf(propertyName);
476: }
477:
478: private static final class MethodFinder implements
479: Task<CompilationController> {
480:
481: private String classBinName;
482: private String methodName;
483: private int argCount;
484: private Public publicFlag;
485: private Static staticFlag;
486: private ElementHandle<ExecutableElement> methodHandle;
487:
488: public MethodFinder(String classBinName, String methodName,
489: int argCount, Public publicFlag, Static staticFlag) {
490: this .classBinName = classBinName;
491: this .methodName = methodName;
492: this .argCount = argCount;
493: this .publicFlag = publicFlag;
494: this .staticFlag = staticFlag;
495: }
496:
497: public void run(CompilationController cc) throws Exception {
498: cc.toPhase(Phase.ELEMENTS_RESOLVED);
499: TypeElement element = findClassElementByBinaryName(
500: classBinName, cc);
501: while (element != null) {
502: List<ExecutableElement> methods = ElementFilter
503: .methodsIn(element.getEnclosedElements());
504: for (ExecutableElement method : methods) {
505: // name match
506: String mName = method.getSimpleName().toString();
507: if (!mName.equals(methodName)) {
508: continue;
509: }
510:
511: // argument match
512: if (this .argCount != -1) {
513: int actualArgCount = method.getParameters()
514: .size();
515: if (actualArgCount != argCount) {
516: continue;
517: }
518: }
519:
520: // static match
521: if (staticFlag != Static.DONT_CARE) {
522: boolean isStatic = method.getModifiers()
523: .contains(Modifier.STATIC);
524: if ((isStatic && staticFlag == Static.NO)
525: || (!isStatic && staticFlag == Static.YES)) {
526: continue;
527: }
528: }
529:
530: // public match
531: if (publicFlag != Public.DONT_CARE) {
532: boolean isPublic = method.getModifiers()
533: .contains(Modifier.PUBLIC);
534: if ((isPublic && publicFlag == Public.NO)
535: || (!isPublic && publicFlag == Public.YES)) {
536: continue;
537: }
538: }
539:
540: // found!
541: this .methodHandle = ElementHandle.create(method);
542: return;
543: }
544:
545: TypeMirror super ClassMirror = element.getSuperclass();
546: if (super ClassMirror instanceof DeclaredType) {
547: DeclaredType declaredType = (DeclaredType) super ClassMirror;
548: Element elem = declaredType.asElement();
549: if (elem.getKind() == ElementKind.CLASS) {
550: element = (TypeElement) elem;
551: }
552: } else {
553: element = null;
554: }
555: }
556: }
557:
558: public ElementHandle<ExecutableElement> getMethodHandle() {
559: return this .methodHandle;
560: }
561: }
562:
563: public static SpringBean getMergedBean(SpringBean origBean,
564: Document doc) {
565: if (origBean == null) {
566: return null;
567: }
568:
569: if (origBean.getParent() == null) {
570: return origBean;
571: }
572:
573: ModelBasedSpringBean logicalBean = new ModelBasedSpringBean(
574: origBean, doc);
575: return getMergedBean(logicalBean, doc);
576: }
577:
578: public static SpringBean getMergedBean(Node beanNode, Document doc) {
579:
580: NodeBasedSpringBean logicalBean = new NodeBasedSpringBean(
581: beanNode, doc);
582: if (!StringUtils.hasText(logicalBean.getParent())) {
583: return logicalBean;
584: }
585:
586: return getMergedBean(logicalBean, doc);
587: }
588:
589: private static SpringBean getMergedBean(
590: MutableSpringBean startBean, Document doc) {
591: final MutableSpringBean[] logicalBean = { startBean };
592: SpringConfigModel model = SpringConfigModel
593: .forFileObject(NbEditorUtilities.getFileObject(doc));
594: if (model == null) {
595: return null;
596: }
597:
598: try {
599: model.runReadAction(new Action<SpringBeans>() {
600:
601: public void run(SpringBeans springBeans) {
602: String currParent = logicalBean[0].getParent();
603: Set<SpringBean> walkedBeans = new HashSet<SpringBean>();
604: while (currParent != null
605: && (logicalBean[0].getClassName() == null
606: || logicalBean[0].getFactoryBean() == null || logicalBean[0]
607: .getFactoryMethod() == null)) {
608: SpringBean currBean = springBeans
609: .findBean(currParent);
610: if (walkedBeans.contains(currBean)) {
611: // circular dep. nullify everything
612: logicalBean[0] = null;
613: break;
614: }
615:
616: if (logicalBean[0].getClassName() == null) {
617: logicalBean[0].setClassName(currBean
618: .getClassName());
619: }
620: if (logicalBean[0].getFactoryBean() == null) {
621: logicalBean[0].setFactoryBean(currBean
622: .getFactoryBean());
623: }
624: if (logicalBean[0].getFactoryMethod() == null) {
625: logicalBean[0].setFactoryMethod(currBean
626: .getFactoryMethod());
627: }
628:
629: walkedBeans.add(currBean);
630: currParent = currBean.getParent();
631: }
632: }
633: });
634: } catch (IOException ioe) {
635: Exceptions.printStackTrace(ioe);
636: logicalBean[0] = null;
637: }
638:
639: return logicalBean[0];
640: }
641:
642: private static interface MutableSpringBean extends SpringBean {
643: void setClassName(String className);
644:
645: void setFactoryBean(String factoryBean);
646:
647: void setFactoryMethod(String factoryMethod);
648: }
649:
650: private static class ModelBasedSpringBean implements
651: MutableSpringBean {
652: private String className;
653: private String factoryBean;
654: private String factoryMethod;
655: private String parent;
656: private String id;
657: private List<String> names;
658: private Location location;
659:
660: public ModelBasedSpringBean(SpringBean springBean, Document doc) {
661: this .className = springBean.getClassName();
662: this .factoryBean = springBean.getFactoryBean();
663: this .factoryMethod = springBean.getFactoryMethod();
664: this .parent = springBean.getParent();
665: this .id = springBean.getId();
666: this .location = springBean.getLocation();
667: this .names = springBean.getNames();
668: }
669:
670: public String getId() {
671: return id;
672: }
673:
674: public List<String> getNames() {
675: return names;
676: }
677:
678: public String getClassName() {
679: return className;
680: }
681:
682: public void setClassName(String className) {
683: this .className = className;
684: }
685:
686: public String getParent() {
687: return parent;
688: }
689:
690: public String getFactoryBean() {
691: return factoryBean;
692: }
693:
694: public void setFactoryBean(String factoryBean) {
695: this .factoryBean = factoryBean;
696: }
697:
698: public String getFactoryMethod() {
699: return factoryMethod;
700: }
701:
702: public void setFactoryMethod(String factoryMethod) {
703: this .factoryMethod = factoryMethod;
704: }
705:
706: public Location getLocation() {
707: return location;
708: }
709:
710: }
711:
712: private static class NodeBasedSpringBean implements
713: MutableSpringBean {
714:
715: private String className;
716: private String factoryBean;
717: private String factoryMethod;
718: private String parent;
719: private String id;
720: private List<String> names;
721: private int offset;
722: private File file;
723:
724: public NodeBasedSpringBean(Node node, Document doc) {
725: this .className = getAttribute(node, "class"); // NOI18N
726: this .factoryBean = getAttribute(node, "factory-bean"); // NOI18N
727: this .factoryMethod = getAttribute(node, "factory-method"); // NOI18N
728: this .parent = getAttribute(node, "parent"); // NOI18N
729: this .id = getAttribute(node, "id"); // NOI18N
730: this .offset = ((Tag) node).getElementOffset();
731: this .file = FileUtil.toFile(NbEditorUtilities
732: .getFileObject(doc));
733:
734: if (!hasAttribute(node, "name")) { // NOI18N
735: this .names = Collections.<String> emptyList();
736: }
737: this .names = StringUtils.tokenize(
738: getAttribute(node, "name"), BEAN_NAME_DELIMITERS); // NOI18N
739: }
740:
741: public String getId() {
742: return this .id;
743: }
744:
745: public List<String> getNames() {
746: return names;
747: }
748:
749: public String getClassName() {
750: return className;
751: }
752:
753: public void setClassName(String className) {
754: this .className = className;
755: }
756:
757: public String getParent() {
758: return this .parent;
759: }
760:
761: public String getFactoryBean() {
762: return this .factoryBean;
763: }
764:
765: public void setFactoryBean(String factoryBean) {
766: this .factoryBean = factoryBean;
767: }
768:
769: public String getFactoryMethod() {
770: return this .factoryMethod;
771: }
772:
773: public void setFactoryMethod(String factoryMethod) {
774: this .factoryMethod = factoryMethod;
775: }
776:
777: public Location getLocation() {
778: return new Location() {
779:
780: public File getFile() {
781: return file;
782: }
783:
784: public int getOffset() {
785: return offset;
786: }
787: };
788: }
789:
790: }
791:
792: public static List<ExecutableElement> findPropertiesOnType(
793: ElementUtilities eu, TypeMirror type, String propertyName,
794: boolean searchGetters, boolean searchSetters) {
795: PropertyAcceptor propertyAcceptor = new PropertyAcceptor(
796: propertyName, searchGetters, searchSetters);
797: Iterable<? extends Element> matchingProp = eu.getMembers(type,
798: propertyAcceptor);
799: Iterator<? extends Element> it = matchingProp.iterator();
800: // no matching element found
801: if (!it.hasNext()) {
802: return Collections.emptyList();
803: }
804:
805: List<ExecutableElement> retList = new ArrayList<ExecutableElement>();
806: for (Element e : matchingProp) {
807: retList.add((ExecutableElement) e);
808: }
809:
810: return retList;
811: }
812:
813: private static class PropertyAcceptor implements
814: ElementUtilities.ElementAcceptor {
815: private boolean searchSetters;
816: private boolean searchGetters;
817: private String propPrefix;
818:
819: public PropertyAcceptor(String propPrefix,
820: boolean searchGetters, boolean searchSetters) {
821: // captialize first character of the property prefix - for matching
822: if (propPrefix.length() > 0) {
823: char[] prop = propPrefix.toCharArray();
824: prop[0] = Character.toUpperCase(prop[0]);
825: this .propPrefix = String.valueOf(prop);
826: } else {
827: this .propPrefix = propPrefix;
828: }
829: this .searchGetters = searchGetters;
830: this .searchSetters = searchSetters;
831: }
832:
833: public boolean accept(Element e, TypeMirror type) {
834: if (e.getKind() != ElementKind.METHOD) {
835: return false;
836: }
837:
838: ExecutableElement ee = (ExecutableElement) e;
839: String methodName = ee.getSimpleName().toString();
840: if (methodName.length() < 4) {
841: return false;
842: }
843:
844: if (ee.getModifiers().contains(Modifier.PRIVATE)
845: || ee.getModifiers().contains(Modifier.STATIC)) {
846: return false;
847: }
848:
849: if (!methodName.startsWith(propPrefix, 3)) {
850: return false;
851: }
852:
853: if (searchSetters && methodName.startsWith("set")
854: && ee.getParameters().size() == 1
855: && ee.getReturnType().getKind() == TypeKind.VOID) { // NOI18N
856: return true;
857: }
858: if (searchGetters && methodName.startsWith("get")
859: && ee.getParameters().size() == 0
860: && ee.getReturnType().getKind() != TypeKind.VOID) { // NOI18N
861: return true;
862: }
863:
864: return false;
865: }
866: }
867: }
|