org.apache.xmlgraphics.ps.dsc.ResourceTracker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xmlgraphics-commons Show documentation
Show all versions of xmlgraphics-commons Show documentation
Apache XML Graphics Commons is a library that consists of several reusable
components used by Apache Batik and Apache FOP. Many of these components
can easily be used separately outside the domains of SVG and XSL-FO.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.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.
*/
/* $Id: ResourceTracker.java 1352945 2012-06-22 16:13:25Z vhennebert $ */
package org.apache.xmlgraphics.ps.dsc;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.xmlgraphics.ps.PSResource;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentDocumentNeededResources;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentDocumentSuppliedResources;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentPageResources;
/**
* This class is used to track resources in a DSC-compliant PostScript file. The distinction is
* made between supplied and needed resources. For the details of this distinction, please see
* the DSC specification.
*/
public class ResourceTracker {
private Set documentSuppliedResources;
private Set documentNeededResources;
private Set usedResources;
private Set pageResources;
//Map
private Map resourceUsageCounts;
/**
* Returns the set of supplied resources.
* @return the set of supplied resources
*/
public Set getDocumentSuppliedResources() {
if (documentSuppliedResources != null) {
return Collections.unmodifiableSet(documentSuppliedResources);
} else {
return Collections.EMPTY_SET;
}
}
/**
* Returns the set of needed resources.
* @return the set of needed resources
*/
public Set getDocumentNeededResources() {
if (documentNeededResources != null) {
return Collections.unmodifiableSet(documentNeededResources);
} else {
return Collections.EMPTY_SET;
}
}
/**
* Notifies the resource tracker that a new page has been started and that the page resource
* set can be cleared.
*/
public void notifyStartNewPage() {
if (pageResources != null) {
pageResources.clear();
}
}
/**
* Registers a supplied resource. If the same resources is already in the set of needed
* resources, it is removed there.
* @param res the resource
*/
public void registerSuppliedResource(PSResource res) {
if (documentSuppliedResources == null) {
documentSuppliedResources = new java.util.HashSet();
}
documentSuppliedResources.add(res);
if (documentNeededResources != null) {
documentNeededResources.remove(res);
}
}
/**
* Registers a needed resource. If the same resources is already in the set of supplied
* resources, it is ignored, i.e. it is assumed to be supplied.
* @param res the resource
*/
public void registerNeededResource(PSResource res) {
if (documentSuppliedResources == null || !documentSuppliedResources.contains(res)) {
if (documentNeededResources == null) {
documentNeededResources = new java.util.HashSet();
}
documentNeededResources.add(res);
}
}
private void preparePageResources() {
if (pageResources == null) {
pageResources = new java.util.HashSet();
}
}
private void prepareUsageCounts() {
if (resourceUsageCounts == null) {
resourceUsageCounts = new java.util.HashMap();
}
}
/**
* Notifies the resource tracker about the usage of a resource on the current page.
* @param res the resource being used
*/
public void notifyResourceUsageOnPage(PSResource res) {
preparePageResources();
pageResources.add(res);
prepareUsageCounts();
Counter counter = (Counter)resourceUsageCounts.get(res);
if (counter == null) {
resourceUsageCounts.put(res, new Counter());
} else {
counter.inc();
}
}
/**
* Notifies the resource tracker about the usage of resources on the current page.
* @param resources the resources being used
*/
public void notifyResourceUsageOnPage(Collection resources) {
preparePageResources();
Iterator iter = resources.iterator();
while (iter.hasNext()) {
PSResource res = (PSResource)iter.next();
notifyResourceUsageOnPage(res);
}
}
/**
* Indicates whether a particular resource is supplied, rather than needed.
* @param res the resource
* @return true if the resource is registered as being supplied.
*/
public boolean isResourceSupplied(PSResource res) {
return (documentSuppliedResources != null) && documentSuppliedResources.contains(res);
}
/**
* Writes a DSC comment for the accumulated used resources, either at page level or
* at document level.
* @param pageLevel true if the DSC comment for the page level should be generated,
* false for the document level (in the trailer)
* @param gen the PSGenerator to write the DSC comments with
* @exception IOException In case of an I/O problem
*/
public void writeResources(boolean pageLevel, PSGenerator gen) throws IOException {
if (pageLevel) {
writePageResources(gen);
} else {
writeDocumentResources(gen);
}
}
/**
* Writes a DSC comment for the accumulated used resources on the current page. Then it commits
* all those resources to the used resources on document level.
* @param gen the PSGenerator to write the DSC comments with
* @exception IOException In case of an I/O problem
*/
public void writePageResources(PSGenerator gen) throws IOException {
new DSCCommentPageResources(pageResources).generate(gen);
if (usedResources == null) {
usedResources = new java.util.HashSet();
}
usedResources.addAll(pageResources);
}
/**
* Writes a DSC comment for the needed and supplied resourced for the current DSC document.
* @param gen the PSGenerator to write the DSC comments with
* @exception IOException In case of an I/O problem
*/
public void writeDocumentResources(PSGenerator gen) throws IOException {
if (usedResources != null) {
Iterator iter = usedResources.iterator();
while (iter.hasNext()) {
PSResource res = (PSResource)iter.next();
if (documentSuppliedResources == null
|| !documentSuppliedResources.contains(res)) {
registerNeededResource(res);
}
}
}
new DSCCommentDocumentNeededResources(documentNeededResources).generate(gen);
new DSCCommentDocumentSuppliedResources(documentSuppliedResources).generate(gen);
}
/**
* This method declares that the given resource will be inlined and can therefore
* be removed from resource tracking. This is useful when you don't know beforehand
* if a resource will be used multiple times. If it's only used once it's better
* to inline the resource to lower the maximum memory needed inside the PostScript
* interpreter.
* @param res the resource
*/
public void declareInlined(PSResource res) {
if (this.documentNeededResources != null) {
this.documentNeededResources.remove(res);
}
if (this.documentSuppliedResources != null) {
this.documentSuppliedResources.remove(res);
}
if (this.pageResources != null) {
this.pageResources.remove(res);
}
if (this.usedResources != null) {
this.usedResources.remove(res);
}
}
/**
* Returns the number of times a resource has been used inside the current DSC document.
* @param res the resource
* @return the number of times the resource has been used
*/
public long getUsageCount(PSResource res) {
Counter counter = (Counter)resourceUsageCounts.get(res);
return (counter != null ? counter.getCount() : 0);
}
private static class Counter {
private long count = 1;
public void inc() {
this.count++;
}
public long getCount() {
return this.count;
}
public String toString() {
return Long.toString(this.count);
}
}
}