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

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

"put updated body" is implemented and tested. Big refactring: simplifying DAO's and pushing their composition to rest methods. add-methods in DAO return now not the classes but internalID-s of the added resources. Still 2 test errors and 2 test failures.

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