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

Last change on this file since 3088 was 3088, checked in by twagoo, 11 years ago

Changes in MdMarshaller? and its usage:

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