Lookup/Ibis web service client API
  • Class

Classes

  • GroupMethods
  • IbisAttribute
  • IbisAttributeScheme
  • IbisClientConnection
  • IbisContactPhoneNumber
  • IbisContactRow
  • IbisContactWebPage
  • IbisDto
  • IbisError
  • IbisGroup
  • IbisIdentifier
  • IbisInstitution
  • IbisMethods
  • IbisPerson
  • IbisResult
  • IbisResultParser
  • InstitutionMethods
  • PersonMethods

Interfaces

  • ClientConnection

Exceptions

  • IbisException
  1 <?php
  2 /*
  3 Copyright (c) 2012, University of Cambridge Computing Service
  4 
  5 This file is part of the Lookup/Ibis client library.
  6 
  7 This library is free software: you can redistribute it and/or modify
  8 it under the terms of the GNU Lesser General Public License as published
  9 by the Free Software Foundation, either version 3 of the License, or
 10 (at your option) any later version.
 11 
 12 This library is distributed in the hope that it will be useful, but
 13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 15 License for more details.
 16 
 17 You should have received a copy of the GNU Lesser General Public License
 18 along with this library.  If not, see <http://www.gnu.org/licenses/>.
 19 */
 20 
 21 require_once "IbisAttribute.php";
 22 require_once "IbisAttributeScheme.php";
 23 require_once "IbisContactPhoneNumber.php";
 24 require_once "IbisContactRow.php";
 25 require_once "IbisContactWebPage.php";
 26 require_once "IbisDto.php";
 27 require_once "IbisError.php";
 28 require_once "IbisGroup.php";
 29 require_once "IbisIdentifier.php";
 30 require_once "IbisInstitution.php";
 31 require_once "IbisPerson.php";
 32 
 33 /**
 34  * Class representing the top-level container for all XML and JSON results.
 35  * This may be just a simple textual value or it may contain more complex
 36  * entities such as people, institutions, groups, attributes, etc.
 37  *
 38  * @author Dean Rasheed (dev-group@ucs.cam.ac.uk)
 39  */
 40 class IbisResult extends IbisDto
 41 {
 42     /* Properties marked as @XmlAttribte in the JAXB class */
 43     protected static $xmlAttrs = array("version");
 44 
 45     /* Properties marked as @XmlElement in the JAXB class */
 46     protected static $xmlElems = array("value", "person", "institution",
 47                                        "group", "identifier", "attribute",
 48                                        "error", "entities");
 49 
 50     /* Properties marked as @XmlElementWrapper in the JAXB class */
 51     protected static $xmlArrays = array("people", "institutions", "groups",
 52                                         "attributes", "attributeSchemes");
 53 
 54     /** @var string The web service API version number. */
 55     public $version;
 56 
 57     /**
 58      * @var string The value returned by methods that return a simple textual
 59      * value.
 60      */
 61     public $value;
 62 
 63     /**
 64      * @var IbisPerson The person returned by methods that return a single
 65      * person.
 66      *
 67      * Note that methods that may return multiple people will always use
 68      * the {@link people} field, even if only one person was returned.
 69      */
 70     public $person;
 71 
 72     /**
 73      * @var IbisInstitution The institution returned by methods that return a
 74      * single institution.
 75      *
 76      * Note that methods that may return multiple institutions will always
 77      * use the {@link institutions} field, even if only one institution
 78      * was returned.
 79      */
 80     public $institution;
 81 
 82     /**
 83      * @var IbisGroup The group returned by methods that return a single
 84      * group.
 85      *
 86      * Note that methods that may return multiple groups will always use
 87      * the {@link groups} field, even if only one group was returned.
 88      */
 89     public $group;
 90 
 91     /**
 92      * @var IbisIdentifier The identifier returned by methods that return a
 93      * single identifier.
 94      */
 95     public $identifier;
 96 
 97     /**
 98      * @var IbisAttribute The person or institution attribute returned by
 99      * methods that return a single attribute.
100      */
101     public $attribute;
102 
103     /** @var IbisError If the method failed, details of the error. */
104     public $error;
105 
106     /**
107      * @var IbisPerson[] The list of people returned by methods that may
108      * return multiple people. This may be empty, or contain one or more
109      * people.
110      */
111     public $people;
112 
113     /**
114      * @var IbisInstitution[] The list of institutions returned by methods
115      * that may return multiple institutions. This may be empty, or contain
116      * one or more institutions.
117      */
118     public $institutions;
119 
120     /**
121      * @var IbisGroup[] The list of groups returned by methods that may
122      * return multiple groups. This may be empty, or contain one or more
123      * groups.
124      */
125     public $groups;
126 
127     /**
128      * @var IbisAttribute[] The list of attributes returned by methods that
129      * return lists of person/institution attributes.
130      */
131     public $attributes;
132 
133     /**
134      * @var IbisAttributeScheme[] The list of attribute schemes returned by
135      * methods that return lists of person/institution attribute schemes.
136      */
137     public $attributeSchemes;
138 
139     /**
140      * @ignore
141      * @var IbisResultEntities In the flattened XML/JSON representation, all
142      * the unique entities returned by the method.
143      *
144      * NOTE: This will be ``null`` unless the "flatten" parameter is
145      * ``true``.
146      */
147     public $entities;
148 
149     /**
150      * @ignore
151      * Unflatten this IbisResult object, resolving any internal ID refs
152      * to build a fully fledged object tree.
153      *
154      * This is necessary if the IbisResult was constructed from XML/JSON in
155      * its flattened representation (with the "flatten" parameter set to
156      * ``true``).
157      *
158      * On entry, the IbisResult object may have people, institutions or
159      * groups in it with "ref" fields referring to objects held in the
160      * "entities" lists. After unflattening, all such references will have
161      * been replaced by actual object references, giving an object tree that
162      * can be traversed normally.
163      *
164      * @return IbisResult This IbisResult object, with its internals
165      * unflattened.
166      */
167     public function unflatten()
168     {
169         if (isset($this->entities))
170         {
171             $em = new IbisResultEntityMap($this);
172 
173             if (isset($this->person))
174                 $this->person = $this->person->unflatten($em);
175             if (isset($this->institution))
176                 $this->institution = $this->institution->unflatten($em);
177             if (isset($this->group))
178                 $this->group = $this->group->unflatten($em);
179 
180             IbisPerson::unflattenPeople($em, $this->people);
181             IbisInstitution::unflattenInsts($em, $this->institutions);
182             IbisGroup::unflattenGroups($em, $this->groups);
183         }
184         return $this;
185     }
186 }
187 
188 /**
189  * @ignore
190  * Class to hold the full details of all the entities returned in a result
191  * (a nested class in Java and Python). This is used only in the flattened
192  * result representation, where each of these entities will have a unique
193  * textual ID, and be referred to from the top-level objects returned (and
194  * by each other).
195  *
196  * In the hierarchical representation, this is not used, since all entities
197  * returned will be at the top-level, or directly contained in those
198  * top-level entities.
199  */
200 class IbisResultEntities extends IbisDto
201 {
202     /* Properties marked as @XmlElementWrapper in the JAXB class */
203     protected static $xmlArrays = array("people", "institutions", "groups");
204 
205     /**
206      * @var IbisPerson[] A list of all the unique people returned by the
207      * method. This may include additional people returned as a result of the
208      * ``fetch`` parameter, so this list may contain more entries than the
209      * corresponding field on the enclosing class.
210      */
211     public $people;
212 
213     /**
214      * @var IbisInstitution[] A list of all the unique institutions returned
215      * by the method. This may include additional institutions returned as a
216      * result of the ``fetch`` parameter, so this list may contain more
217      * entries than the corresponding field on the enclosing class.
218      */
219     public $institutions;
220 
221     /**
222      * @var IbisGroup[] A list of all the unique groups returned by the
223      * method. This may include additional groups returned as a result of the
224      * ``fetch`` parameter, so this list may contain more entries than the
225      * corresponding field on the enclosing class.
226      */
227     public $groups;
228 }
229 
230 /**
231  * @ignore
232  * Class to assist during the unflattening process, maintaining efficient
233  * maps from IDs to entities (people, institutions and groups). This is a
234  * nested class of IbisResult in Java and Python.
235  */
236 class IbisResultEntityMap
237 {
238     private $peopleById;
239     private $instsById;
240     private $groupsById;
241 
242     /** Construct an entity map from a flattened IbisResult. */
243     public function __construct($result)
244     {
245         $this->peopleById = array();
246         $this->instsById = array();
247         $this->groupsById = array();
248 
249         if (isset($result->entities->people))
250             foreach ($result->entities->people as $person)
251                 $this->peopleById[$person->id] = $person;
252         if (isset($result->entities->institutions))
253             foreach ($result->entities->institutions as $inst)
254                 $this->instsById[$inst->id] = $inst;
255         if (isset($result->entities->groups))
256             foreach ($result->entities->groups as $group)
257                 $this->groupsById[$group->id] = $group;
258     }
259 
260     /** Get a person from the entity map, given their ID */
261     public function getPerson($id) { return $this->peopleById[$id]; }
262 
263     /** Get an institution from the entity map, given its ID */
264     public function getInstitution($id) { return $this->instsById[$id]; }
265 
266     /** Get a group from the entity map, given its ID */
267     public function getGroup($id) { return $this->groupsById[$id]; }
268 }
269 
270 /**
271  * @ignore
272  * Class to hold a XML text node's value during XML parsing.
273  */
274 class XmlTextNode
275 {
276     public $tagname;
277     public $data;
278 }
279 
280 /**
281  * Class to parse the XML from the server and produce an IbisResult.
282  */
283 class IbisResultParser
284 {
285     /** The IbisResult produced from the XML */
286     private $result;
287 
288     /** Stack of nodes during XML parsing */
289     private $nodeStack;
290 
291     /** @ignore Start element callback function for XML parsing */
292     public function startElement($parser, $tagname, $attrs)
293     {
294         $element = null;
295         if (!empty($this->nodeStack))
296         {
297             if ($tagname === "person")
298                 $element = new IbisPerson($attrs);
299             elseif ($tagname === "institution")
300                 $element = new IbisInstitution($attrs);
301             elseif ($tagname === "membersOfInst")
302                 $element = new IbisInstitution($attrs);
303             elseif ($tagname === "group")
304                 $element = new IbisGroup($attrs);
305             elseif ($tagname === "identifier")
306                 $element = new IbisIdentifier($attrs);
307             elseif ($tagname === "attribute")
308                 $element = new IbisAttribute($attrs);
309             elseif ($tagname === "error")
310                 $element = new IbisError($attrs);
311             elseif ($tagname === "attributeScheme")
312                 $element = new IbisAttributeScheme($attrs);
313             elseif ($tagname === "contactRow")
314                 $element = new IbisContactRow($attrs);
315             elseif ($tagname === "phoneNumber")
316                 $element = new IbisContactPhoneNumber($attrs);
317             elseif ($tagname === "webPage")
318                 $element = new IbisContactWebPage($attrs);
319             elseif ($tagname === "entities")
320                 $element = new IbisResultEntities($attrs);
321             else
322             {
323                 $parent = end($this->nodeStack);
324                 if (!is_array($parent))
325                     // Need a reference to the parent's child array
326                     $element = &$parent->startChildElement($tagname);
327             }
328 
329             if (is_null($element))
330             {
331                 $element = new XmlTextNode();
332                 $element->tagname = $tagname;
333             }
334         }
335         elseif ($tagname !== "result")
336             throw new Exception("Invalid root element: '" . $tagname . "'");
337         else
338         {
339             $element = new IbisResult($attrs);
340             $this->result = $element;
341         }
342 
343         // Stack the new element. If it is an array, we must stack a
344         // reference to it that we can modify.
345         if (is_array($element)) $this->nodeStack[] = &$element;
346         else $this->nodeStack[] = $element;
347     }
348 
349     /** @ignore End element callback function for XML parsing */
350     public function endElement($parser, $tagname)
351     {
352         if (!empty($this->nodeStack))
353         {
354             $element = array_pop($this->nodeStack);
355             if (!empty($this->nodeStack))
356             {
357                 if (is_array(end($this->nodeStack)))
358                 {
359                     // Add the child to the parent's child array, which
360                     // means that we must use an array reference
361                     $parent = &$this->nodeStack[sizeof($this->nodeStack)-1];
362                     $parent[] = $element instanceof XmlTextNode ?
363                                 $element->data : $element;
364                 }
365                 elseif (!(end($this->nodeStack) instanceof XmlTextNode))
366                 {
367                     $parent = end($this->nodeStack);
368                     $parent->endChildElement($tagname,
369                                              $element instanceof XmlTextNode ?
370                                              $element->data : $element);
371                 }
372             }
373         }
374         else
375             throw new Exception("Unexpected closing tag: '" . $tagname . "'");
376     }
377 
378     /** @ignore Character data callback function for XML parsing */
379     public function charData($parser, $data)
380     {
381         if (!empty($this->nodeStack))
382         {
383             $element = end($this->nodeStack);
384             if ($element instanceof IbisIdentifier)
385             {
386                 if (isset($element->value)) $element->value .= $data;
387                 else $element->value = $data;
388             }
389             elseif ($element instanceof XmlTextNode)
390             {
391                 if (isset($element->data)) $element->data .= $data;
392                 else $element->data = $data;
393             }
394         }
395     }
396 
397     /**
398      * Parse XML data from the specified string and return an IbisResult.
399      *
400      * @param string $data The XML string returned from the server.
401      *
402      * @return IbisResult The parsed results. This may contain lists or trees
403      * of objects representing people, institutions and groups returned from
404      * the server.
405      */
406     public function parseXml($data)
407     {
408         $parser = xml_parser_create();
409         xml_set_object($parser, $this);
410         xml_set_element_handler($parser, "startElement", "endElement");
411         xml_set_character_data_handler($parser, "charData");
412         xml_parser_set_option ($parser, XML_OPTION_CASE_FOLDING, false);
413 
414         $this->result = null;
415         $this->nodeStack = array();
416 
417         xml_parse($parser, $data);
418         xml_parser_free($parser);
419 
420         return $this->result->unflatten();
421     }
422 
423     /**
424      * Parse XML data from the specified stream and return an IbisResult.
425      *
426      * @param resource $file A file pointer to a stream containing XML
427      * returned from the server.
428      *
429      * @return IbisResult The parsed results. This may contain lists or trees
430      * of objects representing people, institutions and groups returned from
431      * the server.
432      */
433     public function parseXmlFile($file)
434     {
435         $parser = xml_parser_create();
436         xml_set_object($parser, $this);
437         xml_set_element_handler($parser, "startElement", "endElement");
438         xml_set_character_data_handler($parser, "charData");
439         xml_parser_set_option ($parser, XML_OPTION_CASE_FOLDING, false);
440 
441         $this->result = null;
442         $this->nodeStack = array();
443 
444         while ($data = fread($file, 4096))
445             xml_parse($parser, $data, feof($file));
446         xml_parser_free($parser);
447 
448         return $this->result->unflatten();
449     }
450 }
451 
Lookup/Ibis web service client API documentation generated by ApiGen