• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15import CheckEmptyUtils, { Constants, convertToSpoolerPrintJob, isValidPrintJob, Log, PrintJob, PrintJobChangeListener, queryAllPrintJobs, SingletonHelper } from '@ohos/common';
16import print from '@ohos.print';
17import FileUtil from '../Common/Utils/FileUtil';
18
19const TAG: string = 'PrintJobManager';
20class PrintJobManager {
21  private localJobMap: Map<string, PrintJob> = new Map();
22  private isStarted: boolean = false;
23  private isRegister: boolean = false;
24  private printJobChangeListeners: Map<string, PrintJobChangeListener> = new Map();
25
26  private onJobStateChanged = (jobState: print.PrintJobState, job: print.PrintJob): void => {
27    Log.info(TAG, `onJobStateChanged jobId:${job?.jobId}, jobState:${jobState}, jobSubstate:${job?.jobSubstate}`);
28    if (!isValidPrintJob(job)) {
29      Log.warn(TAG, 'onJobStateChanged invalid job.');
30      return;
31    }
32    let printJob: PrintJob = convertToSpoolerPrintJob(job);
33    this.deleteLocalSource(printJob);
34    this.updatePrintJob(printJob);
35  };
36
37  onStart(printerId?: string): void {
38    if (this.isStarted) {
39      return;
40    }
41    this.isStarted = true;
42    this.registerCallback();
43  }
44
45  onStop(): void {
46    this.unregisterCallback();
47    this.printJobChangeListeners?.clear();
48  }
49
50  registerCallback(): void {
51    Log.info(TAG, `registerCallback isRegister:${this.isRegister}`);
52    if (!this.isRegister) {
53      print.on(`jobStateChange`, this.onJobStateChanged);
54      this.isRegister = true;
55    }
56  }
57  unregisterCallback(): void {
58    Log.info(TAG, `unregisterCallback isRegister:${this.isRegister}`);
59    if (this.isRegister) {
60      print.off('jobStateChange', (data: boolean) => {
61        Log.info(TAG, `off jobStateChange data:` + JSON.stringify(data));
62      });
63      this.isRegister = false;
64    }
65  }
66
67  registerJobChangeListener(key: string, listener: PrintJobChangeListener): void {
68    Log.info(TAG, `registerJobChangeListener key:${key}`);
69    if (key === null || listener === null) {
70      return;
71    }
72    this.printJobChangeListeners?.set(key, listener);
73  }
74
75  unregisterJobChangeListener(key: string): void {
76    if (key === null) {
77      return;
78    }
79    this.printJobChangeListeners?.delete(key);
80  }
81
82  async getPrintJobQueue(printerId?: string): Promise<void> {
83    let remoteJobQueue: Array<PrintJob> = await Promise.resolve(queryAllPrintJobs(printerId));
84    let sortedJobQueue: Array<PrintJob> = await Promise.resolve(this.sortPrintJobs(remoteJobQueue));
85    await Promise.resolve(this.updateLocalPrintJobQueue(sortedJobQueue));
86  }
87
88  private updateLocalPrintJobQueue(remoteJobQueue?: Array<PrintJob>): void {
89    Log.info(TAG, `updateLocalPrintJobQueue remoteJobQueue.length:${remoteJobQueue.length},localJobMap.length: ${this.localJobMap.size}`)
90    if (remoteJobQueue.length === 0) {
91      this.localJobMap.clear();
92      this.notifyAllPrintJobsFinished();
93      Log.debug(TAG, 'updateLocalPrintJobQueue notifyAllPrintJobsFinished');
94    } else {
95      for (let item of remoteJobQueue) {
96        this.localJobMap.set(item.jobId, item);
97        this.printJobChangeListeners?.forEach((listener, key) => {
98          Log.info(TAG, `updateLocalPrintJobQueue listener.onAddPrintJob:Key:${key}, jobId:${item.jobId}`);
99          listener?.onAddPrintJob(item, this.checkBlockInQueue());
100        });
101      }
102    }
103  }
104
105  cancelPrintJob(jobId: string): void {
106    Log.info(TAG, 'cancelPrintJob enter.');
107    let job = this.localJobMap.get(jobId);
108    if (job) {
109      Log.info(TAG, `cancelPrintJob jobId:${jobId}`);
110      print.cancelPrintJob(jobId).then((data)=> {
111        Log.info(TAG, 'cancelPrintJob success, data:' + JSON.stringify(data));
112      }).catch((err) =>{
113        Log.info(TAG, 'cancelPrintJob failed, err:' + JSON.stringify(err));
114      });
115    }
116    Log.info(TAG, 'cancelPrintJob end.');
117  }
118
119  updatePrintJob(job: PrintJob): void {
120    Log.info(TAG, 'updatePrintJob enter.');
121    if (this.localJobMap.has(job.jobId)) {
122      Log.info(TAG, `updatePrintJob jobId: ${job.jobId}`);
123      this.localJobMap.set(job.jobId, job);
124      this.printJobChangeListeners?.forEach((listener, key) => {
125        Log.info(TAG, `updatePrintJob listener.onUpdatePrintJob: Key:${key}, jobState:${job.jobState}`);
126        listener?.onUpdatePrintJob(job, this.checkBlockInQueue());
127      });
128      this.handleCompleteJob(job);
129    }
130    Log.info(TAG, 'updatePrintJob end.');
131  }
132
133  handleCompleteJob(job: PrintJob): void {
134    Log.info(TAG, 'handleCompleteJob enter.');
135    if (job.jobState == print.PrintJobState.PRINT_JOB_COMPLETED) {
136      setTimeout(() => {
137        Log.info(TAG, 'handleCompleteJob show completed job time out, jobId=' + job.jobId);
138        this.removePrintJob(job.jobId);
139      }, Constants.SHOW_JOB_COMPLETED_TIMEOUT);
140    }
141    Log.info(TAG, `handleCompleteJob end, jobId:${job.jobId}`);
142  }
143
144  private removePrintJob(jobId: string): void {
145    Log.info(TAG, `removePrintJob enter, jobId:${jobId}`);
146    if (this.localJobMap.delete(jobId)) {
147      Log.info(TAG, `removePrintJob jobId:${jobId} success.`);
148      this.printJobChangeListeners?.forEach((listener, key) => {
149        Log.info(TAG, `removePrintJob listener.onRemovePrintJob: Key:${key}, jobId:${jobId}`);
150        listener?.onRemovePrintJob(jobId, this.checkBlockInQueue());
151      });
152    }
153
154    if (this.localJobMap.size === 0) {
155      Log.debug(TAG, 'removePrintJob notifyAllPrintJobsFinished.');
156      this.notifyAllPrintJobsFinished();
157    }
158    Log.info(TAG, `removePrintJob end.`);
159  }
160
161  private deleteLocalSource(job: PrintJob): Promise<void> {
162    if (CheckEmptyUtils.isEmpty(job)) {
163      Log.warn(TAG, 'deleteLocalSource invalid job.');
164      return;
165    }
166    if (job.jobState === print.PrintJobState.PRINT_JOB_BLOCKED || job.jobState === print.PrintJobState.PRINT_JOB_COMPLETED) {
167      Log.info(TAG, `deleteLocalSource jobId:${job.jobId}`);
168      FileUtil.deleteSource(job.jobFiles);
169    }
170    Log.info(TAG, 'deleteLocalSource end.');
171  }
172
173  checkBlockInQueue(): number {
174    for(let value of this.localJobMap.values()) {
175      if (value.jobState === print.PrintJobState.PRINT_JOB_BLOCKED) {
176        return value.jobSubstate;
177      }
178    }
179    return Constants.NEGATIVE_1;
180  }
181
182  private sortPrintJobs(jobArray: Array<PrintJob>): Promise<Array<PrintJob>> {
183    return new Promise((resolve) => {
184      jobArray.sort((job1, job2): number => {
185        return Number(job1.jobId) - Number(job2.jobId);
186      });
187      resolve(jobArray);
188    });
189  }
190
191  private notifyAllPrintJobsFinished(): void {
192    Log.info(TAG, 'notifyAllPrintJobsFinished enter.');
193    this.printJobChangeListeners?.forEach((listener, key) => {
194      Log.info(TAG, 'notifyAllPrintJobsFinished listener.onAllPrintJobsFinished.');
195      listener?.onAllPrintJobsFinished();
196    });
197    Log.info(TAG, 'notifyAllPrintJobsFinished end.');
198  }
199}
200export let printJobMgr = SingletonHelper.getInstance(PrintJobManager, TAG);