org.xmlcml.cml.map.IndexableByIdListManager Maven / Gradle / Ivy
/**
* Copyright 2011 Peter Murray-Rust et. al.
*
* Licensed 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.
*/
package org.xmlcml.cml.map;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.Elements;
import nu.xom.Node;
import nu.xom.ParsingException;
import nu.xom.ValidityException;
import org.xmlcml.cml.base.CMLBuilder;
import org.xmlcml.cml.base.CMLConstants;
import org.xmlcml.cml.base.CMLElement;
import org.xmlcml.cml.base.CMLUtil;
import org.xmlcml.euclid.Util;
/**
* A container for one or more indexables.
*
* indexableList can contain several indexables. These may be related in many
* ways and there is are controlled semantics. However it should not be used for
* a indexable consisting of descendant indexables for which indexable should be
* used. A indexableList can contain nested indexableLists.
*
*/
public class IndexableByIdListManager implements CMLConstants {
/** duplicate id exception */
public final static String DUPLICATE_ID = "duplicate id in indexableList: ";
private IndexableByIdList indexableList;
private Map map;
private Map lowerCaseMap;
private String indexableLocalName; // XML name
/**
* constructor.
*
* @param indexableList
*/
public IndexableByIdListManager(IndexableByIdList indexableList) {
this.indexableList = indexableList;
ensureMap();
// indexList();
}
private void ensureMap() {
if (map == null) {
map = new HashMap();
}
if (lowerCaseMap == null) {
lowerCaseMap = new HashMap();
}
}
/**
* index all current indexable children.
*
* @return map
*/
public Map indexList() {
ensureMap();
map.clear();
lowerCaseMap.clear();
indexableLocalName = indexableList.getIndexableLocalName();
List indexables = CMLUtil.getQueryNodes((Node) indexableList, C_E
+ indexableLocalName, CMLConstants.CML_XPATH);
for (Node node : indexables) {
indexableList.addIndexable((Indexable) node);
}
return map;
}
/**
* make indexableList from URL. either contains a directory with indexable
* in *.xml or an indexableList in a single XML file.
*
* @param url
* @param indexableListClass
* @return list of indexables
*/
public static IndexableByIdList createFrom(URL url, Class> indexableListClass) {
IndexableByIdList indexableList = null;
if ("file".equals(url.getProtocol())) {
File file;
try {
file = new File(url.toURI());
if (file.isDirectory()) {
indexableList = createFromDirectory(file,
indexableListClass);
} else if (file.toString().endsWith(XML_SUFF)) {
try {
indexableList = (IndexableByIdList) new CMLBuilder().build(
file).getRootElement();
} catch (Exception e) {
throw new RuntimeException("Cannot parse " + file, e);
}
} else {
throw new RuntimeException(
"exptected either a directory ot *.xml; found: "
+ url);
}
} catch (URISyntaxException e1) {
e1.printStackTrace();
}
} else {
if (url.toExternalForm().endsWith(XML_SUFF)) {
InputStream in = null;
try {
in = url.openStream();
indexableList = (IndexableByIdList) new CMLBuilder().build(in)
.getRootElement();
} catch (ValidityException e) {
throw new RuntimeException("Problem parsing " + url
+ " as a CML document: " + e.getMessage(), e);
} catch (ParsingException e) {
throw new RuntimeException("Problem parsing " + url
+ " as a CML document: " + e.getMessage(), e);
} catch (IOException e) {
throw new RuntimeException("Problem parsing " + url
+ " as a CML document: " + e.getMessage(), e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
;
}
}
}
} else {
throw new RuntimeException(
"Don't know how to get referenced document(s) from : "
+ url);
}
}
return indexableList;
}
private static IndexableByIdList createFromDirectory(File dir,
Class> indexableListClass) {
IndexableByIdList indexableList = null;
try {
indexableList = (IndexableByIdList) indexableListClass.newInstance();
} catch (Exception e1) {
CMLUtil.BUG("" + e1);
}
File[] files = dir.listFiles();
CMLBuilder builder = new CMLBuilder();
for (File file : files) {
if (file.toString().endsWith(XML_SUFF)) {
try {
Document document = builder.build(file);
Element element = document.getRootElement();
if (element instanceof Indexable) {
indexableList.addIndexable((Indexable) element);
}
} catch (Exception e) {
e.printStackTrace();
System.err.println("Cannot parse XML file: " + file + " /"
+ e);
}
}
}
return indexableList;
}
/**
* get map of id to indexable.
*
* @return map
*/
public Map getIndex() {
ensureMap();
return map;
}
/**
* get case-insensitive map of id to indexable.
*
* @return map
*/
Map getLowerCaseIndex() {
ensureMap();
return lowerCaseMap;
}
/**
* add indexable.
*
* @param indexable
* to add
* @throws RuntimeException
* if id already in map
*/
public void add(Indexable indexable) throws RuntimeException {
ensureMap();
String id = indexable.getId();
if (id == null) {
throw new RuntimeException("indexable has no id: "
+ indexable.getClass());
}
if (map.containsKey(id)) {
throw new RuntimeException(DUPLICATE_ID + id);
}
((Element) indexableList).appendChild((Element) indexable);
map.put(id, indexable);
}
/**
* insert indexable.
*
* @param indexable
* to add
* @param position
* @throws RuntimeException
* if id already in map
*/
public void insert(Indexable indexable, int position)
throws RuntimeException {
ensureMap();
String id = indexable.getId();
if (id == null) {
throw new RuntimeException("indexable has no id: "
+ indexable.getClass());
}
if (map.containsKey(id)) {
throw new RuntimeException(DUPLICATE_ID + id);
}
((Element) indexableList).insertChild((Element) indexable, position);
map.put(indexable.getId(), indexable);
}
/**
* insert indexable.
*
* @param indexable
* to add
* @throws RuntimeException
* if id already in map
*/
public void insertInOrderOfId(Indexable indexable) throws RuntimeException {
String id = indexable.getId();
if (id == null) {
throw new RuntimeException("indexable has no id: "
+ indexable.getClass());
}
if (map.containsKey(id)) {
throw new RuntimeException(DUPLICATE_ID + id);
}
boolean added = false;
Elements elements = ((Element) indexableList).getChildElements();
for (int i = 0; i < elements.size(); i++) {
if (elements.get(i) instanceof Indexable) {
Indexable indexable0 = (Indexable) elements.get(i);
String id0 = indexable0.getId();
if (id.compareTo(id0) < 0) {
((Element) indexableList).insertChild((Element) indexable,
i);
added = true;
break;
}
}
}
if (!added) {
((Element) indexableList).appendChild((Element) indexable);
}
map.put(indexable.getId(), indexable);
}
/**
* get indexable children.
*
* @return indexables
*/
public List getIndexables() {
List list = new ArrayList();
Elements elements = ((Element) indexableList).getChildElements();
for (int i = 0; i < elements.size(); i++) {
Node element = elements.get(i);
if (element instanceof Indexable) {
list.add((Indexable) element);
}
}
return list;
}
/**
* remove indexable. removes BOTH from map and from parent indexableList
*
* @param indexable
* to remove
*/
public void remove(Indexable indexable) {
ensureMap();
String id = indexable.getId();
if (map.containsKey(id)) {
((Element) indexableList).removeChild((Element) indexable);
map.remove(id);
}
}
/**
* get indexable by id.
*
* @param id
* @return indexable or null
*/
public Indexable getById(String id) {
ensureMap();
return map.get(id);
}
/**
*/
public void debug() {
Util.println("IndexableByIdListManager DEBUG");
for (Indexable indexable : indexableList.getIndexables()) {
((CMLElement) indexable).debug("INDEXABLE");
}
Util.println("MAP "+map.size());
for (String key : map.keySet()) {
Util.println(key);
((CMLElement)map.get(key)).debug("MAP");
}
Util.println("LOWERCASE MAP "+map.size());
for (String key : lowerCaseMap.keySet()) {
Util.println(key);
((CMLElement)map.get(key)).debug("KEY");
}
Util.println("indexableLocalName: "+indexableLocalName);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy