001 /* 002 * Copyright 2005 John G. Wilson 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 */ 017 018 package groovy.util.slurpersupport; 019 020 import groovy.lang.Buildable; 021 import groovy.lang.Closure; 022 import groovy.lang.DelegatingMetaClass; 023 import groovy.lang.GroovyObjectSupport; 024 import groovy.lang.MetaClass; 025 import groovy.lang.Writable; 026 027 import java.util.HashMap; 028 import java.util.Iterator; 029 import java.util.LinkedList; 030 import java.util.List; 031 import java.util.Map; 032 033 034 /** 035 * @author John Wilson 036 * 037 */ 038 039 public abstract class GPathResult extends GroovyObjectSupport implements Writable, Buildable { 040 protected final GPathResult parent; 041 protected final String name; 042 protected final String namespacePrefix; 043 protected final Map namespaceMap = new HashMap(); 044 protected final Map namespaceTagHints; 045 046 /** 047 * @param parent 048 * @param name 049 */ 050 public GPathResult(final GPathResult parent, final String name, final String namespacePrefix, final Map namespaceTagHints) { 051 if (parent == null) { 052 // we are the top of the tree 053 this.parent = this; 054 this.namespaceMap.put("xml", "http://www.w3.org/XML/1998/namespace"); // The XML namespace is always defined 055 } else { 056 this.parent = parent; 057 this.namespaceMap.putAll(parent.namespaceMap); 058 } 059 this.name = name; 060 this.namespacePrefix = namespacePrefix; 061 this.namespaceTagHints = namespaceTagHints; 062 063 setMetaClass(getMetaClass()); // wrap the standard MetaClass with the delegate 064 } 065 066 /* (non-Javadoc) 067 * @see groovy.lang.GroovyObjectSupport#setMetaClass(groovy.lang.MetaClass) 068 */ 069 public void setMetaClass(final MetaClass metaClass) { 070 final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) { 071 /* (non-Javadoc) 072 * @see groovy.lang.DelegatingMetaClass#getAttribute(java.lang.Object, java.lang.String) 073 */ 074 public Object getAttribute(Object object, String attribute) { 075 return GPathResult.this.getProperty("@" + attribute); 076 } 077 }; 078 079 super.setMetaClass(newMetaClass); 080 } 081 082 public Object getProperty(final String property) { 083 if ("..".equals(property)) { 084 return parent(); 085 } else if ("*".equals(property)){ 086 return children(); 087 } else if (property.startsWith("@")) { 088 if (property.indexOf(":") != -1) { 089 final int i = property.indexOf(":"); 090 091 return new Attributes(this, "@" + property.substring(i + 1), property.substring(1, i), this.namespaceTagHints); 092 } else { 093 return new Attributes(this, property, this.namespaceTagHints); 094 } 095 } else { 096 if (property.indexOf(":") != -1) { 097 final int i = property.indexOf(":"); 098 099 return new NodeChildren(this, property.substring(i + 1), property.substring(0, i), this.namespaceTagHints); 100 } else { 101 return new NodeChildren(this, property, this.namespaceTagHints); 102 } 103 } 104 } 105 106 public String name() { 107 return this.name; 108 } 109 110 public GPathResult parent() { 111 return this.parent; 112 } 113 114 public GPathResult children() { 115 return new NodeChildren(this, this.namespaceTagHints); 116 } 117 118 public String toString() { 119 return text(); 120 } 121 122 public GPathResult declareNamespace(final Map newNamespaceMapping) { 123 this.namespaceMap.putAll(newNamespaceMapping); 124 125 return this; 126 } 127 128 /* (non-Javadoc) 129 * @see java.lang.Object#equals(java.lang.Object) 130 */ 131 public boolean equals(Object obj) { 132 return text().equals(obj.toString()); 133 } 134 135 public Object getAt(final int index) { 136 final Iterator iter = iterator(); 137 int count = 0; 138 139 140 while (iter.hasNext()) { 141 if (count++ == index) { 142 return iter.next(); 143 } else { 144 iter.next(); 145 } 146 } 147 148 throw new ArrayIndexOutOfBoundsException(index); 149 } 150 151 public List list() { 152 final Iterator iter = nodeIterator(); 153 final List result = new LinkedList(); 154 155 while (iter.hasNext()) { 156 result.add(iter.next()); 157 } 158 159 return result; 160 } 161 162 public abstract int size(); 163 164 public abstract String text(); 165 166 public abstract GPathResult parents(); 167 168 public abstract Iterator childNodes(); 169 170 public abstract Iterator iterator(); 171 172 public abstract GPathResult find(Closure closure); 173 174 public abstract GPathResult findAll(Closure closure); 175 176 public abstract Iterator nodeIterator(); 177 }