source: DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src/main/java/eu/dasish/annotation/backend/dao/impl/DBDispatcherImlp.java @ 5774

Last change on this file since 5774 was 5774, checked in by olhsha@mpi.nl, 10 years ago

updating annotations: if the current user is not owner then the permission part is ignored

File size: 43.5 KB
Line 
1/*
2 * Copyright (C) 2013 DASISH
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 */
18package eu.dasish.annotation.backend.dao.impl;
19
20import eu.dasish.annotation.backend.NotInDataBaseException;
21import eu.dasish.annotation.backend.Resource;
22import eu.dasish.annotation.backend.Helpers;
23import eu.dasish.annotation.backend.MatchMode;
24import eu.dasish.annotation.backend.PrincipalCannotBeDeleted;
25import eu.dasish.annotation.backend.PrincipalExists;
26import eu.dasish.annotation.backend.ResourceAction;
27import eu.dasish.annotation.backend.dao.AnnotationDao;
28import eu.dasish.annotation.backend.dao.CachedRepresentationDao;
29import eu.dasish.annotation.backend.dao.DBDispatcher;
30import eu.dasish.annotation.backend.dao.NotebookDao;
31import eu.dasish.annotation.backend.dao.ResourceDao;
32import eu.dasish.annotation.backend.dao.TargetDao;
33import eu.dasish.annotation.backend.dao.PrincipalDao;
34import eu.dasish.annotation.schema.Action;
35import eu.dasish.annotation.schema.ActionList;
36import eu.dasish.annotation.schema.Annotation;
37import eu.dasish.annotation.schema.AnnotationActionName;
38import eu.dasish.annotation.schema.AnnotationBody;
39import eu.dasish.annotation.schema.AnnotationInfo;
40import eu.dasish.annotation.schema.AnnotationInfoList;
41import eu.dasish.annotation.schema.CachedRepresentationFragment;
42import eu.dasish.annotation.schema.CachedRepresentationFragmentList;
43import eu.dasish.annotation.schema.CachedRepresentationInfo;
44import eu.dasish.annotation.schema.Notebook;
45import eu.dasish.annotation.schema.NotebookInfo;
46import eu.dasish.annotation.schema.NotebookInfoList;
47import eu.dasish.annotation.schema.TargetInfoList;
48import eu.dasish.annotation.schema.Access;
49import eu.dasish.annotation.schema.PermissionActionName;
50import eu.dasish.annotation.schema.PermissionList;
51import eu.dasish.annotation.schema.ReferenceList;
52import eu.dasish.annotation.schema.ResponseBody;
53import eu.dasish.annotation.schema.Target;
54import eu.dasish.annotation.schema.TargetInfo;
55import eu.dasish.annotation.schema.Principal;
56import eu.dasish.annotation.schema.Permission;
57import java.io.IOException;
58import java.io.InputStream;
59import java.io.UnsupportedEncodingException;
60import java.lang.Number;
61import java.net.URLEncoder;
62import java.util.ArrayList;
63import java.util.HashMap;
64import java.util.List;
65import java.util.Map;
66import java.util.UUID;
67import org.springframework.beans.factory.annotation.Autowired;
68import org.slf4j.Logger;
69import org.slf4j.LoggerFactory;
70
71/**
72 *
73 * @author olhsha
74 */
75public class DBDispatcherImlp implements DBDispatcher {
76
77    @Autowired
78    PrincipalDao principalDao;
79    @Autowired
80    CachedRepresentationDao cachedRepresentationDao;
81    @Autowired
82    TargetDao targetDao;
83    @Autowired
84    AnnotationDao annotationDao;
85    @Autowired
86    NotebookDao notebookDao;
87    final static protected String admin = "admin";
88    private static final Logger logger = LoggerFactory.getLogger(DBDispatcherImlp.class);
89
90    //////////////////////////////////
91    private ResourceDao getDao(Resource resource) {
92        switch (resource) {
93            case PRINCIPAL:
94                return principalDao;
95            case ANNOTATION:
96                return annotationDao;
97            case TARGET:
98                return targetDao;
99            case CACHED_REPRESENTATION:
100                return cachedRepresentationDao;
101            case NOTEBOOK:
102                return notebookDao;
103            default:
104                return null;
105        }
106    }
107
108    @Override
109    public void setResourcesPaths(String relServiceURI) {
110        principalDao.setResourcePath(relServiceURI + "/principals/");
111        cachedRepresentationDao.setResourcePath(relServiceURI + "/cached/");
112        targetDao.setResourcePath(relServiceURI + "/targets/");
113        annotationDao.setResourcePath(relServiceURI + "/annotations/");
114        notebookDao.setResourcePath(relServiceURI + "/notebooks/");
115    }
116
117    ///////////// GETTERS //////////////////////////
118    @Override
119    public Number getResourceInternalIdentifier(UUID externalID, Resource resource) throws NotInDataBaseException {
120        return this.getDao(resource).getInternalID(externalID);
121    }
122
123 
124    @Override
125    public UUID getResourceExternalIdentifier(Number resourceID, Resource resource) {
126        return this.getDao(resource).getExternalID(resourceID);
127    }
128
129   
130    @Override
131    public Annotation getAnnotation(Number annotationID) {
132        Annotation result = annotationDao.getAnnotationWithoutTargetsAndPemissions(annotationID);
133        result.setOwnerHref(principalDao.getHrefFromInternalID(annotationDao.getOwner(annotationID)));
134        List<Number> targetIDs = targetDao.getTargetIDs(annotationID);
135        TargetInfoList sis = new TargetInfoList();
136        for (Number targetID : targetIDs) {
137            TargetInfo targetInfo = this.getTargetInfoFromTarget(targetDao.getTarget(targetID));
138            sis.getTargetInfo().add(targetInfo);
139        }
140        result.setTargets(sis);
141        result.setPermissions(this.getPermissions(annotationID, Resource.ANNOTATION));
142        return result;
143    }
144
145    @Override
146    public Number getAnnotationOwnerID(Number annotationID) {
147        return annotationDao.getOwner(annotationID);
148    }
149
150    @Override
151    public Principal getAnnotationOwner(Number annotationID) {
152        Number ownerID = annotationDao.getOwner(annotationID);
153        return principalDao.getPrincipal(ownerID);
154    }
155
156    ///////////////////////////////////////////////////
157    // TODO UNIT tests
158    @Override
159    public PermissionList getPermissions(Number resourceID, Resource resource) {
160        List<Map<Number, String>> principalsAccesss = this.getDao(resource).getPermissions(resourceID);
161        PermissionList result = new PermissionList();
162        result.setPublic(this.getDao(resource).getPublicAttribute(resourceID));
163        List<Permission> list = result.getPermission();
164        for (Map<Number, String> principalAccess : principalsAccesss) {
165            Number[] principal = new Number[1];
166            principalAccess.keySet().toArray(principal);
167            Permission permission = new Permission();
168            permission.setPrincipalHref(principalDao.getHrefFromInternalID(principal[0]));
169            permission.setLevel(Access.fromValue(principalAccess.get(principal[0])));
170            list.add(permission);
171        }
172        return result;
173    }
174
175////////////////////////////////////////////////////////////////////////
176    @Override 
177    public List<Number> getFilteredAnnotationIDs(UUID ownerId, String link, MatchMode matchMode, String text, Number inloggedPrincipalID, String accessMode, String namespace, String after, String before) throws NotInDataBaseException {
178
179        Number ownerID;
180
181        if (ownerId != null) {
182            if (accessMode.equals("owner")) { // inloggedUser is the owner of the annotations
183                if (!ownerId.equals(principalDao.getExternalID(inloggedPrincipalID))) {
184                    logger.info("The inlogged principal is demanded to be the owner of the annotations, however the expected owner is different and has the UUID " + ownerId.toString());
185                    return new ArrayList<Number>();
186                } else {
187                    ownerID = inloggedPrincipalID;
188                }
189            } else {
190                ownerID = principalDao.getInternalID(ownerId);
191            }
192
193        } else {
194            if (accessMode.equals("owner")) {
195                ownerID = inloggedPrincipalID;
196            } else {
197                ownerID = null;
198            }
199        }
200
201
202        //Filtering on the columns  of the annotation table
203        List<Number> annotationIDs = annotationDao.getFilteredAnnotationIDs(ownerID, text, namespace, after, before);
204
205
206        // Filetring on accessMode, the junction table
207        if (annotationIDs != null) {
208            if (!annotationIDs.isEmpty()) {
209                if (!accessMode.equals("owner")) {
210                    Access access = Access.fromValue(accessMode);
211                    List<Number> annotationIDsAccess = annotationDao.getAnnotationIDsForPermission(inloggedPrincipalID, access);
212                    List<Number> annotationIDsPublic = annotationDao.getAnnotationIDsForPublicAccess(access);
213                    List<Number> annotationIDsOwned = annotationDao.getFilteredAnnotationIDs(inloggedPrincipalID, text, namespace, after, before);
214                    int check1 = this.addAllNoRepetitions(annotationIDsAccess, annotationIDsPublic);
215                    int check2 = this.addAllNoRepetitions(annotationIDsAccess, annotationIDsOwned);
216                    annotationIDs.retainAll(annotationIDsAccess);// intersection
217                }
218            }
219
220            // filtering on reference       
221            return this.filterAnnotationIDsOnReference(annotationIDs, link, matchMode);
222        }
223
224        return annotationIDs;
225
226    }
227
228    /// helpers ///
229    private List<Number> filterAnnotationIDsOnReference(List<Number> annotationIDs, String link, MatchMode matchMode) {
230        if (link != null) {
231            if (!link.isEmpty()) {
232                if (annotationIDs != null) {
233                    String partiallyEncoded = this.encodeURLNoSlashEncoded(link);
234                    String urlEncoded = null;
235                    try {
236                        urlEncoded = URLEncoder.encode(link, "UTF-8");
237                    } catch (UnsupportedEncodingException e) {
238                        logger.debug(e.toString());
239                    }
240
241                    List<Number> result = new ArrayList();
242                    for (Number annotationID : annotationIDs) {
243                        List<Number> targets = targetDao.getTargetIDs(annotationID);
244                        for (Number targetID : targets) {
245                            if (!result.contains(annotationID)) {
246                                String linkRunner = targetDao.getLink(targetID);
247                                if (matchCriterium(linkRunner, link, matchMode) || matchCriterium(linkRunner, partiallyEncoded, matchMode)) {
248                                    result.add(annotationID);
249                                } else {
250                                    if (urlEncoded != null) {
251                                        if (matchCriterium(linkRunner, urlEncoded, matchMode)) {
252                                            result.add(annotationID);
253                                        }
254                                    }
255                                }
256                            }
257                        }
258                    }
259                    return result;
260                }
261            }
262        }
263        return annotationIDs;
264    }
265   
266    private boolean matchCriterium(String currentString, String pattern, MatchMode matchMode){       
267        switch (matchMode) {
268            case EXACT: return currentString.equals(pattern);
269            case STARTS_WITH: return currentString.startsWith(pattern);
270            case ENDS_WITH: return currentString.endsWith(pattern);
271            case CONTAINS: return currentString.contains(pattern);
272            default: return false;
273        }
274    }
275
276    public int addAllNoRepetitions(List<Number> list, List<Number> listToAdd) {
277        int result = 0;
278        if (list != null) {
279            if (listToAdd != null) {
280                for (Number element : listToAdd) {
281                    if (!list.contains(element)) {
282                        list.add(element);
283                        result++;
284                    }
285                }
286            }
287        } else {
288            if (listToAdd != null) {
289                list = listToAdd;
290                result = listToAdd.size();
291            }
292        }
293        return result;
294    }
295
296    private String encodeURLNoSlashEncoded(String string) {
297        String[] split = string.split("/");
298        StringBuilder result = new StringBuilder(split[0]);
299        for (int i = 1; i < split.length; i++) {
300            try {
301                result.append("/").append(URLEncoder.encode(split[i], "UTF-8"));
302            } catch (UnsupportedEncodingException e) {
303                result.append("/").append(split[i]);
304                logger.debug(e.toString());
305            }
306        }
307        return result.toString();
308    }
309
310    //////
311    @Override
312    public ReferenceList getAnnotationTargets(Number annotationID) {
313        ReferenceList result = new ReferenceList();
314        List<Number> targetIDs = targetDao.getTargetIDs(annotationID);
315        for (Number targetID : targetIDs) {
316            result.getHref().add(targetDao.getHrefFromInternalID(targetID));
317        }
318        return result;
319    }
320
321    @Override
322    public List<String> getTargetsWithNoCachedRepresentation(Number annotationID) {
323
324        List<String> result = new ArrayList<String>();
325        List<Number> targetIDs = targetDao.getTargetIDs(annotationID);
326        for (Number targetID : targetIDs) {
327            List<Number> versions = cachedRepresentationDao.getCachedRepresentationsForTarget(targetID);
328            if (versions.isEmpty()) {
329                result.add(targetDao.getHrefFromInternalID(targetID));
330            }
331        }
332        return result;
333    }
334
335    @Override
336    public List<String> getPrincipalsWithNoInfo(Number annotationID) {
337        List<String> result = new ArrayList<String>();
338        List<Map<Number, String>> principalsWithAccesss = annotationDao.getPermissions(annotationID);
339        for (Map<Number, String> permission : principalsWithAccesss) {
340            Number[] principalID = new Number[1];
341            permission.keySet().toArray(principalID);
342            Principal principal = principalDao.getPrincipal(principalID[0]);
343            if (principal.getDisplayName() == null || principal.getDisplayName().trim().isEmpty() || principal.getEMail() == null || principal.getEMail().trim().isEmpty()) {
344                result.add(principalDao.getHrefFromInternalID(principalID[0]));
345
346            }
347        }
348        return result;
349    }
350
351    @Override
352    public AnnotationInfoList getFilteredAnnotationInfos(UUID ownerId, String link, MatchMode matchMode, String text, Number inloggedPrincipalID, String access, String namespace, String after, String before) throws NotInDataBaseException {
353        List<Number> annotationIDs = this.getFilteredAnnotationIDs(ownerId, link, matchMode, text, inloggedPrincipalID, access, namespace, after, before);
354        AnnotationInfoList result = new AnnotationInfoList();
355        for (Number annotationID : annotationIDs) {
356            AnnotationInfo annotationInfo = annotationDao.getAnnotationInfoWithoutTargetsAndOwner(annotationID);
357            annotationInfo.setTargets(this.getAnnotationTargets(annotationID));
358            annotationInfo.setOwnerHref(principalDao.getHrefFromInternalID(annotationDao.getOwner(annotationID)));
359            result.getAnnotationInfo().add(annotationInfo);
360        }
361        return result;
362    }
363
364    @Override
365    public AnnotationInfoList getAllAnnotationInfos() {
366        List<Number> annotationIDs = annotationDao.getAllAnnotationIDs();
367        AnnotationInfoList result = new AnnotationInfoList();
368        for (Number annotationID : annotationIDs) {
369            Number ownerID = annotationDao.getOwner(annotationID);
370            ReferenceList targets = this.getAnnotationTargets(annotationID);
371            AnnotationInfo annotationInfo = annotationDao.getAnnotationInfoWithoutTargetsAndOwner(annotationID);
372            annotationInfo.setTargets(targets);
373            annotationInfo.setOwnerHref(principalDao.getHrefFromInternalID(ownerID));
374            result.getAnnotationInfo().add(annotationInfo);
375        }
376        return result;
377
378    }
379
380    // TODO unit test
381    @Override
382    public Target getTarget(Number internalID) {
383        Target result = targetDao.getTarget(internalID);
384        result.setSiblingTargets(this.getTargetsForTheSameLinkAs(internalID));
385        Map<Number, String> cachedIDsFragments = targetDao.getCachedRepresentationFragmentPairs(internalID);
386        CachedRepresentationFragmentList cachedRepresentationFragmentList = new CachedRepresentationFragmentList();
387        for (Number key : cachedIDsFragments.keySet()) {
388            CachedRepresentationFragment cachedRepresentationFragment = new CachedRepresentationFragment();
389            cachedRepresentationFragment.setHref(cachedRepresentationDao.getHrefFromInternalID(key));
390            cachedRepresentationFragment.setFragmentString(cachedIDsFragments.get(key));
391            cachedRepresentationFragmentList.getCached().add(cachedRepresentationFragment);
392        }
393        result.setCachedRepresentations(cachedRepresentationFragmentList);
394        return result;
395    }
396
397    // TODO unit test
398    @Override
399    public CachedRepresentationInfo getCachedRepresentationInfo(Number internalID) {
400        return cachedRepresentationDao.getCachedRepresentationInfo(internalID);
401    }
402
403    //TODO unit test
404    @Override
405    public InputStream getCachedRepresentationBlob(Number cachedID) {
406        return cachedRepresentationDao.getCachedRepresentationBlob(cachedID);
407    }
408
409    @Override
410    public ReferenceList getTargetsForTheSameLinkAs(Number targetID) {
411        List<Number> targetIDs = targetDao.getTargetsForLink(targetDao.getLink(targetID));
412        ReferenceList referenceList = new ReferenceList();
413        for (Number siblingID : targetIDs) {
414            if (!siblingID.equals(targetID)) {
415            referenceList.getHref().add(targetDao.getHrefFromInternalID(siblingID));
416            }
417        }
418        return referenceList;
419    }
420
421    @Override
422    public Principal getPrincipal(Number principalID) {
423        return principalDao.getPrincipal(principalID);
424    }
425
426    @Override
427    public Principal getPrincipalByInfo(String eMail) throws NotInDataBaseException {
428        return principalDao.getPrincipalByInfo(eMail);
429    }
430
431    @Override
432    public String getPrincipalRemoteID(Number internalID) {
433        return principalDao.getRemoteID(internalID);
434    }
435
436    @Override
437    public Access getAccess(Number annotationID, Number principalID) {
438        Access publicAttribute = annotationDao.getPublicAttribute(annotationID);
439        Access access = annotationDao.getAccess(annotationID, principalID);
440        if (access != null) {
441            if (publicAttribute.equals(Access.NONE)) {
442                return access;
443            } else {
444                if (publicAttribute.equals(Access.READ)) {
445                    if (access.equals(Access.NONE)) {
446                        return Access.READ;
447                    } else {
448                        return access;
449                    }
450                } else {
451                    return Access.WRITE;
452                }
453            }
454        } else {
455            return publicAttribute;
456        }
457    }
458
459    @Override
460    public Access getPublicAttribute(Number annotationID) {
461        return annotationDao.getPublicAttribute(annotationID);
462    }
463
464    @Override
465    public Number getPrincipalInternalIDFromRemoteID(String remoteID) throws NotInDataBaseException {
466        return principalDao.getPrincipalInternalIDFromRemoteID(remoteID);
467    }
468   
469    @Override
470    public UUID getPrincipalExternalIDFromRemoteID(String remoteID) throws NotInDataBaseException {
471        return principalDao.getPrincipalExternalIDFromRemoteID(remoteID);
472    }
473
474    @Override
475    public String getTypeOfPrincipalAccount(Number principalID) {
476        return principalDao.getTypeOfPrincipalAccount(principalID);
477    }
478
479    @Override
480    public Principal getDataBaseAdmin() {
481        return principalDao.getPrincipal(principalDao.getDBAdminID());
482    }
483
484    // !!!so far implemented only for annotations!!!
485    @Override
486    public boolean canDo(ResourceAction action, Number principalID, Number resourceID, Resource resource) {
487
488        switch (resource) {
489            case ANNOTATION: {
490                if (principalID.equals(annotationDao.getOwner(resourceID)) || principalDao.getTypeOfPrincipalAccount(principalID).equals(admin)) {
491                    return true;
492                }
493                Access access = this.getAccess(resourceID, principalID);
494                return this.greaterOrEqual(access, action);
495            }
496            case CACHED_REPRESENTATION: {
497                return true;
498            }
499            case TARGET: {
500                return true;
501            }
502            case PRINCIPAL: {
503                return true;
504            }
505            default:
506                return false;
507        }
508
509    }
510
511    private boolean greaterOrEqual(Access access, ResourceAction action) {
512        if (access.equals(Access.WRITE) && (action.equals(ResourceAction.READ) || action.equals(ResourceAction.WRITE))) {
513            return true;
514        }
515        if (access.equals(Access.READ) && action.equals(ResourceAction.READ)) {
516            return true;
517        }
518        return false;
519    }
520////// noetbooks ///////
521/// TODO update for having attribute public!!! /////
522
523    @Override
524    public NotebookInfoList getNotebooks(Number principalID, Access access) {
525        NotebookInfoList result = new NotebookInfoList();
526        if (access.equals(Access.READ) || access.equals(Access.WRITE)) {
527            List<Number> notebookIDs = notebookDao.getNotebookIDs(principalID, access);
528            for (Number notebookID : notebookIDs) {
529                NotebookInfo notebookInfo = notebookDao.getNotebookInfoWithoutOwner(notebookID);
530                Number ownerID = notebookDao.getOwner(notebookID);
531                notebookInfo.setOwnerHref(principalDao.getHrefFromInternalID(ownerID));
532                result.getNotebookInfo().add(notebookInfo);
533            }
534        }
535        return result;
536    }
537
538    @Override
539    public boolean hasAccess(Number notebookID, Number principalID, Access access) {
540        List<Number> notebookIDs = notebookDao.getNotebookIDs(principalID, access);
541        return notebookIDs.contains(notebookID);
542    }
543
544    @Override
545    public ReferenceList getNotebooksOwnedBy(Number principalID) {
546        ReferenceList result = new ReferenceList();
547        List<Number> notebookIDs = notebookDao.getNotebookIDsOwnedBy(principalID);
548        for (Number notebookID : notebookIDs) {
549            String reference = notebookDao.getHrefFromInternalID(notebookID);
550            result.getHref().add(reference);
551        }
552        return result;
553    }
554
555    @Override
556    public ReferenceList getPrincipals(Number notebookID, String access) {
557        ReferenceList result = new ReferenceList();
558        List<Number> principalIDs = principalDao.getPrincipalIDsWithAccessForNotebook(notebookID, Access.fromValue(access));
559        for (Number principalID : principalIDs) {
560            String reference = principalDao.getHrefFromInternalID(principalID);
561            result.getHref().add(reference);
562        }
563        return result;
564    }
565
566    @Override
567    public Notebook getNotebook(Number notebookID) {
568        Notebook result = notebookDao.getNotebookWithoutAnnotationsAndAccesssAndOwner(notebookID);
569
570        result.setOwnerRef(principalDao.getHrefFromInternalID(notebookDao.getOwner(notebookID)));
571
572        ReferenceList annotations = new ReferenceList();
573        List<Number> annotationIDs = annotationDao.getAnnotations(notebookID);
574        for (Number annotationID : annotationIDs) {
575            annotations.getHref().add(annotationDao.getHrefFromInternalID(annotationID));
576        }
577        result.setAnnotations(annotations);
578
579        PermissionList ups = new PermissionList();
580        List<Access> accesss = new ArrayList<Access>();
581        accesss.add(Access.READ);
582        accesss.add(Access.WRITE);
583        for (Access access : accesss) {
584            List<Number> principals = principalDao.getPrincipalIDsWithAccessForNotebook(notebookID, access);
585            if (principals != null) {
586                for (Number principal : principals) {
587                    Permission up = new Permission();
588                    up.setPrincipalHref(principalDao.getHrefFromInternalID(principal));
589                    up.setLevel(access);
590                    ups.getPermission().add(up);
591                }
592            }
593        }
594        result.setPermissions(ups);
595        return result;
596    }
597
598    @Override
599    public Number getNotebookOwner(Number notebookID) {
600        return notebookDao.getOwner(notebookID);
601    }
602
603    /////////////////////////////////////////////////////////////
604    @Override
605    public ReferenceList getAnnotationsForNotebook(Number notebookID, int startAnnotation, int maximumAnnotations, String orderedBy, boolean desc) {
606        List<Number> annotationIDs = annotationDao.getAnnotations(notebookID);
607
608        if (startAnnotation < -1) {
609            logger.info("Variable's startAnnotation value " + startAnnotation + " is invalid. I will return null.");
610            return null;
611        }
612
613        if (maximumAnnotations < -1) {
614            logger.info("Variable's maximumAnnotations value " + maximumAnnotations + " is invalid. I will return null.");
615            return null;
616        }
617
618        int offset = (startAnnotation > 0) ? startAnnotation - 1 : 0;
619        String direction = desc ? "DESC" : "ASC";
620        List<Number> selectedAnnotIDs = annotationDao.sublistOrderedAnnotationIDs(annotationIDs, offset, maximumAnnotations, orderedBy, direction);
621        ReferenceList references = new ReferenceList();
622        for (Number annotationID : selectedAnnotIDs) {
623            references.getHref().add(annotationDao.getHrefFromInternalID(annotationID));
624        }
625        return references;
626    }
627
628    ///// UPDATERS /////////////////
629    @Override
630    public boolean updateResourceIdentifier(Resource resource, UUID oldIdentifier, UUID newIdentifier) {
631        switch (resource) {
632            case PRINCIPAL:
633                return principalDao.updateResourceIdentifier(oldIdentifier, newIdentifier);
634            case ANNOTATION:
635                return annotationDao.updateResourceIdentifier(oldIdentifier, newIdentifier);
636            case TARGET:
637                return targetDao.updateResourceIdentifier(oldIdentifier, newIdentifier);
638            case CACHED_REPRESENTATION:
639                return cachedRepresentationDao.updateResourceIdentifier(oldIdentifier, newIdentifier);
640            case NOTEBOOK:
641                return notebookDao.updateResourceIdentifier(oldIdentifier, newIdentifier);
642            default:
643                return false;
644        } 
645    }
646   
647    @Override
648    public boolean updateAccount(UUID principalExternalID, String account) throws NotInDataBaseException {
649        return principalDao.updateAccount(principalExternalID, account);
650    }
651
652    @Override
653    public int updateAnnotationPrincipalAccess(Number annotationID, Number principalID, Access access) {
654        int result;
655        if (access != null) {
656            Access currentAccess = annotationDao.getAccess(annotationID, principalID);
657            if (currentAccess != null) {
658                result = annotationDao.updateAnnotationPrincipalAccess(annotationID, principalID, access);
659            } else {
660                result = annotationDao.addAnnotationPrincipalAccess(annotationID, principalID, access);
661            }
662        } else {
663            result = annotationDao.deleteAnnotationPrincipalAccess(annotationID, principalID);
664        }
665        return result;
666    }
667
668    @Override
669    public int updatePublicAttribute(Number annotationID, Access publicAttribute) {
670        return annotationDao.updatePublicAttribute(annotationID, publicAttribute);
671    }
672
673    @Override
674    public int updatePermissions(Number annotationID, PermissionList permissionList) throws NotInDataBaseException {
675        annotationDao.updatePublicAttribute(annotationID, permissionList.getPublic());
676        List<Permission> permissions = permissionList.getPermission();
677        int result = 0;
678        for (Permission permission : permissions) {
679            Number principalID = principalDao.getInternalIDFromHref(permission.getPrincipalHref());
680            Access access = permission.getLevel();
681            Access currentAccess = annotationDao.getAccess(annotationID, principalID);
682            if (currentAccess != null) {
683                if (!access.equals(currentAccess)) {
684                    result = result + annotationDao.updateAnnotationPrincipalAccess(annotationID, principalID, access);
685                } else {
686                    result = 0;
687                }
688            } else {
689                result = result + annotationDao.addAnnotationPrincipalAccess(annotationID, principalID, access);
690            }
691
692        }
693        return result;
694    }
695// TODO: optimize (not chnanged targets should not be deleted)
696// TODO: unit test
697
698    @Override
699    public int updateAnnotation(Annotation annotation, String remoteUser) throws NotInDataBaseException {
700        Number annotationID = annotationDao.getInternalID(UUID.fromString(annotation.getId()));
701        Number ownerID = principalDao.getInternalIDFromHref(annotation.getOwnerHref());
702        int updatedAnnotations = annotationDao.updateAnnotation(annotation, annotationID, ownerID);
703        int deletedTargets = annotationDao.deleteAllAnnotationTarget(annotationID);
704        int addedTargets = this.addTargets(annotation, annotationID);
705       
706        Number remoteUserID = principalDao.getPrincipalInternalIDFromRemoteID(remoteUser);
707       
708        if (ownerID.equals(remoteUserID)) {
709            int deletedPrinsipalsAccesss = annotationDao.deleteAnnotationPermissions(annotationID);
710            int addedPrincipalsAccesss = this.addPermissions(annotation.getPermissions().getPermission(), annotationID);
711            int updatedPublicAttribute = annotationDao.updatePublicAttribute(annotationID, annotation.getPermissions().getPublic());
712        };
713        return updatedAnnotations;
714    }
715
716    // TODO: unit test
717    @Override
718    public int updateAnnotationBody(Number internalID, AnnotationBody annotationBody) {
719        String[] body = annotationDao.retrieveBodyComponents(annotationBody);
720        return annotationDao.updateAnnotationBody(internalID, body[0], body[1], annotationBody.getXmlBody() != null);
721    }
722
723    @Override
724    public int updateAnnotationHeadline(Number internalID, String newHeader){
725        return annotationDao.updateAnnotationHeadline(internalID, newHeader);
726    }
727
728    @Override
729    public Number updatePrincipal(Principal principal) throws NotInDataBaseException {
730        return principalDao.updatePrincipal(principal);
731    }
732
733    @Override
734    public int updateTargetCachedFragment(Number targetID, Number cachedID, String fragmentDescriptor) throws NotInDataBaseException {
735        return targetDao.updateTargetCachedRepresentationFragment(targetID, cachedID, fragmentDescriptor);
736    }
737
738    @Override
739    public int updateCachedMetada(CachedRepresentationInfo cachedInfo) throws NotInDataBaseException {
740        Number internalID = cachedRepresentationDao.getInternalID(UUID.fromString(cachedInfo.getId()));
741        return cachedRepresentationDao.updateCachedRepresentationMetadata(internalID, cachedInfo);
742    }
743
744    @Override
745    public int updateCachedBlob(Number internalID, InputStream cachedBlob) throws IOException {
746        return cachedRepresentationDao.updateCachedRepresentationBlob(internalID, cachedBlob);
747    }
748
749    /// notebooks ///
750    @Override
751    public boolean updateNotebookMetadata(Number notebookID, NotebookInfo upToDateNotebookInfo) throws NotInDataBaseException {
752        Number ownerID = principalDao.getInternalIDFromHref(upToDateNotebookInfo.getOwnerHref());
753        return notebookDao.updateNotebookMetadata(notebookID, upToDateNotebookInfo.getTitle(), ownerID);
754    }
755
756    @Override
757    public boolean addAnnotationToNotebook(Number notebookID, Number annotationID) {
758        return notebookDao.addAnnotationToNotebook(notebookID, annotationID);
759    }
760
761    /////////////// ADDERS  /////////////////////////////////
762    @Override
763    public Number[] addCachedForTarget(Number targetID, String fragmentDescriptor, CachedRepresentationInfo cachedInfo, InputStream cachedBlob) throws NotInDataBaseException, IOException {
764        Number[] result = new Number[2];
765        try {
766            result[1] = cachedRepresentationDao.addCachedRepresentation(cachedInfo, cachedBlob);
767        } catch (NotInDataBaseException e1) {
768            logger.info("Something wrong went while adding cached.");
769            throw e1;
770        }
771
772        result[0] = targetDao.addTargetCachedRepresentation(targetID, result[1], fragmentDescriptor);
773        return result;
774
775    }
776
777   
778    @Override
779    public Map<String, String> addTargetsForAnnotation(Number annotationID, List<TargetInfo> targets) throws NotInDataBaseException {
780        Map<String, String> result = new HashMap<String, String>();
781        for (TargetInfo targetInfo : targets) {
782            try {
783                Number targetIDRunner = targetDao.getInternalIDFromHref(targetInfo.getHref());
784                int affectedRows = annotationDao.addAnnotationTarget(annotationID, targetIDRunner);
785            } catch (NotInDataBaseException e) {
786                Target newTarget = this.createFreshTarget(targetInfo);
787                Number targetID = targetDao.addTarget(newTarget);
788                String targetTemporaryId = targetInfo.getHref();
789                result.put(targetTemporaryId, targetDao.getHrefFromInternalID(targetID));
790                int affectedRows = annotationDao.addAnnotationTarget(annotationID, targetID);
791            }
792        }
793        return result;
794    }
795
796    @Override
797    public Number addPrincipalsAnnotation(Number ownerID, Annotation annotation) throws NotInDataBaseException {
798        Number annotationID = annotationDao.addAnnotation(annotation, ownerID);
799        int affectedAnnotRows = this.addTargets(annotation, annotationID);
800        int addedPrincipalsAccesss = this.addPermissions(annotation.getPermissions().getPermission(), annotationID);
801        int updatedPublic = annotationDao.updatePublicAttribute(annotationID, annotation.getPermissions().getPublic());
802        return annotationID;
803    }
804
805    @Override
806    public Number addPrincipal(Principal principal, String remoteID) throws NotInDataBaseException, PrincipalExists {
807        if (principalDao.principalExists(remoteID)) {
808            throw new PrincipalExists(remoteID);
809        } else {
810            return principalDao.addPrincipal(principal, remoteID);
811        }
812    }
813
814    //////////// notebooks //////
815    @Override
816    public Number createNotebook(Notebook notebook, Number ownerID) throws NotInDataBaseException {
817        Number notebookID = notebookDao.createNotebookWithoutAccesssAndAnnotations(notebook, ownerID);
818        boolean updateOwner = notebookDao.setOwner(notebookID, ownerID);
819        List<Permission> permissions = notebook.getPermissions().getPermission();
820        for (Permission permission : permissions) {
821            Number principalID = principalDao.getInternalIDFromHref(permission.getPrincipalHref());
822            Access access = permission.getLevel();
823            boolean updateAccesss = notebookDao.addAccessToNotebook(notebookID, principalID, access);
824        }
825        return notebookID;
826    }
827
828    @Override
829    public boolean createAnnotationInNotebook(Number notebookID, Annotation annotation, Number ownerID) throws NotInDataBaseException {
830        Number newAnnotationID = this.addPrincipalsAnnotation(ownerID, annotation);
831        return notebookDao.addAnnotationToNotebook(notebookID, newAnnotationID);
832    }
833
834    @Override
835    public int addSpringUser(String username, String password, int strength, String salt) {
836        int users = principalDao.addSpringUser(username, password, strength, salt);
837        int authorities = principalDao.addSpringAuthorities(username);
838        return users + authorities;
839    }
840
841    ////////////// DELETERS //////////////////
842    @Override
843    public int deletePrincipal(Number principalID) throws PrincipalCannotBeDeleted {
844        return principalDao.deletePrincipal(principalID);
845    }
846
847    @Override
848    public int deleteCachedRepresentation(Number internalID) {
849
850        if (targetDao.cachedIsInUse(internalID)) {
851            logger.debug("Cached Repr. is in use, and cannot be deleted.");
852            return 0;
853        }
854
855        return cachedRepresentationDao.deleteCachedRepresentation(internalID);
856    }
857
858    @Override
859    public int[] deleteCachedRepresentationOfTarget(Number targetID, Number cachedID) {
860        int[] result = new int[2];
861        result[0] = targetDao.deleteTargetCachedRepresentation(targetID, cachedID);
862        if (result[0] > 0) {
863            result[1] = cachedRepresentationDao.deleteCachedRepresentation(cachedID);
864        } else {
865            result[1] = 0;
866
867        }
868        return result;
869    }
870
871    @Override
872    public int[] deleteAllCachedRepresentationsOfTarget(Number targetID) {
873        int[] result = new int[2];
874        result[0] = 0;
875        result[1] = 0;
876        List<Number> cachedIDs = cachedRepresentationDao.getCachedRepresentationsForTarget(targetID);
877        for (Number cachedID : cachedIDs) {
878            int[] currentResult = this.deleteCachedRepresentationOfTarget(targetID, cachedID);
879            result[0] = result[0] + currentResult[0];
880            result[1] = result[1] + currentResult[1];
881        }
882        return result;
883    }
884
885    @Override
886    public int[] deleteAnnotation(Number annotationID) {
887        int[] result = new int[5];
888        result[1] = annotationDao.deleteAnnotationPermissions(annotationID);
889        List<Number> targetIDs = targetDao.getTargetIDs(annotationID);
890        result[2] = annotationDao.deleteAllAnnotationTarget(annotationID);
891        result[3] = 0;
892        if (targetIDs != null) {
893            for (Number targetID : targetIDs) {
894                this.deleteAllCachedRepresentationsOfTarget(targetID);
895                result[3] = result[3] + this.deleteTarget(targetID);
896
897            }
898        }
899
900        result[4] = annotationDao.deleteAnnotationFromAllNotebooks(annotationID);
901
902        result[0] = annotationDao.deleteAnnotation(annotationID);
903        return result;
904    }
905
906    @Override
907    public int deleteTarget(Number internalID) {
908        if (annotationDao.targetIsInUse(internalID)) {
909            logger.debug("The target is in use, and cannot be deleted.");
910            return 0;
911        }
912        return targetDao.deleteTarget(internalID);
913
914    }
915
916    @Override
917    public boolean deleteNotebook(Number notebookID) {
918        if (notebookDao.deleteAllAccesssForNotebook(notebookID) || notebookDao.deleteAllAnnotationsFromNotebook(notebookID)) {
919            return notebookDao.deleteNotebook(notebookID);
920        } else {
921            return false;
922        }
923    }
924
925    @Override
926    public int deleteAnnotationPrincipalAccess(Number annotationID, Number principalID) {
927        return annotationDao.deleteAnnotationPrincipalAccess(annotationID, principalID);
928    }
929////////////// HELPERS ////////////////////
930    ////////////////////////////////////////
931
932    @Override
933    public ResponseBody makeAnnotationResponseEnvelope(Number annotationID) {
934        ResponseBody result = new ResponseBody();
935        Annotation annotation = this.getAnnotation(annotationID);
936        result.setAnnotation(annotation);
937        List<String> targetsNoCached = this.getTargetsWithNoCachedRepresentation(annotationID);
938        ActionList actionList = new ActionList();
939        result.setActionList(actionList);
940        actionList.getAction().addAll(makeActionList(targetsNoCached, AnnotationActionName.CREATE_CACHED_REPRESENTATION.value()));
941        return result;
942    }
943
944    @Override
945    public ResponseBody makeNotebookResponseEnvelope(Number notebookID) {
946        ResponseBody result = new ResponseBody();
947        result.setPermissions(null);
948        Notebook notebook = this.getNotebook(notebookID);
949        result.setNotebook(notebook);
950        return result;
951    }
952
953    @Override
954    public ResponseBody makeAccessResponseEnvelope(Number resourceID, Resource resource) {
955        ResponseBody result = new ResponseBody();
956        PermissionList permissions = this.getPermissions(resourceID, resource);
957        result.setPermissions(permissions);
958        List<String> principalsWithNoInfo = this.getPrincipalsWithNoInfo(resourceID);
959        ActionList actionList = new ActionList();
960        result.setActionList(actionList);
961        actionList.getAction().addAll(makeActionList(principalsWithNoInfo, PermissionActionName.PROVIDE_PRINCIPAL_INFO.value()));
962        return result;
963    }
964
965    private List<Action> makeActionList(List<String> resourceURIs, String message) {
966        if (resourceURIs != null) {
967            if (resourceURIs.isEmpty()) {
968                return (new ArrayList<Action>());
969            } else {
970                List<Action> result = new ArrayList<Action>();
971                for (String resourceURI : resourceURIs) {
972                    Action action = new Action();
973                    result.add(action);
974                    action.setMessage(message);
975                    action.setObject(resourceURI);
976                }
977                return result;
978            }
979        } else {
980            return null;
981        }
982    }
983   
984    @Override
985    public UUID getPrincipalExternalIdFromName(String fullName) throws NotInDataBaseException{
986       return principalDao.getExternalIdFromName(fullName);
987    }
988   
989    @Override
990    public List<UUID> getAnnotationExternalIdsFromHeadline(String headline){
991        return annotationDao.getExternalIdFromHeadline(headline);
992    }
993   
994    @Override
995    public List<Number> getAnnotationInternalIDsFromHeadline(String headline){
996        return annotationDao.getInternalIDsFromHeadline(headline);
997    }
998
999    //// privee ///
1000    private Target createFreshTarget(TargetInfo targetInfo) {
1001        Target target = new Target();
1002        target.setLink(targetInfo.getLink());
1003        target.setVersion(targetInfo.getVersion());
1004        return target;
1005    }
1006
1007    private int addTargets(Annotation annotation, Number annotationID) throws NotInDataBaseException {
1008        List<TargetInfo> targets = annotation.getTargets().getTargetInfo();
1009        Map<String, String> targetIdPairs = this.addTargetsForAnnotation(annotationID, targets);
1010        AnnotationBody annotationBody = annotation.getBody();
1011        String bodyText;
1012        String newBodyText;
1013        String mimeType;
1014        if (annotationBody.getXmlBody() != null) {
1015            bodyText = Helpers.elementToString(annotation.getBody().getXmlBody().getAny());
1016            mimeType = annotationBody.getXmlBody().getMimeType();
1017        } else {
1018            if (annotation.getBody().getTextBody() != null) {
1019                bodyText = annotation.getBody().getTextBody().getBody();
1020                mimeType = annotationBody.getTextBody().getMimeType();
1021            } else {
1022                logger.error("The client has sent ill-formed annotation body.");
1023                return -1;
1024            }
1025        }
1026        newBodyText = Helpers.replace(bodyText, targetIdPairs);
1027        return annotationDao.updateAnnotationBody(annotationID, newBodyText, mimeType, annotationBody.getXmlBody() != null);
1028    }
1029
1030    private int addPermissions(List<Permission> permissions, Number annotationID) throws NotInDataBaseException {
1031        if (permissions != null) {
1032            int addedPermissions = 0;
1033            for (Permission permission : permissions) {
1034                addedPermissions = addedPermissions + annotationDao.addAnnotationPrincipalAccess(annotationID, principalDao.getInternalIDFromHref(permission.getPrincipalHref()), permission.getLevel());
1035            }
1036            return addedPermissions;
1037        } else {
1038            return 0;
1039        }
1040    }
1041
1042    private TargetInfo getTargetInfoFromTarget(Target target) {
1043        TargetInfo targetInfo = new TargetInfo();
1044        targetInfo.setHref(target.getHref());
1045        targetInfo.setLink(target.getLink());
1046        targetInfo.setVersion(target.getVersion());
1047        return targetInfo;
1048    }
1049}
Note: See TracBrowser for help on using the repository browser.