2 * This document is a part of the source code and related artifacts
3 * for CollectionSpace, an open source collections management system
4 * for museums and related institutions:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2011 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
25 package org.collectionspace.services.common.vocabulary;
27 import org.collectionspace.services.common.XmlTools;
28 import org.collectionspace.services.common.api.Tools;
29 import org.collectionspace.services.common.context.ServiceContext;
30 import org.collectionspace.services.common.relation.IRelationsManager;
31 import org.collectionspace.services.relation.RelationResource;
32 import org.collectionspace.services.relation.RelationsCommonList;
33 import org.collectionspace.services.relation.RelationsDocListItem;
34 import org.collectionspace.services.relation.RelationshipType;
36 import javax.ws.rs.core.MultivaluedMap;
37 import java.util.List;
40 * @author Laramie Crocker
42 public class Hierarchy {
44 public static final String directionQP = "direction";
45 public static final String direction_parents = "parents";
48 /**Call with the URI and CSID of the root element of the tree you wish to inspect. The uri can be a blank string.
49 * @param uri informational, optional - if not known, pass an empty String.
50 * @return String of XML document, including xml processing instruction, root node is "<hierarchy>".
52 public static String dive(ServiceContext ctx, String itemcsid, String uri) {
53 String result = dive(ctx, itemcsid, uri, true);
54 result = "<?xml version='1.0' ?><hierarchy>"+result+"</hierarchy>";
56 result = XmlTools.prettyPrint(result);
57 } catch (Exception e){
62 private static String dive(ServiceContext ctx, String itemcsid, String uri, boolean lookupFirstName) {
63 MultivaluedMap queryParams = ctx.getUriInfo().getQueryParameters();
64 //Run getList() once as sent to get childListOuter:
65 queryParams.putSingle(IRelationsManager.PREDICATE_QP, RelationshipType.HAS_BROADER.value());
66 queryParams.putSingle(IRelationsManager.SUBJECT_QP, null);
67 queryParams.putSingle(IRelationsManager.SUBJECT_TYPE_QP, null);
68 queryParams.putSingle(IRelationsManager.OBJECT_QP, itemcsid);
69 queryParams.putSingle(IRelationsManager.OBJECT_TYPE_QP, null);
70 RelationsCommonList childListOuter = (new RelationResource()).getList(ctx.getUriInfo()); //magically knows all query params because they are in the context.
71 List<RelationsCommonList.RelationListItem> childList = childListOuter.getRelationListItem();
73 StringBuffer sb = new StringBuffer();
75 if (lookupFirstName && childList.size() > 0) {
76 RelationsCommonList.RelationListItem firstItem = childList.get(0);
77 sb.append("<uri>" + firstItem.getObject().getUri() + "</uri>\r\n");
78 sb.append("<uri-called>" + uri + "</uri-called>\r\n");
79 sb.append("<name>" + firstItem.getObject().getName() + "</name><number>" + firstItem.getObject().getNumber() + "</number>\r\n");
81 sb.append("<uri>" + uri + "</uri>\r\n");
83 sb.append("<csid>" + itemcsid + "</csid>\r\n");
84 sb.append("<children>\r\n");
85 for (RelationsCommonList.RelationListItem item : childList) {
86 RelationsDocListItem parent = item.getObject();
87 RelationsDocListItem child = item.getSubject();
88 String childCSID = child.getCsid();
89 String childURI = child.getUri();
90 sb.append("<child>\r\n");
91 sb.append("<parent-uri>" +parent.getUri() + "</parent-uri>\r\n");
92 sb.append(" <name>" + child.getName() + "</name><number>" + child.getNumber() + "</number>\r\n");
93 String s = dive(ctx, childCSID, childURI, false);
95 sb.append("</child>\r\n");
97 sb.append("</children>\r\n");
101 public static String surface(ServiceContext ctx, String itemcsid, String uri) {
102 String result = surface(ctx, itemcsid, uri, true).resultBuffer.toString();
103 result = "<?xml version='1.0' ?><hierarchy direction='"+direction_parents+"'>"+result+"</hierarchy>";
105 result = XmlTools.prettyPrint(result);
106 } catch (Exception e){
110 private static class SurfaceResultStruct {
111 public StringBuffer resultBuffer;
112 public boolean noParents = false;
114 private static SurfaceResultStruct surface(ServiceContext ctx, String itemcsid, String uri, boolean first) {
115 MultivaluedMap queryParams = ctx.getUriInfo().getQueryParameters();
116 //Run getList() once as sent to get parentListOuter:
117 queryParams.putSingle(IRelationsManager.PREDICATE_QP, RelationshipType.HAS_BROADER.value());
118 queryParams.putSingle(IRelationsManager.SUBJECT_QP, itemcsid);
119 queryParams.putSingle(IRelationsManager.SUBJECT_TYPE_QP, null);
120 queryParams.putSingle(IRelationsManager.OBJECT_QP, null);
121 queryParams.putSingle(IRelationsManager.OBJECT_TYPE_QP, null);
122 RelationsCommonList parentListOuter = (new RelationResource()).getList(ctx.getUriInfo()); //magically knows all query params because they are in the context.
123 List<RelationsCommonList.RelationListItem> parentList = parentListOuter.getRelationListItem();
125 StringBuffer sbOuter = new StringBuffer();
126 SurfaceResultStruct resultStruct = new SurfaceResultStruct();
127 resultStruct.resultBuffer = sbOuter;
130 sbOuter.append("<uri>" + uri + "</uri>\r\n");
131 sbOuter.append("<csid>" + itemcsid + "</csid>\r\n");
133 StringBuffer sb = new StringBuffer();
136 String otherNames="";
138 String otherNumbers = "";
140 sb.append("<parents>\r\n");
141 if (parentList.size()==0){
142 resultStruct.noParents = true;
144 for (RelationsCommonList.RelationListItem item : parentList) {
145 resultStruct.noParents = false;
146 RelationsDocListItem parent = item.getObject();
147 RelationsDocListItem child = item.getSubject();
148 String parentCSID =parent.getCsid();
149 String parentURI = parent.getUri();
151 String aName = child.getName();
152 String aNumber = child.getNumber();
153 if (name.length()>0 && (!name.equals(aName))){
154 otherNames = otherNames+";"+aName;
158 if (number.length()>0 && (!number.equals(aNumber))){
159 otherNumbers = otherNumbers+";"+aNumber;
164 sb.append("<parent>\r\n");
165 //sb.append("<parent-uri>" +parentURI + "</parent-uri>\r\n");
167 SurfaceResultStruct struct = surface(ctx, parentCSID, parentURI, false);
168 StringBuffer surfaceResult = struct.resultBuffer;
170 if (struct.noParents){
171 //when there are no more parents, there is no way to look up the name and number, so use this trick:
172 sb.append("<name>" + parent.getName() + "</name><number>" + parent.getNumber() + "</number>\r\n");
175 sb.append(surfaceResult);
176 sb.append("</parent>\r\n");
178 sb.append("</parents>\r\n");
181 if (Tools.notBlank(name))sbOuter.append(" <name>" +name + "</name>\r\n");
182 if (Tools.notBlank(otherNames)) sbOuter.append(" <name-mismatches-by-parents>" +otherNames + "</name-mismatches-by-parents>\r\n");
184 if (Tools.notBlank(number)) sbOuter.append("<number>" +number + "</number>\r\n");
185 if (Tools.notBlank(otherNumbers)) sbOuter.append(" <number-mismatches-by-parents>" +otherNumbers + "</number-mismatches-by-parents>\r\n");