📄 nestedattribute.java
字号:
package dli2fe.helpers;
/**
* Title: Digial Library Interoperable Interface Fudan Edition
* Description: This project contains all the classes required for DLI2FE interface. Developers use these classes to implement the wrapper and client side codes. The basic functions of DLI2FE is as follows:
* Search: Search a digital library source site.
* Metadata: Fetch metadata for a site.
* ResultAccess: Get results for a given query.
* DLI2FE uses Dublin Core as the basic attribute model, DAV/DASL as the general XML-based query language and CORBA as distributed object transportation mechanism.
* Copyright: Copyright (c) 2001
* Company: Fudan University
* @author Carl Tao
* @version 1.0
*/
import java.util.*;
import dli2fe.DLI2FEException;
/* holder for integer values */
import org.omg.CORBA.IntHolder;
/* transport module libraries */
import dli2fe.helpers.*;
/* following packages are imported only if DOM-aware XMLObjects are used */
import dli2fe.xml.*;
import org.w3c.dom.*;
/* DLI2FE XML element names */
import dli2fe.DLI2FE;
/**
* NestedAttribute represents a flat list of XML elements.
* For example, nested attribute
* <pre>
* <coordinate>
* <x/>
* </coordinate>
* </pre>
* is represented by an element vector
* <pre>
* coordinate, x
* </pre>
* NestedAttributes can be collected from the list of document properties requested by the client, or from the metadata returned by the client using the method <tt>collectAttributes</tt>. This class can also be used to filter out the attributes requested by the client from a complete document/resource description using <tt>matchDoc</tt>.
*/
public class NestedAttribute {
Vector list;
String propName;
String propDesc;
public NestedAttribute(Vector v) {
list = (Vector)v.clone();
init();
}
public NestedAttribute(Enumeration en) {
list = new Vector();
while(en.hasMoreElements()) {
list.addElement(en.nextElement());
}
init();
}
/**
* returns the last element in the list
*/
public Element getLast() {
return (Element)list.elementAt(list.size()-1);
}
public Element elementAt(int i) {
return (Element)list.elementAt(i);
}
public int size() {
return list.size();
}
/**
* returns a nested representation of the element list
*/
public Element getNestedElements() {
Element top = null, current = null;
for(Enumeration en = list.elements(); en.hasMoreElements();) {
Element e = (Element)en.nextElement();
Element tmp = (Element)e.cloneNode(false);
if(current == null)
current = tmp;
else {
current.appendChild(tmp);
current = tmp;
}
if(top == null)
top = tmp;
}
return top;
}
void init() {
if(list.size() == 0)
throw new IllegalArgumentException("[NestedAttribute] cannot be empty");
propName = DOMUtil.getChildText(getLast(), DLI2FE.propName);
propDesc = DOMUtil.getChildText(getLast(), DLI2FE.propDesc);
if(propName == null) {
// compute a canonical name
propName = "";
for(Enumeration en = list.elements(); en.hasMoreElements();) {
Element e = (Element)en.nextElement();
if(!"".equals(propName))
propName += ".";
propName += getName(e.getTagName());
}
}
}
static int getNSEnd(String name) {
// first try to detemine namespace directly
int l = name.length()-1;
do {
char c = name.charAt(l);
if(c == '#' || c == ':' || c == '/')
break;
l--;
} while (l >= 0);
l++;
return l;
}
public static String getNS(String name) {
int l = getNSEnd(name);
if(l > 0) {
return name.substring(0, l);
} else
return "";
}
public static String getName(String name) {
int l = getNSEnd(name);
if(l > 0) {
return name.substring(l);
} else
return name;
}
public String getPropName() {
return propName;
}
public String getPropDesc() {
return propDesc == null ? "" : propDesc;
}
/**
* Collects a vector of NestedAttributes from metadata inside <tt>DLI2FE:propList</tt> tag.
*/
public static Vector collectAttributes(Element e) {
if(e == null)
return null;
Stack stack = new Stack();
Vector attrs = new Vector();
collectAttributes(attrs, stack, e);
return attrs;
}
/**
* Whether attribute is searchable
*/
public boolean isSearchable() {
return DOMUtil.getChild(getLast(), DLI2FE.searchable) != null;
}
/**
* Whether attribute is retrievable
*/
public boolean isRetrievable() {
return DOMUtil.getChild(getLast(), DLI2FE.retrievable) != null;
}
private static void collectAttributes(Vector attrs, Stack stack, Element e) {
Element eRetrievable = DOMUtil.getChild(e, DLI2FE.retrievable);
Element eSearchable = DOMUtil.getChild(e, DLI2FE.searchable);
NodeList propList = DOMUtil.getChildElements(e, "*");
if(eRetrievable != null || eSearchable != null || propList.getLength() == 0) {
attrs.addElement(new NestedAttribute(stack));
} else {
for(int j=0; j < propList.getLength(); j++) {
Element eProp = (Element)propList.item(j);
stack.push(eProp);
collectAttributes(attrs, stack, eProp);
stack.pop();
}
}
}
/**
* Returns a subset of attributes from <tt>eDoc</tt> that match NestedAttributes in <tt>attrs</tt>
*/
public static Element matchDoc(Vector attrs, Element eDoc) {
if(attrs == null) // no filter
return (Element)eDoc.cloneNode(true);
Element eDoc2 = (Element)eDoc.cloneNode(false);
eDoc2.appendChild( DOMUtil.getChild(eDoc, DLI2FE.DID).cloneNode(true) );
Element ePropList = DOMUtil.getChild(eDoc, DLI2FE.propList);
Element ePropList2 = NestedAttribute.match(attrs, ePropList);
if(ePropList2 == null) // nothing found
ePropList2 = (Element)ePropList.cloneNode(false);
eDoc2.appendChild(ePropList2);
return eDoc2;
}
/**
* Copies from ePropList a subset of values that match attributes listed in <tt>attrs</tt>.
* Use this function for selective delivery of results to the client.
* Pass <tt>propList</tt> element as parameter.
*/
public static Element match(Vector attrs, Element e) {
NodeList clist = DOMUtil.getChildElements(e, "*");
if(clist.getLength() == 0) { // terminal
// check whether this attribute value is requested
for(int j = 0; j < attrs.size(); j++) {
NestedAttribute a = (NestedAttribute)attrs.elementAt(j);
// check whether the attribute matches the path that leads to e
Element p = e;
boolean matched = true;
for(int h = a.size() - 1; h >=0; h--, p = (Element)e.getParentNode() ) {
if(!p.getTagName().equals(a.elementAt(h).getTagName())) {
matched = false;
break;
}
}
if(matched) { // clone the content including text and return it
return (Element)e.cloneNode(true);
}
}
return null; // terminal not matched anything
}
// match children
Element ePropagator = null;
for(int i = 0; i < clist.getLength(); i++) {
Element c = (Element)clist.item(i);
Element eMatched = match(attrs, c);
if(eMatched != null) { // make sure to propagate this match
if(ePropagator == null)
ePropagator = (Element)e.cloneNode(false);
ePropagator.appendChild(eMatched);
}
}
return ePropagator;
}
/**
* Returns an enumeration of values for the NestedAttribute found inside the given XML element
*/
public Enumeration matchValues(Element e) {
Vector v = new Vector();
matchValues(v, e, -1); // propList => -1
return v.elements();
}
private void matchValues(Vector v, Element e, int i) {
if(i == list.size() - 1) { // found match
v.addElement(DOMUtil.getText(e));
} else {
i++;
NodeList propList = DOMUtil.getChildElements(e, ((Element)list.elementAt(i)).getTagName());
for(int j=0; j < propList.getLength(); j++) {
Element eProp = (Element)propList.item(j);
matchValues(v, eProp, i);
}
}
}
public String toString() {
dli2fe.xml.XMLObject obj = new XMLObject(getNestedElements());
return obj.getString();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -