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;
017
018import java.util.Collection;
019import java.util.EnumSet;
020import java.util.HashMap;
021import java.util.Iterator;
022import java.util.Map;
023import java.util.Set;
024
025import javax.xml.bind.annotation.XmlAccessType;
026import javax.xml.bind.annotation.XmlAccessorType;
027import javax.xml.bind.annotation.XmlElement;
028import javax.xml.bind.annotation.XmlElementWrapper;
029import javax.xml.bind.annotation.XmlEnum;
030import javax.xml.bind.annotation.XmlEnumValue;
031import javax.xml.bind.annotation.XmlRootElement;
032
033import org.apache.commons.lang3.ArrayUtils;
034import org.apache.commons.lang3.StringUtils;
035
036import service.tut.pori.contentanalysis.AbstractTaskDetails.TaskParameters;
037
038/**
039 * Analysis parameters for an analysis task.
040 * 
041 * <h2>Optional Elements</h2>
042 * <ul>
043 *  <li>{@value service.tut.pori.contentanalysis.Definitions#ELEMENT_ANALYSIS_TYPELIST}. If not given, the defaults {@link service.tut.pori.contentanalysis.PhotoParameters.AnalysisType#KEYWORD_EXTRACTION} and {@link service.tut.pori.contentanalysis.PhotoParameters.AnalysisType#VISUAL} should be used.</li>
044 * </ul>
045 * 
046 * <h3>XML Example</h3>
047 * 
048 * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_EXAMPLE]" method="[service.tut.pori.contentanalysis.Definitions#ELEMENT_TASK_PARAMETERS]" type="GET" query="" body_uri=""}
049 * 
050 */
051@XmlRootElement(name=Definitions.ELEMENT_TASK_PARAMETERS)
052@XmlAccessorType(value=XmlAccessType.NONE)
053public final class PhotoParameters extends TaskParameters {
054  private static final String ANALYSIS_TYPE_AUDIO = "AUDIO";
055  private static final String ANALYSIS_TYPE_FACE_DETECTION = "FACE_DETECTION";
056  private static final String ANALYSIS_TYPE_KEYWORD_EXTRACTION = "KEYWORD_EXTRACTION";
057  private static final String ANALYSIS_TYPE_VISUAL = "VISUAL";
058  @XmlElement(name = Definitions.ELEMENT_ANALYSIS_TYPE)
059  @XmlElementWrapper(name = Definitions.ELEMENT_ANALYSIS_TYPELIST)
060  private Set<AnalysisType> _analysisTypes = null;
061
062  /**
063   * The analysis type for the provided content.
064   *
065   */
066  @XmlEnum
067  public enum AnalysisType{
068    /**
069     * Audio content should be analyzed.
070     */
071    @XmlEnumValue(value = ANALYSIS_TYPE_AUDIO)
072    AUDIO,
073    /**
074     * Face detection should be performed for the task contents.
075     */
076    @XmlEnumValue(value = ANALYSIS_TYPE_FACE_DETECTION)
077    FACE_DETECTION,
078    /**
079     * The content should be analyzed for keywords.
080     */
081    @XmlEnumValue(value = ANALYSIS_TYPE_KEYWORD_EXTRACTION)
082    KEYWORD_EXTRACTION,
083    /**
084     * Visual content (photos, videos) should be analyzed.
085     */
086    @XmlEnumValue(value = ANALYSIS_TYPE_VISUAL)
087    VISUAL;
088    
089    /**
090     * 
091     * @return this enumeration as analysis type string
092     */
093    public String toAnalysisTypeString(){
094      switch(this){
095        case AUDIO:
096          return ANALYSIS_TYPE_AUDIO;
097        case FACE_DETECTION:
098          return ANALYSIS_TYPE_FACE_DETECTION;
099        case KEYWORD_EXTRACTION:
100          return ANALYSIS_TYPE_KEYWORD_EXTRACTION;
101        case VISUAL:
102          return ANALYSIS_TYPE_VISUAL;
103        default:
104          throw new UnsupportedOperationException("Unhandeled "+AnalysisType.class.toString()+" : "+name());
105      }
106    }
107    
108    /**
109     * 
110     * @param value
111     * @return the given value converted to analysis type
112     * @throws IllegalArgumentException on bad value
113     */
114    public static AnalysisType fromAnalysisTypeString(String value) throws IllegalArgumentException {
115      if(!StringUtils.isBlank(value)){
116        for(AnalysisType t : AnalysisType.values()){
117          if(t.toAnalysisTypeString().equalsIgnoreCase(value)){
118            return t;
119          }
120        }
121      }
122      throw new IllegalArgumentException("Invalid analysis type value : "+value);
123    }
124
125    /**
126     * 
127     * @param values
128     * @return the values converted to analysis types or null if empty or null value collection was passed
129     * @throws IllegalArgumentException on invalid value
130     */
131    public static EnumSet<AnalysisType> fromAnalysisTypeString(Collection<String> values) throws IllegalArgumentException {
132      if(values == null || values.isEmpty()){
133        return null;
134      }
135      EnumSet<AnalysisType> types = EnumSet.noneOf(AnalysisType.class);
136      for(String value : values){
137        types.add(fromAnalysisTypeString(value));
138      }
139      return types;
140    }
141  } // enum AnalysisType
142
143  /**
144   * @return the analysisTypes
145   * @see #setAnalysisTypes(Set)
146   */
147  public Set<AnalysisType> getAnalysisTypes() {
148    return _analysisTypes;
149  }
150
151  /**
152   * @param analysisTypes the analysisTypes to set
153   * @see #getAnalysisTypes()
154   */
155  public void setAnalysisTypes(Set<AnalysisType> analysisTypes) {
156    _analysisTypes = analysisTypes;
157  }
158
159  @Override
160  public void initialize(Map<String, String> metadata) throws IllegalArgumentException {
161    _analysisTypes = null;
162    if(metadata != null && !metadata.isEmpty()){
163      String[] analysisTypes = StringUtils.split(metadata.get(Definitions.ELEMENT_ANALYSIS_TYPELIST), core.tut.pori.http.Definitions.SEPARATOR_URI_QUERY_PARAM_VALUES);
164      if(!ArrayUtils.isEmpty(analysisTypes)){
165        _analysisTypes = EnumSet.of(AnalysisType.fromAnalysisTypeString(analysisTypes[0]));
166        for(int i=1;i<analysisTypes.length;++i){
167          _analysisTypes.add(AnalysisType.fromAnalysisTypeString(analysisTypes[i]));
168        }
169      }
170    }
171  }
172
173  @Override
174  public HashMap<String, String> toMetadata() {
175    if(_analysisTypes == null || _analysisTypes.isEmpty()){
176      return null;
177    }else{
178      HashMap<String, String> metadata = new HashMap<>(1);
179      Iterator<AnalysisType> typeIter = _analysisTypes.iterator();
180      if(_analysisTypes.size() == 1){
181        metadata.put(Definitions.ELEMENT_ANALYSIS_TYPELIST, typeIter.next().toAnalysisTypeString());
182      }else{
183        StringBuilder tb = new StringBuilder(typeIter.next().toAnalysisTypeString());
184        while(typeIter.hasNext()){
185          tb.append(core.tut.pori.http.Definitions.SEPARATOR_URI_QUERY_PARAM_VALUES);
186          tb.append(typeIter.next().toAnalysisTypeString());
187        }
188        metadata.put(Definitions.ELEMENT_ANALYSIS_TYPELIST, tb.toString());
189      }
190      return metadata;
191    }
192  }
193}