/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2009-2011, Open Source Geospatial Foundation (OSGeo)
*
* 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;
* version 2.1 of the License.
*
* 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 org.geotools.data.complex;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A Collection of AttributeMappings that correspond to complex types that need to be created.
* It returns them in an order such that parent elements are created first, and so children
* elements can be slotted straight into them.
*
* @author Russell Petty (GeoScience Victoria)
*
* @source $URL$
*/
public class AttributeCreateOrderList {
private String rootLabel;
private Map<String, List<AttributeMapping>> childrenList = new HashMap<String, List<AttributeMapping>>();
public AttributeCreateOrderList(String rootLabel) {
this.rootLabel = rootLabel;
List<AttributeMapping> newAttMapping = new ArrayList<AttributeMapping>();
childrenList.put(rootLabel, newAttMapping);
}
/**
* Attempt to add an attribute to the list.
* @param attMapping attribute to add
* @return whether an item was added or not.
*/
public boolean put(AttributeMapping attMapping) {
String parentLabel = attMapping.getParentLabel();
if(attMapping.getLabel() == null || parentLabel == null) {
return false;
}
if(attMapping.getLabel().equals(parentLabel)) {
throw new IllegalArgumentException("Parents label same as label!");
}
List<AttributeMapping> newAttMapping;
if(childrenList.containsKey(parentLabel)) {
newAttMapping = childrenList.get(parentLabel);
} else {
newAttMapping = new ArrayList<AttributeMapping>();
childrenList.put(parentLabel, newAttMapping);
}
newAttMapping.add(attMapping);
return true;
}
public Iterator<AttributeMapping> iterator() {
return new InnerClass();
}
public void setRootLabel(String rootLabel) {
this.rootLabel = rootLabel;
}
class InnerClass implements Iterator<AttributeMapping>{
boolean isInitialised = false;
boolean isHasNextBeenCalled = false;
private Iterator<AttributeMapping> currentListIterator;
private Set<String> unprocessedTreeNodes = new HashSet<String>(childrenList.keySet());
private Set<String> returnedUnprocessedNodes = new HashSet<String>();
public boolean hasNext() {
isHasNextBeenCalled = true;
if(!isInitialised) {
initialise();
}
if(currentListIterator.hasNext()) {
return true;
}
if(unprocessedTreeNodes.isEmpty()) {
return false;
}
getNextList();
return true;
}
public AttributeMapping next() {
if(!isHasNextBeenCalled) {
throw new IllegalStateException("next method called without hasNext being called first.");
}
isHasNextBeenCalled = false;
AttributeMapping next = currentListIterator.next();
returnedUnprocessedNodes.add(next.getLabel());
return next;
}
public void remove() {
throw new UnsupportedOperationException("remove not supported");
}
private void initialise() {
isInitialised = true;
List<AttributeMapping> currentList = childrenList.get(rootLabel);
currentListIterator = currentList.iterator();
unprocessedTreeNodes.remove(rootLabel);
}
private void getNextList() {
if (returnedUnprocessedNodes.isEmpty()) {
throw new IllegalStateException(
"Please check your mapping file. No attribute found for parentLabel: '"
+ unprocessedTreeNodes.toString() + "' or root label has no matching children.");
}
Iterator<String> it = returnedUnprocessedNodes.iterator();
boolean listFound = false;
String element = null;
while (it.hasNext() && !listFound) {
element = it.next();
if (unprocessedTreeNodes.contains(element)) {
listFound = true;
unprocessedTreeNodes.remove(element);
it.remove();
} else {
// returned element has no children to process
// remove for efficiency.
it.remove();
}
}
if(!listFound) {
throw new IllegalStateException("Error in tree structure. No created elements link to unprocessed children elements");
}
List<AttributeMapping> currentList = childrenList.get(element);
currentListIterator = currentList.iterator();
}
}
}