001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.plugins.streetside; 003 004import java.util.Collection; 005import java.util.List; 006import java.util.concurrent.CopyOnWriteArrayList; 007 008import org.openstreetmap.josm.plugins.streetside.model.UserProfile; 009 010import org.openstreetmap.josm.plugins.streetside.utils.StreetsideUtils; 011 012/** 013 * Class that stores a sequence of {@link StreetsideAbstractImage} objects. 014 * 015 * @author nokutu 016 * @see StreetsideAbstractImage 017 */ 018 019public class StreetsideSequence { 020 021 022 /** 023 * Unique identifier. Used only for {@link StreetsideImage} sequences. 024 */ 025 private String id; 026 private UserProfile user; 027 028 private double la; 029 private double lo; 030 031 /** 032 * Epoch time when the sequence was created 033 */ 034 private long cd; 035 036 /** 037 * The images in the sequence. 038 */ 039 private List<StreetsideAbstractImage> images; 040 041 public StreetsideSequence(String id, Long ca) { 042 this.id = id; 043 cd = ca; 044 images = new CopyOnWriteArrayList<>(); 045 } 046 047 public StreetsideSequence(String id, double la, double lo) { 048 this.id = id; 049 this.la = la; 050 this.lo = lo; 051 images = new CopyOnWriteArrayList<>(); 052 } 053 054 /** 055 * No argument constructor for StreetsideSequence - necessary for JSON serialization 056 */ 057 public StreetsideSequence() { 058 images = new CopyOnWriteArrayList<>(); 059 } 060 061 public StreetsideSequence(String id, double la, double lo, long ca) { 062 this.id = id; 063 this.la = la; 064 this.lo = lo; 065 cd = ca; 066 images = new CopyOnWriteArrayList<>(); 067} 068 069// TODO: Are all my sequences only set with id values? (no LatLon/Cas?) @rrh 070public StreetsideSequence(String id) { 071 this.id = id; 072 images = new CopyOnWriteArrayList<>(); 073} 074 075 /** 076 * Adds a new {@link StreetsideAbstractImage} object to the database. 077 * 078 * @param image The {@link StreetsideAbstractImage} object to be added 079 */ 080 public synchronized void add(StreetsideAbstractImage image) { 081 images.add(image); 082 image.setSequence(this); 083 } 084 085 /** 086 * Adds a set of {@link StreetsideAbstractImage} objects to the database. 087 * 088 * @param images The set of {@link StreetsideAbstractImage} objects to be added. 089 */ 090 @SuppressWarnings("unchecked") 091 public synchronized void add(final Collection<? extends StreetsideAbstractImage> images) { 092 Collection<? extends StreetsideAbstractImage> res = images; 093 res = StreetsideUtils.sortImagesInSequence((List<StreetsideAbstractImage>) images); 094 this.images.addAll(images); 095 images.forEach(img -> img.setSequence(this)); 096 } 097 098 /** 099 * Returns the next {@link StreetsideAbstractImage} in the sequence of a given 100 * {@link StreetsideAbstractImage} object. 101 * 102 * @param image The {@link StreetsideAbstractImage} object whose next image is 103 * going to be returned. 104 * 105 * @return The next {@link StreetsideAbstractImage} object in the sequence. 106 * 107 * @throws IllegalArgumentException if the given {@link StreetsideAbstractImage} object doesn't belong 108 * the this sequence. 109 */ 110 public StreetsideAbstractImage next(StreetsideAbstractImage image) { 111 int i = images.indexOf(image); 112 if (i == -1) { 113 throw new IllegalArgumentException(); 114 } 115 if (i == images.size() - 1) { 116 return null; 117 } 118 return images.get(i + 1); 119 } 120 121 /** 122 * Returns the previous {@link StreetsideAbstractImage} in the sequence of a 123 * given {@link StreetsideAbstractImage} object. 124 * 125 * @param image The {@link StreetsideAbstractImage} object whose previous image is 126 * going to be returned. 127 * 128 * @return The previous {@link StreetsideAbstractImage} object in the sequence. 129 * 130 * @throws IllegalArgumentException if the given {@link StreetsideAbstractImage} object doesn't belong 131 * the this sequence. 132 */ 133 public StreetsideAbstractImage previous(StreetsideAbstractImage image) { 134 int i = images.indexOf(image); 135 if (i < 0) { 136 throw new IllegalArgumentException(); 137 } 138 if (i == 0) { 139 return null; 140 } 141 return images.get(i - 1); 142 } 143 144 /** 145 * Removes a {@link StreetsideAbstractImage} object from the database. 146 * 147 * @param image The {@link StreetsideAbstractImage} object to be removed. 148 */ 149 public void remove(StreetsideAbstractImage image) { 150 images.remove(image); 151 } 152 153 /** 154 * @param id the id to set 155 */ 156 public void setId(String id) { 157 this.id = id; 158 } 159 160 /** 161 * @return the la 162 */ 163 public double getLa() { 164 return la; 165 } 166 167 /** 168 * @param la the la to set 169 */ 170 public void setLa(double la) { 171 this.la = la; 172 } 173 174 /** 175 * @return the lo 176 */ 177 public double getLo() { 178 return lo; 179 } 180 181 /** 182 * @param lo the lo to set 183 */ 184 public void setLo(double lo) { 185 this.lo = lo; 186 } 187 188 /** 189 * Returns the Epoch time when the sequence was captured. 190 * 191 * Negative values mean, no value is set. 192 * 193 * @return A long containing the Epoch time when the sequence was captured. 194 */ 195 public long getCd() { 196 return cd; 197 } 198 199 /** 200 * Returns all {@link StreetsideAbstractImage} objects contained by this 201 * object. 202 * 203 * @return A {@link List} object containing all the 204 * {@link StreetsideAbstractImage} objects that are part of the 205 * sequence. 206 */ 207 public List<StreetsideAbstractImage> getImages() { 208 return images; 209 } 210 211 /** 212 * Returns the unique identifier of the sequence. 213 * 214 * @return A {@code String} containing the unique identifier of the sequence. 215 * null means that the sequence has been created locally for imported 216 * images. 217 */ 218 public String getId() { 219 return id; 220 } 221 222 public UserProfile getUser() { 223 return user; 224 } 225}