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 javax.xml.bind.annotation.XmlAccessType;
019import javax.xml.bind.annotation.XmlAccessorType;
020import javax.xml.bind.annotation.XmlElement;
021import javax.xml.bind.annotation.XmlEnum;
022import javax.xml.bind.annotation.XmlEnumValue;
023import javax.xml.bind.annotation.XmlRootElement;
024
025import org.apache.commons.lang3.StringUtils;
026
027/**
028 * Defines a visual shape used in combination with a media object.
029 * 
030 * <h3>XML Example</h3>
031 * 
032 * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_EXAMPLE]" method="[service.tut.pori.contentanalysis.Definitions#ELEMENT_VISUAL_SHAPE]" type="GET" query="" body_uri=""}
033 * 
034 */
035@XmlRootElement(name=Definitions.ELEMENT_VISUAL_SHAPE)
036@XmlAccessorType(XmlAccessType.NONE)
037public class VisualShape {
038  private static final String VISUALSHAPETYPE_CIRCLE = "CIRCLE";
039  private static final String VISUALSHAPETYPE_POLYGON = "POLYGON";
040  private static final String VISUALSHAPETYPE_RECTANGLE = "RECTANGLE";
041  private static final String VISUALSHAPETYPE_TRIANGLE = "TRIANGLE";
042  @XmlElement(name = Definitions.ELEMENT_VISUAL_SHAPE_TYPE)
043  private VisualShapeType _type = null;
044  @XmlElement(name = Definitions.ELEMENT_VALUE)
045  private String _value = null;
046
047  /**
048   * Type of the shape object.
049   */
050  @XmlEnum
051  public enum VisualShapeType{
052    /** Rectangle bounding box. Valid value format is: "topLeftX,topLeftY,bottomRightX,bottomRightY", where all values are positive integers detonating pixel positions in the photo. */
053    @XmlEnumValue(value=VISUALSHAPETYPE_RECTANGLE)
054    RECTANGLE(1),
055    /** Triangle bounding area. Valid value format is: "topX,topY,bottomLeftX,bottomLeftY,bottomRightX,bottomRightY", where all values are positive integers detonating pixel positions in the photo. */
056    @XmlEnumValue(value=VISUALSHAPETYPE_TRIANGLE)
057    TRIANGLE(2),
058    /** Cricle bounding area. Valid value format is: "centerX,centerY,radius", where all values are positive integers detonating pixel positions in the photo. */
059    @XmlEnumValue(value=VISUALSHAPETYPE_CIRCLE)
060    CIRCLE(3),
061    /** Polygon bounding area. Valid value format is: "1X,1Y,2X,2Y...nX,nY", where all values are positive integers detonating pixel positions in the photo. There should be at least 3 coordinates for a valid polygon, though it is recommended to use {@link service.tut.pori.contentanalysis.VisualShape.VisualShapeType#TRIANGLE} and {@link service.tut.pori.contentanalysis.VisualShape.VisualShapeType#RECTANGLE} for simpler objects.*/
062    @XmlEnumValue(value=VISUALSHAPETYPE_POLYGON)
063    POLYGON(4);
064
065    private int _shapeType;
066
067    /**
068     * 
069     * @param shapeType
070     */
071    private VisualShapeType(int shapeType){
072      _shapeType = shapeType;
073    }
074
075    /**
076     * 
077     * @return the type id
078     */
079    public final int toShapeTypeId(){
080      return _shapeType;
081    }
082
083    /**
084     * 
085     * @param shapeType
086     * @return the passed value as shape type
087     * @throws IllegalArgumentException on bad input
088     */
089    public static VisualShapeType fromShapeTypeId(int shapeType) throws IllegalArgumentException{
090      for(VisualShapeType e : VisualShapeType.values()){
091        if(e._shapeType == shapeType){
092          return e;
093        }
094      }
095      throw new IllegalArgumentException("Bad "+VisualShapeType.class.toString()+" : "+shapeType);
096    }
097  }  // enum VisualShapeType
098
099
100  /**
101   * 
102   * @param type
103   * @param value
104   * 
105   */
106  public VisualShape(VisualShapeType type, String value){
107    _type = type;
108    _value = value;
109  }
110
111  /**
112   * 
113   * @return value for the shape. The value differs per shape type.
114   * @see #setValue(String)
115   * @see service.tut.pori.contentanalysis.VisualShape.VisualShapeType
116   */
117  public String getValue() {
118    return _value;
119  }
120
121  /**
122   * 
123   * @param value
124   * @see #getValue()
125   */
126  public void setValue(String value) {
127    _value = value;
128  }
129
130  /**
131   * 
132   * @return type
133   * @see #setVisualShapeType(service.tut.pori.contentanalysis.VisualShape.VisualShapeType)
134   */
135  public VisualShapeType getVisualShapeType() {
136    return _type;
137  }
138
139  /**
140   * 
141   * @param type
142   * @see #getVisualShapeType()
143   */
144  public void setVisualShapeType(VisualShapeType type) {
145    _type = type;
146  }
147
148  /**
149   * for serialization
150   */
151  protected VisualShape(){
152    // nothing needed
153  }
154
155  /**
156   * 
157   * @param shape can be null
158   * @return true if the passed type is valid
159   */
160  public static boolean isValid(VisualShape shape){
161    if(shape == null){
162      return false;
163    }else{
164      return shape.isValid();
165    }
166  }
167
168  /**
169   * use the static, only for sub-classing
170   * @return true if the shape is valid
171   */
172  protected boolean isValid(){
173    if(StringUtils.isBlank(_value) || _type == null){
174      return false;
175    }else{
176      return true;
177    }
178  }
179
180  /**
181   * 
182   * @param shape
183   * @return the value or null if none or the given shape was null
184   */
185  public static String getValue(VisualShape shape){
186    return (shape == null ? null : shape.getValue());
187  }
188
189  /**
190   * Sets the given value to the given Shape. If shape is null, new shape will be returned (with the value).
191   * If value is blank and the given shape is null, null will be returned.
192   * 
193   * @param shape can be null
194   * @param value
195   * @return the passed shape, new object or null
196   */
197  public static VisualShape setValue(VisualShape shape, String value){
198    if(StringUtils.isBlank(value)){
199      if(shape == null){  // no value, no pre-existing shape given
200        return null;
201      }
202    }else if(shape == null){
203      shape = new VisualShape();
204    }
205    shape.setValue(value);
206    return shape;
207  }
208  
209  /**
210   * 
211   * @param shape
212   * @return the shape type or null if shape was null or no type given for the shape
213   */
214  public static Integer getVisualShapeTypeId(VisualShape shape){
215    if(shape == null){
216      return null;
217    }
218    VisualShapeType type = shape.getVisualShapeType();
219    return (type == null ? null : type.toShapeTypeId());
220  }
221  
222  /**
223   * Sets the given value to the given Shape. If shape is null, new shape will be returned (with the value).
224   * 
225   * @param shape can be null
226   * @param value
227   * @return the passed shape, new object or null
228   * @throws IllegalArgumentException on bad value
229   */
230  public static VisualShape setVisualShapeTypeId(VisualShape shape, Integer value) throws IllegalArgumentException{
231    if(value == null){
232      throw new IllegalArgumentException("Value cannot be null.");
233    }else if(shape == null){
234      shape = new VisualShape();
235    }
236    shape.setVisualShapeType(VisualShapeType.fromShapeTypeId(value));
237    return shape;
238  }
239
240  /**
241   * Classes implementing this interface will contain functionality for handling an VisualShape.
242   * 
243   * Remember to annotate the implemented setter methods if you wish to use them with Solr (\@Field annotation).
244   * 
245   * When implementing the methods, the static methods in VisualShapeCapable class may come handy.
246   *
247   */
248  public interface VisualShapeSolrCapable{
249    /**
250     * 
251     * @param type
252     * @throws IllegalArgumentException on bad type value
253     * @see #getVisualShapeTypeId()
254     */
255    public void setVisualShapeTypeId(Integer type) throws IllegalArgumentException;
256    
257    /**
258     * 
259     * @return shape type id
260     * @see #getVisualShapeTypeId()
261     */
262    public Integer getVisualShapeTypeId();
263    
264    /**
265     * 
266     * @param value
267     * @see #getVisualShapeValue()
268     */
269    public void setVisualShapeValue(String value);
270    
271    /**
272     * 
273     * @return shape value
274     * @see #setVisualShapeValue(String)
275     */
276    public String getVisualShapeValue();
277  } // interface VisualShapeSolrCapable
278}