Lines 41-47
Link Here
|
41 |
* Version 2 license, then the option applies only if the new code is |
41 |
* Version 2 license, then the option applies only if the new code is |
42 |
* made subject to such option by the copyright holder. |
42 |
* made subject to such option by the copyright holder. |
43 |
*/ |
43 |
*/ |
44 |
|
|
|
45 |
package org.netbeans.modules.j2ee.jpa.verification.rules.entity; |
44 |
package org.netbeans.modules.j2ee.jpa.verification.rules.entity; |
46 |
|
45 |
|
47 |
import java.util.ArrayList; |
46 |
import java.util.ArrayList; |
Lines 49-75
Link Here
|
49 |
import java.util.List; |
48 |
import java.util.List; |
50 |
import java.util.ListResourceBundle; |
49 |
import java.util.ListResourceBundle; |
51 |
import java.util.Locale; |
50 |
import java.util.Locale; |
52 |
import java.util.Map; |
|
|
53 |
import java.util.MissingResourceException; |
51 |
import java.util.MissingResourceException; |
54 |
import java.util.ResourceBundle; |
52 |
import java.util.ResourceBundle; |
55 |
import java.util.logging.Level; |
53 |
import java.util.logging.Level; |
56 |
import javax.lang.model.element.AnnotationMirror; |
|
|
57 |
import javax.lang.model.element.AnnotationValue; |
58 |
import javax.lang.model.element.ExecutableElement; |
59 |
import javax.lang.model.element.TypeElement; |
54 |
import javax.lang.model.element.TypeElement; |
60 |
import org.eclipse.persistence.jpa.internal.jpql.JPQLQueryProblemResourceBundle; |
55 |
import org.eclipse.persistence.jpa.internal.jpql.JPQLQueryProblemResourceBundle; |
61 |
import org.eclipse.persistence.jpa.jpql.JPQLQueryHelper; |
56 |
import org.eclipse.persistence.jpa.jpql.JPQLQueryHelper; |
62 |
import org.eclipse.persistence.jpa.jpql.JPQLQueryProblem; |
57 |
import org.eclipse.persistence.jpa.jpql.JPQLQueryProblem; |
63 |
import org.eclipse.persistence.jpa.jpql.spi.IQuery; |
|
|
64 |
import org.netbeans.api.project.FileOwnerQuery; |
58 |
import org.netbeans.api.project.FileOwnerQuery; |
65 |
import org.netbeans.api.project.Project; |
59 |
import org.netbeans.api.project.Project; |
66 |
import org.netbeans.modules.j2ee.jpa.model.JPAAnnotations; |
60 |
import org.netbeans.modules.j2ee.jpa.verification.CancelListener; |
67 |
import org.netbeans.modules.j2ee.jpa.verification.JPAClassRule; |
61 |
import org.netbeans.modules.j2ee.jpa.verification.JPAClassRule; |
68 |
import org.netbeans.modules.j2ee.jpa.verification.JPAClassRule.ClassConstraints; |
62 |
import org.netbeans.modules.j2ee.jpa.verification.JPAClassRule.ClassConstraints; |
69 |
import org.netbeans.modules.j2ee.jpa.verification.JPAProblemContext; |
63 |
import org.netbeans.modules.j2ee.jpa.verification.JPAProblemContext; |
70 |
import org.netbeans.modules.j2ee.jpa.verification.JPAProblemFinder; |
64 |
import org.netbeans.modules.j2ee.jpa.verification.JPAProblemFinder; |
71 |
import org.netbeans.modules.j2ee.jpa.verification.common.ProblemContext; |
65 |
import org.netbeans.modules.j2ee.jpa.verification.common.ProblemContext; |
72 |
import org.netbeans.modules.j2ee.jpa.verification.common.Utilities; |
|
|
73 |
import org.netbeans.modules.j2ee.persistence.api.metadata.orm.Entity; |
66 |
import org.netbeans.modules.j2ee.persistence.api.metadata.orm.Entity; |
74 |
import org.netbeans.modules.j2ee.persistence.api.metadata.orm.NamedQuery; |
67 |
import org.netbeans.modules.j2ee.persistence.api.metadata.orm.NamedQuery; |
75 |
import org.netbeans.modules.j2ee.persistence.spi.jpql.ManagedTypeProvider; |
68 |
import org.netbeans.modules.j2ee.persistence.spi.jpql.ManagedTypeProvider; |
Lines 78-182
Link Here
|
78 |
import org.netbeans.spi.editor.hints.Severity; |
71 |
import org.netbeans.spi.editor.hints.Severity; |
79 |
|
72 |
|
80 |
/** |
73 |
/** |
81 |
* Verify content of @NamedQuery query |
74 |
* Verify content of |
82 |
* TODO: good to move warning to query level instead of class level |
75 |
* |
|
|
76 |
* @NamedQuery query TODO: good to move warning to query level instead of class |
77 |
* level |
83 |
*/ |
78 |
*/ |
84 |
public class JPQLValidation extends JPAClassRule { |
79 |
public class JPQLValidation extends JPAClassRule implements CancelListener { |
85 |
|
80 |
|
86 |
/** Creates a new instance of NonFinalClass */ |
81 |
private ManagedTypeProvider mtp;//need to store as jpql validation may be too long and need to be cancelled if required |
|
|
82 |
private JPQLQueryHelper helper; |
83 |
|
84 |
/** |
85 |
* Creates a new instance of NonFinalClass |
86 |
*/ |
87 |
public JPQLValidation() { |
87 |
public JPQLValidation() { |
88 |
setClassContraints(Arrays.asList(ClassConstraints.ENTITY, |
88 |
setClassContraints(Arrays.asList(ClassConstraints.ENTITY, |
89 |
ClassConstraints.EMBEDDABLE, |
89 |
ClassConstraints.EMBEDDABLE, |
90 |
ClassConstraints.MAPPED_SUPERCLASS)); |
90 |
ClassConstraints.MAPPED_SUPERCLASS)); |
91 |
} |
91 |
} |
92 |
|
92 |
|
93 |
@Override public ErrorDescription[] apply(TypeElement subject, ProblemContext ctx){ |
93 |
@Override |
|
|
94 |
public ErrorDescription[] apply(TypeElement subject, ProblemContext ctx) { |
95 |
JPAProblemContext jpaCtx = (JPAProblemContext) ctx; |
96 |
jpaCtx.addCancelListener(this); |
94 |
Object modEl = ctx.getModelElement(); |
97 |
Object modEl = ctx.getModelElement(); |
95 |
Entity entity = (Entity) (modEl instanceof Entity ? modEl : null); |
98 |
Entity entity = (Entity) (modEl instanceof Entity ? modEl : null); |
96 |
List<AnnotationMirror> first = Utilities.findAnnotations(subject, JPAAnnotations.NAMED_QUERY); |
99 |
helper = new JPQLQueryHelper(); |
97 |
ArrayList<String> values = new ArrayList<String>(); |
100 |
Project project = FileOwnerQuery.getOwner(ctx.getFileObject()); |
98 |
ArrayList<String> names = new ArrayList<String>(); |
101 |
List<JPQLQueryProblem> problems = new ArrayList<JPQLQueryProblem>(); |
99 |
if(first == null || first.size()==0){ |
102 |
mtp = new ManagedTypeProvider(project, jpaCtx.getMetaData(), jpaCtx.getCompilationInfo().getElements()); |
100 |
AnnotationMirror qs = Utilities.findAnnotation(subject, JPAAnnotations.NAMED_QUERIES); |
103 |
if (entity != null) { |
101 |
if(qs != null){ |
104 |
for (NamedQuery nq : entity.getNamedQuery()) { |
102 |
Map<? extends ExecutableElement, ? extends AnnotationValue> maps = qs.getElementValues(); |
105 |
if(nq!=null && nq.getQuery()!=null){ |
103 |
for(AnnotationValue vl:maps.values()){ |
106 |
helper.setQuery(new Query(nq, nq.getQuery(), mtp)); |
104 |
List lst = (List) vl.getValue(); |
107 |
List<JPQLQueryProblem> tmp = null; |
105 |
for(Object val:lst){ |
108 |
try { |
106 |
if(val instanceof AnnotationMirror){ |
109 |
tmp = helper.validate(); |
107 |
AnnotationMirror am = (AnnotationMirror) val; |
110 |
} catch (UnsupportedOperationException ex) { |
108 |
if(JPAAnnotations.NAMED_QUERY.equals(am.getAnnotationType().toString())){ |
111 |
JPAProblemFinder.LOG.log(Level.INFO, "Unsupported jpql validation case: " + ex.getMessage(), ex); |
109 |
AnnotationValue qAttrValue = Utilities.getAnnotationAttrValue(am, "query"); |
112 |
} catch (NullPointerException ex) { |
110 |
AnnotationValue nmAttrValue = Utilities.getAnnotationAttrValue(am, "name"); |
113 |
JPAProblemFinder.LOG.log(Level.INFO, "NPE in jpql validation: " + ex.getMessage(), ex); |
111 |
if(qAttrValue != null){ |
|
|
112 |
values.add(qAttrValue.getValue().toString()); |
113 |
names.add(nmAttrValue == null ? "" : nmAttrValue.getValue().toString()); |
114 |
} |
115 |
} |
116 |
} |
117 |
} |
114 |
} |
|
|
115 |
if (tmp != null && tmp.size() > 0) { |
116 |
problems.addAll(tmp); |
117 |
} |
118 |
helper.dispose(); |
118 |
} |
119 |
} |
119 |
} |
120 |
} |
120 |
} |
121 |
} |
121 |
else { |
122 |
ErrorDescription[] ret = null; |
122 |
for(AnnotationMirror mr:first){ |
123 |
if (!ctx.isCancelled() && problems != null && problems.size() > 0) { |
123 |
AnnotationValue qAttrValue = Utilities.getAnnotationAttrValue(mr, "query"); |
124 |
ret = new ErrorDescription[problems.size()]; |
124 |
AnnotationValue nmAttrValue = Utilities.getAnnotationAttrValue(mr, "name"); |
125 |
for (int i = 0; i < ret.length; i++) { |
125 |
if(qAttrValue != null){ |
|
|
126 |
values.add(qAttrValue.getValue().toString()); |
127 |
names.add(nmAttrValue == null ? "" : nmAttrValue.getValue().toString()); |
128 |
} |
129 |
} |
130 |
} |
131 |
JPQLQueryHelper helper = new JPQLQueryHelper(); |
132 |
Project project = FileOwnerQuery.getOwner(ctx.getFileObject()); |
133 |
List<JPQLQueryProblem> problems = new ArrayList<JPQLQueryProblem>(); |
134 |
for(int index=0;index<values.size();index++){ |
135 |
String value = values.get(index); |
136 |
String qName = names.get(index); |
137 |
NamedQuery nq = null; |
138 |
if(entity != null) { |
139 |
nq = entity.newNamedQuery(); |
140 |
nq.setQuery(value); |
141 |
nq.setName(qName); |
142 |
} |
143 |
helper.setQuery(new Query(nq, value, new ManagedTypeProvider(project, ((JPAProblemContext)ctx).getMetaData()))); |
144 |
List<JPQLQueryProblem> tmp = null; |
145 |
try{ |
146 |
tmp = helper.validate(); |
147 |
} catch (UnsupportedOperationException ex) { |
148 |
JPAProblemFinder.LOG.log(Level.INFO, "Unsupported jpql validation case: " + ex.getMessage(), ex); |
149 |
}catch (NullPointerException ex) { |
150 |
JPAProblemFinder.LOG.log(Level.INFO, "NPE in jpql validation: " + ex.getMessage(), ex); |
151 |
} |
152 |
if(tmp!=null && tmp.size()>0)problems.addAll(tmp); |
153 |
helper.dispose(); |
154 |
} |
155 |
if (problems != null && problems.size()>0){ |
156 |
ErrorDescription[] ret = new ErrorDescription[problems.size()]; |
157 |
for(int i=0;i<ret.length;i++){ |
158 |
ListResourceBundle msgBundle = null; |
126 |
ListResourceBundle msgBundle = null; |
159 |
try{ |
127 |
try { |
160 |
msgBundle = (ListResourceBundle) ResourceBundle.getBundle(JPQLQueryProblemResourceBundle.class.getName());//NOI18N |
128 |
msgBundle = (ListResourceBundle) ResourceBundle.getBundle(JPQLQueryProblemResourceBundle.class.getName());//NOI18N |
161 |
} catch (MissingResourceException ex) {//default en |
129 |
} catch (MissingResourceException ex) {//default en |
162 |
msgBundle = (ListResourceBundle) ResourceBundle.getBundle(JPQLQueryProblemResourceBundle.class.getName(), Locale.ENGLISH);//NOI18N |
130 |
msgBundle = (ListResourceBundle) ResourceBundle.getBundle(JPQLQueryProblemResourceBundle.class.getName(), Locale.ENGLISH);//NOI18N |
163 |
} |
131 |
} |
164 |
String message = java.text.MessageFormat.format(msgBundle.getString(problems.get(i).getMessageKey()), (Object[]) problems.get(i).getMessageArguments()); |
132 |
String message = java.text.MessageFormat.format(msgBundle.getString(problems.get(i).getMessageKey()), (Object[]) problems.get(i).getMessageArguments()); |
165 |
String pos = "["+problems.get(i).getStartPosition() + ";"+problems.get(i).getEndPosition()+"]"; |
133 |
String pos = "[" + problems.get(i).getStartPosition() + ";" + problems.get(i).getEndPosition() + "]"; |
166 |
Query q = (Query) problems.get(i).getQuery(); |
134 |
Query q = (Query) problems.get(i).getQuery(); |
167 |
if(q.getNamedQuery() != null && q.getNamedQuery().getName()!=null){ |
135 |
if (q.getNamedQuery() != null && q.getNamedQuery().getName() != null) { |
168 |
pos = q.getNamedQuery().getName()+pos; |
136 |
pos = q.getNamedQuery().getName() + pos; |
169 |
} |
137 |
} |
170 |
ret[i] = createProblem(subject, ctx, pos + ": " + message , Severity.WARNING); |
138 |
ret[i] = createProblem(subject, ctx, pos + ": " + message, Severity.WARNING); |
171 |
} |
139 |
} |
172 |
return ret; |
|
|
173 |
} |
140 |
} |
174 |
return null; |
141 |
jpaCtx.removeCancelListener(this); |
|
|
142 |
mtp = null; |
143 |
helper = null; |
144 |
return ret; |
175 |
} |
145 |
} |
176 |
|
146 |
|
177 |
@Override protected boolean isApplicable(TypeElement subject, ProblemContext ctx) { |
147 |
@Override |
178 |
JPAProblemContext jpaCtx = (JPAProblemContext)ctx; |
148 |
protected boolean isApplicable(TypeElement subject, ProblemContext ctx) { |
179 |
|
149 |
JPAProblemContext jpaCtx = (JPAProblemContext) ctx; |
|
|
150 |
|
180 |
return (jpaCtx.isEntity() || jpaCtx.isMappedSuperClass()); |
151 |
return (jpaCtx.isEntity() || jpaCtx.isMappedSuperClass()); |
181 |
} |
152 |
} |
|
|
153 |
|
154 |
@Override |
155 |
public void cancelled() { |
156 |
if (mtp != null) { |
157 |
mtp.invalidate(); |
158 |
} |
159 |
if (helper != null) { |
160 |
helper.dispose(); |
161 |
} |
162 |
} |
182 |
} |
163 |
} |