| /******************************************************************************* |
| * Copyright (C) 2007 The University of Manchester |
| * |
| * Modifications to the initial code base are copyright of their |
| * respective authors, or their employers as appropriate. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public License |
| * as published by the Free Software Foundation; either version 2.1 of |
| * the License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
| ******************************************************************************/ |
| package net.sf.taverna.t2.reference.impl; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import net.sf.taverna.t2.reference.ContextualizedT2Reference; |
| import net.sf.taverna.t2.reference.ErrorDocument; |
| import net.sf.taverna.t2.reference.ErrorDocumentServiceException; |
| import net.sf.taverna.t2.reference.ExternalReferenceSPI; |
| import net.sf.taverna.t2.reference.Identified; |
| import net.sf.taverna.t2.reference.IdentifiedList; |
| import net.sf.taverna.t2.reference.ListServiceException; |
| import net.sf.taverna.t2.reference.ReferenceContext; |
| import net.sf.taverna.t2.reference.ReferenceService; |
| import net.sf.taverna.t2.reference.ReferenceServiceException; |
| import net.sf.taverna.t2.reference.ReferenceSet; |
| import net.sf.taverna.t2.reference.ReferenceSetServiceException; |
| import net.sf.taverna.t2.reference.StreamToValueConverterSPI; |
| import net.sf.taverna.t2.reference.T2Reference; |
| import net.sf.taverna.t2.reference.T2ReferenceType; |
| import net.sf.taverna.t2.reference.ValueCarryingExternalReference; |
| import net.sf.taverna.t2.reference.ValueToReferenceConversionException; |
| import net.sf.taverna.t2.reference.ValueToReferenceConverterSPI; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| /** |
| * Implementation of ReferenceService, inject with ReferenceSetService, |
| * ErrorDocumentService and ListService to enable. |
| * |
| * @author Tom Oinn |
| * @author Alan R Williams |
| * @author Stuart Owen |
| * @author Stian Soiland-Reyes |
| */ |
| public class ReferenceServiceImpl extends AbstractReferenceServiceImpl |
| implements ReferenceService { |
| |
| private final Log log = LogFactory.getLog(ReferenceServiceImpl.class); |
| |
| /** |
| * The top level registration method is used to register either as yet |
| * unregistered ErrorDocuments and ReferenceSets (if these are passed in and |
| * already have an identifier this call does nothing) and arbitrarily nested |
| * Lists of the same. In addition any ExternalReferenceSPI instances found |
| * will be wrapped in a single item ReferenceSet and registered, and any |
| * Throwables will be wrapped in an ErrorDocument and registered. Lists will |
| * be converted to IdentifiedList<T2Reference> and registered if all |
| * children can be (or were already) appropriately named. |
| * <p> |
| * This method is only valid on parameters of the following type : |
| * <ol> |
| * <li>{@link ReferenceSet} - registered if not already registered, |
| * otherwise returns existing T2Reference</li> |
| * <li>{@link ErrorDocument} - same behaviour as ReferenceSet</li> |
| * <li>{@link ExternalReferenceSPI} - wrapped in ReferenceSet, registered |
| * and ID returned</li> |
| * <li>Throwable - wrapped in ErrorDocument with no message, registered and |
| * ID returned</li> |
| * <li>List - all children are first registered, if this succeeds the list |
| * is itself registered as an IdentifiedList of T2Reference and its |
| * reference returned.</li> |
| * </ol> |
| * The exception to this is if the useConvertorSPI parameter is set to true |
| * - in this case any objects which do not match the above allowed list will |
| * be run through any available ValueToReferenceConvertorSPI instances in |
| * turn until one succeeds or all fail, which may result in the creation of |
| * ExternalReferenceSPI instances. As these can be registered such objects |
| * will not cause an exception to be thrown. |
| * |
| * @param o |
| * the object to register with the reference system, must comply |
| * with and will be interpreted as shown in the type list above. |
| * @param targetDepth |
| * the depth of the top level object supplied. This is needed |
| * when registering empty collections and error documents, |
| * whether as top level types or as members of a collection |
| * within the top level type. If registering a collection this is |
| * the collection depth, so a List of ReferenceSchemeSPI would be |
| * depth 1. Failing to specify this correctly will result in |
| * serious problems downstream so be careful! We can't catch all |
| * potential problems in this method (although some errors will |
| * be trapped). |
| * @param useConverterSPI |
| * whether to attempt to use the ValueToReferenceConvertorSPI |
| * registry (if defined and available) to map arbitrary objects |
| * to ExternalReferenceSPI instances on the fly. The registry of |
| * converters is generally injected into the implementation of |
| * this service. |
| * @param context |
| * ReferenceContext to use if required by component services, |
| * this is most likely to be used by the object to reference |
| * converters if engaged. |
| * <p> |
| * If the context is null a new empty reference context is |
| * inserted. |
| * @return a T2Reference to the registered object |
| * @throws ReferenceServiceException |
| * if the object type (or, for collections, the recursive type |
| * of its contents) is not in the allowed list or if a problem |
| * occurs during registration. Also thrown if attempting to use |
| * the converter SPI without an attached registry. |
| */ |
| public T2Reference register(Object o, int targetDepth, |
| boolean useConverterSPI, ReferenceContext context) |
| throws ReferenceServiceException { |
| checkServices(); |
| if (context == null) { |
| context = new EmptyReferenceContext(); |
| } |
| if (useConverterSPI) { |
| checkConverterRegistry(); |
| } |
| return getNameForObject(o, targetDepth, useConverterSPI, context); |
| } |
| |
| private T2Reference getNameForObject(Object o, int currentDepth, |
| boolean useConverterSPI, ReferenceContext context) |
| throws ReferenceServiceException { |
| if (currentDepth < 0) { |
| throw new ReferenceServiceException("Cannot register at depth " + currentDepth + ": " + o); |
| } |
| // First check whether this is an Identified, and if so whether it |
| // already has an ID. If this is the case then return it, we assume that |
| // anything which has an identifier already allocated must have been |
| // registered (this is implicit in the contract for the various |
| // sub-services |
| if (o instanceof Identified) { |
| Identified i = (Identified) o; |
| if (i.getId() != null) { |
| return i.getId(); |
| } |
| } |
| // Then check whether the item *is* a T2Reference, in which case we can |
| // just return it (useful for when registering lists of existing |
| // references) |
| if (o instanceof T2Reference) { |
| return (T2Reference) o; |
| } |
| |
| if (o.getClass().isArray()) { |
| Class<?> elementType = o.getClass().getComponentType(); |
| if (elementType.getCanonicalName().equals("char")) { |
| char[] cArray = (char[]) o; |
| List<Character> cList = new ArrayList<Character>(); |
| for (char c : cArray) { |
| cList.add(new Character(c)); |
| } |
| o = cList; |
| } else if (elementType.getCanonicalName().equals("short")) { |
| short[] cArray = (short[]) o; |
| List<Short> cList = new ArrayList<Short>(); |
| for (short c : cArray) { |
| cList.add(new Short(c)); |
| } |
| o = cList; |
| } else if (elementType.getCanonicalName().equals("int")) { |
| int[] cArray = (int[]) o; |
| List<Integer> cList = new ArrayList<Integer>(); |
| for (int c : cArray) { |
| cList.add(new Integer(c)); |
| } |
| o = cList; |
| } else if (elementType.getCanonicalName().equals("long")) { |
| long[] cArray = (long[]) o; |
| List<Long> cList = new ArrayList<Long>(); |
| for (long c : cArray) { |
| cList.add(new Long(c)); |
| } |
| o = cList; |
| } else if (elementType.getCanonicalName().equals("float")) { |
| float[] cArray = (float[]) o; |
| List<Float> cList = new ArrayList<Float>(); |
| for (float c : cArray) { |
| cList.add(new Float(c)); |
| } |
| o = cList; |
| } else if (elementType.getCanonicalName().equals("double")) { |
| double[] cArray = (double[]) o; |
| List<Double> cList = new ArrayList<Double>(); |
| for (double c : cArray) { |
| cList.add(new Double(c)); |
| } |
| o = cList; |
| } else if (elementType.getCanonicalName().equals("boolean")) { |
| boolean[] cArray = (boolean[]) o; |
| List<Boolean> cList = new ArrayList<Boolean>(); |
| for (boolean c : cArray) { |
| cList.add(new Boolean(c)); |
| } |
| o = cList; |
| } else if (!elementType.getCanonicalName().equals("byte")){ |
| // Covert arrays of objects |
| Object[] cArray = (Object[]) o; |
| List<Object> cList = new ArrayList<Object>(); |
| for (Object c : cArray) { |
| cList.add(c); |
| } |
| o = cList; |
| } |
| } |
| |
| // If a Collection but not a List |
| if ((o instanceof Collection) && !(o instanceof List)) { |
| List<Object> cList = new ArrayList<Object>(); |
| cList.addAll((Collection)o); |
| o = cList; |
| } |
| // Next check lists. |
| if (o instanceof List) { |
| if (currentDepth < 1) { |
| throw new ReferenceServiceException("Cannot register list at depth " + currentDepth); |
| } |
| List<?> l = (List<?>) o; |
| // If the list is empty then register a new empty list of the |
| // appropriate depth and return it |
| if (l.isEmpty()) { |
| try { |
| IdentifiedList<T2Reference> newList = listService |
| .registerEmptyList(currentDepth); |
| return newList.getId(); |
| } catch (ListServiceException lse) { |
| throw new ReferenceServiceException(lse); |
| } |
| } |
| // Otherwise construct a new list of T2Reference and register it, |
| // calling the getNameForObject method on all children of the list |
| // to construct the list of references |
| else { |
| List<T2Reference> references = new ArrayList<T2Reference>(); |
| for (Object item : l) { |
| // Recursively call this method with a depth one lower than |
| // the current depth |
| references.add(getNameForObject(item, currentDepth - 1, |
| useConverterSPI, context)); |
| } |
| try { |
| IdentifiedList<T2Reference> newList = listService |
| .registerList(references); |
| return newList.getId(); |
| } catch (ListServiceException lse) { |
| throw new ReferenceServiceException(lse); |
| } |
| } |
| } else { |
| // Neither a list nor an already identified object, first thing is |
| // to engage the converters if enabled. Only engage if we don't |
| // already have a Throwable or an ExternalReferenceSPI instance |
| if (useConverterSPI && (o instanceof Throwable == false) |
| && (o instanceof ExternalReferenceSPI == false)) { |
| if (currentDepth != 0) { |
| throw new ReferenceServiceException( |
| "Cannot register object " + o + " at depth " |
| + currentDepth); |
| } |
| |
| for (ValueToReferenceConverterSPI converter : converterRegistry) { |
| if (converter.canConvert(o, context)) { |
| try { |
| ExternalReferenceSPI ers = converter.convert(o, |
| context); |
| o = ers; |
| break; |
| } catch (ValueToReferenceConversionException vtrce) { |
| // Fail, but that doesn't matter at the moment as |
| // there may be more converters to try. TODO - log |
| // this! |
| } |
| } |
| } |
| } |
| // If the object is neither a Throwable nor an ExternalReferenceSPI |
| // instance at this point we should fail the registration process, |
| // this means either that the conversion process wasn't enabled or |
| // that it failed to map the object type correctly. |
| if ((o instanceof Throwable == false) |
| && (o instanceof ExternalReferenceSPI == false)) { |
| throw new ReferenceServiceException( |
| "Failed to register object " + o + ", found a type '" |
| + o.getClass().getCanonicalName() |
| + "' which cannot currently be registered with the reference manager"); |
| } |
| // Have either a Throwable or an ExternalReferenceSPI |
| else { |
| if (o instanceof Throwable) { |
| // Wrap in an ErrorDocument and return the ID |
| try { |
| ErrorDocument doc = errorDocumentService.registerError( |
| (Throwable) o, currentDepth); |
| return doc.getId(); |
| } catch (ErrorDocumentServiceException edse) { |
| throw new ReferenceServiceException(edse); |
| } |
| } else if (o instanceof ExternalReferenceSPI) { |
| if (currentDepth != 0) { |
| throw new ReferenceServiceException("Cannot register external references at depth " + currentDepth); |
| } |
| try { |
| Set<ExternalReferenceSPI> references = new HashSet<ExternalReferenceSPI>(); |
| references.add((ExternalReferenceSPI) o); |
| ReferenceSet rs = referenceSetService |
| .registerReferenceSet(references); |
| return rs.getId(); |
| } catch (ReferenceSetServiceException rsse) { |
| throw new ReferenceServiceException(rsse); |
| } |
| } |
| } |
| } |
| throw new ReferenceServiceException( |
| "Should never see this, reference registration" |
| + " logic has fallen off the end of the" |
| + " world, check the code!"); |
| } |
| |
| /** |
| * Perform recursive identifier resolution, building a collection structure |
| * of Identified objects, any collection elements being IdentifiedLists of |
| * Identified subclasses. If the id has depth 0 this will just return the |
| * Identified to which that id refers. |
| * |
| * @param id |
| * the T2Reference to resolve |
| * @param ensureTypes |
| * a set of ExternalReferenceSPI classes, this is used to augment |
| * any resolved ReferenceSet instances to ensure that each one |
| * has at least one of the specified types. If augmentation is |
| * not required this can be set to null. |
| * @param context |
| * the ReferenceContext to use to resolve this and any |
| * recursively resolved identifiers |
| * <p> |
| * If the context is null a new EmptyReferenceContext is inserted |
| * in its place. |
| * @return fully resolved Identified subclass - this is either a (recursive) |
| * IdentifiedList of Identified, a ReferenceSet or an ErrorDocument |
| * @throws ReferenceServiceException |
| * if any problems occur during resolution |
| */ |
| public Identified resolveIdentifier(T2Reference id, |
| Set<Class<ExternalReferenceSPI>> ensureTypes, |
| ReferenceContext context) throws ReferenceServiceException { |
| checkServices(); |
| if (context == null) { |
| context = new EmptyReferenceContext(); |
| } |
| switch (id.getReferenceType()) { |
| |
| case ReferenceSet: |
| try { |
| ReferenceSet rs; |
| if (ensureTypes == null) { |
| rs = referenceSetService.getReferenceSet(id); |
| } else { |
| rs = referenceSetService.getReferenceSetWithAugmentation( |
| id, ensureTypes, context); |
| } |
| return rs; |
| } catch (ReferenceSetServiceException rsse) { |
| throw new ReferenceServiceException(rsse); |
| } |
| |
| case ErrorDocument: |
| try { |
| ErrorDocument ed = errorDocumentService.getError(id); |
| return ed; |
| } catch (ErrorDocumentServiceException edse) { |
| throw new ReferenceServiceException(edse); |
| } |
| |
| case IdentifiedList: |
| try { |
| IdentifiedList<T2Reference> idList = listService.getList(id); |
| // Construct a new list, and populate with the result of |
| // resolving each ID in turn |
| IdentifiedArrayList<Identified> newList = new IdentifiedArrayList<Identified>(); |
| for (T2Reference item : idList) { |
| newList.add(resolveIdentifier(item, ensureTypes, context)); |
| } |
| newList.setTypedId(T2ReferenceImpl.getAsImpl(id)); |
| return newList; |
| } catch (ListServiceException lse) { |
| throw new ReferenceServiceException(lse); |
| } |
| |
| default: |
| throw new ReferenceServiceException("Unsupported ID type : " |
| + id.getReferenceType()); |
| } |
| } |
| |
| public Object renderIdentifier(T2Reference id, Class<?> leafClass, |
| ReferenceContext context) throws ReferenceServiceException { |
| // Check we have the services installed |
| checkServices(); |
| |
| // Insert an empty context if context was null |
| if (context == null) { |
| context = new EmptyReferenceContext(); |
| } |
| |
| // Reject if the source reference contains errors |
| if (id.containsErrors()) { |
| throw new ReferenceServiceException( |
| "Can't render an identifier which contains errors to a POJO"); |
| } |
| |
| // Attempt to find an appropriate StreamToValueConverterSPI instance to |
| // build the specified class |
| StreamToValueConverterSPI<?> converter = null; |
| if (valueBuilderRegistry != null) { |
| for (StreamToValueConverterSPI<?> stvc : valueBuilderRegistry) { |
| Class<?> builtClass = stvc.getPojoClass(); |
| if (leafClass.isAssignableFrom(builtClass)) { |
| converter = stvc; |
| break; |
| } |
| } |
| } |
| if (converter == null) { |
| log.warn("No stream->value converters found for type '" |
| + leafClass.getCanonicalName() + "'"); |
| } |
| |
| // Render the identifier |
| return renderIdentifierInner(id, leafClass, context, converter); |
| } |
| |
| private Object renderIdentifierInner(T2Reference id, Class<?> leafClass, |
| ReferenceContext context, StreamToValueConverterSPI<?> converter) |
| throws ReferenceServiceException { |
| checkServices(); |
| |
| switch (id.getReferenceType()) { |
| |
| case IdentifiedList: |
| try { |
| IdentifiedList<T2Reference> idList = listService.getList(id); |
| List<Object> result = new ArrayList<Object>(); |
| for (T2Reference child : idList) { |
| result.add(renderIdentifierInner(child, leafClass, context, |
| converter)); |
| } |
| return result; |
| } catch (ListServiceException lse) { |
| throw new ReferenceServiceException(lse); |
| } |
| |
| case ReferenceSet: |
| try { |
| ReferenceSet rs = referenceSetService.getReferenceSet(id); |
| // Check that there are references in the set |
| if (rs.getExternalReferences().isEmpty()) { |
| throw new ReferenceServiceException( |
| "Can't render an empty reference set to a POJO"); |
| } |
| // If we can't directly map to an appropriate value keep track |
| // of the cheapest reference from which to try to build the pojo |
| // from a stream |
| ExternalReferenceSPI cheapestReference = null; |
| float cheapestReferenceCost = 10.0f; |
| for (ExternalReferenceSPI ers : rs.getExternalReferences()) { |
| if (ers instanceof ValueCarryingExternalReference<?>) { |
| ValueCarryingExternalReference<?> vcer = (ValueCarryingExternalReference<?>) ers; |
| if (leafClass.isAssignableFrom(vcer.getValueType())) { |
| return vcer.getValue(); |
| } |
| } |
| // Got here so this wasn't an appropriate value type |
| if (cheapestReference == null |
| || ers.getResolutionCost() < cheapestReferenceCost) { |
| cheapestReference = ers; |
| cheapestReferenceCost = ers.getResolutionCost(); |
| } |
| } |
| if (converter != null) { |
| return converter.renderFrom(cheapestReference |
| .openStream(context)); |
| } |
| } catch (Exception e) { |
| throw new ReferenceServiceException(e); |
| } |
| throw new ReferenceServiceException( |
| "No converter found, and reference set didn't contain" |
| + " an appropriate value carrying reference, cannot render to POJO"); |
| |
| default: |
| throw new ReferenceServiceException("Unsupported ID type : " |
| + id.getReferenceType()); |
| } |
| } |
| |
| /** |
| * Initiates a traversal of the specified t2reference, traversing to |
| * whatever level of depth is required such that all identifiers returned |
| * within the iterator have the specified depth. The context (i.e. the index |
| * path from the originally specified reference to each reference within the |
| * iteration) is included through use of the ContextualizedT2Reference |
| * wrapper class |
| * |
| * @param source |
| * the T2Reference from which to traverse. In general this is the |
| * root of a collection structure. |
| * @param desiredDepth |
| * the desired depth of all returned T2References, must be less |
| * than or equal to that of the source reference. |
| * @throws ReferenceServiceException |
| * if unable to create the iterator for some reason. Note that |
| * implementations are free to lazily perform the iteration so |
| * this method may succeed but the iterator produced can fail |
| * when used. If the iterator fails it will do so by throwing |
| * one of the underlying sub-service exceptions. |
| */ |
| public Iterator<ContextualizedT2Reference> traverseFrom(T2Reference source, |
| int desiredDepth) throws ReferenceServiceException { |
| checkServices(); |
| if (desiredDepth < 0) { |
| throw new ReferenceServiceException( |
| "Cannot traverse to a negative depth"); |
| } |
| List<ContextualizedT2Reference> workingSet = new ArrayList<ContextualizedT2Reference>(); |
| workingSet.add(new ContextualizedT2ReferenceImpl(source, new int[0])); |
| int currentDepth = source.getDepth(); |
| while (currentDepth > desiredDepth) { |
| List<ContextualizedT2Reference> newSet = new ArrayList<ContextualizedT2Reference>(); |
| for (ContextualizedT2Reference ci : workingSet) { |
| T2ReferenceImpl ref = (T2ReferenceImpl) ci.getReference(); |
| switch (ref.getReferenceType()) { |
| case IdentifiedList: |
| try { |
| List<T2Reference> children = getListService().getList( |
| ref); |
| int position = 0; |
| for (T2Reference child : children) { |
| newSet.add(new ContextualizedT2ReferenceImpl(child, |
| addIndex(ci.getIndex(), position++))); |
| } |
| } catch (ListServiceException lse) { |
| throw new ReferenceServiceException(lse); |
| } |
| break; |
| case ReferenceSet: |
| throw new ReferenceServiceException( |
| "Should never be trying to drill inside a data document identifier"); |
| case ErrorDocument: |
| newSet.add(new ContextualizedT2ReferenceImpl(ref |
| .getDeeperErrorReference(), addIndex(ci.getIndex(), |
| 0))); |
| break; |
| default: |
| throw new ReferenceServiceException( |
| "Fallen off end of case statement, unknown reference type!"); |
| } |
| } |
| currentDepth--; |
| workingSet = newSet; |
| } |
| return workingSet.iterator(); |
| } |
| |
| /** |
| * Append to an int[] |
| * |
| * @param current |
| * current int[] |
| * @param head |
| * new int item to append to the current array |
| * @return new array of int with the head added |
| */ |
| private static int[] addIndex(int[] current, int head) { |
| int[] result = new int[current.length + 1]; |
| System.arraycopy(current, 0, result, 0, current.length); |
| result[current.length] = head; |
| return result; |
| } |
| |
| /** |
| * Parse the reference contained in the string and return a |
| * {@link T2Reference} with the correct properties |
| */ |
| public T2Reference referenceFromString(String reference) { |
| T2ReferenceImpl newRef = new T2ReferenceImpl(); |
| Map<String, String> parseRef = parseRef(reference); |
| newRef.setNamespacePart(parseRef.get("namespace")); |
| newRef.setLocalPart(parseRef.get("localPart")); |
| String type = parseRef.get("type"); |
| if (type.equals("ref")) { |
| newRef.setReferenceType(T2ReferenceType.ReferenceSet); |
| } else if (type.equals("list")) { |
| newRef.setReferenceType(T2ReferenceType.IdentifiedList); |
| newRef.setContainsErrors(Boolean |
| .parseBoolean(parseRef.get("error"))); |
| newRef.setDepth(Integer.parseInt(parseRef.get("depth"))); |
| } else if (type.equals("error")) { |
| newRef.setReferenceType(T2ReferenceType.ErrorDocument); |
| newRef.setDepth(Integer.parseInt(parseRef.get("depth"))); |
| } else { |
| return null; |
| // should throw an error |
| } |
| |
| return newRef; |
| } |
| |
| /** |
| * Parse the reference and return a map with localPart, namespace, depth, |
| * contains errors and the type |
| * |
| * @param ref |
| * @return |
| */ |
| private Map<String, String> parseRef(String ref) { |
| String[] split = ref.split("\\?"); |
| // get the bit before and after the final '/' ie. the local part and the |
| // depth, there might not be a split1[1] since it might not be a list |
| String[] split2 = split[1].split("/"); |
| // get the t2:abc:// and the namespace |
| String[] split3 = split[0].split("//"); |
| // get the t2 bit and the reference type bit |
| String[] split4 = split3[0].split(":"); |
| |
| Map<String, String> refPartsMap = new HashMap<String, String>(); |
| refPartsMap.put("type", split4[1]); |
| refPartsMap.put("namespace", split3[1]); |
| refPartsMap.put("localPart", split2[0]); |
| |
| if (refPartsMap.get("type").equals("list")) { |
| refPartsMap.put("error", split2[1]); |
| refPartsMap.put("depth", split2[2]); |
| } |
| if (refPartsMap.get("type").equals("error")) { |
| refPartsMap.put("depth", split2[1]); |
| } |
| |
| return refPartsMap; |
| |
| } |
| |
| |
| public boolean delete(List<T2Reference> references) |
| throws ReferenceServiceException { |
| boolean result=true; |
| for (T2Reference reference : references) { |
| delete(reference); |
| } |
| return result; |
| } |
| |
| public boolean delete(T2Reference reference) |
| throws ReferenceServiceException { |
| boolean result=false; |
| switch (reference.getReferenceType()) { |
| case IdentifiedList: |
| result=listService.delete(reference); |
| break; |
| case ReferenceSet: |
| result=referenceSetService.delete(reference); |
| break; |
| case ErrorDocument: |
| result=referenceSetService.delete(reference); |
| break; |
| default: |
| throw new ReferenceServiceException( |
| "Unknown reference type!"); |
| } |
| return result; |
| } |
| |
| } |