001/** 002 * Copyright 2015 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.video; 017 018import java.util.ArrayList; 019import java.util.List; 020 021import javax.xml.bind.annotation.XmlAccessType; 022import javax.xml.bind.annotation.XmlAccessorType; 023import javax.xml.bind.annotation.XmlElement; 024import javax.xml.bind.annotation.XmlRootElement; 025 026import org.apache.commons.lang3.StringUtils; 027import org.apache.log4j.Logger; 028 029/** 030 * A list of media object time codes. 031 * 032 * <h3>XML Example</h3> 033 * 034 * {@doc.restlet service="[service.tut.pori.contentanalysis.video.reference.Definitions#SERVICE_VCA_REFERENCE_EXAMPLE]" method="[service.tut.pori.contentanalysis.video.Definitions#ELEMENT_TIMECODELIST]" type="GET" query="" body_uri=""} 035 * 036 * @see service.tut.pori.contentanalysis.video.Timecode 037 */ 038@XmlRootElement(name=Definitions.ELEMENT_TIMECODELIST) 039@XmlAccessorType(value=XmlAccessType.NONE) 040public class TimecodeList { 041 private static final Logger LOGGER = Logger.getLogger(TimecodeList.class); 042 private static final String SOLR_SEPARATOR = ";"; 043 @XmlElement(name = Definitions.ELEMENT_TIMECODE) 044 private List<Timecode> _timecodes = null; 045 046 /** 047 * @return the timecodes 048 * @see #setTimecodes(List) 049 */ 050 public List<Timecode> getTimecodes() { 051 return _timecodes; 052 } 053 054 /** 055 * @param timecodes the timecodes to set 056 * @see #getTimecodes() 057 */ 058 public void setTimecodes(List<Timecode> timecodes) { 059 _timecodes = timecodes; 060 } 061 062 /** 063 * Only for sub-classing, use the static. 064 * 065 * @return true if the list contains no items 066 * @see #isEmpty(TimecodeList) 067 */ 068 protected boolean isEmpty() { 069 return (_timecodes == null ? true : _timecodes.isEmpty()); 070 } 071 072 /** 073 * Only for sub-classing, use the static. 074 * 075 * @return true if the list contains only valid values 076 * @see #isValid(TimecodeList) 077 */ 078 protected boolean isValid() { 079 if(isEmpty()){ 080 return false; 081 } 082 for(Timecode tc : _timecodes){ 083 if(!Timecode.isValid(tc)){ 084 return false; 085 } 086 } 087 return true; 088 } 089 090 /** 091 * 092 * @param timecodes 093 * @return true if the passed list is not null, not empty, and valid 094 */ 095 public static boolean isValid(TimecodeList timecodes) { 096 return (timecodes == null ? false : timecodes.isValid()); 097 } 098 099 /** 100 * 101 * @param timecodes 102 * @return true if the passed list is null, empty or contains no items 103 */ 104 public static boolean isEmpty(TimecodeList timecodes) { 105 return (timecodes == null ? true : timecodes.isEmpty()); 106 } 107 108 /** 109 * 110 * @param solrTimecodes if null or empty, this does nothing 111 * @return a populated timecode list 112 * @throws IllegalArgumentException on bad data 113 */ 114 public static TimecodeList populateTimecodes(List<String> solrTimecodes) throws IllegalArgumentException{ 115 if(solrTimecodes == null || solrTimecodes.isEmpty()){ 116 LOGGER.debug("No timecodes given."); 117 return null; 118 } 119 List<Timecode> timecodes = new ArrayList<>(solrTimecodes.size()); 120 for(String solrTimecode : solrTimecodes){ 121 String codes[] = StringUtils.split(solrTimecode, SOLR_SEPARATOR); 122 if(codes.length<2){ 123 LOGGER.warn("Invalid timecode ignored."); 124 continue; 125 } 126 try{ 127 Timecode code = new Timecode(); 128 code.setStart(Double.valueOf(codes[0])); 129 code.setEnd(Double.valueOf(codes[1])); 130 timecodes.add(code); 131 }catch(NumberFormatException ex){ 132 LOGGER.debug(ex,ex); 133 throw new IllegalArgumentException("Malformed timecode data."); 134 } 135 } 136 if(timecodes.isEmpty()){ 137 return null; 138 }else{ 139 TimecodeList timecodeList = new TimecodeList(); 140 timecodeList.setTimecodes(timecodes); 141 return timecodeList; 142 } 143 } 144 145 /** 146 * 147 * @param timecodes if null or empty this does nothing 148 * @return list of combined timecodes [{start;end}] 149 * @throws IllegalArgumentException on missing values 150 */ 151 public static List<String> getSolrTimecodes(TimecodeList timecodes) throws IllegalArgumentException{ 152 if(timecodes == null || timecodes.isEmpty()){ 153 LOGGER.debug("No timecodes given."); 154 return null; 155 } 156 List<String> retval = new ArrayList<>(timecodes.getTimecodes().size()); 157 for(Timecode timecode : timecodes.getTimecodes()){ 158 if(timecode == null || timecode.getStart() == null || timecode.getEnd() == null){ 159 throw new IllegalArgumentException("Timecode data was missing."); 160 } 161 retval.add(timecode.getStart().toString()+SOLR_SEPARATOR+timecode.getEnd().toString()); 162 } 163 return retval; 164 } 165 166 /** 167 * Add new timecode. This will NOT check for duplicates. 168 * 169 * @param timecode 170 */ 171 public void addTimecode(Timecode timecode) { 172 if(_timecodes == null){ 173 _timecodes = new ArrayList<>(); 174 } 175 _timecodes.add(timecode); 176 } 177}