View Javadoc

1   /*
2    * ----------------------------------------------------------------------
3    * Copyright (C) 2009 Enrique Lara (k957@68k.org)
4    *
5    * TinLizard is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU Lesser General Public License
7    * as published by the Free Software Foundation; either version 3.0
8    * of the License, or (at your option) any later version.
9    *
10   * TinLizard is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public License
16   * along with TinLizard. If not, see http://www.gnu.org/licenses/.
17   * ----------------------------------------------------------------------
18   */
19  package tinlizard.model;
20  
21  import tinlizard.dao.jpa.JpaDao;
22  import tinlizard.dao.jpa.Persistable;
23  
24  import java.util.ArrayList;
25  import java.util.Calendar;
26  import java.util.Collection;
27  import java.util.Date;
28  import java.util.Iterator;
29  
30  import javax.persistence.Column;
31  import javax.persistence.Entity;
32  import javax.persistence.EntityManager;
33  import javax.persistence.EntityNotFoundException;
34  import javax.persistence.EntityTransaction;
35  import javax.persistence.GeneratedValue;
36  import javax.persistence.GenerationType;
37  import javax.persistence.Id;
38  import javax.persistence.JoinColumn;
39  import javax.persistence.ManyToOne;
40  import javax.persistence.NamedQueries;
41  import javax.persistence.NamedQuery;
42  import javax.persistence.Query;
43  import javax.persistence.Table;
44  import javax.persistence.UniqueConstraint;
45  import javax.persistence.Version;
46  
47  import org.apache.log4j.Logger;
48  import org.apache.maven.model.Model;
49  
50  import org.codehaus.plexus.util.StringUtils;
51  
52  import org.hibernate.annotations.Cache;
53  import org.hibernate.annotations.CacheConcurrencyStrategy;
54  import org.hibernate.search.annotations.DateBridge;
55  import org.hibernate.search.annotations.Field;
56  import org.hibernate.search.annotations.Index;
57  import org.hibernate.search.annotations.Indexed;
58  import org.hibernate.search.annotations.Resolution;
59  import org.hibernate.search.annotations.Store;
60  
61  /***
62   * A Codeline is a branch.
63   */
64  @Entity(name = "Codeline")
65  @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "tinlizard.model.Codeline")
66  @Table(name = "TL_CODELINE", uniqueConstraints =  {
67      @UniqueConstraint(columnNames =  {
68          "NAME", "PROJECT_ID"}
69      )
70      , @UniqueConstraint(columnNames =  {
71          "NAME", "SCM_CONNECTION"}
72      )
73  }
74  )
75  @NamedQueries({@NamedQuery(name = QueryNames.CODELINE_BY_NAME,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where o.name = ? and p = ?" + Codeline.ORDER_BY)
76      , @NamedQuery(name = QueryNames.CODELINES_MODIFIED_SINCE_DATE,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where o.lastModified >= ?" + Codeline.ORDER_BY + " DESC")
77      , @NamedQuery(name = QueryNames.CODELINES_BY_NAME_AND_SCM_CONNECTION,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where o.name = ? and o.scmConnection = ?" + Codeline.ORDER_BY)
78      , @NamedQuery(name = QueryNames.CODELINE_MAIN_LINE,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where o.mainLine = true and p = ?" + Codeline.ORDER_BY)
79      , @NamedQuery(name = QueryNames.CODELINES_ACTIVE,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where o.policy.active = true " + Codeline.ORDER_BY)
80      , @NamedQuery(name = QueryNames.CODELINES_ACTIVE_FOR_PROJECT,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where p = ? and o.policy.active = true " + Codeline.ORDER_BY)
81      , @NamedQuery(name = QueryNames.CODELINES_ACTIVE_FOR_VIEW,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where c = ? and o.policy.active = true " + Codeline.ORDER_BY)
82      , @NamedQuery(name = QueryNames.CODELINES_ALL_FOR_PROJECT,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where p = ?" + Codeline.ORDER_BY)
83      , @NamedQuery(name = QueryNames.CODELINES_ALL_FOR_VIEW,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where c = ?" + Codeline.ORDER_BY)
84      , @NamedQuery(name = QueryNames.CODELINES_ALL_FOR_POLICY,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where policy = ?" + Codeline.ORDER_BY)
85      , @NamedQuery(name = QueryNames.CODELINES_DEFINING_ARTIFACT,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where o.groupId = ? and o.artifactId = ? and o.version = ?" + Codeline.ORDER_BY)
86      , @NamedQuery(name = QueryNames.CODELINES_DEFINING_ARTIFACT_ANY_VERSION,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where o.groupId = ? and o.artifactId = ?" + Codeline.ORDER_BY)
87      , @NamedQuery(name = QueryNames.CODELINES_DEPENDENT_ON_ARTIFACT,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where o in (select distinct dep.codeline from Dependency dep where dep.groupId = ? and dep.artifactId = ? and dep.version = ?)" + Codeline.ORDER_BY)
88      , @NamedQuery(name = QueryNames.CODELINES_DEPENDENT_ON_ARTIFACT_ANY_VERSION,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where o in (select distinct dep.codeline from Dependency dep where dep.groupId = ? and dep.artifactId = ?)" + Codeline.ORDER_BY)
89      , @NamedQuery(name = QueryNames.CODELINES_BY_USER,query = Codeline.SELECT_FROM + Codeline.LEFT_JOINS + " where user = ?" + Codeline.ORDER_BY)
90  })
91  @Indexed
92  public final class Codeline implements Persistable {
93      static final String SELECT_FROM = "select o from Codeline o ";
94      static final String LEFT_JOINS = " left join o.owner user " + " left join o.policy policy " + " left join o.view c " + " left join o.project p ";
95      static final String ORDER_BY = " order by o.name";
96      private static final Class<Codeline> CLASS = Codeline.class;
97      private static final Logger LOG = Logger.getLogger(CLASS);
98      @Id
99      @GeneratedValue(strategy = GenerationType.AUTO)
100     @Column(name = "ID")
101     private Integer id;
102     @Column(name = "NAME", nullable = false)
103     @Field(index = Index.TOKENIZED, store = Store.NO)
104     private String name;
105     @Column(name = "CREATED", nullable = false)
106     @Field(index = Index.UN_TOKENIZED, store = Store.YES)
107     @DateBridge(resolution = Resolution.SECOND)
108     private Date created;
109     @Column(name = "CREATED_BY", nullable = false)
110     @Field(index = Index.TOKENIZED, store = Store.NO)
111     private String createdBy;
112     @Version
113     @Column(name = "LAST_MODIFIED")
114     @Field(index = Index.UN_TOKENIZED, store = Store.YES)
115     @DateBridge(resolution = Resolution.SECOND)
116     private Date lastModified;
117     @Column(name = "LAST_MODIFIED_BY")
118     @Field(index = Index.TOKENIZED, store = Store.NO)
119     private String lastModifiedBy;
120     @Column(name = "SCM_CONNECTION")
121     @Field(index = Index.TOKENIZED, store = Store.NO)
122     private String scmConnection;
123     @Column(name = "GROUP_ID")
124     @Field(index = Index.TOKENIZED, store = Store.NO)
125     private String groupId;
126     @Column(name = "ARTIFACT_ID")
127     @Field(index = Index.TOKENIZED, store = Store.NO)
128     private String artifactId;
129     @Column(name = "VERSION")
130     @Field(index = Index.TOKENIZED, store = Store.NO)
131     private String version;
132     @ManyToOne
133     @JoinColumn(name = "OWNER_ID", nullable = false)
134     private User owner;
135     @ManyToOne
136     @JoinColumn(name = "POLICY_ID", nullable = false)
137     private Policy policy;
138     @Column(name = "MAIN_FLAG", nullable = false)
139     private Boolean mainLine = false;
140     @ManyToOne
141     @JoinColumn(name = "VIEW_ID") //, nullable = false)
142 
143     private View view;
144     @ManyToOne
145     @JoinColumn(name = "PROJECT_ID") //, nullable = false)
146 
147     private Project project;
148     @Column(name = "DESCRIPTION")
149     @Field(index = Index.TOKENIZED, store = Store.NO)
150     private String description;
151 
152     public Integer getId() {
153         return this.id;
154     }
155 
156     public String getName() {
157         return this.name;
158     }
159 
160     public Date getCreated() {
161         return this.created;
162     }
163 
164     public String getCreatedBy() {
165         return this.createdBy;
166     }
167 
168     public Date getLastModified() {
169         return this.lastModified;
170     }
171 
172     public String getLastModifiedBy() {
173         return this.lastModifiedBy;
174     }
175 
176     public void setId(final Integer id) {
177         this.id = id;
178     }
179 
180     public void setName(final String name) {
181         this.name = name;
182     }
183 
184     public void setCreated(final Date created) {
185         this.created = created;
186     }
187 
188     public void setCreatedBy(final String createdBy) {
189         this.createdBy = createdBy;
190     }
191 
192     public void setLastModified(final Date lastModified) {
193         this.lastModified = lastModified;
194     }
195 
196     public void setLastModifiedBy(final String lastModifiedBy) {
197         this.lastModifiedBy = lastModifiedBy;
198     }
199 
200     public String getScmConnection() {
201         return this.scmConnection;
202     }
203 
204     public String getGroupId() {
205         return this.groupId;
206     }
207 
208     public String getArtifactId() {
209         return this.artifactId;
210     }
211 
212     public String getVersion() {
213         return this.version;
214     }
215 
216     public View getView() {
217         return this.view;
218     }
219 
220     public Project getProject() {
221         return this.project;
222     }
223 
224     public User getOwner() {
225         return this.owner;
226     }
227 
228     public Policy getPolicy() {
229         return this.policy;
230     }
231 
232     public boolean isMainLine() {
233         return mainLine;
234     }
235 
236     public Boolean getMainLine() {
237         return mainLine;
238     }
239 
240     public String getDescription() {
241         return this.description;
242     }
243 
244     public void setScmConnection(final String scmConnection) {
245         this.scmConnection = scmConnection;
246     }
247 
248     public void setGroupId(final String groupId) {
249         this.groupId = groupId;
250     }
251 
252     public void setArtifactId(final String artifactId) {
253         this.artifactId = artifactId;
254     }
255 
256     public void setVersion(final String version) {
257         this.version = version;
258     }
259 
260     public void setView(final View view) {
261         this.view = view;
262     }
263 
264     public void setProject(final Project project) {
265         this.project = project;
266     }
267 
268     public void setOwner(final User owner) {
269         this.owner = owner;
270     }
271 
272     public void setPolicy(final Policy policy) {
273         this.policy = policy;
274     }
275 
276     public void setMainLine(final Boolean mainLine) {
277         this.mainLine = mainLine;
278     }
279 
280     public void setDescription(final String description) {
281         this.description = description;
282     }
283 
284     public boolean addDependency(final Dependency dep) {
285         dep.setCodeline(this);
286 
287         return true;
288     }
289 
290     public static Collection<Codeline> findAll() {
291         return JpaDao.getInstance().findAll(CLASS);
292     }
293 
294     public static Collection<Codeline> findAllActive() {
295         Object[] params = {  };
296 
297         return JpaDao.getInstance().findByNamedQuery(CLASS, QueryNames.CODELINES_ACTIVE, params);
298     }
299 
300     public static Collection<Codeline> findRecentlyModified(final int daysAgo) {
301         Calendar cal = Calendar.getInstance();
302         cal.add(Calendar.DATE, -daysAgo);
303 
304         Object[] params = {
305                               cal.getTime()
306         }; //XXX assert daysAgo is positive.
307 
308         return JpaDao.getInstance().findByNamedQuery(CLASS, QueryNames.CODELINES_MODIFIED_SINCE_DATE, params);
309     }
310 
311     public static Collection<Codeline> findByNameAndScmConnection(final String name, final String scmConnection) {
312         Object[] params = {
313                               name,
314                               scmConnection
315         };
316 
317         return JpaDao.getInstance().findByNamedQuery(CLASS, QueryNames.CODELINES_BY_NAME_AND_SCM_CONNECTION, params);
318     }
319 
320     public Collection<Codeline> findAllConsumers(final boolean useVersion) {
321         if (useVersion) {
322             Object[] params = {
323                                   getGroupId(),
324                                   getArtifactId(),
325                                   getVersion()
326             };
327 
328             return JpaDao.getInstance().findByNamedQuery(CLASS, QueryNames.CODELINES_DEPENDENT_ON_ARTIFACT, params);
329         } else {
330             Object[] params = {
331                                   getGroupId(),
332                                   getArtifactId()
333             };
334 
335             return JpaDao.getInstance().findByNamedQuery(CLASS, QueryNames.CODELINES_DEPENDENT_ON_ARTIFACT_ANY_VERSION, params);
336         }
337     }
338 
339     public void add() {
340         JpaDao.getInstance().add(this);
341     }
342 
343     public void update() {
344         JpaDao.getInstance().update(this);
345     }
346 
347     public void index() {
348         JpaDao.getInstance().index(this);
349     }
350 
351     public void delete() {
352         TinLizard.getInstance().getScmDao().releaseFiles(this);
353 
354         EntityManager em = JpaDao.getInstance().getEm();
355         EntityTransaction tx = em.getTransaction();
356         tx.begin();
357 
358         Class<?> clazz = CLASS;
359         Integer id = getId();
360 
361         try {
362             String clazzName;
363             int deleted;
364 
365             //
366             clazzName = Dependency.class.getSimpleName();
367 
368             Query query = em.createQuery("delete from " + clazzName + " o where o.codeline.id = :id");
369             query.setParameter("id", id);
370             deleted = query.executeUpdate();
371 
372             if (LOG.isDebugEnabled()) {
373                 LOG.debug("Deleted " + deleted + " of type " + clazzName + ".");
374             }
375 
376             //
377             clazzName = Codeline.class.getSimpleName();
378             query = em.createQuery("delete from " + clazzName + " o where o.id = :id");
379             query.setParameter("id", id);
380             deleted = query.executeUpdate();
381 
382             if (LOG.isDebugEnabled()) {
383                 LOG.debug("Deleted " + deleted + " of type " + clazzName + ".");
384             }
385 
386             //
387             em.refresh(project);
388 
389             tx.commit();
390         } catch (EntityNotFoundException e) {
391             JpaDao.getInstance().handleInfo(tx, ("Object " + clazz + "#" + id + " did not exist"), e);
392         } catch (Exception e) {
393             JpaDao.getInstance().handleError(tx, "Delete Error", e);
394         }
395     }
396 
397     public void deleteAllDependencies() {
398         EntityManager em = JpaDao.getInstance().getEm();
399         EntityTransaction tx = em.getTransaction();
400         tx.begin();
401 
402         Integer id = getId();
403 
404         try {
405             String clazzName = Dependency.class.getSimpleName();
406 
407             Query query = em.createQuery("delete from " + clazzName + " o where o.codeline.id = :id");
408             query.setParameter("id", id);
409 
410             int deleted = query.executeUpdate();
411 
412             if (LOG.isDebugEnabled()) {
413                 LOG.debug("Deleted " + deleted + " of type " + clazzName + ".");
414             }
415 
416             tx.commit();
417         } catch (Exception e) {
418             JpaDao.getInstance().handleError(tx, "Delete Error", e);
419         }
420     }
421 
422     public Collection<Dependency> findAllDependencies() {
423         Object[] params = {
424                               this
425         };
426 
427         return JpaDao.getInstance().findByNamedQuery(Dependency.class, QueryNames.DEPENDENCIES_BY_CODELINE, params);
428     }
429 
430     public void refresh() {
431         TinLizard.getInstance().getScmDao().update(this);
432         updateFromPom();
433     }
434 
435     @SuppressWarnings("unchecked")
436     private void updateFromPom() {
437         Model pom = TinLizard.getInstance().getScmDao().getPOM(this); //XXX what about getEffectivePom(pb); ?
438 
439         if (StringUtils.isNotBlank(pom.getGroupId())) {
440             setGroupId(pom.getGroupId());
441         } else {
442             setGroupId(pom.getParent().getGroupId());
443         }
444 
445         setArtifactId(pom.getArtifactId());
446         setVersion(pom.getVersion());
447 
448         deleteAllDependencies();
449 
450         Collection<org.apache.maven.model.Dependency> dependencies = pom.getDependencies();
451 
452         for (org.apache.maven.model.Dependency dependency : dependencies) {
453             Dependency dep = new Dependency();
454             dep.setGroupId(dependency.getGroupId());
455             dep.setArtifactId(dependency.getArtifactId());
456             dep.setVersion(dependency.getVersion());
457             dep.setClassifier(dependency.getClassifier());
458             addDependency(dep);
459             dep.add();
460         }
461 
462         update();
463     }
464 
465     public Model getPOM() {
466         return TinLizard.getInstance().getScmDao().getPOM(this);
467     }
468 
469     @SuppressWarnings("unchecked")
470     public static Collection<String> findAllGroupIds() {
471         EntityManager em = JpaDao.getInstance().getEm();
472         EntityTransaction tx = em.getTransaction();
473         tx.begin();
474 
475         Collection<String> groupIds = null;
476 
477         try {
478             groupIds = new ArrayList<String>();
479 
480             Collection results = em.createQuery("select distinct o.groupId from Codeline o").getResultList();
481 
482             for (Iterator it = results.iterator(); it.hasNext();) {
483                 Object obj = it.next();
484                 groupIds.add(obj.toString());
485             }
486 
487             tx.commit();
488         } catch (Exception e) {
489             JpaDao.getInstance().handleError(tx, "Delete Error", e);
490         }
491 
492         return groupIds;
493     }
494 
495     @SuppressWarnings("unchecked")
496     public static Collection<String> findAllArtifactIds(final String groupId) {
497         EntityManager em = JpaDao.getInstance().getEm();
498         EntityTransaction tx = em.getTransaction();
499         tx.begin();
500 
501         Collection<String> artifactIds = null;
502 
503         try {
504             artifactIds = new ArrayList<String>();
505 
506             Collection results = em.createQuery("select distinct o.artifactId from Codeline o where groupId = ?").setParameter(1, groupId).getResultList();
507 
508             for (Iterator it = results.iterator(); it.hasNext();) {
509                 Object obj = it.next();
510                 artifactIds.add(obj.toString());
511             }
512 
513             tx.commit();
514         } catch (Exception e) {
515             JpaDao.getInstance().handleError(tx, "Delete Error", e);
516         }
517 
518         return artifactIds;
519     }
520 
521     public static Collection<Codeline> search(final String query) {
522         String[] fields = {
523                               "name",
524                               "created",
525                               "createdBy",
526                               "lastModified",
527                               "lastModifiedBy",
528                               "scmConnection",
529                               "groupId",
530                               "artifactId",
531                               "version"
532         };
533 
534         return JpaDao.getInstance().findByTextSearch(CLASS, query, fields);
535     }
536 
537     public static void indexAll() {
538         JpaDao.getInstance().indexAll(CLASS);
539     }
540 }