001/** 002 * Copyright 2014 Tampere University of Technology, Pori Department 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package service.tut.pori.contentanalysis; 017 018import java.util.ArrayList; 019import java.util.Iterator; 020import java.util.List; 021 022import javax.xml.bind.annotation.XmlAccessType; 023import javax.xml.bind.annotation.XmlAccessorType; 024import javax.xml.bind.annotation.XmlElement; 025import javax.xml.bind.annotation.XmlRootElement; 026 027import org.apache.commons.lang3.StringUtils; 028import org.apache.log4j.Logger; 029 030import core.tut.pori.http.ResponseData; 031import core.tut.pori.utils.MediaUrlValidator.MediaType; 032import service.tut.pori.contentanalysis.MediaObject.MediaObjectType; 033 034/** 035 * A list of media objects, which can be directly used as a data for XML response. 036 * 037 * <h3>XML Example</h3> 038 * 039 * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_EXAMPLE]" method="[service.tut.pori.contentanalysis.Definitions#ELEMENT_MEDIA_OBJECTLIST]" type="GET" query="" body_uri=""} 040 * 041 * @see service.tut.pori.contentanalysis.MediaObject 042 */ 043@XmlRootElement(name=Definitions.ELEMENT_MEDIA_OBJECTLIST) 044@XmlAccessorType(XmlAccessType.NONE) 045public class MediaObjectList extends ResponseData{ 046 private static final Logger LOGGER = Logger.getLogger(MediaObjectList.class); 047 private static final String MEDIA_OBJECT_PARAMETER_DELIMITER = ":"; //like: OBJECT1_VALUE1:OBJECT1_VALUE2... 048 @XmlElement(name = Definitions.ELEMENT_MEDIA_OBJECT) 049 private List<MediaObject> _mediaObjects = null; 050 @XmlElement(name = Definitions.ELEMENT_RESULT_INFO) 051 private ResultInfo _resultInfo = null; 052 053 /** 054 * @return list of photos 055 * @see #addMediaObject(MediaObject) 056 * @see #addMediaObjects(MediaObjectList) 057 */ 058 public List<MediaObject> getMediaObjects() { 059 if(_mediaObjects != null && _mediaObjects.size() > 0){ 060 return _mediaObjects; 061 }else{ 062 return null; 063 } 064 } 065 066 /** 067 * Note: calling this method will clear the list's result info if any is present 068 * 069 * @param mediaObject 070 * @see #getMediaObjects() 071 */ 072 public void addMediaObject(MediaObject mediaObject){ 073 if(_mediaObjects == null){ 074 _mediaObjects = new ArrayList<>(); 075 } 076 _mediaObjects.add(mediaObject); 077 if(_resultInfo != null){ // if there was a result info, it may now be incorrect 078 LOGGER.debug("Removing possibly incorrect result info."); 079 _resultInfo = null; 080 } 081 } 082 083 /** 084 * add the media object list to this media object list, empty list is ignored 085 * 086 * Note: calling this method will clear the list's result info if any is present 087 * 088 * @param mediaObjects 089 * @see #getMediaObjects() 090 */ 091 public void addMediaObjects(MediaObjectList mediaObjects){ 092 if(MediaObjectList.isEmpty(mediaObjects)){ 093 return; 094 } 095 if(_mediaObjects == null){ 096 _mediaObjects = new ArrayList<>(); 097 } 098 _mediaObjects.addAll(mediaObjects.getMediaObjects()); 099 if(_resultInfo != null){ // if there was a result info, it may now be incorrect 100 LOGGER.debug("Removing possibly incorrect result info."); 101 _resultInfo = null; 102 } 103 } 104 105 /** 106 * 107 * @param mediaObjectId non-null id 108 * @return the media object or null if not found 109 */ 110 public MediaObject getMediaObject(String mediaObjectId){ 111 if(isEmpty()){ 112 return null; 113 } 114 for(Iterator<MediaObject> iter = _mediaObjects.iterator(); iter.hasNext();){ 115 MediaObject v = iter.next(); 116 if(mediaObjectId.equals(v.getMediaObjectId())){ 117 return v; 118 } 119 } 120 return null; 121 } 122 123 /** 124 * 125 * @return list of media object ids for this list or null if none 126 */ 127 public List<String> getMediaObjectIds(){ 128 if(isEmpty()){ 129 LOGGER.debug("Empty media object list."); 130 return null; 131 } 132 List<String> voids = new ArrayList<>(_mediaObjects.size()); 133 for(MediaObject v : _mediaObjects){ 134 String mediaObjectId = v.getMediaObjectId(); 135 if(StringUtils.isBlank(mediaObjectId)){ 136 LOGGER.debug("Ignored media object without id."); 137 }else{ 138 voids.add(mediaObjectId); 139 } 140 } 141 return (voids.isEmpty() ? null : voids); 142 } 143 144 /** 145 * 146 * @param list 147 * @return true if this list contains no objects, or the list is null 148 */ 149 public static boolean isEmpty(MediaObjectList list){ 150 if(list == null){ 151 return true; 152 }else{ 153 return list.isEmpty(); 154 } 155 } 156 157 /** 158 * use the static, only for sub-classing 159 * @return true if the list is empty 160 * @see #isEmpty(MediaObjectList) 161 */ 162 protected boolean isEmpty(){ 163 return (_mediaObjects == null || _mediaObjects.isEmpty() ? true : false); 164 } 165 166 /** 167 * 168 * @param objects 169 * @param resultInfo 170 * @return list or null if null or empty list is passed 171 */ 172 public static MediaObjectList getMediaObjectList(List<? extends MediaObject> objects, ResultInfo resultInfo){ 173 if(objects == null || objects.isEmpty()){ 174 LOGGER.debug("Ignored empty list."); 175 return null; 176 }else{ 177 MediaObjectList list = new MediaObjectList(); 178 list._mediaObjects = new ArrayList<>(objects); 179 list._resultInfo = resultInfo; 180 return list; 181 } 182 } 183 184 /** 185 * <p>Parse given keywords given in following format:</p> 186 * <pre>keyword:confidence:backendId,keyword:confidence:backendId,...</pre> 187 * <p><em>keyword</em> is required, <em>confidence</em> and <em>backendId</em> are optional.</p> 188 * @param keywords 189 * @return list of media objects based on the keywords or null if none was found 190 */ 191 public static MediaObjectList getMediaObjectListFromKeywords(List<String> keywords){ 192 List<MediaObject> objects = null; 193 if(keywords != null && !keywords.isEmpty()){ 194 objects = new ArrayList<>(); 195 for(Iterator<String> iter = keywords.iterator();iter.hasNext();){ 196 String[] keywordParts = iter.next().split(MEDIA_OBJECT_PARAMETER_DELIMITER); 197 MediaObject o = new MediaObject(MediaType.PHOTO, MediaObjectType.KEYWORD); 198 o.setValue(keywordParts[0]); 199 if(keywordParts.length > 1){ 200 o.setConfidence(Double.valueOf(keywordParts[1])); 201 } 202 if(keywordParts.length > 2){ 203 o.setBackendId(Integer.valueOf(keywordParts[2])); 204 } 205 objects.add(o); 206 } // for 207 } 208 return getMediaObjectList(objects, null); 209 } 210 211 /** 212 * 213 * @param list can be null 214 * @return true if the passed list is valid 215 */ 216 public static boolean isValid(MediaObjectList list){ 217 if(list == null){ 218 return false; 219 }else{ 220 return list.isValid(); 221 } 222 } 223 224 /** 225 * use the static, only for sub-classing 226 * @return true if the list is valid 227 * @see #isValid(MediaObjectList) 228 */ 229 protected boolean isValid(){ 230 if(_mediaObjects == null){ 231 return false; 232 }else{ 233 for(Iterator<MediaObject> iter = _mediaObjects.iterator();iter.hasNext();){ 234 if(!iter.next().isValid()){ 235 return false; 236 } 237 } 238 return true; 239 } 240 } 241 242 /** 243 * Default data groups: {@value service.tut.pori.contentanalysis.Definitions#DATA_GROUP_RESULT_INFO} 244 * 245 * @return the resultInfo 246 * @see #setResultInfo(ResultInfo) 247 */ 248 public ResultInfo getResultInfo() { 249 return _resultInfo; 250 } 251 252 /** 253 * @param resultInfo the resultInfo to set 254 * @see #getResultInfo() 255 */ 256 public void setResultInfo(ResultInfo resultInfo) { 257 _resultInfo = resultInfo; 258 } 259}