001: //==============================================================================
002: //===
003: //=== MetadataSchema
004: //===
005: //==============================================================================
006: //=== Copyright (C) 2001-2007 Food and Agriculture Organization of the
007: //=== United Nations (FAO-UN), United Nations World Food Programme (WFP)
008: //=== and United Nations Environment Programme (UNEP)
009: //===
010: //=== This program is free software; you can redistribute it and/or modify
011: //=== it under the terms of the GNU General Public License as published by
012: //=== the Free Software Foundation; either version 2 of the License, or (at
013: //=== your option) any later version.
014: //===
015: //=== This program is distributed in the hope that it will be useful, but
016: //=== WITHOUT ANY WARRANTY; without even the implied warranty of
017: //=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
018: //=== General Public License for more details.
019: //===
020: //=== You should have received a copy of the GNU General Public License
021: //=== along with this program; if not, write to the Free Software
022: //=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
023: //===
024: //=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
025: //=== Rome - Italy. email: geonetwork@osgeo.org
026: //==============================================================================
027:
028: package org.fao.geonet.kernel.schema;
029:
030: import java.util.*;
031:
032: import org.jdom.Element;
033:
034: //==============================================================================
035:
036: public class MetadataSchema {
037: private Map<String, List<String>> hmElements = new HashMap<String, List<String>>();
038: private Map<String, List<List>> hmRestric = new HashMap<String, List<List>>();
039: private HashMap hmTypes = new HashMap();
040: private HashMap hmSubs = new HashMap();
041: private HashMap hmSubsLink = new HashMap();
042: private HashMap hmNameSpaces = new HashMap();
043: private String schemaName;
044:
045: //---------------------------------------------------------------------------
046: //---
047: //--- Constructor
048: //---
049: //---------------------------------------------------------------------------
050:
051: MetadataSchema(Element root) {
052: schemaName = "UNKNOWN";
053: }
054:
055: //---------------------------------------------------------------------------
056: //---
057: //--- API methods
058: //---
059: //---------------------------------------------------------------------------
060:
061: public void setName(String inName) {
062: schemaName = inName;
063: return;
064: }
065:
066: public String getName() {
067: return schemaName;
068: }
069:
070: //---------------------------------------------------------------------------
071:
072: public MetadataType getTypeInfo(String type) {
073: Logger.log("metadataSchema: Asking for type " + type);
074: if (hmTypes.get(type) == null)
075: return new MetadataType();
076: else
077: return (MetadataType) hmTypes.get(type);
078: }
079:
080: //---------------------------------------------------------------------------
081:
082: public String getElementType(String elem, String parent)
083: throws Exception {
084: // two cases here - if we have just one element (or a substitute) with
085: // this name then return its type
086:
087: Logger.log("metadataSchema: Asking for element " + elem
088: + " parent " + parent);
089: List<String> childType = hmElements.get(elem);
090: if (childType == null) {
091: // Check and see whether we can substitute another element from the
092: // substitution link
093: String oldelem = elem;
094: elem = (String) hmSubsLink.get(elem);
095: Logger.log(" -- substitute " + elem);
096: childType = hmElements.get(elem);
097: if (childType == null) {
098: System.out
099: .println("ERROR: Mismatch between schema and xml: No type for 'element' : "
100: + oldelem + " with parent " + parent);
101: System.out.println("Returning xs:string");
102: return "xs:string";
103: }
104: }
105: if (childType.size() == 1)
106: return childType.get(0);
107:
108: Logger.log("-- Multiple elements so moving to parent");
109: // OTHERWISE get the type by examining the parent:
110: // for each parent with that name parent
111: // 1. retrieve its mdt
112: List<String> exType = hmElements.get(parent);
113: if (exType == null)
114: return "xs:string";
115: Iterator i = exType.iterator();
116: while (i.hasNext()) {
117: // 2. search that mdt for the element names elem
118: String type = (String) i.next();
119: MetadataType mdt = getTypeInfo(type);
120: for (int k = 0; k < mdt.getElementCount(); k++) {
121: String elemTest = mdt.getElementAt(k);
122: // 3. return the type name of that element
123: if (elem.equals(elemTest))
124: return mdt.getElementTypeAt(k);
125: }
126: }
127:
128: Logger.log("ERROR: could not find type for element " + elem
129: + " with parent " + parent);
130: return null;
131: }
132:
133: //---------------------------------------------------------------------------
134: /** A simple type is a type that has no children and no attributes (but can
135: * have restrictions on its value)
136: */
137:
138: public boolean isSimpleElement(String elem, String parent)
139: throws Exception {
140: String type = getElementType(elem, parent);
141: if (type == null)
142: return false;
143: else
144: return !hmTypes.containsKey(type);
145: }
146:
147: //---------------------------------------------------------------------------
148:
149: public ArrayList getElementSubs(String elem) {
150: return ((ArrayList) hmSubs.get(elem));
151: }
152:
153: //---------------------------------------------------------------------------
154:
155: public ArrayList getElementValues(String elem, String parent)
156: throws Exception {
157:
158: String type = getElementType(elem, parent);
159: String restricName = elem;
160: if (type != null)
161: restricName = restricName + "+" + type;
162:
163: // two cases here - if we have just one element with this name
164: // then return its values
165: List<List> childValues = hmRestric.get(restricName);
166: if (childValues == null)
167: return null;
168: if (childValues.size() == 1)
169: return (ArrayList) childValues.get(0);
170:
171: // OTHERWISE we don't know what to do so return the first one anyway! This
172: // should not happen....
173: Logger
174: .log("WARNING: returning first set of values for element "
175: + elem
176: + " this should not happen and it may not be correct.....check logs for VALUESCLASH statements and fix schema");
177: return (ArrayList) childValues.get(0);
178: }
179:
180: //---------------------------------------------------------------------------
181: //---
182: //--- Package protected API methods
183: //---
184: //---------------------------------------------------------------------------
185:
186: void addElement(String name, String type, ArrayList alValues,
187: ArrayList alSubs, String subLink) {
188: // first just add the subs - because these are for global elements we
189: // never have a clash because global elements are all in the same scope
190: // and are thus unique
191: if (alSubs != null && alSubs.size() > 0)
192: hmSubs.put(name, alSubs);
193: if (subLink != null && subLink.length() > 0)
194: hmSubsLink.put(name, subLink);
195:
196: List<String> exType = hmElements.get(name);
197:
198: // it's already there but the type has been added already
199: if (exType != null && exType.contains(type))
200: return;
201:
202: // it's already there but doesn't have this type
203: if (exType != null && !(exType.contains(type))) {
204: Logger.log("CLASH: trying to add " + name + " with type "
205: + type + ": already exists with type: " + exType
206: + " - adding overflows and code to cope");
207:
208: // it's not there so add a new list
209: } else {
210: hmElements.put(name, exType = new ArrayList<String>());
211: }
212: exType.add(type);
213:
214: String restricName = name;
215: if (type != null)
216: restricName = name + "+" + type;
217:
218: // it's already there
219: List<List> exValues = hmRestric.get(restricName);
220: if (exValues != null) {
221: Logger.log("VALUESCLASH: trying to add " + restricName
222: + " with values " + alValues
223: + ": already exists with values " + exValues
224: + " - this should not happen");
225:
226: // it's not there so add a new list of lists
227: } else {
228: hmRestric
229: .put(restricName, exValues = new ArrayList<List>());
230: }
231: exValues.add(alValues);
232: }
233:
234: //---------------------------------------------------------------------------
235:
236: public void addType(String name, MetadataType mdt) {
237: mdt.setName(name);
238: hmTypes.put(name, mdt);
239: }
240:
241: //---------------------------------------------------------------------------
242:
243: public void addNS(String targetNSPrefix, String targetNS) {
244: hmNameSpaces.put(targetNSPrefix, targetNS);
245: }
246:
247: //---------------------------------------------------------------------------
248:
249: public String getNS(String targetNSPrefix) {
250: return (String) hmNameSpaces.get(targetNSPrefix);
251: }
252:
253: }
254:
255: //==============================================================================
|