/*
* ImageI/O-Ext - OpenSource Java Image translation Library
* http://www.geo-solutions.it/
* http://java.net/projects/imageio-ext/
* (C) 2008, GeoSolutions
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* either version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*/
package it.geosolutions.imageio.plugins.jp2k;
import it.geosolutions.imageio.plugins.jp2k.box.ASOCBox;
import it.geosolutions.imageio.plugins.jp2k.box.ASOCBoxMetadataNode;
import it.geosolutions.imageio.plugins.jp2k.box.BoxUtilities;
import it.geosolutions.imageio.plugins.jp2k.box.ContiguousCodestreamBox;
import it.geosolutions.imageio.plugins.jp2k.box.JP2KFileBox;
import it.geosolutions.imageio.plugins.jp2k.box.UUIDBox;
import it.geosolutions.imageio.plugins.jp2k.box.UUIDBoxMetadataNode;
import it.geosolutions.imageio.plugins.jp2k.box.XMLBox;
import it.geosolutions.imageio.plugins.jp2k.box.XMLBoxMetadataNode;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import org.w3c.dom.Node;
public class JP2KStreamMetadata extends IIOMetadata {
public final static String NUM_CODESTREAMS = "NumberOfCodestreams";
public static final String nativeMetadataFormatName = "it_geosolutions_imageio_plugins_jp2k_StreamMetadata_1.0";
private DefaultTreeModel treeModel;
private int numCodestreams;
private SoftReference<Node> nativeTreeNodeRef;
public JP2KStreamMetadata(final TreeModel treeModel,
final int numCodestreams) {
final JP2KFileBox box = (JP2KFileBox) treeModel.getRoot();
if (box == null)
throw new IllegalArgumentException("Originating tree is empty");
this.numCodestreams = numCodestreams;
final JP2KFileBox root = (JP2KFileBox) box.clone();
this.treeModel = new DefaultTreeModel(root);
final int childCount = box.getChildCount();
int i = 0;
while (i < childCount) {
JP2KBox child = (JP2KBox) box.getChildAt(i);
cloneTree(child, root, i++);
}
}
private void cloneTree(final JP2KBox toBeCloned, final JP2KBox parent,
int index) {
final JP2KBox currentBox = (JP2KBox) ((JP2KBox) toBeCloned).clone();
parent.insert(currentBox, index++);
final int childCount = toBeCloned.getChildCount();
int i = 0;
while (i < childCount) {
final JP2KBox child = (JP2KBox) toBeCloned.getChildAt(i);
cloneTree(child, currentBox, i++);
}
}
@Override
public Node getAsTree(String formatName) {
if (formatName.equalsIgnoreCase(nativeMetadataFormatName))
return getNativeTree();
else
throw new IllegalArgumentException(formatName
+ " is not a supported format name");
}
private Node getNativeTree() {
Node nativeTree = this.nativeTreeNodeRef == null ? null
: this.nativeTreeNodeRef.get();
if (nativeTree == null) {
IIOMetadataNode node = new IIOMetadataNode(nativeMetadataFormatName);
JP2KBoxMetadata root = (JP2KBoxMetadata) treeModel.getRoot();
nativeTree = buildTree(root);
node.appendChild(nativeTree);
this.nativeTreeNodeRef = new SoftReference<Node>(nativeTree);
}
return nativeTree;
}
private Node buildTree(final JP2KBoxMetadata node) {
if (node == null)
throw new IllegalArgumentException("Null node provided ");
IIOMetadataNode mdNode;
switch (node.getType()) {
// Using LazyBox in the following 3 cases.
case XMLBox.BOX_TYPE:
mdNode = new XMLBoxMetadataNode(node);
break;
case UUIDBox.BOX_TYPE:
mdNode = new UUIDBoxMetadataNode(node);
break;
case ASOCBox.BOX_TYPE:
mdNode = new ASOCBoxMetadataNode(node);
break;
case JP2KFileBox.BOX_TYPE:
mdNode = node.getNativeNode();
mdNode.setAttribute(NUM_CODESTREAMS, Integer.toString(0));
break;
case ContiguousCodestreamBox.BOX_TYPE:
return null;
default:
mdNode = node.getNativeNode();
}
final int childCount = node.getChildCount();
int i = 0;
while (i < childCount) {
final Node appendMe = buildTree((JP2KBoxMetadata) node
.getChildAt(i++));
if (appendMe != null)
mdNode.appendChild(appendMe);
}
return mdNode;
}
@Override
public boolean isReadOnly() {
return true;
}
// private ASOCBoxMetadataNode findParentASOCBoxMetadataNode(){
// final Node rootNode = createNativeTree();
// final IIOMetadataNode returnedNode[] = new IIOMetadataNode[1];
// searchFirstOccurrenceNode (rootNode,
// BoxUtilities.getName(ASOCBox.BOX_TYPE), returnedNode);
// if (returnedNode[0]!=null)
// return (ASOCBoxMetadataNode)returnedNode[0];
// return null;
// }
//
/**
* Search the first occurrence of a node related to the specified box type
* and return it as a {@link IIOMetadataNode} or null in case of not found.
* Search is performed visiting the children of a node before the brothers.
*/
public IIOMetadataNode searchFirstOccurrenceNode(final int requestedBoxType) {
final Node rootNode = getAsTree(nativeMetadataFormatName);
final List<IIOMetadataNode> returnedNodes = new ArrayList<IIOMetadataNode>(1);
searchOccurrencesNode(rootNode, BoxUtilities
.getName(requestedBoxType), returnedNodes, true);
if (!returnedNodes.isEmpty())
return returnedNodes.get(0);
return null;
}
/**
* Search any JP2 Box metadata node occurrence of the specified type.
* @param requestedBoxType
* the box type to be searched.
* @return
* a List containing any occurrence found.
*/
public List<IIOMetadataNode> searchOccurrencesNode(final int requestedBoxType) {
final Node rootNode = getAsTree(nativeMetadataFormatName);
final List<IIOMetadataNode> returnedNodes = new ArrayList<IIOMetadataNode>(1);
searchOccurrencesNode(rootNode, BoxUtilities
.getName(requestedBoxType), returnedNodes, false);
return returnedNodes;
}
private void searchOccurrencesNode(final Node node, final String requestedBoxType,
final List<IIOMetadataNode> returnedNodes, final boolean exitFirstFound) {
if (node != null) {
if (node.getNodeName().equalsIgnoreCase(requestedBoxType)) {
boolean sameNode = false;
for (IIOMetadataNode foundNode : returnedNodes){
if (foundNode == node){
sameNode = true;
break;
}
}
if (!sameNode){
returnedNodes.add((IIOMetadataNode) node);
if (exitFirstFound)
return;
}
}
if (node.hasChildNodes()) {
searchOccurrencesNode(node.getFirstChild(),
requestedBoxType, returnedNodes, exitFirstFound);
if (returnedNodes != null && !returnedNodes.isEmpty() && exitFirstFound)
return;
Node sibling = node.getNextSibling();
while (sibling != null) {
searchOccurrencesNode(sibling, requestedBoxType,
returnedNodes, exitFirstFound);
if (returnedNodes != null && !returnedNodes.isEmpty() && exitFirstFound)
return;
sibling = sibling.getNextSibling();
}
}
}
return;
}
//
//
// public void parseGML(){
// final ASOCBoxMetadataNode mainAsocBoxNode =
// findParentASOCBoxMetadataNode();
// if (mainAsocBoxNode!=null){
// Node firstLabel = mainAsocBoxNode.getFirstChild();
// if (firstLabel!=null &&
// ((BaseJP2KBoxMetadataNode)firstLabel).getBoxType().equalsIgnoreCase(BoxUtilities.getBoxName(LabelBox.BOX_TYPE))){
// String content = ((LabelBoxMetadataNode)firstLabel).getText();
// if (content.equalsIgnoreCase(LabelBoxMetadataNode.GML_DATA)){
// Node asocSubNode = firstLabel.getNextSibling();
// while (asocSubNode!=null){
// Node labelNode = asocSubNode.getFirstChild();
// Node xmlNode = labelNode.getNextSibling();
// if (xmlNode!=null && xmlNode instanceof XMLBoxMetadataNode){
// XMLBoxMetadataNode xmlBoxNode = (XMLBoxMetadataNode) xmlNode;
//
// }
// }
// }
// else{
// if (LOGGER.isLoggable(Level.FINE)){
// LOGGER.fine("Unable to find " + LabelBoxMetadataNode.GML_DATA + " Label
// in this ASOC box");
// }
// }
// }
// }
// }
@Override
public void mergeTree(String formatName, Node root)
throws IIOInvalidTreeException {
throw new UnsupportedOperationException("MergeTree is unsupported");
}
@Override
public void reset() {
}
}