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

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

filtering annotations on link is now exact. also added the parameter "matchMode", so the search request may looks like one of the follows:

GET api/annotations?link=Sagrada&matchMode=contains
GET api/annotations?link=http://nl.wikipedia.org/wiki/Sagrada_Fam%C3%ADlia&matchMode=exact
GET api/annotations?link=http://nl.wikipedia.org/wiki&matchMode=starts_with
GET api/annotations?link=_Fam%C3%ADlia&matchMode=ends_with
GET api/annotations?link=http://nl.wikipedia.org/wiki/Sagrada_Fam%C3%ADlia

Issue 16 github is fixed: now the list of siblings of the target exclude the target itself.

File size: 43.2 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.setCachedRepresentatinons(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) throws NotInDataBaseException {
700        Number annotationID = annotationDao.getInternalID(UUID.fromString(annotation.getId()));
701        int updatedAnnotations = annotationDao.updateAnnotation(annotation, annotationID, principalDao.getInternalIDFromHref(annotation.getOwnerHref()));
702        int deletedTargets = annotationDao.deleteAllAnnotationTarget(annotationID);
703        int deletedPrinsipalsAccesss = annotationDao.deleteAnnotationPermissions(annotationID);
704        int addedTargets = this.addTargets(annotation, annotationID);
705        int addedPrincipalsAccesss = this.addPermissions(annotation.getPermissions().getPermission(), annotationID);
706        int updatedPublicAttribute = annotationDao.updatePublicAttribute(annotationID, annotation.getPermissions().getPublic());
707        return updatedAnnotations;
708    }
709
710    // TODO: unit test
711    @Override
712    public int updateAnnotationBody(Number internalID, AnnotationBody annotationBody) {
713        String[] body = annotationDao.retrieveBodyComponents(annotationBody);
714        return annotationDao.updateAnnotationBody(internalID, body[0], body[1], annotationBody.getXmlBody() != null);
715    }
716
717    @Override
718    public int updateAnnotationHeadline(Number internalID, String newHeader){
719        return annotationDao.updateAnnotationHeadline(internalID, newHeader);
720    }
721
722    @Override
723    public Number updatePrincipal(Principal principal) throws NotInDataBaseException {
724        return principalDao.updatePrincipal(principal);
725    }
726
727    @Override
728    public int updateTargetCachedFragment(Number targetID, Number cachedID, String fragmentDescriptor) throws NotInDataBaseException {
729        return targetDao.updateTargetCachedRepresentationFragment(targetID, cachedID, fragmentDescriptor);
730    }
731
732    @Override
733    public int updateCachedMetada(CachedRepresentationInfo cachedInfo) throws NotInDataBaseException {
734        Number internalID = cachedRepresentationDao.getInternalID(UUID.fromString(cachedInfo.getId()));
735        return cachedRepresentationDao.updateCachedRepresentationMetadata(internalID, cachedInfo);
736    }
737
738    @Override
739    public int updateCachedBlob(Number internalID, InputStream cachedBlob) throws IOException {
740        return cachedRepresentationDao.updateCachedRepresentationBlob(internalID, cachedBlob);
741    }
742
743    /// notebooks ///
744    @Override
745    public boolean updateNotebookMetadata(Number notebookID, NotebookInfo upToDateNotebookInfo) throws NotInDataBaseException {
746        Number ownerID = principalDao.getInternalIDFromHref(upToDateNotebookInfo.getOwnerHref());
747        return notebookDao.updateNotebookMetadata(notebookID, upToDateNotebookInfo.getTitle(), ownerID);
748    }
749
750    @Override
751    public boolean addAnnotationToNotebook(Number notebookID, Number annotationID) {
752        return notebookDao.addAnnotationToNotebook(notebookID, annotationID);
753    }
754
755    /////////////// ADDERS  /////////////////////////////////
756    @Override
757    public Number[] addCachedForTarget(Number targetID, String fragmentDescriptor, CachedRepresentationInfo cachedInfo, InputStream cachedBlob) throws NotInDataBaseException, IOException {
758        Number[] result = new Number[2];
759        try {
760            result[1] = cachedRepresentationDao.addCachedRepresentation(cachedInfo, cachedBlob);
761        } catch (NotInDataBaseException e1) {
762            logger.info("Something wrong went while adding cached.");
763            throw e1;
764        }
765
766        result[0] = targetDao.addTargetCachedRepresentation(targetID, result[1], fragmentDescriptor);
767        return result;
768
769    }
770
771   
772    @Override
773    public Map<String, String> addTargetsForAnnotation(Number annotationID, List<TargetInfo> targets) throws NotInDataBaseException {
774        Map<String, String> result = new HashMap<String, String>();
775        for (TargetInfo targetInfo : targets) {
776            try {
777                Number targetIDRunner = targetDao.getInternalIDFromHref(targetInfo.getHref());
778                int affectedRows = annotationDao.addAnnotationTarget(annotationID, targetIDRunner);
779            } catch (NotInDataBaseException e) {
780                Target newTarget = this.createFreshTarget(targetInfo);
781                Number targetID = targetDao.addTarget(newTarget);
782                String targetTemporaryId = targetInfo.getHref();
783                result.put(targetTemporaryId, targetDao.getHrefFromInternalID(targetID));
784                int affectedRows = annotationDao.addAnnotationTarget(annotationID, targetID);
785            }
786        }
787        return result;
788    }
789
790    @Override
791    public Number addPrincipalsAnnotation(Number ownerID, Annotation annotation) throws NotInDataBaseException {
792        Number annotationID = annotationDao.addAnnotation(annotation, ownerID);
793        int affectedAnnotRows = this.addTargets(annotation, annotationID);
794        int addedPrincipalsAccesss = this.addPermissions(annotation.getPermissions().getPermission(), annotationID);
795        int updatedPublic = annotationDao.updatePublicAttribute(annotationID, annotation.getPermissions().getPublic());
796        return annotationID;
797    }
798
799    @Override
800    public Number addPrincipal(Principal principal, String remoteID) throws NotInDataBaseException, PrincipalExists {
801        if (principalDao.principalExists(remoteID)) {
802            throw new PrincipalExists(remoteID);
803        } else {
804            return principalDao.addPrincipal(principal, remoteID);
805        }
806    }
807
808    //////////// notebooks //////
809    @Override
810    public Number createNotebook(Notebook notebook, Number ownerID) throws NotInDataBaseException {
811        Number notebookID = notebookDao.createNotebookWithoutAccesssAndAnnotations(notebook, ownerID);
812        boolean updateOwner = notebookDao.setOwner(notebookID, ownerID);
813        List<Permission> permissions = notebook.getPermissions().getPermission();
814        for (Permission permission : permissions) {
815            Number principalID = principalDao.getInternalIDFromHref(permission.getPrincipalHref());
816            Access access = permission.getLevel();
817            boolean updateAccesss = notebookDao.addAccessToNotebook(notebookID, principalID, access);
818        }
819        return notebookID;
820    }
821
822    @Override
823    public boolean createAnnotationInNotebook(Number notebookID, Annotation annotation, Number ownerID) throws NotInDataBaseException {
824        Number newAnnotationID = this.addPrincipalsAnnotation(ownerID, annotation);
825        return notebookDao.addAnnotationToNotebook(notebookID, newAnnotationID);
826    }
827
828    @Override
829    public int addSpringUser(String username, String password, int strength, String salt) {
830        int users = principalDao.addSpringUser(username, password, strength, salt);
831        int authorities = principalDao.addSpringAuthorities(username);
832        return users + authorities;
833    }
834
835    ////////////// DELETERS //////////////////
836    @Override
837    public int deletePrincipal(Number principalID) throws PrincipalCannotBeDeleted {
838        return principalDao.deletePrincipal(principalID);
839    }
840
841    @Override
842    public int deleteCachedRepresentation(Number internalID) {
843
844        if (targetDao.cachedIsInUse(internalID)) {
845            logger.debug("Cached Repr. is in use, and cannot be deleted.");
846            return 0;
847        }
848
849        return cachedRepresentationDao.deleteCachedRepresentation(internalID);
850    }
851
852    @Override
853    public int[] deleteCachedRepresentationOfTarget(Number targetID, Number cachedID) {
854        int[] result = new int[2];
855        result[0] = targetDao.deleteTargetCachedRepresentation(targetID, cachedID);
856        if (result[0] > 0) {
857            result[1] = cachedRepresentationDao.deleteCachedRepresentation(cachedID);
858        } else {
859            result[1] = 0;
860
861        }
862        return result;
863    }
864
865    @Override
866    public int[] deleteAllCachedRepresentationsOfTarget(Number targetID) {
867        int[] result = new int[2];
868        result[0] = 0;
869        result[1] = 0;
870        List<Number> cachedIDs = cachedRepresentationDao.getCachedRepresentationsForTarget(targetID);
871        for (Number cachedID : cachedIDs) {
872            int[] currentResult = this.deleteCachedRepresentationOfTarget(targetID, cachedID);
873            result[0] = result[0] + currentResult[0];
874            result[1] = result[1] + currentResult[1];
875        }
876        return result;
877    }
878
879    @Override
880    public int[] deleteAnnotation(Number annotationID) {
881        int[] result = new int[5];
882        result[1] = annotationDao.deleteAnnotationPermissions(annotationID);
883        List<Number> targetIDs = targetDao.getTargetIDs(annotationID);
884        result[2] = annotationDao.deleteAllAnnotationTarget(annotationID);
885        result[3] = 0;
886        if (targetIDs != null) {
887            for (Number targetID : targetIDs) {
888                this.deleteAllCachedRepresentationsOfTarget(targetID);
889                result[3] = result[3] + this.deleteTarget(targetID);
890
891            }
892        }
893
894        result[4] = annotationDao.deleteAnnotationFromAllNotebooks(annotationID);
895
896        result[0] = annotationDao.deleteAnnotation(annotationID);
897        return result;
898    }
899
900    @Override
901    public int deleteTarget(Number internalID) {
902        if (annotationDao.targetIsInUse(internalID)) {
903            logger.debug("The target is in use, and cannot be deleted.");
904            return 0;
905        }
906        return targetDao.deleteTarget(internalID);
907
908    }
909
910    @Override
911    public boolean deleteNotebook(Number notebookID) {
912        if (notebookDao.deleteAllAccesssForNotebook(notebookID) || notebookDao.deleteAllAnnotationsFromNotebook(notebookID)) {
913            return notebookDao.deleteNotebook(notebookID);
914        } else {
915            return false;
916        }
917    }
918
919    @Override
920    public int deleteAnnotationPrincipalAccess(Number annotationID, Number principalID) {
921        return annotationDao.deleteAnnotationPrincipalAccess(annotationID, principalID);
922    }
923////////////// HELPERS ////////////////////
924    ////////////////////////////////////////
925
926    @Override
927    public ResponseBody makeAnnotationResponseEnvelope(Number annotationID) {
928        ResponseBody result = new ResponseBody();
929        Annotation annotation = this.getAnnotation(annotationID);
930        result.setAnnotation(annotation);
931        List<String> targetsNoCached = this.getTargetsWithNoCachedRepresentation(annotationID);
932        ActionList actionList = new ActionList();
933        result.setActionList(actionList);
934        actionList.getAction().addAll(makeActionList(targetsNoCached, AnnotationActionName.CREATE_CACHED_REPRESENTATION.value()));
935        return result;
936    }
937
938    @Override
939    public ResponseBody makeNotebookResponseEnvelope(Number notebookID) {
940        ResponseBody result = new ResponseBody();
941        result.setPermissions(null);
942        Notebook notebook = this.getNotebook(notebookID);
943        result.setNotebook(notebook);
944        return result;
945    }
946
947    @Override
948    public ResponseBody makeAccessResponseEnvelope(Number resourceID, Resource resource) {
949        ResponseBody result = new ResponseBody();
950        PermissionList permissions = this.getPermissions(resourceID, resource);
951        result.setPermissions(permissions);
952        List<String> principalsWithNoInfo = this.getPrincipalsWithNoInfo(resourceID);
953        ActionList actionList = new ActionList();
954        result.setActionList(actionList);
955        actionList.getAction().addAll(makeActionList(principalsWithNoInfo, PermissionActionName.PROVIDE_PRINCIPAL_INFO.value()));
956        return result;
957    }
958
959    private List<Action> makeActionList(List<String> resourceURIs, String message) {
960        if (resourceURIs != null) {
961            if (resourceURIs.isEmpty()) {
962                return (new ArrayList<Action>());
963            } else {
964                List<Action> result = new ArrayList<Action>();
965                for (String resourceURI : resourceURIs) {
966                    Action action = new Action();
967                    result.add(action);
968                    action.setMessage(message);
969                    action.setObject(resourceURI);
970                }
971                return result;
972            }
973        } else {
974            return null;
975        }
976    }
977   
978    @Override
979    public UUID getPrincipalExternalIdFromName(String fullName) throws NotInDataBaseException{
980       return principalDao.getExternalIdFromName(fullName);
981    }
982   
983    @Override
984    public List<UUID> getAnnotationExternalIdsFromHeadline(String headline){
985        return annotationDao.getExternalIdFromHeadline(headline);
986    }
987   
988    @Override
989    public List<Number> getAnnotationInternalIDsFromHeadline(String headline){
990        return annotationDao.getInternalIDsFromHeadline(headline);
991    }
992
993    //// privee ///
994    private Target createFreshTarget(TargetInfo targetInfo) {
995        Target target = new Target();
996        target.setLink(targetInfo.getLink());
997        target.setVersion(targetInfo.getVersion());
998        return target;
999    }
1000
1001    private int addTargets(Annotation annotation, Number annotationID) throws NotInDataBaseException {
1002        List<TargetInfo> targets = annotation.getTargets().getTargetInfo();
1003        Map<String, String> targetIdPairs = this.addTargetsForAnnotation(annotationID, targets);
1004        AnnotationBody annotationBody = annotation.getBody();
1005        String bodyText;
1006        String newBodyText;
1007        String mimeType;
1008        if (annotationBody.getXmlBody() != null) {
1009            bodyText = Helpers.elementToString(annotation.getBody().getXmlBody().getAny());
1010            mimeType = annotationBody.getXmlBody().getMimeType();
1011        } else {
1012            if (annotation.getBody().getTextBody() != null) {
1013                bodyText = annotation.getBody().getTextBody().getBody();
1014                mimeType = annotationBody.getTextBody().getMimeType();
1015            } else {
1016                logger.error("The client has sent ill-formed annotation body.");
1017                return -1;
1018            }
1019        }
1020        newBodyText = Helpers.replace(bodyText, targetIdPairs);
1021        return annotationDao.updateAnnotationBody(annotationID, newBodyText, mimeType, annotationBody.getXmlBody() != null);
1022    }
1023
1024    private int addPermissions(List<Permission> permissions, Number annotationID) throws NotInDataBaseException {
1025        if (permissions != null) {
1026            int addedPermissions = 0;
1027            for (Permission permission : permissions) {
1028                addedPermissions = addedPermissions + annotationDao.addAnnotationPrincipalAccess(annotationID, principalDao.getInternalIDFromHref(permission.getPrincipalHref()), permission.getLevel());
1029            }
1030            return addedPermissions;
1031        } else {
1032            return 0;
1033        }
1034    }
1035
1036    private TargetInfo getTargetInfoFromTarget(Target target) {
1037        TargetInfo targetInfo = new TargetInfo();
1038        targetInfo.setHref(target.getHref());
1039        targetInfo.setLink(target.getLink());
1040        targetInfo.setVersion(target.getVersion());
1041        return targetInfo;
1042    }
1043}
Note: See TracBrowser for help on using the repository browser.