source: ComponentRegistry/trunk/ComponentRegistry/src/main/java/clarin/cmdi/componentregistry/impl/database/ComponentRegistryDbImpl.java @ 1892

Last change on this file since 1892 was 1892, checked in by twagoo, 12 years ago

Added canDelete property to Comment
ComponentRegistryDbImpl? sets property for all returned comments based on current principal
Comment retrieval methods of ComponentRegistry interface now require principal as parameter

Tests modified and extended

File size: 25.0 KB
Line 
1package clarin.cmdi.componentregistry.impl.database;
2
3import clarin.cmdi.componentregistry.CMDComponentSpecExpander;
4import java.io.ByteArrayInputStream;
5import java.io.ByteArrayOutputStream;
6import java.io.IOException;
7import java.io.InputStream;
8import java.io.OutputStream;
9import java.io.UnsupportedEncodingException;
10import java.security.Principal;
11import java.text.ParseException;
12import java.util.Calendar;
13import java.util.Date;
14import java.util.List;
15
16import javax.xml.bind.JAXBException;
17
18import org.slf4j.Logger;
19import org.slf4j.LoggerFactory;
20import org.springframework.beans.factory.annotation.Autowired;
21import org.springframework.beans.factory.annotation.Qualifier;
22import org.springframework.dao.DataAccessException;
23
24import clarin.cmdi.componentregistry.ComponentRegistry;
25import clarin.cmdi.componentregistry.ComponentRegistryException;
26import clarin.cmdi.componentregistry.Configuration;
27import clarin.cmdi.componentregistry.DeleteFailedException;
28import clarin.cmdi.componentregistry.MDMarshaller;
29import clarin.cmdi.componentregistry.UserUnauthorizedException;
30import clarin.cmdi.componentregistry.components.CMDComponentSpec;
31import clarin.cmdi.componentregistry.impl.ComponentRegistryImplBase;
32import clarin.cmdi.componentregistry.model.AbstractDescription;
33import clarin.cmdi.componentregistry.model.Comment;
34import clarin.cmdi.componentregistry.model.ComponentDescription;
35import clarin.cmdi.componentregistry.model.ProfileDescription;
36import clarin.cmdi.componentregistry.model.RegistryUser;
37import java.util.Collection;
38import java.util.Collections;
39
40/**
41 * Implementation of ComponentRegistry that uses Database Acces Objects for
42 * accessing the registry (ergo: a database implementation)
43 *
44 * @author Twan Goosen <twan.goosen@mpi.nl>
45 */
46public class ComponentRegistryDbImpl extends ComponentRegistryImplBase implements ComponentRegistry {
47
48    private final static Logger LOG = LoggerFactory.getLogger(ComponentRegistryDbImpl.class);
49    private Number userId;
50    @Autowired
51    private Configuration configuration;
52    @Autowired
53    private ProfileDescriptionDao profileDescriptionDao;
54    @Autowired
55    private ComponentDescriptionDao componentDescriptionDao;
56    @Autowired
57    private UserDao userDao;
58    @Autowired
59    @Qualifier("componentsCache")
60    private CMDComponentSpecCache componentsCache;
61    @Autowired
62    @Qualifier("profilesCache")
63    private CMDComponentSpecCache profilesCache;
64    @Autowired
65    private CommentsDao commentsDao;
66
67    /**
68     * Default constructor, makes this a (spring) bean. No user is set, so
69     * public registry by default. Use setUser() to make it a user registry.
70     *
71     * @see setUser
72     */
73    public ComponentRegistryDbImpl() {
74    }
75
76    /**
77     * Creates a new ComponentRegistry (either public or not) for the provided
78     * user
79     *
80     * @param userId
81     * User id of the user to create registry for. Pass null for
82     * public
83     */
84    public ComponentRegistryDbImpl(Number userId) {
85        this.userId = userId;
86    }
87
88    @Override
89    public List<ProfileDescription> getProfileDescriptions() throws ComponentRegistryException {
90        try {
91            if (isPublic()) {
92                return profileDescriptionDao.getPublicProfileDescriptions();
93            } else {
94                return profileDescriptionDao.getUserspaceDescriptions(getUserId());
95            }
96        } catch (DataAccessException ex) {
97            throw new ComponentRegistryException("Database access error while trying to get profile descriptions", ex);
98        }
99    }
100
101    @Override
102    public ProfileDescription getProfileDescription(String id) throws ComponentRegistryException {
103        try {
104            return profileDescriptionDao.getByCmdId(id, getUserId());
105        } catch (DataAccessException ex) {
106            throw new ComponentRegistryException("Database access error while trying to get profile description", ex);
107        }
108    }
109
110    @Override
111    public List<ComponentDescription> getComponentDescriptions() throws ComponentRegistryException {
112        try {
113            if (isPublic()) {
114                return componentDescriptionDao.getPublicComponentDescriptions();
115            } else {
116                return componentDescriptionDao.getUserspaceDescriptions(getUserId());
117            }
118        } catch (DataAccessException ex) {
119            throw new ComponentRegistryException("Database access error while trying to get component descriptions", ex);
120        }
121    }
122
123    @Override
124    public ComponentDescription getComponentDescription(String id) throws ComponentRegistryException {
125        try {
126            return componentDescriptionDao.getByCmdId(id, getUserId());
127        } catch (DataAccessException ex) {
128            throw new ComponentRegistryException("Database access error while trying to get component description", ex);
129        }
130    }
131
132    @Override
133    public List<Comment> getCommentsInProfile(String profileId, Principal principal) throws ComponentRegistryException {
134        try {
135            if (profileDescriptionDao.isInRegistry(profileId, getUserId())) {
136                final List<Comment> commentsFromProfile = commentsDao.getCommentsFromProfile(profileId);
137                setCanDeleteInComments(commentsFromProfile, principal);
138                return commentsFromProfile;
139            } else {
140                // Profile does not exist (at least not in this registry)
141                throw new ComponentRegistryException("Profile " + profileId + " does not exist in specified registry");
142            }
143        } catch (DataAccessException ex) {
144            throw new ComponentRegistryException("Database access error while trying to get list of comments from profile", ex);
145        }
146    }
147
148    @Override
149    public Comment getSpecifiedCommentInProfile(String profileId, String commentId, Principal principal) throws ComponentRegistryException {
150        try {
151            Comment comment = commentsDao.getSpecifiedCommentFromProfile(commentId);
152            if (comment != null
153                    && profileId.equals(comment.getProfileDescriptionId())
154                    && profileDescriptionDao.isInRegistry(comment.getProfileDescriptionId(), getUserId())) {
155                setCanDeleteInComments(Collections.singleton(comment), principal);
156                return comment;
157            } else {
158                // Comment exists in DB, but profile is not in this registry
159                throw new ComponentRegistryException("Comment " + commentId + " cannot be found in specified registry");
160            }
161        } catch (DataAccessException ex) {
162            throw new ComponentRegistryException("Database access error while trying to get comment from profile", ex);
163        }
164    }
165
166    @Override
167    public List<Comment> getCommentsInComponent(String componentId, Principal principal) throws ComponentRegistryException {
168        try {
169            if (componentDescriptionDao.isInRegistry(componentId, getUserId())) {
170                final List<Comment> commentsFromComponent = commentsDao.getCommentsFromComponent(componentId);
171                setCanDeleteInComments(commentsFromComponent, principal);
172                return commentsFromComponent;
173            } else {
174                // Component does not exist (at least not in this registry)
175                throw new ComponentRegistryException("Component " + componentId + " does not exist in specified registry");
176            }
177        } catch (DataAccessException ex) {
178            throw new ComponentRegistryException("Database access error while trying to get list of comments from component", ex);
179        }
180    }
181
182    @Override
183    public Comment getSpecifiedCommentInComponent(String componentId, String commentId, Principal principal) throws ComponentRegistryException {
184        try {
185            Comment comment = commentsDao.getSpecifiedCommentFromComponent(commentId);
186            if (comment != null
187                    && componentId.equals(comment.getComponentDescriptionId())
188                    && componentDescriptionDao.isInRegistry(comment.getComponentDescriptionId(), getUserId())) {
189                setCanDeleteInComments(Collections.singleton(comment), principal);
190                return comment;
191            } else {
192                // Comment does not exists in DB or component is not in this registry
193                throw new ComponentRegistryException("Comment " + commentId + " cannot be found in specified registry for specified component");
194            }
195        } catch (DataAccessException ex) {
196            throw new ComponentRegistryException("Database access error while trying to get comment from component", ex);
197        }
198    }
199
200    /**
201     * Sets the {@link Comment#setCanDelete(boolean) canDelete} property on all comments in the provided collection for the perspective of
202     * the specified principal.
203     * Comment owners (determined by {@link Comment#getUserId() }) and admins can delete, others cannot.
204     *
205     * @param comments comments to configure
206     * @param principal user to configure for
207     * @see Comment#isCanDelete()
208     */
209    private void setCanDeleteInComments(Collection<Comment> comments, Principal principal) {
210        if (principal != null && principal.getName() != null) {
211            final RegistryUser registryUser = userDao.getByPrincipalName(principal.getName());
212            final String registryUserId = registryUser.getId().toString();
213            final boolean isAdmin = configuration.isAdminUser(principal);
214            for (Comment comment : comments) {
215                comment.setCanDelete(isAdmin || comment.getUserId().equals(registryUserId));
216            }
217        }
218    }
219
220    @Override
221    public CMDComponentSpec getMDProfile(String id) throws ComponentRegistryException {
222        if (inWorkspace(profileDescriptionDao, id)) {
223            CMDComponentSpec result = profilesCache.get(id);
224            if (result == null && !profilesCache.containsKey(id)) {
225                result = getUncachedMDProfile(id);
226                profilesCache.put(id, result);
227            }
228            return result;
229        } else {
230            // May exist, but not in this workspace
231            LOG.warn("Could not find profile '{}' in registry '{}'", new Object[]{id, this.toString()});
232            return null;
233        }
234    }
235
236    public CMDComponentSpec getUncachedMDProfile(String id) throws ComponentRegistryException {
237        try {
238            return getUncachedMDComponent(id, profileDescriptionDao);
239        } catch (DataAccessException ex) {
240            throw new ComponentRegistryException("Database access error while trying to get profile", ex);
241        }
242    }
243
244    @Override
245    public CMDComponentSpec getMDComponent(String id) throws ComponentRegistryException {
246        if (inWorkspace(componentDescriptionDao, id)) {
247            CMDComponentSpec result = componentsCache.get(id);
248            if (result == null && !componentsCache.containsKey(id)) {
249                result = getUncachedMDComponent(id);
250                componentsCache.put(id, result);
251            }
252            return result;
253        } else {
254            // May exist, but not in this workspace
255            LOG.warn("Could not find component '{}' was in registry '{}'", new Object[]{id, this.toString()});
256            return null;
257        }
258    }
259
260    public CMDComponentSpec getUncachedMDComponent(String id) throws ComponentRegistryException {
261        try {
262            return getUncachedMDComponent(id, componentDescriptionDao);
263        } catch (DataAccessException ex) {
264            throw new ComponentRegistryException("Database access error while trying to get component", ex);
265        }
266    }
267
268    @Override
269    public int register(AbstractDescription description, CMDComponentSpec spec) {
270        enrichSpecHeader(spec, description);
271        try {
272            String xml = componentSpecToString(spec);
273            // Convert principal name to user record id
274            Number uid = convertUserInDescription(description);
275            getDaoForDescription(description).insertDescription(description, xml, isPublic(), uid);
276            invalidateCache(description);
277            return 0;
278        } catch (DataAccessException ex) {
279            LOG.error("Database error while registering component", ex);
280            return -1;
281        } catch (JAXBException ex) {
282            LOG.error("Error while registering component", ex);
283            return -2;
284        } catch (UnsupportedEncodingException ex) {
285            LOG.error("Error while registering component", ex);
286            return -3;
287        }
288    }
289
290    @Override
291    public int registerComment(Comment comment, String principalName) throws ComponentRegistryException {
292        try {
293            if (comment.getComponentDescriptionId() != null && componentDescriptionDao.isInRegistry(comment.getComponentDescriptionId(), getUserId())
294                    || comment.getProfileDescriptionId() != null && profileDescriptionDao.isInRegistry(comment.getProfileDescriptionId(), getUserId())) {
295                // Convert principal name to user record id
296                Number uid = convertUserIdInComment(comment, principalName);
297                // Set date to current date
298                comment.setCommentDate(Comment.createNewDate());
299                Number commentId = commentsDao.insertComment(comment, uid);
300                comment.setId(commentId.toString());
301            } else {
302                throw new ComponentRegistryException("Cannot insert comment into this registry. Unknown profileId or componentId");
303            }
304            return 0;
305        } catch (DataAccessException ex) {
306            LOG.error("Database error while registering component", ex);
307            return -1;
308        }
309    }
310
311    /**
312     * Calling service sets user id to principle. Our task is to convert this to
313     * an id for later reference. If none is set and this is a user's workspace,
314     * set from that user's id.
315     *
316     * It also sets the name in the description according to the display name in the database.
317     *
318     * @param description
319     * Description containing principle name as userId
320     * @return Id (from database)
321     * @throws DataAccessException
322     */
323    private Number convertUserInDescription(AbstractDescription description) throws DataAccessException {
324        Number uid = null;
325        String name = null;
326        if (description.getUserId() != null) {
327            RegistryUser user = userDao.getByPrincipalName(description.getUserId());
328            if (user != null) {
329                uid = user.getId();
330                name = user.getName();
331            }
332        } else {
333            uid = userId;
334        }
335        if (uid != null) {
336            description.setUserId(uid.toString());
337        }
338        if (name != null) {
339            description.setCreatorName(name);
340        }
341        return uid;
342    }
343
344    /**
345     * Calling service sets user id to principle. Our task is to convert this to
346     * an id for later reference. If none is set and this is a user's workspace,
347     * set from that user's id.
348     *
349     * @param comment
350     * Comment containing principle name as userId
351     * @return Id (from database)
352     * @throws DataAccessException
353     */
354    private Number convertUserIdInComment(Comment comment, String principalName) throws DataAccessException, ComponentRegistryException {
355        if (principalName != null) {
356            RegistryUser user = userDao.getByPrincipalName(principalName);
357            if (user != null) {
358                Number id = user.getId();
359                if (id != null) {
360                    // Set user id in comment for convenience of calling method
361                    comment.setUserId(id.toString());
362                    // Set name to user's preferred display name
363                    comment.setUserName(user.getName());
364                    return id;
365                } else {
366                    throw new ComponentRegistryException("Cannot find user with principal name: " + principalName);
367                }
368            }
369        }
370        return null;
371    }
372
373    @Override
374    public int update(AbstractDescription description, CMDComponentSpec spec, Principal principal, boolean forceUpdate) {
375        try {
376            checkAuthorisation(description, principal);
377            checkAge(description, principal);
378            // For public components, check if used in other components or profiles (unless forced)
379            if (!forceUpdate && this.isPublic() && !description.isProfile()) {
380                checkStillUsed(description.getId());
381            }
382            AbstractDescriptionDao<?> dao = getDaoForDescription(description);
383            dao.updateDescription(getIdForDescription(description), description, componentSpecToString(spec));
384            invalidateCache(description);
385            return 0;
386        } catch (JAXBException ex) {
387            LOG.error("Error while updating component", ex);
388            return -1;
389        } catch (UnsupportedEncodingException ex) {
390            LOG.error("Error while updating component", ex);
391            return -1;
392        } catch (IllegalArgumentException ex) {
393            LOG.error("Error while updating component", ex);
394            return -1;
395        } catch (UserUnauthorizedException e) {
396            LOG.error("Error while updating component", e);
397            return -1;
398        } catch (DeleteFailedException e) {
399            LOG.error("Error while updating component", e);
400            return -1;
401        } catch (ComponentRegistryException e) {
402            LOG.error("Error while updating component", e);
403            return -1;
404        }
405    }
406
407    @Override
408    public int publish(AbstractDescription desc, CMDComponentSpec spec, Principal principal) {
409        int result = 0;
410        AbstractDescriptionDao<?> dao = getDaoForDescription(desc);
411        if (!isPublic()) { // if already in public workspace there is nothing todo
412            desc.setHref(AbstractDescription.createPublicHref(desc.getHref()));
413            Number id = getIdForDescription(desc);
414            try {
415                // Update description & content
416                dao.updateDescription(id, desc, componentSpecToString(spec));
417                // Set to public
418                dao.setPublished(id, true);
419            } catch (DataAccessException ex) {
420                LOG.error("Database error while updating component", ex);
421                return -1;
422            } catch (JAXBException ex) {
423                LOG.error("Error while updating component", ex);
424                return -2;
425            } catch (UnsupportedEncodingException ex) {
426                LOG.error("Error while updating component", ex);
427                return -3;
428            }
429        }
430        return result;
431    }
432
433    @Override
434    public void getMDProfileAsXml(String profileId, OutputStream output) throws ComponentRegistryException {
435        CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl.expandProfile(profileId, this);
436        writeXml(expandedSpec, output);
437    }
438
439    @Override
440    public void getMDProfileAsXsd(String profileId, OutputStream outputStream) throws ComponentRegistryException {
441        CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl.expandProfile(profileId, this);
442        writeXsd(expandedSpec, outputStream);
443    }
444
445    @Override
446    public void getMDComponentAsXml(String componentId, OutputStream output) throws ComponentRegistryException {
447        CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl.expandComponent(componentId, this);
448        writeXml(expandedSpec, output);
449    }
450
451    @Override
452    public void getMDComponentAsXsd(String componentId, OutputStream outputStream) throws ComponentRegistryException {
453        CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl.expandComponent(componentId, this);
454        writeXsd(expandedSpec, outputStream);
455    }
456
457    @Override
458    public void deleteMDProfile(String profileId, Principal principal) throws UserUnauthorizedException, DeleteFailedException,
459            ComponentRegistryException {
460        ProfileDescription desc = getProfileDescription(profileId);
461        if (desc != null) {
462            try {
463                checkAuthorisation(desc, principal);
464                checkAge(desc, principal);
465                profileDescriptionDao.setDeleted(desc, true);
466                invalidateCache(desc);
467            } catch (DataAccessException ex) {
468                throw new DeleteFailedException("Database access error while trying to delete profile", ex);
469            }
470        }
471    }
472
473    @Override
474    public void deleteMDComponent(String componentId, Principal principal, boolean forceDelete) throws UserUnauthorizedException,
475            DeleteFailedException, ComponentRegistryException {
476        ComponentDescription desc = componentDescriptionDao.getByCmdId(componentId);
477        if (desc != null) {
478            try {
479                checkAuthorisation(desc, principal);
480                checkAge(desc, principal);
481
482                if (!forceDelete) {
483                    checkStillUsed(componentId);
484                }
485                componentDescriptionDao.setDeleted(desc, true);
486                invalidateCache(desc);
487            } catch (DataAccessException ex) {
488                throw new DeleteFailedException("Database access error while trying to delete component", ex);
489            }
490        }
491    }
492
493    @Override
494    public boolean isPublic() {
495        return null == userId;
496    }
497
498    public void setPublic() {
499        this.userId = null;
500    }
501
502    /**
503     * @return The user, or null if this is the public registry.
504     */
505    public Number getUserId() {
506        return userId;
507    }
508
509    /**
510     * @param User
511     * for which this should be the registry. Pass null for the
512     * public registry
513     */
514    public void setUserId(Number user) {
515        this.userId = user;
516    }
517
518    private void invalidateCache(AbstractDescription description) {
519        if (description.isProfile()) {
520            profilesCache.remove(description.getId());
521        } else {
522            componentsCache.remove(description.getId());
523        }
524    }
525
526    private AbstractDescriptionDao<?> getDaoForDescription(AbstractDescription description) {
527        return description.isProfile() ? profileDescriptionDao : componentDescriptionDao;
528    }
529
530    /**
531     * Looks up description on basis of CMD Id. This will also check if such a
532     * record even exists.
533     *
534     * @param description
535     * Description to look up
536     * @return Database id for description
537     * @throws IllegalArgumentException
538     * If description with non-existing id is passed
539     */
540    private Number getIdForDescription(AbstractDescription description) throws IllegalArgumentException {
541        Number dbId = null;
542        AbstractDescriptionDao<?> dao = getDaoForDescription(description);
543        try {
544            dbId = dao.getDbId(description.getId());
545        } catch (DataAccessException ex) {
546            LOG.error("Error getting dbId for component with id " + description.getId(), ex);
547        }
548        if (dbId == null) {
549            throw new IllegalArgumentException("Could not get database Id for description");
550        } else {
551            return dbId;
552        }
553    }
554
555    private String componentSpecToString(CMDComponentSpec spec) throws UnsupportedEncodingException, JAXBException {
556        ByteArrayOutputStream os = new ByteArrayOutputStream();
557        MDMarshaller.marshal(spec, os);
558        String xml = os.toString("UTF-8");
559        return xml;
560    }
561
562    private CMDComponentSpec getUncachedMDComponent(String id, AbstractDescriptionDao dao) {
563        String xml = dao.getContent(false, id);
564        if (xml != null) {
565            try {
566                InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));
567                return MDMarshaller.unmarshal(CMDComponentSpec.class, is, null);
568
569            } catch (JAXBException ex) {
570                LOG.error(null, ex);
571            } catch (UnsupportedEncodingException ex) {
572                LOG.error(null, ex);
573            }
574        }
575        return null;
576    }
577
578    private void checkAuthorisation(AbstractDescription desc, Principal principal) throws UserUnauthorizedException {
579        if (!isOwnerOfDescription(desc, principal.getName()) && !configuration.isAdminUser(principal)) {
580            throw new UserUnauthorizedException("Unauthorized operation user '" + principal.getName()
581                    + "' is not the creator (nor an administrator) of the " + (desc.isProfile() ? "profile" : "component") + "(" + desc
582                    + ").");
583        }
584    }
585
586    private void checkAuthorisationComment(Comment desc, Principal principal) throws UserUnauthorizedException {
587        if (!isOwnerOfComment(desc, principal.getName()) && !configuration.isAdminUser(principal)) {
588            throw new UserUnauthorizedException("Unauthorized operation user '" + principal.getName()
589                    + "' is not the creator (nor an administrator) of the " + (desc.getId()) + "(" + desc
590                    + ").");
591        }
592    }
593
594    private boolean isOwnerOfDescription(AbstractDescription desc, String principalName) {
595        String owner = getDaoForDescription(desc).getOwnerPrincipalName(getIdForDescription(desc));
596        return owner != null // If owner is null, no one can be owner
597                && principalName.equals(owner);
598    }
599
600    private boolean isOwnerOfComment(Comment com, String principalName) {
601        String owner = commentsDao.getOwnerPrincipalName(Integer.parseInt(com.getId()));
602        return owner != null // If owner is null, no one can be owner
603                && principalName.equals(owner);
604    }
605
606    private void checkAge(AbstractDescription desc, Principal principal) throws DeleteFailedException {
607        if (isPublic() && !configuration.isAdminUser(principal)) {
608            try {
609                Date regDate = AbstractDescription.getDate(desc.getRegistrationDate());
610                Calendar calendar = Calendar.getInstance();
611                calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
612                if (regDate.before(calendar.getTime())) { // More then month old
613                    throw new DeleteFailedException(
614                            "The "
615                            + (desc.isProfile() ? "Profile" : "Component")
616                            + " is more then a month old and cannot be deleted anymore. It might have been used to create metadata, deleting it would invalidate that metadata.");
617                }
618            } catch (ParseException e) {
619                LOG.error("Cannot parse date of " + desc + " Error:" + e);
620            }
621        }
622    }
623
624    private boolean inWorkspace(AbstractDescriptionDao<?> dao, String cmdId) {
625        if (isPublic()) {
626            return dao.isPublic(cmdId);
627        } else {
628            return dao.isInUserSpace(cmdId, getUserId());
629        }
630    }
631
632    @Override
633    public String getName() {
634        if (isPublic()) {
635            return ComponentRegistry.PUBLIC_NAME;
636        } else {
637            return "Registry of " + userDao.getById(getUserId()).getName();
638        }
639    }
640
641    @Override
642    public List<ProfileDescription> getDeletedProfileDescriptions() {
643        return profileDescriptionDao.getDeletedDescriptions(getUserId());
644    }
645
646    @Override
647    public List<ComponentDescription> getDeletedComponentDescriptions() {
648        return componentDescriptionDao.getDeletedDescriptions(getUserId());
649    }
650
651    @Override
652    public void deleteComment(String commentId, Principal principal) throws IOException,
653            ComponentRegistryException, UserUnauthorizedException, DeleteFailedException {
654        try {
655            Comment comment = commentsDao.getById(commentId);
656            if (comment != null
657                    // Comment must have an existing (in this registry) componentId or profileId
658                    && (comment.getComponentDescriptionId() != null && componentDescriptionDao.isInRegistry(comment.getComponentDescriptionId(), getUserId())
659                    || comment.getProfileDescriptionId() != null && profileDescriptionDao.isInRegistry(comment.getProfileDescriptionId(), getUserId()))) {
660                checkAuthorisationComment(comment, principal);
661                commentsDao.deleteComment(comment);
662            } else {
663                // Comment exists in DB, but component is not in this registry
664                throw new ComponentRegistryException("Comment " + commentId + " cannot be found in specified registry");
665            }
666        } catch (DataAccessException ex) {
667            throw new DeleteFailedException("Database access error while trying to delete component", ex);
668        }
669    }
670
671    @Override
672    public CMDComponentSpecExpander getExpander() {
673        return new CMDComponentSpecExpanderDbImpl(this);
674    }
675
676    @Override
677    public String toString() {
678        return getName();
679    }
680}
Note: See TracBrowser for help on using the repository browser.