/*
* Copyright 2009-2012 by KNURT Systeme (http://www.knurt.de)
*
* Licensed under the Creative Commons License Attribution-NonCommercial-ShareAlike 3.0 Unported;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://creativecommons.org/licenses/by-nc-sa/3.0/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.knurt.fam.template.controller.json;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.jcouchdb.document.Attachment;
import org.json.JSONException;
import org.json.JSONObject;
import de.knurt.fam.core.aspects.logging.FamLog;
import de.knurt.fam.core.aspects.security.auth.SessionAuth;
import de.knurt.fam.core.model.persist.User;
import de.knurt.fam.core.model.persist.booking.Booking;
import de.knurt.fam.core.model.persist.booking.Cancelation;
import de.knurt.fam.core.model.persist.booking.FamShoppingCart;
import de.knurt.fam.core.model.persist.document.Job;
import de.knurt.fam.core.model.persist.document.JobDataProcessing;
import de.knurt.fam.core.persistence.dao.FamDaoProxy;
import de.knurt.fam.core.persistence.dao.couchdb.FamCouchDBDao;
import de.knurt.fam.core.util.bu.FileOfUser;
import de.knurt.heinzelmann.util.nebc.bu.JSONObject2Properties;
import de.knurt.heinzelmann.util.query.HttpServletRequestConverter;
/**
* post job surveys. if there is a key "attachments" and the value of
* "attachments" is an JSONArray with files exist for the user auth, it is
* interpreted and inserted as {@link Attachment}
*
* @author Daniel Oltmanns
* @since 1.7.0 (03/06/2012)
*/
public class JobSurveyPostController extends JSONController2 {
private boolean succ = false;
private String reason = null;
private Booking booking = null;
private int step;
private JSONObject jobSurvey = null;
private JobDataProcessing jdp = null;
private User user = null;
private JSONObject inputs = null;
public JobSurveyPostController(HttpServletRequest request) {
try {
inputs = HttpServletRequestConverter.me().getJSONObject(request);
user = SessionAuth.user(request);
fou = new FileOfUser(user);
boolean insertJob = this.setParameter() && this.setBooking();
if (insertJob) {
this.setAndInsertNotice();
this.setAndInsertJob();
}
} catch (Exception e) {
// idiot or none inputs
FamLog.exception(e, 201203071247l);
succ = false;
reason = "invalid request";
this.rollback();
}
}
private void setAndInsertNotice() {
try {
if (inputs.getJSONObject("main").getString("notice").trim().isEmpty() == false) {
booking.setNotice(inputs.getJSONObject("main").getString("notice"));
booking.update();
}
} catch (Exception e) {
// OK!
}
}
/**
* return true on a valid request
*/
private boolean setParameter() {
boolean result = false;
if (user == null) {
reason = "lost session";
} else {
try {
JSONObject main = inputs.getJSONObject("main");
if (inputs == null || main.get("step") == null || main.get("idJobDataProcessing") == null || main.get("idJobDataProcessing").toString().isEmpty() || inputs.get("jobSurvey") == null) {
reason = "invalid inputs";
}
step = Integer.parseInt(main.getString("step"));
if (step < 0 || step > 4) {
reason = "invalid job step";
}
jobSurvey = inputs.getJSONObject("jobSurvey");
jdp = FamCouchDBDao.getInstance().getOne(main.getString("idJobDataProcessing"), JobDataProcessing.class);
try {
if (jdp == null) {
FamLog.error("invalid job data processing id", 201203061218l);
reason = "invalid job data processing id";
} else if (jobSurvey == null) {
FamLog.error("invalid job data processing id", 201203071118l);
reason = "invalid job data processing id";
} else {
// here everything is set as needed!
result = true;
}
} catch (Exception e2) {
FamLog.exception(e2, 201203061217l);
reason = "invalid job data processing id";
}
} catch (NumberFormatException e) {
FamLog.exception(e, 201203061213l);
reason = "invalid job step";
} catch (JSONException e) {
FamLog.exception(e, 201203061212l);
reason = "invalid inputs";
} catch (Exception e) {
FamLog.exception(e, 201203061211l);
reason = "unknown reason";
}
}
return result;
}
private boolean isRequestForBooking() {
boolean result = false;
try {
FamShoppingCart cs = user.getShoppingCart();
result = cs != null && cs.getArticles().size() > 0 && (Booking) cs.getArticle(inputs.getJSONObject("main").getString("v")) != null;
} catch (Exception e) { // not a request for booking
result = false;
}
return result;
}
private boolean setBooking() {
if (this.isRequestForBooking()) {
boolean hasBeenPurchased = false;
if (user != null && step == 0) {
FamShoppingCart sc = user.getShoppingCart();
try {
booking = (Booking) sc.getArticle(inputs.getJSONObject("main").getString("v"));
hasBeenPurchased = booking.purchase();
} catch (Exception e) { // wrong object for this id
succ = false;
reason = "someone snatched the time slot from under your nose. Please try again with different time";
FamLog.logException(this.getClass(), e, "session", 201203071231l);
}
} else if (user != null) { // step > 0
succ = false;
reason = "lost session";
FamLog.error("session", 201203301314l);
}
if (!hasBeenPurchased) {
succ = false;
reason = "someone snatched the time slot from under your nose. Please try again with different time";
}
return hasBeenPurchased;
} else {
boolean bookingIsGivenAndIsValid = false;
try {
int jobid = Integer.parseInt(inputs.getJSONObject("main").getString("jobid"));
Booking candidate = FamDaoProxy.bookingDao().getBookingWithId(jobid);
if (candidate != null && (candidate.getUsername().equals(user.getUsername()) || user.hasResponsibility4Facility(candidate.getFacility()))) {
bookingIsGivenAndIsValid = true;
booking = candidate;
}
} catch (Exception e) {
// OK!
}
return bookingIsGivenAndIsValid;
}
}
private FileOfUser fou = null;
private void setAndInsertJob() {
boolean hasAttachments = jobSurvey.has("attachments");
boolean errorOnInserAttachments = false;
Job job = new Job();
job.setStep(step);
job.setUsername(user.getUsername());
job.setIdJobDataProcessing(jdp.getId());
job.setJobSurvey(new JSONObject2Properties().process(jobSurvey));
job.setJobId(booking.getId());
// try to insert many files
if (hasAttachments) {
List<File> attachments = new ArrayList<File>();
try {
for (int i = 0; i < jobSurvey.getJSONArray("attachments").length(); i++) {
String filename = jobSurvey.getJSONArray("attachments").getString(i);
File attachment = fou.process(filename);
if (attachment != null) {
attachments.add(attachment);
} else {
errorOnInserAttachments = true;
reason = String.format("file %s does not exist anymore. please click reload, add attachment and retry.", filename);
break;
}
}
} catch (JSONException e) {
try {
// attachments is not an array - just one file!
File attachment = fou.process(jobSurvey.getString("attachments"));
attachments.add(attachment);
} catch (JSONException e2) {
// okay, something went wrong!
FamLog.exception(e2, 201204201633l);
}
}
job.addAttachments(attachments);
}
if (!hasAttachments || hasAttachments && !errorOnInserAttachments) {
succ = job.insertOrUpdate();
}
if (!succ) {
if (reason == null)
reason = "unknown error while saving the job data";
this.rollback();
}
}
private void rollback() {
if (booking != null && this.isRequestForBooking()) {
if (!booking.delete()) {
FamLog.error("could not delete booking " + booking.getId(), 201204231058l);
booking.cancel(new Cancelation(user, Cancelation.REASON_UNKNOWN_ERROR));
}
}
}
/** {@inheritDoc} */
@Override
public JSONObject getJSONObject() {
JSONObject result = new JSONObject();
try {
result.put("succ", succ);
if (succ) {
result.put("jobId", booking.getId());
} else {
result.put("reason", reason);
}
} catch (JSONException e) {
FamLog.exception(e, 201203061026l);
}
return result;
}
/** {@inheritDoc} */
@Override
public void onIOException(IOException ex) {
FamLog.exception(ex, 201203061024l);
}
}