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

Last change on this file since 3367 was 3367, checked in by olhsha, 11 years ago

correction getting the list of annotation IDs, where annotations are filtered by link, text, etc. So far body is considered as a text (got from xmls list of elements, vis get(0)). NOT TESTED yet!

Getting sourceIDs of the sources referreing to a given link

File size: 14.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.Helpers;
21import eu.dasish.annotation.backend.dao.SourceDao;
22import eu.dasish.annotation.backend.dao.VersionDao;
23import eu.dasish.annotation.backend.identifiers.SourceIdentifier;
24import eu.dasish.annotation.backend.identifiers.VersionIdentifier;
25import eu.dasish.annotation.schema.NewOrExistingSourceInfo;
26import eu.dasish.annotation.schema.NewOrExistingSourceInfos;
27import eu.dasish.annotation.schema.NewSourceInfo;
28import eu.dasish.annotation.schema.Source;
29import eu.dasish.annotation.schema.SourceInfo;
30import java.sql.ResultSet;
31import java.sql.SQLException;
32import java.util.ArrayList;
33import java.util.HashMap;
34import java.util.List;
35import java.util.Map;
36import javax.sql.DataSource;
37import javax.xml.datatype.DatatypeConfigurationException;
38import javax.xml.datatype.XMLGregorianCalendar;
39import org.springframework.beans.factory.annotation.Autowired;
40import org.springframework.jdbc.core.RowMapper;
41
42/**
43 *
44 * @author olhsha
45 */
46public class JdbcSourceDao extends JdbcResourceDao implements SourceDao {
47
48    @Autowired
49    VersionDao versionDao;
50
51    public JdbcSourceDao(DataSource dataSource) {
52        setDataSource(dataSource);
53        internalIdName = source_id;
54        resourceTableName = sourceTableName;
55    }
56
57    //////////////////////////////////////////////////////////////////////////////////////////////////////
58    @Override
59    public SourceIdentifier getExternalID(Number internalID) {
60        return new SourceIdentifier(super.getExternalIdentifier(internalID));
61    }
62
63    @Override
64    public List<Number> retrieveSourceIDs(Number annotationID) {
65        String sql = "SELECT " + source_id + " FROM " + annotationsSourcesTableName + " WHERE " + annotation_id + "= ?";
66        List<Number> result = getSimpleJdbcTemplate().query(sql, annotationSourceRowMapper, annotationID);       
67        return result;
68    }
69    private final RowMapper<Number> annotationSourceRowMapper = new RowMapper<Number>() {
70        @Override
71        public Number mapRow(ResultSet rs, int rowNumber) throws SQLException {
72            Number result = rs.getInt(source_id);
73            return result;
74        }
75    };
76
77    ///////////////////////////////////////////////////////////////////////////////
78    @Override
79    public Source getSource(Number internalID) {
80        String sql = "SELECT " + sourceStar + "FROM " + sourceTableName + " WHERE " + source_id + " = ?";
81        List<Source> result = getSimpleJdbcTemplate().query(sql, SourceRowMapper, internalID);
82        return result.get(0);
83    }
84    private final RowMapper<Source> SourceRowMapper = new RowMapper<Source>() {
85        @Override
86        public Source mapRow(ResultSet rs, int rowNumber) throws SQLException {
87            try {
88                XMLGregorianCalendar xmlDate = Helpers.setXMLGregorianCalendar(rs.getTimestamp(time_stamp));
89                Source result = constructSource(new SourceIdentifier(rs.getString(external_id)), rs.getString(link_uri),
90                        versionDao.getExternalID(rs.getInt(version_id)), xmlDate);
91                return result;
92            } catch (DatatypeConfigurationException e) {
93                // TODO: what logger are we going to use
94                System.out.println("Cannot construct time stam: probably worng date/time format");
95                return null;
96            }
97        }
98    };
99
100    ///////////////////////////////////////////////////////////////////
101    @Override
102    public int deleteSource(Number internalID) {
103
104        // check if there are annotations referring to the source with "internalID", in the table "annotations_sources"
105        String sqlAnnotationsSources = "SELECT " + annotation_id + " FROM " + annotationsSourcesTableName + " WHERE " + source_id + "= ?";
106        List<Number> resultAnnotationsSources = getSimpleJdbcTemplate().query(sqlAnnotationsSources, annotationsSourcesRowMapper, internalID);
107
108        if (resultAnnotationsSources.isEmpty()) {
109
110            // You can remove the source!
111
112            // retrieve the list of versions of the source to be deleted
113            List<Number> versions = versionDao.retrieveVersionList(internalID);
114
115            // remove all the pairs (internalID, version_id) from the joint table
116            deleteSourceVersionRows(internalID);
117            // the main action: remove the source with internalID from "source" table
118            String sql = "DELETE FROM " + sourceTableName + " where " + source_id + " = ?";
119            int affected_source_rows = getSimpleJdbcTemplate().update(sql, internalID);
120
121            // remove the versions of "versions" from the DB unless they are still mentioned in "sources_versions"
122            for (Number versionID : versions) {
123                versionDao.deleteVersion(versionID);
124            }
125
126            return (affected_source_rows);
127        } else {
128            // do not remove
129            return 0;
130        }
131    }
132    private final RowMapper<Number> annotationsSourcesRowMapper = new RowMapper<Number>() {
133        @Override
134        public Number mapRow(ResultSet rs, int rowNumber) throws SQLException {
135            Number result = rs.getInt(annotation_id);
136            return result;
137        }
138    };
139
140    ///////////////////////////////////////////////////////////////////
141    @Override
142    public Source addSource(Source freshSource) throws SQLException{
143
144        SourceIdentifier externalIdentifier = new SourceIdentifier();
145
146        Map<String, Object> params = new HashMap<String, Object>();
147        params.put("externalId", externalIdentifier.toString());
148        params.put("linkUri", freshSource.getLink());
149        params.put("versionId", freshSource.getVersion());
150        String sql = "INSERT INTO " + sourceTableName + "(" + external_id + "," + link_uri + "," + version_id + " ) VALUES (:externalId, :linkUri,  :versionId)";
151        final int affectedRows = getSimpleJdbcTemplate().update(sql, params);
152
153        Map<String, Object> paramsJoint = new HashMap<String, Object>();
154        paramsJoint.put("sourceId", getInternalID(externalIdentifier));
155        paramsJoint.put("versionId", freshSource.getVersion());
156        String sqlSourceVersion = "INSERT INTO " + sourcesVersionsTableName + "(" + source_id + "," + version_id + " ) VALUES (:sourceId, :versionId)";
157        int affectedRowsJoint = getSimpleJdbcTemplate().update(sqlSourceVersion, paramsJoint);
158       
159        if (affectedRows == 1 && affectedRowsJoint == 1) {
160            Source result = makeFreshCopy(freshSource);
161            result.setURI(externalIdentifier.toString());
162           
163            //retrieve taime stamp for the just added annotation
164            XMLGregorianCalendar timeStamp =this.retrieveTimeStamp(getInternalID(new SourceIdentifier(externalIdentifier.toString()))); 
165            result.setTimeSatmp(timeStamp);
166           
167            return result;
168        } else {
169            throw new SQLException("Cannot add the source");
170        }
171         
172    }
173
174    ////////////////////////////////////////////////////////////////
175    ///////////////////////////////////////////////////////////////////
176    @Override
177    public List<SourceInfo> getSourceInfos(Number annotationID) {
178        List<Number> sources = retrieveSourceIDs(annotationID);
179        if (sources == null) {
180            return null;
181        }
182        if (sources.isEmpty()) {
183            return new ArrayList<SourceInfo>();
184        }
185       
186        String sourceIDs = makeListOfValues(sources);
187        String sql = "SELECT " + external_id + "," + link_uri + "," + version_id + " FROM " + sourceTableName + " WHERE " + source_id + " IN " + sourceIDs;
188        List<SourceInfo> result = getSimpleJdbcTemplate().query(sql, SourceInfoRowMapper);
189        return result;
190    }
191    private final RowMapper<SourceInfo> SourceInfoRowMapper = new RowMapper<SourceInfo>() {
192        @Override
193        public SourceInfo mapRow(ResultSet rs, int rowNumber) throws SQLException {
194            return constructSourceInfo(new SourceIdentifier(rs.getString(external_id)), rs.getString(link_uri), versionDao.getExternalID(rs.getInt(version_id)));
195        }
196    };
197
198    //////////////////////////////////////////
199    @Override
200    public NewOrExistingSourceInfos contructNewOrExistingSourceInfo(List<SourceInfo> sourceInfoList) {
201        List<NewOrExistingSourceInfo> noeSourceInfoList = new ArrayList<NewOrExistingSourceInfo>();
202        for (SourceInfo sourceInfo : sourceInfoList) {
203            NewOrExistingSourceInfo noeSourceInfo = new NewOrExistingSourceInfo();
204            noeSourceInfo.setSource(sourceInfo);
205            noeSourceInfoList.add(noeSourceInfo);
206        }
207        NewOrExistingSourceInfos result = new NewOrExistingSourceInfos();
208        result.getTarget().addAll(noeSourceInfoList);
209        return result;
210    }
211   
212   
213   
214
215    /////////////////////////////////////////////////
216    @Override
217    public int deleteSourceVersionRows(Number sourceID) {
218        // remove all the pairs (internalID, version_id) from the joint table       
219        String sqlSourcesVersions = "DELETE FROM " + sourcesVersionsTableName + " where " + source_id + " = ?";
220        return (getSimpleJdbcTemplate().update(sqlSourcesVersions, sourceID));
221
222    }
223   
224   
225   
226   
227   
228     ////////////////////////////////////////////////////////////////////////
229    @Override
230    public Map<NewOrExistingSourceInfo, NewOrExistingSourceInfo> addTargetSources(Number annotationID, List<NewOrExistingSourceInfo> sources) throws SQLException {
231
232        Map<NewOrExistingSourceInfo, NewOrExistingSourceInfo> result = new HashMap<NewOrExistingSourceInfo, NewOrExistingSourceInfo>();
233       
234        for (NewOrExistingSourceInfo noeSourceInfo : sources) {
235            SourceInfo sourceInfo = noeSourceInfo.getSource();
236            if (sourceInfo != null) {
237                // this is an old source, already exists in the DB
238                result.put(noeSourceInfo, noeSourceInfo);               
239                addAnnotationSourcePair(annotationID, getInternalID(new SourceIdentifier(sourceInfo.getRef())));
240            } else {
241                Source newSource = constructNewSource(noeSourceInfo.getNewSource());
242                Source addedSource = addSource(newSource);
243                int affectedRows = addAnnotationSourcePair(annotationID, getInternalID(new SourceIdentifier(addedSource.getURI())));
244               
245                //  create updated source info
246                SourceInfo updatedSourceInfo = new SourceInfo();
247                updatedSourceInfo.setLink(addedSource.getLink());
248                updatedSourceInfo.setRef(addedSource.getURI());
249                updatedSourceInfo.setVersion(addedSource.getVersion());
250
251                NewOrExistingSourceInfo updatedInfo = new NewOrExistingSourceInfo();
252                updatedInfo.setSource(updatedSourceInfo);
253                result.put(noeSourceInfo, updatedInfo);
254            }
255           
256        }
257        return result;
258    }
259
260    @Override
261    public List<Number> getSourcesForLink(String link){
262      StringBuilder sql = new StringBuilder("SELECT ");
263      sql.append(source_id).append(" FROM ").append(sourceTableName).append(" WHERE ").append(link_uri).append(" LIKE '%").append(link).append("%'");
264      List<Number> result = getSimpleJdbcTemplate().query(sql.toString(), internalIDRowMapper);
265      return result;
266    }
267
268    //////// HELPERS //////////////////////
269    ////////////////////////////////////////////////////////
270   
271 
272    private int addAnnotationSourcePair(Number annotationID, Number sourceID) throws SQLException{
273        // source is "old" i.e. exists in the DB, onlu the table annotations_target_sources should be updated
274        Map<String, Object> paramsAnnotationsSources = new HashMap<String, Object>();
275        paramsAnnotationsSources.put("annotationId", annotationID);
276        paramsAnnotationsSources.put("sourceId",  sourceID);
277        String sqlAnnotationsSources = "INSERT INTO " + annotationsSourcesTableName + "(" + annotation_id + "," + source_id + " ) VALUES (:annotationId, :sourceId)";
278        int affectedRows = getSimpleJdbcTemplate().update(sqlAnnotationsSources, paramsAnnotationsSources);
279        if (affectedRows != 1) {
280            throw (new SQLException("Cannot add annotation properly"));
281
282        }       
283        return (affectedRows);
284    }
285   
286   
287   
288    private SourceInfo constructSourceInfo(SourceIdentifier sourceIdentifier, String link, VersionIdentifier versionIdentifier) {
289        SourceInfo sourceInfo = new SourceInfo();
290        sourceInfo.setRef(sourceIdentifier.toString());
291        sourceInfo.setLink(link);
292        sourceInfo.setVersion(versionIdentifier.toString());
293        return sourceInfo;
294    }
295
296      ///////////////////
297    private Source constructNewSource(NewSourceInfo newSourceInfo) {
298        Source result = new Source();
299        result.setLink(newSourceInfo.getLink());
300        result.setVersion(newSourceInfo.getVersion());
301        // source's internalID will be generated by the DB
302        // source's time stamp will be generated by the DB
303        // source's externalID will be generated by the add-source-dao
304        return result;
305    }
306   
307   
308    private Source constructSource(SourceIdentifier sourceIdentifier, String link, VersionIdentifier version, XMLGregorianCalendar xmlTimeStamp) {
309        Source source = new Source();
310        source.setURI(sourceIdentifier.toString());
311        source.setTimeSatmp(xmlTimeStamp);
312        source.setLink(link);
313        source.setVersion(version.toString());
314
315        return source;
316    }
317
318    // TODO: make deep copy for source, otherwise testing will be unfair!!
319    private Source makeFreshCopy(Source source) {
320        Source result = new Source();
321        result.setLink(source.getLink());
322        result.setURI(source.getURI());
323        result.setVersion(source.getVersion());
324        result.setTimeSatmp(source.getTimeSatmp());
325        //versions-siblings are mentioned in the table sources_versions
326        return result;
327    }
328   
329   
330}
Note: See TracBrowser for help on using the repository browser.