001package org.deepamehta.plugins.review; 002 003import de.deepamehta.core.ChildTopics; 004import de.deepamehta.core.Topic; 005import de.deepamehta.core.TopicType; 006import de.deepamehta.core.model.AssociationDefinitionModel; 007import de.deepamehta.core.osgi.PluginActivator; 008import de.deepamehta.core.service.Transactional; 009import java.util.Collection; 010import java.util.logging.Logger; 011import javax.ws.rs.*; 012import javax.ws.rs.core.MediaType; 013import org.deepamehta.plugins.review.service.ReviewService; 014 015 016 017/** 018 * A very stupid plugin for counting likes/dislikes on any kind of topics in DeepaMehta. 019 * 020 * * Counting values seperately as "Good" and "So-so", depends on introducing Migration2 to your application model. 021 * * Counting values as one accumulate "Score", depends on introducing Migration1 to your application model. 022 * 023 * @author Malte Reißig (<malte@mikromedia.de>) 024 * @website https://github.com/mukil/dm4-reviews 025 * @version 0.3.7 026 * 027 */ 028 029@Path("/review") 030@Consumes(MediaType.APPLICATION_JSON) 031@Produces(MediaType.APPLICATION_JSON) 032public class ReviewPlugin extends PluginActivator implements ReviewService { 033 034 private Logger log = Logger.getLogger(getClass().getName()); 035 036 public final static String SCORE_TYPE_URI = "org.deepamehta.reviews.score"; 037 public final static String GOOD_TYPE_URI = "org.deepamehta.reviews.good"; 038 public final static String SOSO_TYPE_URI = "org.deepamehta.reviews.soso"; 039 040 041 /** Increments the number of supportive voices (yelling "Good!"). 042 * @param resourceId 043 **/ 044 045 @GET 046 @Path("/good/{id}") 047 @Produces("application/json") 048 @Override 049 @Transactional 050 public Topic addToGood(@PathParam("id") long resourceId) { 051 Topic topic = null; 052 try { 053 topic = dms.getTopic(resourceId); 054 TopicType typeDef = dms.getTopicType(topic.getTypeUri()); 055 Collection<AssociationDefinitionModel> typeModel = typeDef.getModel().getAssocDefs(); 056 boolean hasGoodTypeDef = false; 057 for (AssociationDefinitionModel associationDefinitionModel : typeModel) { 058 if (associationDefinitionModel.getChildTypeUri().equals(GOOD_TYPE_URI)) hasGoodTypeDef = true; 059 } 060 if (hasGoodTypeDef) { 061 topic.loadChildTopics(GOOD_TYPE_URI); 062 addOne(topic.getChildTopics(), GOOD_TYPE_URI); 063 dms.updateTopic(topic.getModel()); // ### timestamp bug in 4.4 064 } else { 065 throw new WebApplicationException(new RuntimeException("The TypeDefinition (model) of the given topic " 066 + "does not contain the \"org.deepamehta.reviews.good\"-type")); 067 } 068 } catch (Exception e) { 069 throw new RuntimeException("something went wrong", e); 070 } 071 return topic; 072 } 073 074 075 /** Increments the number of supportive voices (yelling "Well, so so."). 076 * @param resourceId 077 **/ 078 079 @GET 080 @Path("/soso/{id}") 081 @Produces("application/json") 082 @Override 083 @Transactional 084 public Topic addToSoso(@PathParam("id") long resourceId) { 085 Topic topic = null; 086 try { 087 topic = dms.getTopic(resourceId); 088 TopicType typeDef = dms.getTopicType(topic.getTypeUri()); 089 Collection<AssociationDefinitionModel> typeModel = typeDef.getModel().getAssocDefs(); 090 boolean hasSosoTypeDef = false; 091 for (AssociationDefinitionModel associationDefinitionModel : typeModel) { 092 if (associationDefinitionModel.getChildTypeUri().equals(SOSO_TYPE_URI)) hasSosoTypeDef = true; 093 } 094 if (hasSosoTypeDef) { 095 topic.loadChildTopics(SOSO_TYPE_URI); 096 addOne(topic.getChildTopics(), SOSO_TYPE_URI); 097 dms.updateTopic(topic.getModel()); // ### timestamp bug in 4.4 098 } else { 099 throw new WebApplicationException(new RuntimeException("The TypeDefinition (model) of the given topic " 100 + "does not contain the \"org.deepamehta.reviews.soso\"-type")); 101 } 102 } catch (Exception e) { 103 throw new RuntimeException("something went wrong", e); 104 } 105 return topic; 106 } 107 108 /** Increments the score of any given topic. 109 * @param resourceId 110 **/ 111 112 @GET 113 @Path("/upvote/{id}") 114 @Produces("application/json") 115 @Override 116 @Transactional 117 public Topic upvoteResourceById(@PathParam("id") long resourceId) { 118 Topic topic = null; 119 try { 120 topic = dms.getTopic(resourceId); 121 TopicType typeDef = dms.getTopicType(topic.getTypeUri()); 122 Collection<AssociationDefinitionModel> typeModel = typeDef.getModel().getAssocDefs(); 123 boolean hasScoreTypeDef = false; 124 for (AssociationDefinitionModel associationDefinitionModel : typeModel) { 125 if (associationDefinitionModel.getChildTypeUri().equals(SCORE_TYPE_URI)) hasScoreTypeDef = true; 126 } 127 if (hasScoreTypeDef) { 128 topic.loadChildTopics(SCORE_TYPE_URI); 129 addOne(topic.getChildTopics(), SCORE_TYPE_URI); 130 dms.updateTopic(topic.getModel()); // ### timestamp bug in 4.4 131 } else { 132 throw new RuntimeException("The TypeDefinition (model) of the given topic " 133 + "does not contain the \"org.deepamehta.reviews.score\"-type"); 134 } 135 } catch (Exception e) { 136 throw new RuntimeException("something went wrong", e); 137 } 138 return topic; 139 } 140 141 /** Decrements the score of any given topic. 142 * @param resourceId 143 * @param clientState */ 144 145 @GET 146 @Path("/downvote/{id}") 147 @Produces("application/json") 148 @Override 149 @Transactional 150 public Topic downvoteResourceById(@PathParam("id") long resourceId) { 151 Topic topic = null; 152 try { 153 topic = dms.getTopic(resourceId); 154 TopicType typeDef = dms.getTopicType(topic.getTypeUri()); 155 Collection<AssociationDefinitionModel> typeModel = typeDef.getModel().getAssocDefs(); 156 boolean hasScoreTypeDef = false; 157 for (AssociationDefinitionModel associationDefinitionModel : typeModel) { 158 if (associationDefinitionModel.getChildTypeUri().equals(SCORE_TYPE_URI)) hasScoreTypeDef = true; 159 } 160 if (hasScoreTypeDef) { 161 topic.loadChildTopics(SCORE_TYPE_URI); 162 substractOne(topic.getChildTopics(), SCORE_TYPE_URI); 163 dms.updateTopic(topic.getModel()); // ### timestamp bug in 4.4 164 } else { 165 throw new RuntimeException("The TypeDefinition (model) of the given topic " 166 + "does not contain the \"org.deepamehta.reviews.score\"-type"); 167 } 168 } catch (Exception e) { 169 throw new RuntimeException("something went wrong", e); 170 } 171 return topic; 172 } 173 174 private void addOne (ChildTopics childTopics, String childTypeUri) { 175 int score = 1; 176 try { 177 if (!childTopics.getModel().has(childTypeUri)) { 178 // initialize with +1 179 childTopics.set(childTypeUri, score); 180 } else { 181 // add 1 182 score = childTopics.getModel().getInt(childTypeUri) + 1; 183 childTopics.set(childTypeUri, score); 184 } 185 } catch (ClassCastException ce) { 186 // dm4-webclient has written a string into our dm4.core.numbers field 187 String value = "1"; 188 try { 189 score = Integer.parseInt(childTopics.getModel().getString(childTypeUri)); 190 value = "" + (score + 1); 191 } catch (NumberFormatException ne) { 192 // initialize string number (cause this is the type written to neo4j by dm4-core via dm4-webclient) 193 // with "1" 194 } 195 childTopics.set(childTypeUri, value); 196 } 197 } 198 199 private void substractOne (ChildTopics childTopics, String childTypeUri) { 200 int score = -1; 201 try { 202 if (!childTopics.getModel().has(childTypeUri)) { 203 // initialize with -1 204 childTopics.set(childTypeUri, score); 205 } else { 206 // subtract 1 207 score = childTopics.getModel().getInt(childTypeUri) - 1; 208 childTopics.set(childTypeUri, score); 209 } 210 } catch (ClassCastException ce) { 211 // dm4-webclient has written a string into our dm4.core.numbers field 212 String value = "-1"; 213 try { 214 score = Integer.parseInt(childTopics.getModel().getString(childTypeUri)); 215 value = "" + (score - 1); 216 } catch (NumberFormatException ne) { 217 // initialize string number (cause this is the type written to neo4j by dm4-core via dm4-webclient) 218 // with "-1" 219 } 220 childTopics.set(childTypeUri, value); 221 } 222 } 223 224}