source: ComponentRegistry/trunk/ComponentRegistry/src/main/java/clarin/cmdi/componentregistry/persistence/impl/AbstractDescriptionDaoImpl.java @ 3451

Last change on this file since 3451 was 3451, checked in by George.Georgovassilis@mpi.nl, 11 years ago

#360 Fixes for shha lux16 environment and renaming of DAO interfaces and implementations

File size: 16.0 KB
Line 
1package clarin.cmdi.componentregistry.persistence.impl;
2
3import java.sql.ResultSet;
4import java.sql.SQLException;
5import java.sql.Timestamp;
6import java.text.ParseException;
7import java.util.Collections;
8import java.util.Date;
9import java.util.HashMap;
10import java.util.List;
11import java.util.Map;
12
13import org.slf4j.Logger;
14import org.slf4j.LoggerFactory;
15import org.springframework.dao.DataAccessException;
16import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
17import org.springframework.jdbc.core.simple.ParameterizedSingleColumnRowMapper;
18import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
19
20import clarin.cmdi.componentregistry.model.AbstractDescription;
21import clarin.cmdi.componentregistry.model.ComponentDescription;
22import clarin.cmdi.componentregistry.model.ProfileDescription;
23import clarin.cmdi.componentregistry.persistence.AbstractDescriptionDao;
24
25import java.util.Arrays;
26import java.util.Collection;
27
28import org.apache.commons.collections.ListUtils;
29
30/**
31 * Base DAO which can be extended to serve {@link ComponentDescription}s and {@link ProfileDescription}s
32 * @author Twan Goosen <twan.goosen@mpi.nl>
33 * @author George.Georgovassilis@mpi.nl
34 */
35public abstract class AbstractDescriptionDaoImpl<T extends AbstractDescription>
36        extends ComponentRegistryDaoImpl<T> implements AbstractDescriptionDao<T> {
37
38    private final static Logger LOG = LoggerFactory
39            .getLogger(AbstractDescriptionDaoImpl.class);
40
41    protected abstract String getTableName();
42
43    protected abstract String getCMDIdColumn();
44
45    protected abstract String getCommentsForeignKeyColumn();
46
47    /**
48     * Class object required to instantiate new description domain objects
49     */
50    private final Class<T> _class;
51
52    protected AbstractDescriptionDaoImpl(Class<T> _class) {
53        this._class = _class;
54    }
55
56    /**
57     *
58     * @param cmdId
59     *            CMD id
60     * @return Whether the specified item is in the public space
61     */
62    @Override
63    public boolean isPublic(String cmdId) {
64        StringBuilder query = new StringBuilder("SELECT COUNT(*) FROM ");
65        query.append(getTableName());
66        query.append(" WHERE is_public = true AND ").append(getCMDIdColumn())
67                .append(" = ?");
68        return (0 < getJdbcTemplate().queryForInt(query.toString(), cmdId));
69    }
70
71    /**
72     *
73     * @param cmdId
74     *            CMD id
75     * @param userId
76     *            User db id of workspace owner
77     * @return Whether the specified item is in the specified user's workspace
78     */
79    @Override
80    public boolean isInUserSpace(String cmdId, Number userId) {
81        StringBuilder query = new StringBuilder("SELECT COUNT(*) FROM ");
82        query.append(getTableName());
83        query.append(" WHERE is_public = false AND user_id = ? AND ")
84                .append(getCMDIdColumn()).append(" = ?");
85        return (0 < getJdbcTemplate().queryForInt(query.toString(), userId,
86                cmdId));
87    }
88
89    /**
90     *
91     * @param cmdId
92     *            CMD id
93     * @param userId
94     *            User db id of workspace owner, null for public registry
95     * @return Whether the specified item is in the specified workspace (user or
96     *         public)
97     */
98    @Override
99    public boolean isInRegistry(String cmdId, Number userId) {
100        if (userId == null) {
101            return isPublic(cmdId);
102        } else {
103            return isInUserSpace(cmdId, userId);
104        }
105    }
106
107    /**
108     *
109     * @param cmdId
110     *            Profile or component Id (not primary key)
111     * @return String value of XML content for profile or component
112     */
113    @Override
114    public String getContent(boolean isDeleted, String cmdId)
115            throws DataAccessException {
116        String select = "SELECT content FROM " + TABLE_XML_CONTENT + " JOIN "
117                + getTableName() + " ON " + TABLE_XML_CONTENT + "." + COLUMN_ID
118                + " = " + getTableName() + ".content_id"
119                + " WHERE is_deleted = ? AND " + getTableName() + "."
120                + getCMDIdColumn() + " = ?";
121
122        List<String> result = getJdbcTemplate().query(select,
123                new ParameterizedSingleColumnRowMapper<String>(), isDeleted,
124                cmdId);
125        if (result.size() > 0) {
126            return result.get(0);
127        } else {
128            return null;
129        }
130    }
131
132    /**
133     * @param description
134     *            Description to insert
135     * @param content
136     *            Content to insert and refer to from description
137     * @return Id of newly inserted description
138     */
139    @Override
140    public Number insertDescription(AbstractDescription description,
141            String content, boolean isPublic, Number userId)
142            throws DataAccessException {
143
144        SimpleJdbcInsert insert = new SimpleJdbcInsert(getJdbcTemplate())
145                .withTableName(TABLE_XML_CONTENT).usingGeneratedKeyColumns(
146                        COLUMN_ID);
147        Number contentId = insert.executeAndReturnKey(Collections.singletonMap(
148                "content", (Object) content));
149
150        SimpleJdbcInsert insertDescription = new SimpleJdbcInsert(
151                getJdbcTemplate()).withTableName(getTableName())
152                .usingGeneratedKeyColumns(COLUMN_ID);
153        Map<String, Object> params = new HashMap<String, Object>();
154        putInsertParameters(params, description, contentId, userId, isPublic);
155
156        Number id = insertDescription.executeAndReturnKey(params);
157        return id;
158    }
159
160    private Timestamp extractTimestamp(AbstractDescription description) {
161        if (description.getRegistrationDate() != null) {
162            try {
163                Date date = AbstractDescription.getDate(description
164                        .getRegistrationDate());
165                return new Timestamp(date.getTime());
166            } catch (ParseException ex) {
167                LOG.warn(
168                        "Could not convert registration date "
169                                + description.getRegistrationDate()
170                                + " to date", ex);
171            } catch (IllegalArgumentException ex) {
172                LOG.warn(
173                        "Could not convert registration date "
174                                + description.getRegistrationDate()
175                                + " to timestamp", ex);
176            }
177        }
178        return null;
179    }
180
181    /**
182     * Updates a description by database id
183     *
184     * @param id
185     *            Id (key) of description record
186     * @param description
187     *            New values for description (leave null to not change)
188     * @param content
189     *            New content for description (leave null to not change)
190     */
191    @Override
192    public void updateDescription(Number id, AbstractDescription description,
193            String content) {
194        if (description != null) {
195            // Update description
196            StringBuilder updateDescription = new StringBuilder();
197            updateDescription.append("UPDATE ").append(getTableName());
198            appendUpdateColumnsStatement(updateDescription);
199            updateDescription.append(" WHERE " + COLUMN_ID + " = ?");
200            Collection updateParams = ListUtils.union(
201                    getUpdateParameterValues(description),
202                    Collections.singletonList(id));
203            getJdbcTemplate().update(updateDescription.toString(),
204                    updateParams.toArray());
205        }
206
207        if (content != null) {
208            // Update content
209            StringBuilder updateContent = new StringBuilder();
210            updateContent.append("UPDATE " + TABLE_XML_CONTENT
211                    + " SET content = ? WHERE " + COLUMN_ID + " = ");
212            updateContent.append("(SELECT content_id FROM ")
213                    .append(getTableName())
214                    .append(" WHERE " + COLUMN_ID + "= ?)");
215
216            getJdbcTemplate().update(updateContent.toString(), content, id);
217        }
218    }
219
220    /**
221     * Retrieves description by it's primary key Id
222     *
223     * @param id
224     *            Description key
225     * @return The description, if it exists; null otherwise
226     */
227    @Override
228    public T getById(Number id) throws DataAccessException {
229        return getFirstOrNull(
230                getSelectStatement("WHERE is_deleted = false AND id = ?"), id);
231    }
232
233    /**
234     * Get by ComponentId / ProfileId, whether in userspace or public
235     *
236     * @param id
237     *            Full component id
238     * @return The description, if it exists; null otherwise
239     */
240    @Override
241    public T getByCmdId(String id) throws DataAccessException {
242        return getFirstOrNull(
243                getSelectStatement("WHERE is_deleted = false AND "
244                        + getCMDIdColumn() + " = ?"), id);
245    }
246
247    /**
248     * Get by ComponentId / ProfileId
249     *
250     * @param id
251     *            Full component id
252     * @param userId
253     *            Db id of user for workspace; null for public space
254     * @return The description, if it exists; null otherwise
255     */
256    @Override
257    public T getByCmdId(String id, Number userId) throws DataAccessException {
258        StringBuilder query = new StringBuilder("WHERE is_deleted = false AND ")
259                .append(getCMDIdColumn()).append(" = ?");
260        if (userId == null) {
261            return getFirstOrNull(
262                    getSelectStatement(query.append(" AND is_public = true")
263                            .toString()), id);
264        } else {
265            return getFirstOrNull(
266                    getSelectStatement(query.append(
267                            " AND is_public = false AND user_id = ?")
268                            .toString()), id, userId);
269        }
270    }
271
272    /**
273     *
274     * @param cmdId
275     *            CMD Id of description
276     * @return Database id for description record
277     */
278    @Override
279    public Number getDbId(String cmdId) {
280        StringBuilder query = new StringBuilder("SELECT " + COLUMN_ID
281                + " FROM ").append(getTableName());
282        query.append(" WHERE ").append(getCMDIdColumn()).append(" = ?");
283        return getJdbcTemplate().queryForInt(query.toString(), cmdId);
284    }
285
286    /**
287     *
288     * @return All descriptions in the public space
289     */
290    @Override
291    public List<T> getPublicDescriptions() throws DataAccessException {
292        return getList(getSelectStatement(
293                " WHERE is_deleted = false AND is_public = true ").append(
294                getOrderByClause()));
295    }
296
297    /**
298     * @return List of deleted descriptions in user space or in public when
299     *         userId=null
300     * @param userId
301     */
302    @Override
303    public List<T> getDeletedDescriptions(Number userId) {
304        if (userId != null) {
305            String select = getSelectStatement()
306                    .append(" WHERE is_deleted = true AND is_public = false AND user_id = ?")
307                    .append(getOrderByClause()).toString();
308            return getList(select, userId);
309        } else {
310            String select = getSelectStatement()
311                    .append(" WHERE is_deleted = true AND is_public = true")
312                    .append(getOrderByClause()).toString();
313            return getList(select);
314        }
315    }
316
317    /**
318     *
319     * @return All the user's descriptions not in the public space
320     */
321    @Override
322    public List<T> getUserspaceDescriptions(Number userId)
323            throws DataAccessException {
324        String select = getSelectStatement()
325                .append(" WHERE is_deleted = false AND is_public = false AND user_id = ?")
326                .append(getOrderByClause()).toString();
327        return getList(select, userId);
328    }
329
330    @Override
331    public void setDeleted(AbstractDescription desc, boolean isDeleted)
332            throws DataAccessException {
333        Number dbId = getDbId(desc.getId());
334        StringBuilder update = new StringBuilder("UPDATE ")
335                .append(getTableName());
336        update.append(" SET is_deleted = ").append(Boolean.toString(isDeleted))
337                .append(" WHERE " + COLUMN_ID + " = ?");
338        getJdbcTemplate().update(update.toString(), dbId);
339    }
340
341    @Override
342    public void setPublished(Number id, boolean published) {
343        StringBuilder update = new StringBuilder("UPDATE ")
344                .append(getTableName());
345        update.append(" SET is_public = ? WHERE " + COLUMN_ID + " = ?");
346        getJdbcTemplate().update(update.toString(), published, id);
347    }
348
349    /**
350     *
351     * @param id
352     *            Id of description record
353     * @return Principal name of description's owner, if any. Otherwise, null.
354     */
355    @Override
356    public String getOwnerPrincipalName(Number id) {
357        StringBuilder select = new StringBuilder("SELECT principal_name FROM "
358                + TABLE_REGISTRY_USER);
359        select.append(" JOIN ").append(getTableName());
360        select.append(" ON user_id = " + TABLE_REGISTRY_USER + ".id ");
361        select.append(" WHERE ").append(getTableName()).append(".id = ?");
362        List<String> owner = getJdbcTemplate().query(select.toString(),
363                new ParameterizedSingleColumnRowMapper<String>(), id);
364        if (owner.isEmpty()) {
365            return null;
366        } else {
367            return owner.get(0);
368        }
369    }
370
371    /**
372     * @return the rowMapper
373     */
374    @Override
375    protected ParameterizedRowMapper<T> getRowMapper() {
376        return rowMapper;
377    }
378
379    /**
380     * Inserts parameters int <column, value> parameters map
381     *
382     * @param params
383     * @param description
384     * @param contentId
385     * @param userId
386     * @param isPublic
387     */
388    protected void putInsertParameters(Map<String, Object> params,
389            AbstractDescription description, Number contentId, Number userId,
390            boolean isPublic) {
391        params.put("content_id", contentId);
392        params.put("user_id", userId);
393        params.put("is_public", isPublic);
394        params.put("is_deleted", Boolean.FALSE);
395        params.put(getCMDIdColumn(), description.getId());
396        params.put("name", description.getName());
397        params.put("description", description.getDescription());
398        params.put("creator_name", description.getCreatorName());
399        params.put("group_name", description.getGroupName());
400        params.put("domain_name", description.getDomainName());
401        params.put("href", description.getHref());
402        params.put("registration_date", extractTimestamp(description));
403    }
404
405    /**
406     * Sets values on a new description object from specified ResultSet
407     *
408     * @param rs
409     *            ResultSet from database query
410     * @param newDescription
411     *            Newly created description object to be filled
412     * @throws SQLException
413     */
414    protected void setDescriptionValuesFromResultSet(ResultSet rs,
415            AbstractDescription newDescription) throws SQLException {
416        Timestamp registrationDate = rs.getTimestamp("registration_date");
417        newDescription.setName(rs.getString("name"));
418        newDescription.setDescription(rs.getString("description"));
419        newDescription.setId(rs.getString(getCMDIdColumn()));
420        newDescription
421                .setRegistrationDate(registrationDate == null ? null
422                        : AbstractDescription.createNewDate(registrationDate
423                                .getTime()));
424        newDescription.setCreatorName(rs.getString("creator_name"));
425        newDescription.setDomainName(rs.getString("domain_name"));
426        newDescription.setGroupName(rs.getString("group_name"));
427        newDescription.setHref(rs.getString("href"));
428        newDescription.setCommentsCount(rs.getInt("columns_count"));
429
430        Object userId = rs.getObject("user_id");
431        if (!rs.wasNull()) {
432            newDescription.setUserId(userId.toString());
433        }
434    }
435
436    protected void appendUpdateColumnsStatement(StringBuilder updateDescription) {
437        updateDescription
438                .append(" SET name = ?, description = ?, registration_date=?, creator_name=?, domain_name=?, group_name=?, href=?");
439    }
440
441    protected List getUpdateParameterValues(AbstractDescription description) {
442        List updateParams = Arrays.asList(description.getName(),
443                description.getDescription(), extractTimestamp(description),
444                description.getCreatorName(), description.getDomainName(),
445                description.getGroupName(), description.getHref());
446        return updateParams;
447    }
448
449    /*
450     * DAO HELPER METHODS
451     */
452
453    private StringBuilder getSelectStatement(String... where)
454            throws DataAccessException {
455        StringBuilder select = new StringBuilder("SELECT ")
456                .append(getDescriptionColumnList());
457        select.append(" FROM ").append(getTableName());
458        if (where.length > 0) {
459            select.append(" ");
460            for (String str : where) {
461                select.append(" ").append(str);
462            }
463        }
464        return select;
465    }
466
467    /**
468     *
469     * @return List of all description columns to be used in SELECT queries
470     */
471    protected StringBuilder getDescriptionColumnList() {
472
473        StringBuilder sb = new StringBuilder();
474        sb.append(getOrderByColumn());
475        sb.append(",description,registration_date,creator_name,domain_name,group_name,href,user_id,");
476        sb.append(getCMDIdColumn());
477        sb.append(", (SELECT COUNT(*) FROM comments WHERE ")
478                .append(getCommentsForeignKeyColumn()).append(" = ")
479                .append(getCMDIdColumn()).append(") AS columns_count");
480        return sb;
481    }
482
483    private String getOrderByColumn() {
484        return "name";
485    }
486
487    private String getOrderByClause() {
488        return " order by upper(" + getOrderByColumn() + "), "
489                + getCMDIdColumn() + " asc ";
490    }
491
492    private final ParameterizedRowMapper<T> rowMapper = new ParameterizedRowMapper<T>() {
493
494        @Override
495        public T mapRow(ResultSet rs, int rowNumber) throws SQLException {
496            try {
497                AbstractDescription newDescription = (AbstractDescription) _class
498                        .newInstance();
499                setDescriptionValuesFromResultSet(rs, newDescription);
500                return (T) newDescription;
501            } catch (InstantiationException ex) {
502                LOG.error("Error in row mapping", ex);
503            } catch (IllegalAccessException ex) {
504                LOG.error("Error in row mapping", ex);
505            }
506            return null;
507        }
508    };
509
510}
Note: See TracBrowser for help on using the repository browser.