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 tinlizard.util.Messages;
25  
26  import java.util.Collection;
27  import java.util.Date;
28  
29  import javax.persistence.Column;
30  import javax.persistence.Entity;
31  import javax.persistence.EntityManager;
32  import javax.persistence.EntityNotFoundException;
33  import javax.persistence.EntityTransaction;
34  import javax.persistence.GeneratedValue;
35  import javax.persistence.GenerationType;
36  import javax.persistence.Id;
37  import javax.persistence.NamedQueries;
38  import javax.persistence.NamedQuery;
39  import javax.persistence.Query;
40  import javax.persistence.Table;
41  import javax.persistence.UniqueConstraint;
42  import javax.persistence.Version;
43  
44  import org.apache.log4j.Logger;
45  import org.apache.maven.scm.ScmException;
46  
47  import org.codehaus.plexus.util.StringUtils;
48  
49  import org.hibernate.search.annotations.DateBridge;
50  import org.hibernate.search.annotations.Field;
51  import org.hibernate.search.annotations.Index;
52  import org.hibernate.search.annotations.Indexed;
53  import org.hibernate.search.annotations.Resolution;
54  import org.hibernate.search.annotations.Store;
55  
56  /***
57   * The main artifact generated by a codeline or collection of codelines.
58   */
59  @Entity(name = "Project")
60  @Table(name = "TL_PROJECT", uniqueConstraints =  {
61      @UniqueConstraint(columnNames =  {
62          "NAME"}
63      )
64  }
65  )
66  @NamedQueries({@NamedQuery(name = QueryNames.PROJECT_BY_NAME,query = "select o from Project o where o.name = ?" + Project.ORDER_BY)
67  })
68  @Indexed
69  public final class Project implements Persistable {
70      static final String ORDER_BY = " order by o.name";
71      private static final Class<Project> CLASS = Project.class;
72      private static final Logger LOG = Logger.getLogger(CLASS);
73      @Id
74      @GeneratedValue(strategy = GenerationType.AUTO)
75      @Column(name = "ID")
76      private Integer id;
77      @Column(name = "NAME", nullable = false)
78      @Field(index = Index.TOKENIZED, store = Store.NO)
79      private String name;
80      @Column(name = "CREATED", nullable = false)
81      @Field(index = Index.UN_TOKENIZED, store = Store.YES)
82      @DateBridge(resolution = Resolution.SECOND)
83      private Date created;
84      @Column(name = "CREATED_BY", nullable = false)
85      @Field(index = Index.TOKENIZED, store = Store.NO)
86      private String createdBy;
87      @Version
88      @Column(name = "LAST_MODIFIED")
89      @Field(index = Index.UN_TOKENIZED, store = Store.YES)
90      @DateBridge(resolution = Resolution.SECOND)
91      private Date lastModified;
92      @Column(name = "LAST_MODIFIED_BY")
93      @Field(index = Index.TOKENIZED, store = Store.NO)
94      private String lastModifiedBy;
95      @Column(name = "DESCRIPTION")
96      @Field(index = Index.TOKENIZED, store = Store.NO)
97      private String description;
98  
99      public Integer getId() {
100         return this.id;
101     }
102 
103     public String getName() {
104         return this.name;
105     }
106 
107     public Date getCreated() {
108         return this.created;
109     }
110 
111     public String getCreatedBy() {
112         return this.createdBy;
113     }
114 
115     public Date getLastModified() {
116         return this.lastModified;
117     }
118 
119     public String getLastModifiedBy() {
120         return this.lastModifiedBy;
121     }
122 
123     public void setId(final Integer id) {
124         this.id = id;
125     }
126 
127     public void setName(final String name) {
128         this.name = name;
129     }
130 
131     public void setCreated(final Date created) {
132         this.created = created;
133     }
134 
135     public void setCreatedBy(final String createdBy) {
136         this.createdBy = createdBy;
137     }
138 
139     public void setLastModified(final Date lastModified) {
140         this.lastModified = lastModified;
141     }
142 
143     public void setLastModifiedBy(final String lastModifiedBy) {
144         this.lastModifiedBy = lastModifiedBy;
145     }
146 
147     public String getDescription() {
148         return this.description;
149     }
150 
151     public void setDescription(final String description) {
152         this.description = description;
153     }
154 
155     public static Collection<Project> findAll() {
156         return JpaDao.getInstance().findAll(CLASS);
157     }
158 
159     public static Project findByName(final String name) {
160         Object[] params = {
161                               name
162         };
163 
164         return JpaDao.getInstance().findSingleByNamedQuery(CLASS, QueryNames.PROJECT_BY_NAME, params);
165     }
166 
167     public void add() {
168         JpaDao.getInstance().add(this);
169     }
170 
171     public void update() {
172         JpaDao.getInstance().update(this);
173     }
174 
175     public void index() {
176         JpaDao.getInstance().index(this);
177     }
178 
179     public void delete() {
180         TinLizard.getInstance().getScmDao().releaseFiles(getCodelines());
181 
182         EntityManager em = JpaDao.getInstance().getEm();
183         EntityTransaction tx = em.getTransaction();
184         tx.begin();
185 
186         Class<?> clazz = CLASS;
187         Integer id = getId();
188 
189         try {
190             String clazzName;
191             int deleted;
192 
193             //
194             clazzName = Dependency.class.getSimpleName();
195 
196             Query query = em.createQuery("delete from " + clazzName + " o where o.codeline in (select c from " + Codeline.class.getSimpleName() + " c where c.project.id = :id)");
197             query.setParameter("id", id);
198             deleted = query.executeUpdate();
199 
200             if (LOG.isDebugEnabled()) {
201                 LOG.debug("Deleted " + deleted + " of type " + clazzName + ".");
202             }
203 
204             //
205             clazzName = Codeline.class.getSimpleName();
206             query = em.createQuery("delete from " + clazzName + " o where o.project.id = :id");
207             query.setParameter("id", id);
208             deleted = query.executeUpdate();
209 
210             if (LOG.isDebugEnabled()) {
211                 LOG.debug("Deleted " + deleted + " of type " + clazzName + ".");
212             }
213 
214             //
215             clazzName = Project.class.getSimpleName();
216             query = em.createQuery("delete from " + clazzName + " o where o.id = :id");
217             query.setParameter("id", id);
218             deleted = query.executeUpdate();
219 
220             if (LOG.isDebugEnabled()) {
221                 LOG.debug("Deleted " + deleted + " of type " + clazzName + ".");
222             }
223 
224             //
225             tx.commit();
226         } catch (EntityNotFoundException e) {
227             JpaDao.getInstance().handleInfo(tx, ("Object " + clazz + "#" + id + " did not exist"), e);
228         } catch (Exception e) {
229             JpaDao.getInstance().handleError(tx, "Delete Error", e);
230         }
231     }
232 
233     public Codeline findMainLine() {
234         Object[] params = {
235                               this
236         };
237 
238         return JpaDao.getInstance().findSingleByNamedQuery(Codeline.class, QueryNames.CODELINE_MAIN_LINE, params);
239     }
240 
241     //XXX maybe shouldn't throw error if not found, since that is client/user input.
242     public Codeline getCodeline(final String name) {
243         Object[] params = {
244                               name,
245                               this
246         };
247 
248         return JpaDao.getInstance().findSingleByNamedQuery(Codeline.class, QueryNames.CODELINE_BY_NAME, params);
249     }
250 
251     public Collection<Codeline> getCodelines() {
252         Object[] params = {
253                               this
254         };
255 
256         return JpaDao.getInstance().findByNamedQuery(Codeline.class, QueryNames.CODELINES_ALL_FOR_PROJECT, params);
257     }
258 
259     public Collection<Codeline> getActiveCodelines() {
260         Object[] params = {
261                               this
262         };
263 
264         return JpaDao.getInstance().findByNamedQuery(Codeline.class, QueryNames.CODELINES_ACTIVE_FOR_PROJECT, params);
265     }
266 
267     public void addCodeline(final Codeline pb) {
268         //XXX add integrity checks that there is only 1 main line.
269         pb.setMainLine(false);
270         pb.setProject(this);
271 
272         if (pb.getView() == null) {
273             View view = View.getDefaultView();
274             pb.setView(view);
275         }
276 
277         pb.add();
278     }
279 
280     public static Project add(final User user, final Project project, final Codeline mainline, final boolean updateFromPom) throws ScmException {
281         if (project == null) {
282             throw new IllegalArgumentException(Messages.error_0106());
283         }
284 
285         String scmUrl = mainline.getScmConnection();
286 
287         if (StringUtils.isBlank(project.getName())) {
288             throw new IllegalArgumentException(Messages.error_0101());
289         }
290 
291         if (StringUtils.isBlank(scmUrl)) {
292             throw new IllegalArgumentException(Messages.error_0102());
293         }
294 
295         if (Project.findByName(project.getName()) != null) {
296             throw new IllegalArgumentException(Messages.error_0103(project.getName()));
297         }
298 
299         String mainLineName = "HEAD"; //XXX
300 
301         Collection<Codeline> existingCodelines = Codeline.findByNameAndScmConnection(mainLineName, scmUrl);
302 
303         if ((existingCodelines != null) && !existingCodelines.isEmpty()) {
304             throw new IllegalArgumentException(Messages.error_0107(mainLineName, scmUrl));
305         }
306 
307         project.add();
308 
309         Codeline pb = mainline;
310         pb.setName(mainLineName);
311         pb.setScmConnection(scmUrl);
312         pb.setOwner(user);
313         pb.setPolicy(Policy.getDefaultPolicy());
314         pb.setMainLine(true);
315         pb.setProject(project);
316         pb.setView(View.getDefaultView());
317         pb.add();
318 
319         if (updateFromPom) {
320             pb.refresh();
321         }
322 
323         return project;
324     }
325 
326     public static Collection<Project> search(final String query) {
327         String[] fields = {
328                               "name",
329                               "created",
330                               "createdBy",
331                               "lastModified",
332                               "lastModifiedBy",
333                               "description"
334         };
335 
336         return JpaDao.getInstance().findByTextSearch(CLASS, query, fields);
337     }
338 
339     public static void indexAll() {
340         JpaDao.getInstance().indexAll(CLASS);
341     }
342 }