/* * Catroid: An on-device visual programming system for Android devices * Copyright (C) 2010-2016 The Catrobat Team * (<http://developer.catrobat.org/credits>) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * An additional term exception under section 7 of the GNU Affero * General Public License, version 3, is available at * http://developer.catrobat.org/license_additional_term * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.catrobat.catroid.scratchconverter.protocol; import android.util.Log; import com.google.common.base.Preconditions; import com.koushikdutta.async.http.WebSocket; import org.catrobat.catroid.scratchconverter.Client; import org.catrobat.catroid.scratchconverter.Client.ConvertCallback; import org.catrobat.catroid.scratchconverter.protocol.JsonKeys.JsonDataKeys; import org.catrobat.catroid.scratchconverter.protocol.message.Message.CategoryType; import org.catrobat.catroid.scratchconverter.protocol.message.base.BaseMessage; import org.catrobat.catroid.scratchconverter.protocol.message.job.JobMessage; import org.json.JSONException; import org.json.JSONObject; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; public class WebSocketMessageListener implements MessageListener, WebSocket.StringCallback { private static final String TAG = WebSocketMessageListener.class.getSimpleName(); private BaseMessageHandler baseMessageHandler; private Map<Long, JobHandler> jobHandlers; public WebSocketMessageListener() { this.baseMessageHandler = null; this.jobHandlers = Collections.synchronizedMap(new LinkedHashMap<Long, JobHandler>()); } public void setBaseMessageHandler(final BaseMessageHandler baseMessageHandler) { this.baseMessageHandler = baseMessageHandler; } @Override public synchronized void onStringAvailable(String s) { try { if (s == null) { return; } Log.d(TAG, "Receiving new message: " + s); JSONObject jsonMessage = new JSONObject(s); if (jsonMessage.length() == 0) { return; } final int categoryID = jsonMessage.getInt(JsonKeys.CATEGORY.toString()); final CategoryType categoryType = CategoryType.valueOf(categoryID); switch (categoryType) { case BASE: baseMessageHandler.onBaseMessage(BaseMessage.fromJson(jsonMessage)); break; case JOB: final JSONObject jsonData = jsonMessage.getJSONObject(JsonKeys.DATA.toString()); final long jobID = jsonData.getLong(JsonDataKeys.JOB_ID.toString()); JobHandler jobHandler = jobHandlers.get(jobID); if (jobHandler != null) { jobHandler.onJobMessage(JobMessage.fromJson(jsonMessage)); } else { Log.w(TAG, "No JobHandler registered for job with ID: " + jobID); } break; default: Log.w(TAG, "Message of unsupported category-type " + categoryType + " received"); break; } } catch (JSONException ex) { Log.e(TAG, ex.getMessage()); } } @Override public boolean isJobInProgress(long jobID) { final JobHandler jobHandler = jobHandlers.get(jobID); if (jobHandler == null) { return false; } return jobHandler.isInProgress(); } @Override public void onUserCanceledConversion(long jobID) { final JobHandler jobHandler = jobHandlers.get(jobID); if (jobHandler == null) { return; } jobHandler.onUserCanceledConversion(); } @Override public int getNumberOfJobsInProgress() { int numberOfJobsInProgress = 0; for (final JobHandler jobHandler : jobHandlers.values()) { if (jobHandler.isInProgress()) { ++numberOfJobsInProgress; } } return numberOfJobsInProgress; } private JobHandler createOrUseExistingJobHandlerForJobIfPossible(final Job job, final boolean force, final Client.ConvertCallback convertCallback) { JobHandler jobHandler = jobHandlers.get(job.getJobID()); if (jobHandler != null) { Log.d(TAG, "JobHandler for jobID " + job.getJobID() + " already exists!"); if (!force && jobHandler.isInProgress()) { return null; } jobHandler.setCallback(convertCallback); } else { Log.d(TAG, "Creating new JobHandler for jobID " + job.getJobID()); jobHandler = new JobHandler(job, convertCallback); jobHandlers.put(jobHandler.getJobID(), jobHandler); } return jobHandler; } @Override public boolean scheduleJob(final Job job, final boolean force, final ConvertCallback convertCallback) { final JobHandler jobHandler = createOrUseExistingJobHandlerForJobIfPossible(job, force, convertCallback); if (jobHandler == null) { return false; } jobHandler.onJobScheduled(); return true; } @Override public Client.DownloadCallback restoreJobIfRunning(Job job, ConvertCallback convertCallback) { final JobHandler jobHandler = createOrUseExistingJobHandlerForJobIfPossible(job, true, convertCallback); Preconditions.checkState(jobHandler != null); if (job.getState() == Job.State.FINISHED && job.getDownloadURL() != null) { return jobHandler; } return null; } }