Input: Checks if { @link ProofStep } is derived by { @link ElkClassInclusionExistentialComposition } inference where the last premise is derived from { @link ElkPropertyInclusionOfTransitiveObjectProperty } [CODESPLIT] static ProofNode < OWLAxiom > canConvertStep ( ProofStep < OWLAxiom > step ) { if ( step . getName ( ) != ElkClassInclusionExistentialComposition . NAME ) { return null ; } List < ? extends ProofNode < OWLAxiom > > premises = step . getPremises ( ) ; ProofNode < OWLAxiom > lastPremise = premises . get ( premises . size ( ) - 1 ) ; Collection < ? extends ProofStep < OWLAxiom > > lastPremiseSteps = lastPremise . getInferences ( ) ; if ( lastPremiseSteps . size ( ) != 1 ) { return null ; } // else for ( ProofStep < OWLAxiom > lastPremiseStep : lastPremiseSteps ) { if ( lastPremiseStep . getName ( ) == ElkPropertyInclusionOfTransitiveObjectProperty . NAME ) { return lastPremiseStep . getPremises ( ) . get ( 0 ) ; } } // else return null ; }


Input:
Prunes { @link #toAdd_ } . <p > <strong > { @code taxonomy_ } must not be { @code null } !< / strong > [CODESPLIT] private int pruneToAdd ( ) { final Iterator < IndexedClass > iter = toAdd_ . iterator ( ) ; int size = 0 ; while ( iter . hasNext ( ) ) { final IndexedClass cls = iter . next ( ) ; /* @formatter:off
			 *
			 * Should be pruned when:
			 * it is not in ontology, or
			 * it is in the top node, or
			 * it has super-nodes in taxonomy.
			 *
			 * @formatter:on
			 */ if ( ! cls . occurs ( ) ) { iter . remove ( ) ; continue ; } // else final Context context = saturationState_ . getContext ( cls ) ; if ( context == null || ! context . isInitialized ( ) || ! context . isSaturated ( ) ) { // it is not saturated. size ++ ; continue ; } // else final TaxonomyNode < ElkClass > node = taxonomy_ . getNode ( cls . getElkEntity ( ) ) ; if ( node == null ) { // it is not in taxonomy size ++ ; continue ; } // else if ( node . equals ( taxonomy_ . getTopNode ( ) ) ) { iter . remove ( ) ; continue ; } // else if ( ! node . getDirectSuperNodes ( ) . isEmpty ( ) ) { iter . remove ( ) ; continue ; } // else size ++ ; } return size ; }


Input:
Prunes { @link #toRemove_ } . <p > <strong > { @code taxonomy_ } must not be { @code null } !< / strong > [CODESPLIT] private int pruneToRemove ( ) { final Iterator < IndexedClass > iter = toRemove_ . iterator ( ) ; int size = 0 ; while ( iter . hasNext ( ) ) { final IndexedClass cls = iter . next ( ) ; /* @formatter:off
			 *
			 * Should be pruned when
			 * it is not in taxonomy, or
			 * it is in the bottom class.
			 *
			 * @formatter:on
			 */ final TaxonomyNode < ElkClass > node = taxonomy_ . getNode ( cls . getElkEntity ( ) ) ; if ( node == null ) { iter . remove ( ) ; continue ; } // else if ( cls == ontologyIndex_ . getOwlNothing ( ) ) { iter . remove ( ) ; continue ; } size ++ ; } return size ; }


Input: Add the values the corresponding values of the given counter [CODESPLIT] public synchronized void add ( RuleCounter counter ) { countOwlThingContextInitRule += counter . countOwlThingContextInitRule ; countRootContextInitializationRule += counter . countRootContextInitializationRule ; countDisjointSubsumerFromMemberRule += counter . countDisjointSubsumerFromMemberRule ; countContradictionFromNegationRule += counter . countContradictionFromNegationRule ; countObjectIntersectionFromFirstConjunctRule += counter . countObjectIntersectionFromFirstConjunctRule ; countObjectIntersectionFromSecondConjunctRule += counter . countObjectIntersectionFromSecondConjunctRule ; countSuperClassFromSubClassRule += counter . countSuperClassFromSubClassRule ; countPropagationFromExistentialFillerRule += counter . countPropagationFromExistentialFillerRule ; countObjectUnionFromDisjunctRule += counter . countObjectUnionFromDisjunctRule ; countBackwardLinkChainFromBackwardLinkRule += counter . countBackwardLinkChainFromBackwardLinkRule ; countSubsumerBackwardLinkRule += counter . countSubsumerBackwardLinkRule ; countContradictionOverBackwardLinkRule += counter . countContradictionOverBackwardLinkRule ; countContradictionPropagationRule += counter . countContradictionPropagationRule ; countContradictionCompositionRule += counter . countContradictionCompositionRule ; countNonReflexiveBackwardLinkCompositionRule += counter . countNonReflexiveBackwardLinkCompositionRule ; countIndexedObjectIntersectionOfDecomposition += counter . countIndexedObjectIntersectionOfDecomposition ; countIndexedObjectSomeValuesFromDecomposition += counter . countIndexedObjectSomeValuesFromDecomposition ; countIndexedObjectComplementOfDecomposition += counter . countIndexedObjectComplementOfDecomposition ; countIndexedObjectHasSelfDecomposition += counter . countIndexedObjectHasSelfDecomposition ; countContradictionFromOwlNothingRule += counter . countContradictionFromOwlNothingRule ; countSubsumerPropagationRule += counter . countSubsumerPropagationRule ; countReflexiveBackwardLinkCompositionRule += counter . countReflexiveBackwardLinkCompositionRule ; countPropagationInitializationRule += counter . countPropagationInitializationRule ; countBackwardLinkFromForwardLinkRule += counter . countBackwardLinkFromForwardLinkRule ; countComposedFromDecomposedSubsumerRule += counter . countComposedFromDecomposedSubsumerRule ; countIndexedClassDecompositionRule += counter . countIndexedClassDecompositionRule ; countIndexedClassFromDefinitionRule += counter . countIndexedClassFromDefinitionRule ; countEquivalentClassFirstFromSecondRule += counter . countEquivalentClassFirstFromSecondRule ; countEquivalentClassSecondFromFirstRule += counter . countEquivalentClassSecondFromFirstRule ; }


Input: Process the given input concurrently using the provided input processor . If the process has been interrupted this method can be called again to continue the computation . [CODESPLIT] public void process ( ) { if ( ! start ( ) ) { String message = "Could not start workers required for reasoner computation!" ; LOGGER_ . error ( message ) ; throw new ElkRuntimeException ( message ) ; } try { finish ( ) ; } catch ( InterruptedException e ) { // restore interrupt status Thread . currentThread ( ) . interrupt ( ) ; throw new ElkRuntimeException ( "Reasoner computation interrupted externally!" ) ; } }


Input: From { [CODESPLIT] private InputStream getBodyFromServletRequestParameters ( HttpServletRequest request , String charset ) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream ( 1024 ) ; Writer writer = new OutputStreamWriter ( bos , charset ) ; @ SuppressWarnings ( "unchecked" ) Map < String , String [ ] > form = request . getParameterMap ( ) ; for ( Iterator < String > nameIterator = form . keySet ( ) . iterator ( ) ; nameIterator . hasNext ( ) ; ) { String name = nameIterator . next ( ) ; List < String > values = Arrays . asList ( form . get ( name ) ) ; for ( Iterator < String > valueIterator = values . iterator ( ) ; valueIterator . hasNext ( ) ; ) { String value = valueIterator . next ( ) ; writer . write ( URLEncoder . encode ( name , charset ) ) ; if ( value != null ) { writer . write ( ' ' ) ; writer . write ( URLEncoder . encode ( value , charset ) ) ; if ( valueIterator . hasNext ( ) ) { writer . write ( ' ' ) ; } } } if ( nameIterator . hasNext ( ) ) { writer . append ( ' ' ) ; } } writer . flush ( ) ; return new ByteArrayInputStream ( bos . toByteArray ( ) ) ; }


Input: Recursively converts object to xhtml data . [CODESPLIT] private void writeResource ( XhtmlWriter writer , Object object ) { if ( object == null ) { return ; } try { if ( object instanceof Resource ) { Resource < ? > resource = ( Resource < ? > ) object ; writer . beginListItem ( ) ; writeResource ( writer , resource . getContent ( ) ) ; writer . writeLinks ( resource . getLinks ( ) ) ; writer . endListItem ( ) ; } else if ( object instanceof Resources ) { Resources < ? > resources = ( Resources < ? > ) object ; // TODO set name using EVO see HypermediaSupportBeanDefinitionRegistrar writer . beginListItem ( ) ; writer . beginUnorderedList ( ) ; Collection < ? > content = resources . getContent ( ) ; writeResource ( writer , content ) ; writer . endUnorderedList ( ) ; writer . writeLinks ( resources . getLinks ( ) ) ; writer . endListItem ( ) ; } else if ( object instanceof ResourceSupport ) { ResourceSupport resource = ( ResourceSupport ) object ; writer . beginListItem ( ) ; writeObject ( writer , resource ) ; writer . writeLinks ( resource . getLinks ( ) ) ; writer . endListItem ( ) ; } else if ( object instanceof Collection ) { Collection < ? > collection = ( Collection < ? > ) object ; for ( Object item : collection ) { writeResource ( writer , item ) ; } } else { // TODO: write li for simple objects in Resources Collection writeObject ( writer , object ) ; } } catch ( Exception ex ) { throw new RuntimeException ( "failed to transform object " + object , ex ) ; } }


Input: Gets input parameter info which is part of the URL mapping be it request parameters path variables or request body attributes . [CODESPLIT] @ Override public ActionInputParameter getActionInputParameter ( String name ) { ActionInputParameter ret = requestParams . get ( name ) ; if ( ret == null ) { ret = pathVariables . get ( name ) ; } if ( ret == null ) { for ( ActionInputParameter annotatedParameter : getInputParameters ( ) ) { // TODO create ActionInputParameter for bean property at property path // TODO field access in addition to bean? PropertyDescriptor pd = getPropertyDescriptorForPropertyPath ( name , annotatedParameter . getParameterType ( ) ) ; if ( pd != null ) { if ( pd . getWriteMethod ( ) != null ) { Object callValue = annotatedParameter . getValue ( ) ; Object propertyValue = null ; if ( callValue != null ) { BeanWrapper beanWrapper = PropertyAccessorFactory . forBeanPropertyAccess ( callValue ) ; propertyValue = beanWrapper . getPropertyValue ( name ) ; } ret = new SpringActionInputParameter ( new MethodParameter ( pd . getWriteMethod ( ) , 0 ) , propertyValue ) ; } break ; } } } return ret ; }


Input: Recursively navigate to return a BeanWrapper for the nested property path . [CODESPLIT] PropertyDescriptor getPropertyDescriptorForPropertyPath ( String propertyPath , Class < ? > propertyType ) { int pos = PropertyAccessorUtils . getFirstNestedPropertySeparatorIndex ( propertyPath ) ; // Handle nested properties recursively. if ( pos > - 1 ) { String nestedProperty = propertyPath . substring ( 0 , pos ) ; String nestedPath = propertyPath . substring ( pos + 1 ) ; PropertyDescriptor propertyDescriptor = BeanUtils . getPropertyDescriptor ( propertyType , nestedProperty ) ; //            BeanWrapperImpl nestedBw = getNestedBeanWrapper(nestedProperty); return getPropertyDescriptorForPropertyPath ( nestedPath , propertyDescriptor . getPropertyType ( ) ) ; } else { return BeanUtils . getPropertyDescriptor ( propertyType , propertyPath ) ; } }


Input: Determines action input parameters for required url variables . [CODESPLIT] @ Override public Map < String , ActionInputParameter > getRequiredParameters ( ) { Map < String , ActionInputParameter > ret = new HashMap < String , ActionInputParameter > ( ) ; for ( Map . Entry < String , ActionInputParameter > entry : requestParams . entrySet ( ) ) { ActionInputParameter annotatedParameter = entry . getValue ( ) ; if ( annotatedParameter . isRequired ( ) ) { ret . put ( entry . getKey ( ) , annotatedParameter ) ; } } for ( Map . Entry < String , ActionInputParameter > entry : pathVariables . entrySet ( ) ) { ActionInputParameter annotatedParameter = entry . getValue ( ) ; ret . put ( entry . getKey ( ) , annotatedParameter ) ; } // requestBody not supported, would have to use exploded modifier return ret ; }


Input: Determines if the given class holds only one data item . Can be useful to determine if a value should be rendered as scalar . [CODESPLIT] public static boolean isSingleValueType ( Class < ? > clazz ) { boolean ret ; if ( isNumber ( clazz ) || isBoolean ( clazz ) || isString ( clazz ) || isEnum ( clazz ) || isDate ( clazz ) || isCalendar ( clazz ) || isCurrency ( clazz ) ) { ret = true ; } else { ret = false ; } return ret ; }


Input: Determines if the given string contains only 0 - 9 [ ISO - LATIN - 1 ] or an optional leading + / - sign . [CODESPLIT] public static boolean isIsoLatin1Number ( String str ) { if ( str == null ) return false ; char [ ] data = str . toCharArray ( ) ; if ( data . length == 0 ) return false ; int index = 0 ; if ( data . length > 1 && ( data [ 0 ] == ' ' || data [ 0 ] == ' ' ) ) index = 1 ; for ( ; index < data . length ; index ++ ) { if ( data [ index ] < ' ' || data [ index ] > ' ' ) return false ; } return true ; }


Input: The relation type of the link . [CODESPLIT] public void addRel ( String rel ) { Assert . hasLength ( rel ) ; linkParams . add ( REL . paramName , rel ) ; }


Input: The type parameter when present is a hint indicating what the media type of the result of dereferencing the link should be . Note that this is only a hint ; for example it does not override the Content - Type header of a HTTP response obtained by actually following the link . There MUST NOT be more than one type parameter in a link - value . [CODESPLIT] public void setType ( String mediaType ) { if ( mediaType != null ) linkParams . set ( TYPE . paramName , mediaType ) ; else linkParams . remove ( TYPE . paramName ) ; }


Input: The hreflang parameter when present is a hint indicating what the language of the result of dereferencing the link should be . Note that this is only a hint ; for example it does not override the Content - Language header of a HTTP response obtained by actually following the link . Multiple hreflang parameters on a single link - value indicate that multiple languages are available from the indicated resource . [CODESPLIT] public void addHreflang ( String hreflang ) { Assert . hasLength ( hreflang ) ; linkParams . add ( HREFLANG . paramName , hreflang ) ; }


Input: The title parameter when present is used to label the destination of a link such that it can be used as a human - readable identifier ( e . g . a menu entry ) in the language indicated by the Content - Language header ( if present ) . The title parameter MUST NOT appear more than once in a given link - value ; occurrences after the first MUST be ignored by parsers . [CODESPLIT] public void setTitle ( String title ) { if ( title != null ) linkParams . set ( TITLE . paramName , title ) ; else { linkParams . remove ( TITLE . paramName ) ; } }


Input:
The title * parameter can be used to encode the title label in a different character set and / or contain language information as per  RFC - 5987 . The title * parameter MUST NOT appear more than once in a given link - value ; occurrences after the first MUST be ignored by parsers . If the parameter does not contain language information its language is indicated by the Content - Language header ( when present ) .
 If both the title and title * parameters appear in a link - value processors SHOULD use the title * parameter s value .
 The example below shows an instance of the Link header encoding a link title using  RFC - 2231 encoding to encode both non - ASCII characters and language information .

 Link : &lt ; / TheBook / chapter2&gt ; rel = next ; title * = UTF - 8 de n%c3%a4chstes%20Kapitel
 [CODESPLIT] public void setTitleStar ( String titleStar ) { if ( titleStar != null ) linkParams . set ( TITLE_STAR . paramName , titleStar ) ; else linkParams . remove ( TITLE_STAR . paramName ) ; }


Input: The media parameter when present is used to indicate intended destination medium or media for style information ( see [ W3C . REC - html401 - 19991224 ] Section 6 . 13 ) . Note that this may be updated by [ W3C . CR - css3 - mediaqueries - 20090915 ] ) . Its value MUST be quoted if it contains a semicolon ( ; ) or comma ( ) and there MUST NOT be more than one media parameter in a link - value . [CODESPLIT] public void setMedia ( String mediaDesc ) { if ( mediaDesc != null ) linkParams . set ( MEDIA . paramName , mediaDesc ) ; else linkParams . remove ( MEDIA . paramName ) ; }


Input: The rev parameter has been used in the past to indicate that the semantics of the relationship are in the reverse direction . That is a link from A to B with REL = X expresses the same relationship as a link from B to A with REV = X . rev is deprecated by this specification because it often confuses authors and readers ; in most cases using a separate relation type is preferable . [CODESPLIT] public void addRev ( String rev ) { Assert . hasLength ( rev ) ; linkParams . add ( REV . paramName , rev ) ; }


Input: By default the context of a link conveyed in the Link header field is the IRI of the requested resource . <p > When present the anchor parameter overrides this with another URI such as a fragment of this resource or a third resource ( i . e . when the anchor value is an absolute URI ) . If the anchor parameter s value is a relative URI parsers MUST resolve it as per [ RFC3986 ] Section 5 . Note that any base URI from the body s content is not applied . [CODESPLIT] public void setAnchor ( String anchor ) { if ( anchor != null ) linkParams . set ( ANCHOR . paramName , anchor ) ; else linkParams . remove ( ANCHOR . paramName ) ; }


Input: Adds link - extension params i . e . custom params which are not described in the web linking rfc . [CODESPLIT] public void addLinkParam ( String paramName , String ... values ) { Assert . notEmpty ( values ) ; for ( String value : values ) { Assert . hasLength ( value ) ; linkParams . add ( paramName , value ) ; } }


Input: Affordance represented as http link header value . Note that the href may be templated for convenience you can use { @link #getHeaderName () } to ensure a Link or Link - Header is produced appropriately . [CODESPLIT] public String asHeader ( ) { StringBuilder result = new StringBuilder ( ) ; for ( Map . Entry < String , List < String > > linkParamEntry : linkParams . entrySet ( ) ) { if ( result . length ( ) != 0 ) { result . append ( "; " ) ; } String linkParamEntryKey = linkParamEntry . getKey ( ) ; if ( REL . paramName . equals ( linkParamEntryKey ) || REV . paramName . equals ( linkParamEntryKey ) ) { result . append ( linkParamEntryKey ) . append ( "=" ) ; result . append ( "\"" ) . append ( StringUtils . collectionToDelimitedString ( linkParamEntry . getValue ( ) , " " ) ) . append ( "\"" ) ; } else { StringBuilder linkParams = new StringBuilder ( ) ; for ( String value : linkParamEntry . getValue ( ) ) { if ( linkParams . length ( ) != 0 ) { linkParams . append ( "; " ) ; } linkParams . append ( linkParamEntryKey ) . append ( "=" ) ; linkParams . append ( "\"" ) . append ( value ) . append ( "\"" ) ; } result . append ( linkParams ) ; } } String linkHeader = "<" + partialUriTemplate . asComponents ( ) . toString ( ) + ">; " ; return result . insert ( 0 , linkHeader ) . toString ( ) ; }


Input: Expands template variables arguments must satisfy all required template variables unsatisfied optional arguments will be removed . [CODESPLIT] @ Override public Affordance expand ( Map < String , ? extends Object > arguments ) { UriTemplate template = new UriTemplate ( partialUriTemplate . asComponents ( ) . toString ( ) ) ; String expanded = template . expand ( arguments ) . toASCIIString ( ) ; return new Affordance ( expanded , linkParams , actionDescriptors ) ; }


Input: Expands template variables as far as possible unsatisfied variables will remain variables . This is primarily for manually created affordances . If the Affordance has been created with linkTo - methodOn it should not be necessary to expand the affordance again . [CODESPLIT] public Affordance expandPartially ( Object ... arguments ) { return new Affordance ( partialUriTemplate . expand ( arguments ) . toString ( ) , linkParams , actionDescriptors ) ; }


Input: Expands template variables as far as possible unsatisfied variables will remain variables . This is primarily for manually created affordances . If the Affordance has been created with linkTo - methodOn it should not be necessary to expand the affordance again . [CODESPLIT] public Affordance expandPartially ( Map < String , ? extends Object > arguments ) { return new Affordance ( partialUriTemplate . expand ( ( Map < String , Object > ) arguments ) . toString ( ) , linkParams , actionDescriptors ) ; }


Input: Allows to retrieve all rels defined for this affordance . [CODESPLIT] @ JsonIgnore public List < String > getRels ( ) { final List < String > rels = linkParams . get ( REL . paramName ) ; return rels == null ? Collections . < String > emptyList ( ) : Collections . unmodifiableList ( rels ) ; }


Input: Retrieves all revs for this affordance . [CODESPLIT] @ JsonIgnore public List < String > getRevs ( ) { final List < String > revs = linkParams . get ( REV . paramName ) ; return revs == null ? Collections . < String > emptyList ( ) : Collections . unmodifiableList ( revs ) ; }


Input: Determines if the affordance has unsatisfied required variables . This allows to decide if the affordance can also be treated as a plain Link without template variables if the caller omits all optional variables . Serializers can use this to render it as a resource with optional search features . [CODESPLIT] @ JsonIgnore public boolean hasUnsatisfiedRequiredVariables ( ) { for ( ActionDescriptor actionDescriptor : actionDescriptors ) { Map < String , ActionInputParameter > requiredParameters = actionDescriptor . getRequiredParameters ( ) ; for ( ActionInputParameter annotatedParameter : requiredParameters . values ( ) ) { if ( ! annotatedParameter . hasValue ( ) ) { return true ; } } } return false ; }


Input: Creates a new { @link ForwardedHeader } from the given source . [CODESPLIT] public static ForwardedHeader of ( String source ) { if ( ! StringUtils . hasText ( source ) ) { return NO_HEADER ; } Map < String , String > elements = new HashMap < String , String > ( ) ; for ( String part : source . split ( ";" ) ) { String [ ] keyValue = part . split ( "=" ) ; if ( keyValue . length != 2 ) { continue ; } elements . put ( keyValue [ 0 ] . trim ( ) , keyValue [ 1 ] . trim ( ) ) ; } Assert . notNull ( elements , "Forwarded elements must not be null!" ) ; Assert . isTrue ( ! elements . isEmpty ( ) , "At least one forwarded element needs to be present!" ) ; return new ForwardedHeader ( elements ) ; }


Input: The value of the parameter at sample invocation time formatted according to conversion configuration . [CODESPLIT] public String getValueFormatted ( ) { String ret ; if ( value == null ) { ret = null ; } else { ret = ( String ) conversionService . convert ( value , typeDescriptor , TypeDescriptor . valueOf ( String . class ) ) ; } return ret ; }


Input: Gets HTML5 parameter type for input field according to { @link Type } annotation . [CODESPLIT] @ Override public Type getHtmlInputFieldType ( ) { final Type ret ; if ( inputAnnotation == null || inputAnnotation . value ( ) == Type . FROM_JAVA ) { if ( isArrayOrCollection ( ) || isRequestBody ( ) ) { ret = null ; } else if ( DataType . isNumber ( getParameterType ( ) ) ) { ret = Type . NUMBER ; } else { ret = Type . TEXT ; } } else { ret = inputAnnotation . value ( ) ; } return ret ; }


Input: Determines if request body input parameter has a hidden input property . [CODESPLIT] @ Override public boolean isHidden ( String property ) { Annotation [ ] paramAnnotations = methodParameter . getParameterAnnotations ( ) ; Input inputAnnotation = methodParameter . getParameterAnnotation ( Input . class ) ; return inputAnnotation != null && arrayContains ( inputAnnotation . hidden ( ) , property ) ; }


Input: Find out if property is included by searching through all annotations . [CODESPLIT] private boolean containsPropertyIncludeValue ( String property ) { return arrayContains ( inputAnnotation . readOnly ( ) , property ) || arrayContains ( inputAnnotation . hidden ( ) , property ) || arrayContains ( inputAnnotation . include ( ) , property ) ; }


Input: Has any explicit include value or might have implicit includes because there is a hidden or readOnly flag . [CODESPLIT] private boolean hasExplicitOrImplicitPropertyIncludeValue ( ) { // TODO maybe not a useful optimization return inputAnnotation != null && inputAnnotation . readOnly ( ) . length > 0 || inputAnnotation . hidden ( ) . length > 0 || inputAnnotation . include ( ) . length > 0 ; }


Input: Determines if request body input parameter should be excluded considering { @link Input#exclude } . [CODESPLIT] @ Override public boolean isExcluded ( String property ) { return inputAnnotation != null && arrayContains ( inputAnnotation . exclude ( ) , property ) ; }


Input: Is this action input parameter required based on the presence of a default value the parameter annotations and the kind of input parameter . [CODESPLIT] public boolean isRequired ( ) { boolean ret ; if ( isRequestBody ( ) ) { ret = requestBody . required ( ) ; } else if ( isRequestParam ( ) ) { ret = ! ( isDefined ( requestParam . defaultValue ( ) ) || ! requestParam . required ( ) ) ; } else if ( isRequestHeader ( ) ) { ret = ! ( isDefined ( requestHeader . defaultValue ( ) ) || ! requestHeader . required ( ) ) ; } else { ret = true ; } return ret ; }


Input: Determines default value of request param or request header if available . [CODESPLIT] public String getDefaultValue ( ) { String ret ; if ( isRequestParam ( ) ) { ret = isDefined ( requestParam . defaultValue ( ) ) ? requestParam . defaultValue ( ) : null ; } else if ( isRequestHeader ( ) ) { ret = ! ( ValueConstants . DEFAULT_NONE . equals ( requestHeader . defaultValue ( ) ) ) ? requestHeader . defaultValue ( ) : null ; } else { ret = null ; } return ret ; }


Input: Allows convenient access to multiple call values in case that this input parameter is an array or collection . Make sure to check { @link #isArrayOrCollection () } before calling this method . [CODESPLIT] public Object [ ] getValues ( ) { Object [ ] callValues ; if ( ! isArrayOrCollection ( ) ) { throw new UnsupportedOperationException ( "parameter is not an array or collection" ) ; } Object callValue = getValue ( ) ; if ( callValue == null ) { callValues = new Object [ 0 ] ; } else { Class < ? > parameterType = getParameterType ( ) ; if ( parameterType . isArray ( ) ) { callValues = ( Object [ ] ) callValue ; } else { callValues = ( ( Collection < ? > ) callValue ) . toArray ( ) ; } } return callValues ; }


Input: Gets request parameter name of this action input parameter . [CODESPLIT] @ Override public String getParameterName ( ) { String ret = null ; if ( requestParam != null ) { String requestParamName = requestParam . value ( ) ; if ( ! requestParamName . isEmpty ( ) ) ret = requestParamName ; } if ( pathVariable != null ) { String pathVariableName = pathVariable . value ( ) ; if ( ! pathVariableName . isEmpty ( ) ) ret = pathVariableName ; } if ( ret == null ) { String parameterName = methodParameter . getParameterName ( ) ; if ( parameterName == null ) { methodParameter . initParameterNameDiscovery ( new LocalVariableTableParameterNameDiscoverer ( ) ) ; ret = methodParameter . getParameterName ( ) ; } else { ret = parameterName ; } } return ret ; }


Input: Writes bean description recursively . [CODESPLIT] private void recurseSupportedProperties ( JsonGenerator jgen , String currentVocab , Class < ? > valueType , ActionDescriptor allRootParameters , ActionInputParameter rootParameter , Object currentCallValue , String propertyPath ) throws IntrospectionException , IOException { Map < String , ActionInputParameter > properties = new HashMap < String , ActionInputParameter > ( ) ; // collect supported properties from ctor Constructor [ ] constructors = valueType . getConstructors ( ) ; // find default ctor Constructor constructor = PropertyUtils . findDefaultCtor ( constructors ) ; // find ctor with JsonCreator ann if ( constructor == null ) { constructor = PropertyUtils . findJsonCreator ( constructors , JsonCreator . class ) ; } if ( constructor == null ) { // TODO this can be a generic collection, find a way to describe it LOG . warn ( "can't describe supported properties, no default constructor or JsonCreator found for type " + valueType . getName ( ) ) ; return ; } int parameterCount = constructor . getParameterTypes ( ) . length ; if ( parameterCount > 0 ) { Annotation [ ] [ ] annotationsOnParameters = constructor . getParameterAnnotations ( ) ; Class [ ] parameters = constructor . getParameterTypes ( ) ; int paramIndex = 0 ; for ( Annotation [ ] annotationsOnParameter : annotationsOnParameters ) { for ( Annotation annotation : annotationsOnParameter ) { if ( JsonProperty . class == annotation . annotationType ( ) ) { JsonProperty jsonProperty = ( JsonProperty ) annotation ; // TODO use required attribute of JsonProperty String paramName = jsonProperty . value ( ) ; Object propertyValue = PropertyUtils . getPropertyOrFieldValue ( currentCallValue , paramName ) ; ActionInputParameter constructorParamInputParameter = new SpringActionInputParameter ( new MethodParameter ( constructor , paramIndex ) , propertyValue ) ; // TODO collect ctor params, setter params and process // TODO then handle single, collection and bean for both properties . put ( paramName , constructorParamInputParameter ) ; paramIndex ++ ; // increase for each @JsonProperty } } } Assert . isTrue ( parameters . length == paramIndex , "not all constructor arguments of @JsonCreator " + constructor . getName ( ) + " are annotated with @JsonProperty" ) ; } // collect supported properties from setters // TODO support Option provider by other method args? final BeanInfo beanInfo = Introspector . getBeanInfo ( valueType ) ; final PropertyDescriptor [ ] propertyDescriptors = beanInfo . getPropertyDescriptors ( ) ; // TODO collection and map // TODO distinguish which properties should be printed as supported - now just setters for ( PropertyDescriptor propertyDescriptor : propertyDescriptors ) { final Method writeMethod = propertyDescriptor . getWriteMethod ( ) ; if ( writeMethod == null ) { continue ; } // TODO: the property name must be a valid URI - need to check context for terms? String propertyName = getWritableExposedPropertyOrPropertyName ( propertyDescriptor ) ; Object propertyValue = PropertyUtils . getPropertyOrFieldValue ( currentCallValue , propertyDescriptor . getName ( ) ) ; MethodParameter methodParameter = new MethodParameter ( propertyDescriptor . getWriteMethod ( ) , 0 ) ; ActionInputParameter propertySetterInputParameter = new SpringActionInputParameter ( methodParameter , propertyValue ) ; properties . put ( propertyName , propertySetterInputParameter ) ; } // write all supported properties // TODO we are using the annotatedParameter.parameterName but should use the key of properties here: for ( ActionInputParameter annotatedParameter : properties . values ( ) ) { String nextPropertyPathLevel = propertyPath . isEmpty ( ) ? annotatedParameter . getParameterName ( ) : propertyPath + ' ' + annotatedParameter . getParameterName ( ) ; Class < ? > parameterType = annotatedParameter . getParameterType ( ) ; if ( DataType . isSingleValueType ( parameterType ) ) { final Object [ ] possiblePropertyValues = rootParameter . getPossibleValues ( allRootParameters ) ; if ( rootParameter . isIncluded ( nextPropertyPathLevel ) && ! rootParameter . isExcluded ( nextPropertyPathLevel ) ) { writeSupportedProperty ( jgen , currentVocab , annotatedParameter , annotatedParameter . getParameterName ( ) , possiblePropertyValues ) ; } // TODO collections? //                        } else if (DataType.isArrayOrCollection(parameterType)) { //                            Object[] callValues = rootParameter.getValues(); //                            int items = callValues.length; //                            for (int i = 0; i < items; i++) { //                                Object value; //                                if (i < callValues.length) { //                                    value = callValues[i]; //                                } else { //                                    value = null; //                                } //                                recurseSupportedProperties(jgen, currentVocab, rootParameter // .getParameterType(), //                                        allRootParameters, rootParameter, value); //                            } } else { jgen . writeStartObject ( ) ; jgen . writeStringField ( "hydra:property" , annotatedParameter . getParameterName ( ) ) ; // TODO: is the property required -> for bean props we need the Access annotation to express that Expose expose = AnnotationUtils . getAnnotation ( parameterType , Expose . class ) ; String subClass = null ; if ( expose != null ) { subClass = expose . value ( ) ; } else { if ( List . class . isAssignableFrom ( parameterType ) ) { Type genericParameterType = annotatedParameter . getGenericParameterType ( ) ; if ( genericParameterType instanceof ParameterizedType ) { ParameterizedType parameterizedType = ( ParameterizedType ) genericParameterType ; Type [ ] actualTypeArguments = parameterizedType . getActualTypeArguments ( ) ; if ( actualTypeArguments . length == 1 ) { Type actualTypeArgument = actualTypeArguments [ 0 ] ; if ( actualTypeArgument instanceof Class ) { parameterType = ( Class < ? > ) actualTypeArgument ; subClass = parameterType . getSimpleName ( ) ; } else if ( actualTypeArgument instanceof ParameterizedType ) { ParameterizedType genericItemType = ( ParameterizedType ) actualTypeArgument ; Type rawType = genericItemType . getRawType ( ) ; if ( rawType instanceof Class ) { parameterType = ( Class < ? > ) rawType ; subClass = parameterType . getSimpleName ( ) ; } } } } if ( subClass != null ) { String multipleValueProp = getPropertyOrClassNameInVocab ( currentVocab , "multipleValues" , LdContextFactory . HTTP_SCHEMA_ORG , "schema:" ) ; jgen . writeBooleanField ( multipleValueProp , true ) ; } } } if ( subClass == null ) { subClass = parameterType . getSimpleName ( ) ; } jgen . writeObjectFieldStart ( getPropertyOrClassNameInVocab ( currentVocab , "rangeIncludes" , LdContextFactory . HTTP_SCHEMA_ORG , "schema:" ) ) ; jgen . writeStringField ( getPropertyOrClassNameInVocab ( currentVocab , "subClassOf" , "http://www.w3.org/2000/01/rdf-schema#" , "rdfs:" ) , subClass ) ; jgen . writeArrayFieldStart ( "hydra:supportedProperty" ) ; // TODO let defaultValue be an filled list, if needed Object propertyValue = PropertyUtils . getPropertyOrFieldValue ( currentCallValue , annotatedParameter . getParameterName ( ) ) ; recurseSupportedProperties ( jgen , currentVocab , parameterType , allRootParameters , rootParameter , propertyValue , nextPropertyPathLevel ) ; jgen . writeEndArray ( ) ; jgen . writeEndObject ( ) ; jgen . writeEndObject ( ) ; } } }


Input: Gets property or class name in the current context either without prefix if the current vocab is the given vocabulary or prefixed otherwise . [CODESPLIT] private String getPropertyOrClassNameInVocab ( @ Nullable String currentVocab , String propertyOrClassName , String vocabulary , String vocabularyPrefixWithColon ) { Assert . notNull ( vocabulary ) ; String ret ; if ( vocabulary . equals ( currentVocab ) ) { ret = propertyOrClassName ; } else { ret = vocabularyPrefixWithColon + propertyOrClassName ; } return ret ; }


Input: } [CODESPLIT] private void writeHydraVariableMapping ( JsonGenerator jgen , @ Nullable ActionDescriptor annotatedParameters , Collection < String > variableNames ) throws IOException { if ( annotatedParameters != null ) { for ( String variableName : variableNames ) { // TODO: find also @Input ActionInputParameter annotatedParameter = annotatedParameters . getActionInputParameter ( variableName ) ; // TODO access @Input parameter, too // only unsatisfied parameters become hydra variables if ( annotatedParameter != null && annotatedParameter . getValue ( ) == null ) { jgen . writeStartObject ( ) ; jgen . writeStringField ( "@type" , "hydra:IriTemplateMapping" ) ; jgen . writeStringField ( "hydra:variable" , annotatedParameter . getParameterName ( ) ) ; jgen . writeBooleanField ( "hydra:required" , annotatedParameter . isRequired ( ) ) ; jgen . writeStringField ( "hydra:property" , getExposedPropertyOrParamName ( annotatedParameter ) ) ; jgen . writeEndObject ( ) ; } } } }


Input: Gets exposed property or parameter name . [CODESPLIT] private String getExposedPropertyOrParamName ( ActionInputParameter inputParameter ) { final Expose expose = inputParameter . getAnnotation ( Expose . class ) ; String property ; if ( expose != null ) { property = expose . value ( ) ; } else { property = inputParameter . getParameterName ( ) ; } return property ; }


Input: Gets exposed property or parameter name for properties with an appropriate setter ( = write ) method . [CODESPLIT] private String getWritableExposedPropertyOrPropertyName ( PropertyDescriptor inputParameter ) { final Method writeMethod = inputParameter . getWriteMethod ( ) ; final Expose expose = writeMethod . getAnnotation ( Expose . class ) ; String propertyName ; if ( expose != null ) { propertyName = expose . value ( ) ; } else { propertyName = inputParameter . getName ( ) ; } return propertyName ; }


Input: Recursively converts object to nodes of uber data . [CODESPLIT] public static void toUberData ( AbstractUberNode objectNode , Object object ) { Set < String > filtered = FILTER_RESOURCE_SUPPORT ; if ( object == null ) { return ; } try { // TODO: move all returns to else branch of property descriptor handling if ( object instanceof Resource ) { Resource < ? > resource = ( Resource < ? > ) object ; objectNode . addLinks ( resource . getLinks ( ) ) ; toUberData ( objectNode , resource . getContent ( ) ) ; return ; } else if ( object instanceof Resources ) { Resources < ? > resources = ( Resources < ? > ) object ; // TODO set name using EVO see HypermediaSupportBeanDefinitionRegistrar objectNode . addLinks ( resources . getLinks ( ) ) ; Collection < ? > content = resources . getContent ( ) ; toUberData ( objectNode , content ) ; return ; } else if ( object instanceof ResourceSupport ) { ResourceSupport resource = ( ResourceSupport ) object ; objectNode . addLinks ( resource . getLinks ( ) ) ; // wrap object attributes below to avoid endless loop } else if ( object instanceof Collection ) { Collection < ? > collection = ( Collection < ? > ) object ; for ( Object item : collection ) { // TODO name must be repeated for each collection item UberNode itemNode = new UberNode ( ) ; objectNode . addData ( itemNode ) ; toUberData ( itemNode , item ) ; } return ; } if ( object instanceof Map ) { Map < ? , ? > map = ( Map < ? , ? > ) object ; for ( Entry < ? , ? > entry : map . entrySet ( ) ) { String key = entry . getKey ( ) . toString ( ) ; Object content = entry . getValue ( ) ; Object value = getContentAsScalarValue ( content ) ; UberNode entryNode = new UberNode ( ) ; objectNode . addData ( entryNode ) ; entryNode . setName ( key ) ; if ( value != null ) { entryNode . setValue ( value ) ; } else { toUberData ( entryNode , content ) ; } } } else { Map < String , PropertyDescriptor > propertyDescriptors = PropertyUtils . getPropertyDescriptors ( object ) ; for ( PropertyDescriptor propertyDescriptor : propertyDescriptors . values ( ) ) { String name = propertyDescriptor . getName ( ) ; if ( filtered . contains ( name ) ) { continue ; } UberNode propertyNode = new UberNode ( ) ; Object content = propertyDescriptor . getReadMethod ( ) . invoke ( object ) ; if ( isEmptyCollectionOrMap ( content , propertyDescriptor . getPropertyType ( ) ) ) { continue ; } Object value = getContentAsScalarValue ( content ) ; propertyNode . setName ( name ) ; objectNode . addData ( propertyNode ) ; if ( value != null ) { // for each scalar property of a simple bean, add valuepair nodes to data propertyNode . setValue ( value ) ; } else { toUberData ( propertyNode , content ) ; } } Field [ ] fields = object . getClass ( ) . getFields ( ) ; for ( Field field : fields ) { String name = field . getName ( ) ; if ( ! propertyDescriptors . containsKey ( name ) ) { Object content = field . get ( object ) ; Class < ? > type = field . getType ( ) ; if ( isEmptyCollectionOrMap ( content , type ) ) { continue ; } UberNode propertyNode = new UberNode ( ) ; Object value = getContentAsScalarValue ( content ) ; propertyNode . setName ( name ) ; objectNode . addData ( propertyNode ) ; if ( value != null ) { // for each scalar property of a simple bean, add valuepair nodes to data propertyNode . setValue ( value ) ; } else { toUberData ( propertyNode , content ) ; } } } } } catch ( Exception ex ) { throw new RuntimeException ( "failed to transform object " + object , ex ) ; } }


Input: Converts single link to uber node . [CODESPLIT] public static UberNode toUberLink ( String href , ActionDescriptor actionDescriptor , String ... rels ) { return toUberLink ( href , actionDescriptor , Arrays . asList ( rels ) ) ; }


Input: Converts single link to uber node . [CODESPLIT] public static UberNode toUberLink ( String href , ActionDescriptor actionDescriptor , List < String > rels ) { Assert . notNull ( actionDescriptor , "actionDescriptor must not be null" ) ; UberNode uberLink = new UberNode ( ) ; uberLink . setRel ( rels ) ; PartialUriTemplateComponents partialUriTemplateComponents = new PartialUriTemplate ( href ) . expand ( Collections . < String , Object > emptyMap ( ) ) ; uberLink . setUrl ( partialUriTemplateComponents . toString ( ) ) ; uberLink . setTemplated ( partialUriTemplateComponents . hasVariables ( ) ? Boolean . TRUE : null ) ; uberLink . setModel ( getModelProperty ( href , actionDescriptor ) ) ; if ( actionDescriptor != null ) { RequestMethod requestMethod = RequestMethod . valueOf ( actionDescriptor . getHttpMethod ( ) ) ; uberLink . setAction ( UberAction . forRequestMethod ( requestMethod ) ) ; } return uberLink ; }


Input: Renders input fields for bean properties of bean to add or update or patch . [CODESPLIT] private static void recurseBeanCreationParams ( List < UberField > uberFields , Class < ? > beanType , ActionDescriptor annotatedParameters , ActionInputParameter annotatedParameter , Object currentCallValue , String parentParamName , Set < String > knownFields ) { // TODO collection, map and object node creation are only describable by an annotation, not via type reflection if ( ObjectNode . class . isAssignableFrom ( beanType ) || Map . class . isAssignableFrom ( beanType ) || Collection . class . isAssignableFrom ( beanType ) || beanType . isArray ( ) ) { return ; // use @Input(include) to list parameter names, at least? Or mix with hdiv's form builder? } try { Constructor [ ] constructors = beanType . getConstructors ( ) ; // find default ctor Constructor constructor = PropertyUtils . findDefaultCtor ( constructors ) ; // find ctor with JsonCreator ann if ( constructor == null ) { constructor = PropertyUtils . findJsonCreator ( constructors , JsonCreator . class ) ; } Assert . notNull ( constructor , "no default constructor or JsonCreator found for type " + beanType . getName ( ) ) ; int parameterCount = constructor . getParameterTypes ( ) . length ; if ( parameterCount > 0 ) { Annotation [ ] [ ] annotationsOnParameters = constructor . getParameterAnnotations ( ) ; Class [ ] parameters = constructor . getParameterTypes ( ) ; int paramIndex = 0 ; for ( Annotation [ ] annotationsOnParameter : annotationsOnParameters ) { for ( Annotation annotation : annotationsOnParameter ) { if ( JsonProperty . class == annotation . annotationType ( ) ) { JsonProperty jsonProperty = ( JsonProperty ) annotation ; // TODO use required attribute of JsonProperty for required fields String paramName = jsonProperty . value ( ) ; Class parameterType = parameters [ paramIndex ] ; Object propertyValue = PropertyUtils . getPropertyOrFieldValue ( currentCallValue , paramName ) ; MethodParameter methodParameter = new MethodParameter ( constructor , paramIndex ) ; addUberFieldsForMethodParameter ( uberFields , methodParameter , annotatedParameter , annotatedParameters , parentParamName , paramName , parameterType , propertyValue , knownFields ) ; paramIndex ++ ; // increase for each @JsonProperty } } } Assert . isTrue ( parameters . length == paramIndex , "not all constructor arguments of @JsonCreator " + constructor . getName ( ) + " are annotated with @JsonProperty" ) ; } Set < String > knownConstructorFields = new HashSet < String > ( uberFields . size ( ) ) ; for ( UberField sirenField : uberFields ) { knownConstructorFields . add ( sirenField . getName ( ) ) ; } // TODO support Option provider by other method args? Map < String , PropertyDescriptor > propertyDescriptors = PropertyUtils . getPropertyDescriptors ( beanType ) ; // add input field for every setter for ( PropertyDescriptor propertyDescriptor : propertyDescriptors . values ( ) ) { final Method writeMethod = propertyDescriptor . getWriteMethod ( ) ; String propertyName = propertyDescriptor . getName ( ) ; if ( writeMethod == null || knownFields . contains ( parentParamName + propertyName ) ) { continue ; } final Class < ? > propertyType = propertyDescriptor . getPropertyType ( ) ; Object propertyValue = PropertyUtils . getPropertyOrFieldValue ( currentCallValue , propertyName ) ; MethodParameter methodParameter = new MethodParameter ( propertyDescriptor . getWriteMethod ( ) , 0 ) ; addUberFieldsForMethodParameter ( uberFields , methodParameter , annotatedParameter , annotatedParameters , parentParamName , propertyName , propertyType , propertyValue , knownConstructorFields ) ; } } catch ( Exception e ) { throw new RuntimeException ( "Failed to write input fields for constructor" , e ) ; } }


Input: Returns { @link ActionInputParameter } s contained in the method link . [CODESPLIT] private static Map < String , ActionInputParameter > getActionInputParameters ( Class < ? extends Annotation > annotation , Method method , Object ... arguments ) { Assert . notNull ( method , "MethodInvocation must not be null!" ) ; MethodParameters parameters = new MethodParameters ( method ) ; Map < String , ActionInputParameter > result = new HashMap < String , ActionInputParameter > ( ) ; for ( MethodParameter parameter : parameters . getParametersWith ( annotation ) ) { final int parameterIndex = parameter . getParameterIndex ( ) ; final Object argument ; if ( parameterIndex < arguments . length ) { argument = arguments [ parameterIndex ] ; } else { argument = null ; } ActionInputParameter inputParameter = new SpringActionInputParameter ( parameter , argument ) ; result . put ( inputParameter . getParameterName ( ) , inputParameter ) ; } return result ; }


Input: TODO move to PropertyUtil and remove current method for propertyDescriptors cache search results [CODESPLIT] public static Object getPropertyOrFieldValue ( Object currentCallValue , String propertyOrFieldName ) { if ( currentCallValue == null ) { return null ; } Object propertyValue = getBeanPropertyValue ( currentCallValue , propertyOrFieldName ) ; if ( propertyValue == null ) { propertyValue = getFieldValue ( currentCallValue , propertyOrFieldName ) ; } return propertyValue ; }


Input: Gets vocab for given bean . [CODESPLIT] public String getVocab ( MixinSource mixinSource , Object bean , Class < ? > mixInClass ) { if ( proxyUnwrapper != null ) { bean = proxyUnwrapper . unwrapProxy ( bean ) ; } // determine vocab in context String classVocab = bean == null ? null : vocabFromClassOrPackage ( bean . getClass ( ) ) ; final Vocab mixinVocab = findAnnotation ( mixInClass , Vocab . class ) ; Object nestedContextProviderFromMixin = getNestedContextProviderFromMixin ( mixinSource , bean , mixInClass ) ; String contextProviderVocab = null ; if ( nestedContextProviderFromMixin != null ) { contextProviderVocab = getVocab ( mixinSource , nestedContextProviderFromMixin , null ) ; } String vocab ; if ( mixinVocab != null ) { vocab = mixinVocab . value ( ) ; // wins over class } else if ( classVocab != null ) { vocab = classVocab ; // wins over context provider } else if ( contextProviderVocab != null ) { vocab = contextProviderVocab ; // wins over last resort } else { vocab = HTTP_SCHEMA_ORG ; } return vocab ; }


Input: Gets explicitly defined terms e . g . on package class or mixin . [CODESPLIT] private Map < String , Object > getAnnotatedTerms ( AnnotatedElement annotatedElement , String name ) { final Terms annotatedTerms = findAnnotation ( annotatedElement , Terms . class ) ; final Term annotatedTerm = findAnnotation ( annotatedElement , Term . class ) ; if ( annotatedTerms != null && annotatedTerm != null ) { throw new IllegalStateException ( "found both @Terms and @Term in " + name + ", use either one or the other" ) ; } Map < String , Object > annotatedTermsMap = new LinkedHashMap < String , Object > ( ) ; if ( annotatedTerms != null ) { final Term [ ] terms = annotatedTerms . value ( ) ; for ( Term term : terms ) { collectTerms ( name , annotatedTermsMap , term ) ; } } else if ( annotatedTerm != null ) { // only one term collectTerms ( name , annotatedTermsMap , annotatedTerm ) ; } return annotatedTermsMap ; }


Input: } [CODESPLIT] @ RequestMapping ( method = RequestMethod . GET ) @ ResponseBody public ResponseEntity < Resources < Event > > findEvents ( @ RequestParam ( required = false ) String name ) { List < Event > events = assembler . toResources ( eventBackend . getEvents ( ) ) ; List < Event > matches = new ArrayList < Event > ( ) ; for ( Event event : events ) { if ( name == null || event . workPerformed . getContent ( ) . name . equals ( name ) ) { addAffordances ( event ) ; matches . add ( event ) ; } } Resources < Event > eventResources = new Resources < Event > ( matches ) ; eventResources . add ( AffordanceBuilder . linkTo ( AffordanceBuilder . methodOn ( EventController . class ) . addEvent ( new Event ( null , new CreativeWork ( null ) , null , EventStatusType . EVENT_SCHEDULED ) ) ) . withSelfRel ( ) ) ; eventResources . add ( AffordanceBuilder . linkTo ( AffordanceBuilder . methodOn ( EventController . class ) . findEvents ( null ) ) . withRel ( "hydra:search" ) ) ; return new ResponseEntity < Resources < Event > > ( eventResources , HttpStatus . OK ) ; }


Input: Query consisting of expanded parameters and unexpanded parameters . [CODESPLIT] public String getQuery ( ) { StringBuilder query = new StringBuilder ( ) ; if ( queryTail . length ( ) > 0 ) { if ( queryHead . length ( ) == 0 ) { query . append ( "{?" ) . append ( queryTail ) . append ( "}" ) ; } else if ( queryHead . length ( ) > 0 ) { query . append ( queryHead ) . append ( "{&" ) . append ( queryTail ) . append ( "}" ) ; } } else { query . append ( queryHead ) ; } return query . toString ( ) ; }


Input: Appends form and squashes non - GET or POST to POST . If required adds _method field for handling by an appropriate filter such as Spring s HiddenHttpMethodFilter . [CODESPLIT] private void appendForm ( Affordance affordance , ActionDescriptor actionDescriptor ) throws IOException { String formName = actionDescriptor . getActionName ( ) ; RequestMethod httpMethod = RequestMethod . valueOf ( actionDescriptor . getHttpMethod ( ) ) ; // Link's expand method removes non-required variables from URL String actionUrl = affordance . expand ( ) . getHref ( ) ; beginForm ( OptionalAttributes . attr ( "action" , actionUrl ) . and ( "method" , getHtmlConformingHttpMethod ( httpMethod ) ) . and ( "name" , formName ) ) ; write ( "<h4>" ) ; write ( "Form " + formName ) ; write ( "</h4>" ) ; writeHiddenHttpMethodField ( httpMethod ) ; // build the form if ( actionDescriptor . hasRequestBody ( ) ) { // parameter bean ActionInputParameter requestBody = actionDescriptor . getRequestBody ( ) ; Class < ? > parameterType = requestBody . getParameterType ( ) ; recurseBeanProperties ( parameterType , actionDescriptor , requestBody , requestBody . getValue ( ) , "" ) ; } else { // plain parameter list Collection < String > requestParams = actionDescriptor . getRequestParamNames ( ) ; for ( String requestParamName : requestParams ) { ActionInputParameter actionInputParameter = actionDescriptor . getActionInputParameter ( requestParamName ) ; Object [ ] possibleValues = actionInputParameter . getPossibleValues ( actionDescriptor ) ; // TODO duplication with appendInputOrSelect if ( possibleValues . length > 0 ) { if ( actionInputParameter . isArrayOrCollection ( ) ) { appendSelectMulti ( requestParamName , possibleValues , actionInputParameter ) ; } else { appendSelectOne ( requestParamName , possibleValues , actionInputParameter ) ; } } else { if ( actionInputParameter . isArrayOrCollection ( ) ) { // have as many inputs as there are call values, list of 5 nulls gives you five input fields // TODO support for free list input instead, code on demand? Object [ ] callValues = actionInputParameter . getValues ( ) ; int items = callValues . length ; for ( int i = 0 ; i < items ; i ++ ) { Object value ; if ( i < callValues . length ) { value = callValues [ i ] ; } else { value = null ; } appendInput ( requestParamName , actionInputParameter , value , actionInputParameter . isReadOnly ( requestParamName ) ) ; // not readonly } } else { String callValueFormatted = actionInputParameter . getValueFormatted ( ) ; appendInput ( requestParamName , actionInputParameter , callValueFormatted , actionInputParameter . isReadOnly ( requestParamName ) ) ; // not readonly } } } } inputButton ( Type . SUBMIT , capitalize ( httpMethod . name ( ) . toLowerCase ( ) ) ) ; endForm ( ) ; }


Input: Classic submit or reset button . [CODESPLIT] private void inputButton ( Type type , String value ) throws IOException { write ( "<input type=\"" ) ; write ( type . toString ( ) ) ; write ( "\" " ) ; write ( "value" ) ; write ( "=" ) ; quote ( ) ; write ( value ) ; quote ( ) ; write ( "/>" ) ; }


Input: Renders input fields for bean properties of bean to add or update or patch . [CODESPLIT] private void recurseBeanProperties ( Class < ? > beanType , ActionDescriptor actionDescriptor , ActionInputParameter actionInputParameter , Object currentCallValue , String parentParamName ) throws IOException { // TODO support Option provider by other method args? final BeanInfo beanInfo = getBeanInfo ( beanType ) ; final PropertyDescriptor [ ] propertyDescriptors = beanInfo . getPropertyDescriptors ( ) ; // TODO collection and map // TODO: do not add two inputs for setter and ctor // TODO almost duplicate of HtmlResourceMessageConverter.recursivelyCreateObject if ( RequestMethod . POST == RequestMethod . valueOf ( actionDescriptor . getHttpMethod ( ) ) ) { try { Constructor [ ] constructors = beanType . getConstructors ( ) ; // find default ctor Constructor constructor = PropertyUtils . findDefaultCtor ( constructors ) ; // find ctor with JsonCreator ann if ( constructor == null ) { constructor = PropertyUtils . findJsonCreator ( constructors , JsonCreator . class ) ; } Assert . notNull ( constructor , "no default constructor or JsonCreator found for type " + beanType . getName ( ) ) ; int parameterCount = constructor . getParameterTypes ( ) . length ; if ( parameterCount > 0 ) { Annotation [ ] [ ] annotationsOnParameters = constructor . getParameterAnnotations ( ) ; Class [ ] parameters = constructor . getParameterTypes ( ) ; int paramIndex = 0 ; for ( Annotation [ ] annotationsOnParameter : annotationsOnParameters ) { for ( Annotation annotation : annotationsOnParameter ) { if ( JsonProperty . class == annotation . annotationType ( ) ) { JsonProperty jsonProperty = ( JsonProperty ) annotation ; // TODO use required attribute of JsonProperty String paramName = jsonProperty . value ( ) ; Class parameterType = parameters [ paramIndex ] ; // TODO duplicate below for PropertyDescriptors and in appendForm if ( DataType . isSingleValueType ( parameterType ) ) { if ( actionInputParameter . isIncluded ( paramName ) ) { Object propertyValue = PropertyUtils . getPropertyOrFieldValue ( currentCallValue , paramName ) ; ActionInputParameter constructorParamInputParameter = new SpringActionInputParameter ( new MethodParameter ( constructor , paramIndex ) , propertyValue ) ; final Object [ ] possibleValues = actionInputParameter . getPossibleValues ( constructor , paramIndex , actionDescriptor ) ; appendInputOrSelect ( actionInputParameter , parentParamName + paramName , constructorParamInputParameter , possibleValues ) ; } } else if ( DataType . isArrayOrCollection ( parameterType ) ) { Object [ ] callValues = actionInputParameter . getValues ( ) ; int items = callValues . length ; for ( int i = 0 ; i < items ; i ++ ) { Object value ; if ( i < callValues . length ) { value = callValues [ i ] ; } else { value = null ; } recurseBeanProperties ( actionInputParameter . getParameterType ( ) , actionDescriptor , actionInputParameter , value , parentParamName ) ; } } else { beginDiv ( ) ; write ( paramName + ":" ) ; Object propertyValue = PropertyUtils . getPropertyOrFieldValue ( currentCallValue , paramName ) ; recurseBeanProperties ( parameterType , actionDescriptor , actionInputParameter , propertyValue , paramName + "." ) ; endDiv ( ) ; } paramIndex ++ ; // increase for each @JsonProperty } } } Assert . isTrue ( parameters . length == paramIndex , "not all constructor arguments of @JsonCreator " + constructor . getName ( ) + " are annotated with @JsonProperty" ) ; } } catch ( Exception e ) { throw new RuntimeException ( "Failed to write input fields for constructor" , e ) ; } } else { // non-POST // TODO non-writable properties and public fields: make sure the inputs are part of a form // write input field for every setter for ( PropertyDescriptor propertyDescriptor : propertyDescriptors ) { final Method writeMethod = propertyDescriptor . getWriteMethod ( ) ; if ( writeMethod == null ) { continue ; } final Class < ? > propertyType = propertyDescriptor . getPropertyType ( ) ; String propertyName = propertyDescriptor . getName ( ) ; if ( DataType . isSingleValueType ( propertyType ) ) { final Property property = new Property ( beanType , propertyDescriptor . getReadMethod ( ) , propertyDescriptor . getWriteMethod ( ) , propertyDescriptor . getName ( ) ) ; Object propertyValue = PropertyUtils . getPropertyOrFieldValue ( currentCallValue , propertyName ) ; MethodParameter methodParameter = new MethodParameter ( propertyDescriptor . getWriteMethod ( ) , 0 ) ; ActionInputParameter propertySetterInputParameter = new SpringActionInputParameter ( methodParameter , propertyValue ) ; final Object [ ] possibleValues = actionInputParameter . getPossibleValues ( propertyDescriptor . getWriteMethod ( ) , 0 , actionDescriptor ) ; appendInputOrSelect ( actionInputParameter , propertyName , propertySetterInputParameter , possibleValues ) ; } else if ( actionInputParameter . isArrayOrCollection ( ) ) { Object [ ] callValues = actionInputParameter . getValues ( ) ; int items = callValues . length ; for ( int i = 0 ; i < items ; i ++ ) { Object value ; if ( i < callValues . length ) { value = callValues [ i ] ; } else { value = null ; } recurseBeanProperties ( actionInputParameter . getParameterType ( ) , actionDescriptor , actionInputParameter , value , parentParamName ) ; } } else { beginDiv ( ) ; write ( propertyName + ":" ) ; Object propertyValue = PropertyUtils . getPropertyValue ( currentCallValue , propertyDescriptor ) ; recurseBeanProperties ( propertyType , actionDescriptor , actionInputParameter , propertyValue , parentParamName ) ; endDiv ( ) ; } } } }


Input: Appends simple input or select depending on availability of possible values . [CODESPLIT] private void appendInputOrSelect ( ActionInputParameter parentInputParameter , String paramName , ActionInputParameter childInputParameter , Object [ ] possibleValues ) throws IOException { if ( possibleValues . length > 0 ) { if ( childInputParameter . isArrayOrCollection ( ) ) { // TODO multiple formatted callvalues appendSelectMulti ( paramName , possibleValues , childInputParameter ) ; } else { appendSelectOne ( paramName , possibleValues , childInputParameter ) ; } } else { appendInput ( paramName , childInputParameter , childInputParameter . getValue ( ) , parentInputParameter . isReadOnly ( paramName ) ) ; } }


Input: Creates a new { @link AffordanceBuilder } with a base of the mapping annotated to the given controller class . The additional parameters are used to fill up potentially available path variables in the class scope request mapping . [CODESPLIT] public static AffordanceBuilder linkTo ( Class < ? > controller , Object ... parameters ) { return FACTORY . linkTo ( controller , parameters ) ; }


Input: Creates a new { @link AffordanceBuilder } with a base of the mapping annotated to the given controller class . The additional parameters are used to fill up potentially available path variables in the class scop request mapping . [CODESPLIT] public static AffordanceBuilder linkTo ( Class < ? > controller , Map < String , ? > parameters ) { return FACTORY . linkTo ( controller , parameters ) ; }


Input: Builds affordance with one or multiple rels which must have been defined previously using { @link #rel ( String ) } or { @link #reverseRel ( String String ) } . <p > The motivation for multiple rels is this statement in the web linking rfc - 5988 : &quot ; Note that link - values can convey multiple links between the same target and context IRIs ; for example : < / p > <pre > Link : &lt ; http : // example . org / &gt ; rel = start http : // example . net / relation / other < / pre > Here the link to http : // example . org / has the registered relation type start and the extension relation type http : // example . net / relation / other . &quot ; [CODESPLIT] public Affordance build ( ) { Assert . state ( ! ( rels . isEmpty ( ) && reverseRels . isEmpty ( ) ) , "no rels or reverse rels found, call rel() or rev() before building the affordance" ) ; final Affordance affordance ; affordance = new Affordance ( new PartialUriTemplate ( this . toString ( ) ) , actionDescriptors , rels . toArray ( new String [ rels . size ( ) ] ) ) ; for ( Map . Entry < String , List < String > > linkParamEntry : linkParams . entrySet ( ) ) { final List < String > values = linkParamEntry . getValue ( ) ; for ( String value : values ) { affordance . addLinkParam ( linkParamEntry . getKey ( ) , value ) ; } } for ( String reverseRel : reverseRels ) { affordance . addRev ( reverseRel ) ; } affordance . setCollectionHolder ( collectionHolder ) ; return affordance ; }


Input: Allows to define one or more reverse link relations ( a rev in terms of rfc - 5988 ) where the resource that has the affordance will be considered the object in a subject - predicate - object statement . <p > E . g . if you had a rel <code > ex : parent< / code > which connects a child to its father you could also use ex : parent on the father to point to the child by reverting the direction of ex : parent . This is mainly useful when you have no other way to express in your context that the direction of a relationship is inverted . < / p > [CODESPLIT] public AffordanceBuilder reverseRel ( String rev , String revertedRel ) { this . rels . add ( revertedRel ) ; this . reverseRels . add ( rev ) ; return this ; }


Input: Allows to define one or more reverse link relations ( a rev in terms of rfc - 5988 ) to collections in cases where the resource that has the affordance is not the object in a subject - predicate - object statement about each collection item . See { @link #rel ( TypedResource String ) } for explanation . [CODESPLIT] public AffordanceBuilder reverseRel ( String rev , String revertedRel , TypedResource object ) { this . collectionHolder = object ; this . rels . add ( 0 , revertedRel ) ; this . reverseRels . add ( rev ) ; return this ; }


Input: Allows to define one or more link relations for affordances that point to collections in cases where the resource that has the affordance is not the subject in a subject - predicate - object statement about each collection item . E . g . a product might have a loose relationship to ordered items where it can be POSTed but the ordered items do not belong to the product but to an order . You can express that by saying : <pre > TypedResource order = new TypedResource ( http : // schema . org / Order ) ; // holds the ordered items Resource&lt ; Product&gt ; product = new Resource&lt ; &gt ; () ; // has a loose relationship to ordered items product . add ( linkTo ( methodOn ( OrderController . class ) . postOrderedItem () . rel ( order orderedItem )) ; // order has ordered items not product has ordered items < / pre > If the order doesn t exist yet it cannot be identified . In that case you may pass null to express that [CODESPLIT] public AffordanceBuilder rel ( TypedResource subject , String rel ) { this . collectionHolder = subject ; this . rels . add ( rel ) ; return this ; }


Input: Allows to define link header params ( not UriTemplate variables ) . [CODESPLIT] public AffordanceBuilder withLinkParam ( String name , String value ) { this . linkParams . add ( name , value ) ; return this ; }


Input: Returns a { @link UriComponentsBuilder } obtained from the current servlet mapping with scheme tweaked in case the request contains an { @code X - Forwarded - Ssl } header which is not ( yet ) supported by the underlying { @link UriComponentsBuilder } . If no { @link RequestContextHolder } exists ( you re outside a Spring Web call ) fall back to relative URIs . [CODESPLIT] static UriComponentsBuilder getBuilder ( ) { if ( RequestContextHolder . getRequestAttributes ( ) == null ) { return UriComponentsBuilder . fromPath ( "/" ) ; } HttpServletRequest request = getCurrentRequest ( ) ; UriComponentsBuilder builder = ServletUriComponentsBuilder . fromServletMapping ( request ) ; // special case handling for X-Forwarded-Ssl: // apply it, but only if X-Forwarded-Proto is unset. String forwardedSsl = request . getHeader ( "X-Forwarded-Ssl" ) ; ForwardedHeader forwarded = ForwardedHeader . of ( request . getHeader ( ForwardedHeader . NAME ) ) ; String proto = hasText ( forwarded . getProto ( ) ) ? forwarded . getProto ( ) : request . getHeader ( "X-Forwarded-Proto" ) ; if ( ! hasText ( proto ) && hasText ( forwardedSsl ) && forwardedSsl . equalsIgnoreCase ( "on" ) ) { builder . scheme ( "https" ) ; } return builder ; }


Input: Copy of { @link ServletUriComponentsBuilder#getCurrentRequest () } until SPR - 10110 gets fixed . [CODESPLIT] private static HttpServletRequest getCurrentRequest ( ) { RequestAttributes requestAttributes = RequestContextHolder . getRequestAttributes ( ) ; Assert . state ( requestAttributes != null , "Could not find current request via RequestContextHolder" ) ; Assert . isInstanceOf ( ServletRequestAttributes . class , requestAttributes ) ; HttpServletRequest servletRequest = ( ( ServletRequestAttributes ) requestAttributes ) . getRequest ( ) ; Assert . state ( servletRequest != null , "Could not find current HttpServletRequest" ) ; return servletRequest ; }


Input: Adds actionDescriptors of the given AffordanceBuilder to this affordanceBuilder . [CODESPLIT] public AffordanceBuilder and ( AffordanceBuilder affordanceBuilder ) { for ( ActionDescriptor actionDescriptor : affordanceBuilder . actionDescriptors ) { this . actionDescriptors . add ( actionDescriptor ) ; } return this ; }


Input: Returns the template as uri components without variable expansion . [CODESPLIT] public PartialUriTemplateComponents asComponents ( ) { return getUriTemplateComponents ( Collections . < String , Object > emptyMap ( ) , Collections . < String > emptyList ( ) ) ; }


Input: Expands the template using given parameters [CODESPLIT] public PartialUriTemplateComponents expand ( Object ... parameters ) { List < String > variableNames = getVariableNames ( ) ; Map < String , Object > parameterMap = new LinkedHashMap < String , Object > ( ) ; int i = 0 ; for ( String variableName : variableNames ) { if ( i < parameters . length ) { parameterMap . put ( variableName , parameters [ i ++ ] ) ; } else { break ; } } return getUriTemplateComponents ( parameterMap , Collections . < String > emptyList ( ) ) ; }


Input: Expands the template using given parameters [CODESPLIT] public PartialUriTemplateComponents expand ( Map < String , ? > parameters ) { return getUriTemplateComponents ( parameters , Collections . < String > emptyList ( ) ) ; }


Input: Applies parameters to template variables . [CODESPLIT] private PartialUriTemplateComponents getUriTemplateComponents ( Map < String , ? > parameters , List < String > requiredArgs ) { Assert . notNull ( parameters , "Parameters must not be null!" ) ; final StringBuilder baseUrl = new StringBuilder ( urlComponents . get ( 0 ) ) ; final StringBuilder queryHead = new StringBuilder ( ) ; final StringBuilder queryTail = new StringBuilder ( ) ; final StringBuilder fragmentIdentifier = new StringBuilder ( ) ; for ( int i = 1 ; i < urlComponents . size ( ) ; i ++ ) { final String part = urlComponents . get ( i ) ; final List < Integer > variablesInPart = variableIndices . get ( i ) ; if ( variablesInPart . isEmpty ( ) ) { if ( part . startsWith ( "?" ) || part . startsWith ( "&" ) ) { queryHead . append ( part ) ; } else if ( part . startsWith ( "#" ) ) { fragmentIdentifier . append ( part ) ; } else { baseUrl . append ( part ) ; } } else { for ( Integer variableInPart : variablesInPart ) { final TemplateVariable variable = variables . get ( variableInPart ) ; final Object value = parameters . get ( variable . getName ( ) ) ; if ( value == null ) { switch ( variable . getType ( ) ) { case REQUEST_PARAM : case REQUEST_PARAM_CONTINUED : if ( requiredArgs . isEmpty ( ) || requiredArgs . contains ( variable . getName ( ) ) ) { // query vars without value always go last (query tail) if ( queryTail . length ( ) > 0 ) { queryTail . append ( ' ' ) ; } queryTail . append ( variable . getName ( ) ) ; } break ; case FRAGMENT : fragmentIdentifier . append ( variable . toString ( ) ) ; break ; case PATH_VARIABLE : if ( queryHead . length ( ) != 0 ) { // level 1 variable in query queryHead . append ( variable . toString ( ) ) ; } else { baseUrl . append ( variable . toString ( ) ) ; } break ; case SEGMENT : baseUrl . append ( variable . toString ( ) ) ; } } else { switch ( variable . getType ( ) ) { case REQUEST_PARAM : case REQUEST_PARAM_CONTINUED : if ( queryHead . length ( ) == 0 ) { queryHead . append ( ' ' ) ; } else { queryHead . append ( ' ' ) ; } queryHead . append ( variable . getName ( ) ) . append ( ' ' ) . append ( urlEncode ( value . toString ( ) ) ) ; break ; case SEGMENT : baseUrl . append ( ' ' ) ; // fall through case PATH_VARIABLE : if ( queryHead . length ( ) != 0 ) { // level 1 variable in query queryHead . append ( urlEncode ( value . toString ( ) ) ) ; } else { baseUrl . append ( urlEncode ( value . toString ( ) ) ) ; } break ; case FRAGMENT : fragmentIdentifier . append ( ' ' ) ; fragmentIdentifier . append ( urlEncode ( value . toString ( ) ) ) ; break ; } } } } } return new PartialUriTemplateComponents ( baseUrl . toString ( ) , queryHead . toString ( ) , queryTail . toString ( ) , fragmentIdentifier . toString ( ) , variableNames ) ; }


Input: Strips all variables which are not required by any of the given action descriptors . If no action descriptors are given nothing will be stripped . [CODESPLIT] public PartialUriTemplateComponents stripOptionalVariables ( List < ActionDescriptor > actionDescriptors ) { return getUriTemplateComponents ( Collections . < String , Object > emptyMap ( ) , getRequiredArgNames ( actionDescriptors ) ) ; }


Input: Gets first child of this uber node having the given name attribute . [CODESPLIT] public UberNode getFirstByName ( String name ) { // TODO consider less naive impl UberNode ret = null ; for ( UberNode node : data ) { if ( name . equals ( node . getName ( ) ) ) { ret = node ; break ; } } return ret ; }


Input: Gets first child of this uber node having the given rel attribute . [CODESPLIT] public UberNode getFirstByRel ( String rel ) { // TODO consider less naive impl for ( UberNode node : data ) { List < String > myRels = node . getRel ( ) ; if ( myRels != null ) { for ( String myRel : myRels ) { if ( rel . equals ( myRel ) ) { return node ; } } } } return null ; }


Input: Allows iterating over children of this uber node which have a data attribute . [CODESPLIT] @ Override public Iterator < UberNode > iterator ( ) { return new Iterator < UberNode > ( ) { int index = 0 ; @ Override public void remove ( ) { throw new UnsupportedOperationException ( "removing from uber node is not supported" ) ; } @ Override public UberNode next ( ) { index = findNextChildWithData ( ) ; return data . get ( index ++ ) ; } @ Override public boolean hasNext ( ) { return findNextChildWithData ( ) != - 1 ; } private int findNextChildWithData ( ) { for ( int i = index ; i < data . size ( ) ; i ++ ) { if ( ! data . get ( i ) . getData ( ) . isEmpty ( ) ) { return i ; } } return - 1 ; } } ; }


Input: Works around some type inference limitations of Java 8 . [CODESPLIT] public static < E > MutableHashSet < E > emptyMutable ( Equator < E > eq ) { return empty ( eq ) . mutable ( ) ; }


Input: Returns a new PersistentHashSet of the values . The vararg version of this method is { @link org . organicdesign . fp . StaticImports#set ( Object ... ) } If the input contains duplicate elements later values overwrite earlier ones . [CODESPLIT] public static < E > PersistentHashSet < E > of ( Iterable < E > elements ) { PersistentHashSet < E > empty = empty ( ) ; MutableSet < E > ret = empty . mutable ( ) ; for ( E e : elements ) { ret . put ( e ) ; } return ( PersistentHashSet < E > ) ret . immutable ( ) ; }


Input: Works around some type inference limitations of Java 8 . [CODESPLIT] public static < K , V > MutableHashMap < K , V > emptyMutable ( ) { return PersistentHashMap . < K , V > empty ( ) . mutable ( ) ; }


Input: Works around some type inference limitations of Java 8 . [CODESPLIT] public static < K , V > MutableHashMap < K , V > emptyMutable ( Equator < K > e ) { return PersistentHashMap . < K , V > empty ( e ) . mutable ( ) ; }


Input: Returns a new PersistentHashMap of the given keys and their paired values skipping any null Entries . [CODESPLIT] @ SuppressWarnings ( "WeakerAccess" ) public static < K , V > PersistentHashMap < K , V > ofEq ( Equator < K > eq , Iterable < Map . Entry < K , V > > es ) { if ( es == null ) { return empty ( eq ) ; } MutableHashMap < K , V > map = emptyMutable ( eq ) ; for ( Map . Entry < K , V > entry : es ) { if ( entry != null ) { map . assoc ( entry . getKey ( ) , entry . getValue ( ) ) ; } } return map . immutable ( ) ; }


Input: Returns a new PersistentHashMap of the given keys and their paired values . There is also a varargs version of this method : { @link org . organicdesign . fp . StaticImports#map ( Map . Entry ... ) } . Use the { @link org . organicdesign . fp . StaticImports#tup ( Object Object ) } method to define key / value pairs briefly and easily . [CODESPLIT] public static < K , V > PersistentHashMap < K , V > of ( Iterable < Map . Entry < K , V > > kvPairs ) { if ( kvPairs == null ) { return empty ( ) ; } PersistentHashMap < K , V > m = empty ( ) ; MutableHashMap < K , V > map = m . mutable ( ) ; for ( Map . Entry < K , V > entry : kvPairs ) { if ( entry != null ) { map . assoc ( entry . getKey ( ) , entry . getValue ( ) ) ; } } return map . immutable ( ) ; }


Input: / * public static void main ( String [] args ) { try { ArrayList words = new ArrayList () ; Scanner s = new Scanner ( new File ( args [ 0 ] )) ; s . useDelimiter ( Pattern . compile ( \\ W )) ; while ( s . hasNext () ) { String word = s . next () ; words . add ( word ) ; } System . out . println ( words : + words . size () ) ; ImMap map = PersistentHashMap . EMPTY ; ImMap map = new PersistentHashMap () ; Map ht = new Hashtable () ; Map ht = new HashMap () ; Random rand ; [CODESPLIT] private static < K , V > INode < K , V > [ ] cloneAndSet ( INode < K , V > [ ] array , int i , INode < K , V > a ) { INode < K , V > [ ] clone = array . clone ( ) ; clone [ i ] = a ; return clone ; }


Input: } [CODESPLIT] public static String ordinal ( final int origI ) { final int i = ( origI < 0 ) ? - origI : origI ; final int modTen = i % 10 ; if ( ( modTen < 4 ) && ( modTen > 0 ) ) { int modHundred = i % 100 ; if ( ( modHundred < 21 ) && ( modHundred > 3 ) ) { return Integer . toString ( origI ) + "th" ; } switch ( modTen ) { case 1 : return Integer . toString ( origI ) + "st" ; case 2 : return Integer . toString ( origI ) + "nd" ; case 3 : return Integer . toString ( origI ) + "rd" ; } } return Integer . toString ( origI ) + "th" ; }


Input: Returns a new PersistentTreeMap of the given comparable keys and their paired values skipping any null Entries . [CODESPLIT] public static < K extends Comparable < K > , V > PersistentTreeMap < K , V > of ( Iterable < Map . Entry < K , V > > es ) { if ( es == null ) { return empty ( ) ; } PersistentTreeMap < K , V > map = new PersistentTreeMap <> ( Equator . defaultComparator ( ) , null , 0 ) ; for ( Map . Entry < K , V > entry : es ) { if ( entry != null ) { map = map . assoc ( entry . getKey ( ) , entry . getValue ( ) ) ; } } return map ; }


Input: Returns a new PersistentTreeMap of the specified comparator and the given key / value pairs . [CODESPLIT] public static < K , V > PersistentTreeMap < K , V > ofComp ( Comparator < ? super K > comp , Iterable < Map . Entry < K , V > > kvPairs ) { if ( kvPairs == null ) { return new PersistentTreeMap <> ( comp , null , 0 ) ; } PersistentTreeMap < K , V > map = new PersistentTreeMap <> ( comp , null , 0 ) ; for ( Map . Entry < K , V > entry : kvPairs ) { if ( entry != null ) { map = map . assoc ( entry . getKey ( ) , entry . getValue ( ) ) ; } } return map ; }


Input: Be extremely careful with this because it uses the default comparator which only works for items that implement Comparable ( have a natural ordering ) . An attempt to use it with other items will blow up at runtime . Either a withComparator () method will be added or this will be removed . [CODESPLIT] @ SuppressWarnings ( "unchecked" ) public static < K extends Comparable < K > , V > PersistentTreeMap < K , V > empty ( ) { return ( PersistentTreeMap < K , V > ) EMPTY ; }


Input: Returns a new empty PersistentTreeMap that will use the specified comparator . [CODESPLIT] public static < K , V > PersistentTreeMap < K , V > empty ( Comparator < ? super K > c ) { return new PersistentTreeMap <> ( c , null , 0 ) ; }


Input: Returns a view of the mappings contained in this map . The set should actually contain UnmodMap . UnEntry items but that return signature is illegal in Java so you ll just have to remember . [CODESPLIT] @ Override public ImSortedSet < Entry < K , V > > entrySet ( ) { // This is the pretty way to do it. return this . fold ( PersistentTreeSet . ofComp ( new KeyComparator <> ( comp ) ) , PersistentTreeSet :: put ) ; }


Input: { [CODESPLIT] @ Override public ImSortedMap < K , V > subMap ( K fromKey , K toKey ) { int diff = comp . compare ( fromKey , toKey ) ; if ( diff > 0 ) { throw new IllegalArgumentException ( "fromKey is greater than toKey" ) ; } UnEntry < K , V > last = last ( ) ; K lastKey = last . getKey ( ) ; int compFromKeyLastKey = comp . compare ( fromKey , lastKey ) ; // If no intersect, return empty. We aren't checking the toKey vs. the firstKey() because // that's a single pass through the iterator loop which is probably as cheap as checking // here. if ( ( diff == 0 ) || ( compFromKeyLastKey > 0 ) ) { return new PersistentTreeMap <> ( comp , null , 0 ) ; } // If map is entirely contained, just return it. if ( ( comp . compare ( fromKey , firstKey ( ) ) <= 0 ) && ( comp . compare ( toKey , lastKey ) > 0 ) ) { return this ; } // Don't iterate through entire map for only the last item. if ( compFromKeyLastKey == 0 ) { return ofComp ( comp , Collections . singletonList ( last ) ) ; } ImSortedMap < K , V > ret = new PersistentTreeMap <> ( comp , null , 0 ) ; UnmodIterator < UnEntry < K , V > > iter = this . iterator ( ) ; while ( iter . hasNext ( ) ) { UnEntry < K , V > next = iter . next ( ) ; K key = next . getKey ( ) ; if ( comp . compare ( toKey , key ) <= 0 ) { break ; } if ( comp . compare ( fromKey , key ) > 0 ) { continue ; } ret = ret . assoc ( key , next . getValue ( ) ) ; } return ret ; }


Input: { [CODESPLIT] @ Override public Option < UnEntry < K , V > > head ( ) { Node < K , V > t = tree ; if ( t != null ) { while ( t . left ( ) != null ) { t = t . left ( ) ; } } return Option . some ( t ) ; }


Input: Returns the comparator used to order the keys in this map or null if it uses Fn2 . DEFAULT_COMPARATOR ( for compatibility with java . util . SortedMap ) . [CODESPLIT] @ Override public Comparator < ? super K > comparator ( ) { return ( comp == Equator . Comp . DEFAULT ) ? null : comp ; }


Input: { [CODESPLIT] @ Override public PersistentTreeMap < K , V > assoc ( K key , V val ) { Box < Node < K , V > > found = new Box <> ( null ) ; Node < K , V > t = add ( tree , key , val , found ) ; //null == already contains key if ( t == null ) { Node < K , V > foundNode = found . val ; //note only get same collection on identity of val, not equals() if ( foundNode . getValue ( ) == val ) { return this ; } return new PersistentTreeMap <> ( comp , replace ( tree , key , val ) , size ) ; } return new PersistentTreeMap <> ( comp , t . blacken ( ) , size + 1 ) ; }


Input: { [CODESPLIT] @ Override public PersistentTreeMap < K , V > without ( K key ) { Box < Node < K , V > > found = new Box <> ( null ) ; Node < K , V > t = remove ( tree , key , found ) ; if ( t == null ) { //null == doesn't contain key if ( found . val == null ) { return this ; } //empty return new PersistentTreeMap <> ( comp , null , 0 ) ; } return new PersistentTreeMap <> ( comp , t . blacken ( ) , size - 1 ) ; }


Input: Returns the last key in this map or throws a NoSuchElementException if the map is empty . [CODESPLIT] @ Override public K lastKey ( ) { UnEntry < K , V > max = last ( ) ; if ( max == null ) { throw new NoSuchElementException ( "this map is empty" ) ; } return max . getKey ( ) ; }


Input: Returns the last key / value pair in this map or null if the map is empty . [CODESPLIT] public UnEntry < K , V > last ( ) { Node < K , V > t = tree ; if ( t != null ) { while ( t . right ( ) != null ) t = t . right ( ) ; } return t ; }


Input: Returns an Option of the key / value pair matching the given key or Option . none () if the key is not found . [CODESPLIT] @ Override public Option < UnmodMap . UnEntry < K , V > > entry ( K key ) { Node < K , V > t = tree ; while ( t != null ) { int c = comp . compare ( key , t . getKey ( ) ) ; if ( c == 0 ) return Option . some ( t ) ; else if ( c < 0 ) t = t . left ( ) ; else t = t . right ( ) ; } return Option . none ( ) ; // t; // t is always null }


Input: } [CODESPLIT] private Node < K , V > add ( Node < K , V > t , K key , V val , Box < Node < K , V > > found ) { if ( t == null ) { //            if (val == null) //                return new Red<>(key); return new Red <> ( key , val ) ; } int c = comp . compare ( key , t . getKey ( ) ) ; if ( c == 0 ) { found . val = t ; return null ; } Node < K , V > ins = add ( c < 0 ? t . left ( ) : t . right ( ) , key , val , found ) ; if ( ins == null ) //found below return null ; if ( c < 0 ) return t . addLeft ( ins ) ; return t . addRight ( ins ) ; }


Input: Node<K V > concat ( Node<K1 V1 > left Node<K2 V2 > right ) { [CODESPLIT] @ SuppressWarnings ( "unchecked" ) private static < K , V > Node < K , V > append ( Node < ? extends K , ? extends V > left , Node < ? extends K , ? extends V > right ) { if ( left == null ) return ( Node < K , V > ) right ; else if ( right == null ) return ( Node < K , V > ) left ; else if ( left instanceof PersistentTreeMap . Red ) { if ( right instanceof PersistentTreeMap . Red ) { Node < K , V > app = append ( left . right ( ) , right . left ( ) ) ; if ( app instanceof PersistentTreeMap . Red ) return red ( app . getKey ( ) , app . getValue ( ) , red ( left . getKey ( ) , left . getValue ( ) , left . left ( ) , app . left ( ) ) , red ( right . getKey ( ) , right . getValue ( ) , app . right ( ) , right . right ( ) ) ) ; else return red ( left . getKey ( ) , left . getValue ( ) , left . left ( ) , red ( right . getKey ( ) , right . getValue ( ) , app , right . right ( ) ) ) ; } else return red ( left . getKey ( ) , left . getValue ( ) , left . left ( ) , append ( left . right ( ) , right ) ) ; } else if ( right instanceof PersistentTreeMap . Red ) return red ( right . getKey ( ) , right . getValue ( ) , append ( left , right . left ( ) ) , right . right ( ) ) ; else //black/black { Node < K , V > app = append ( left . right ( ) , right . left ( ) ) ; if ( app instanceof PersistentTreeMap . Red ) return red ( app . getKey ( ) , app . getValue ( ) , black ( left . getKey ( ) , left . getValue ( ) , left . left ( ) , app . left ( ) ) , black ( right . getKey ( ) , right . getValue ( ) , app . right ( ) , right . right ( ) ) ) ; else return balanceLeftDel ( left . getKey ( ) , left . getValue ( ) , left . left ( ) , black ( right . getKey ( ) , right . getValue ( ) , app , right . right ( ) ) ) ; } }


Input: Static factory methods [CODESPLIT] public static < T > Xform < T > of ( Iterable < ? extends T > list ) { if ( list == null ) { return empty ( ) ; } return new SourceProviderIterableDesc <> ( list ) ; }


Input: than lazily evaluated and cached linked - list Sequence model . [CODESPLIT] @ SuppressWarnings ( "unchecked" ) private static < H > H _fold ( Iterable source , Operation [ ] ops , int opIdx , H ident , Fn2 reducer ) { Object ret = ident ; // This is a label - the first one I have used in Java in years, or maybe ever. // I'm assuming this is fast, but will have to test to confirm it. sourceLoop : for ( Object o : source ) { for ( int j = opIdx ; j < ops . length ; j ++ ) { Operation op = ops [ j ] ; if ( ( op . filter != null ) && ! op . filter . apply ( o ) ) { // stop processing this source item and go to the next one. continue sourceLoop ; } if ( op . map != null ) { o = op . map . apply ( o ) ; // This is how map can handle takeWhile, take, and other termination marker // roles.  Remember, the fewer functions we have to check for, the faster this // will execute. if ( o == TERMINATE ) { return ( H ) ret ; } } else if ( op . flatMap != null ) { ret = _fold ( op . flatMap . apply ( o ) , ops , j + 1 , ( H ) ret , reducer ) ; // stop processing this source item and go to the next one. continue sourceLoop ; } //                    if ( (op.terminate != null) && op.terminate.apply(o) ) { //                        return (G) ret; //                    } } // Here, the item made it through all the operations.  Combine it with the result. ret = reducer . apply ( ret , o ) ; } return ( H ) ret ; }


Input: } [CODESPLIT] @ Override public Xform < A > concat ( Iterable < ? extends A > list ) { if ( list == null ) { throw new IllegalArgumentException ( "Can't concat a null iterable" ) ; } return new AppendIterDesc <> ( this , new SourceProviderIterableDesc <> ( list ) ) ; }


Input: } [CODESPLIT] @ Override public Xform < A > precat ( Iterable < ? extends A > list ) { if ( list == null ) { throw new IllegalArgumentException ( "Can't precat a null iterable" ) ; } return new AppendIterDesc <> ( of ( list ) , this ) ; }


Input: The number of items to drop from the beginning of the output . [CODESPLIT] @ Override public Xform < A > dropWhile ( Fn1 < ? super A , Boolean > predicate ) { if ( predicate == null ) { throw new IllegalArgumentException ( "Can't dropWhile without a function." ) ; } return new DropWhileDesc <> ( this , predicate ) ; }


Input: Provides a way to collect the results of the transformation . [CODESPLIT] @ Override public < B > B fold ( B ident , Fn2 < ? super B , ? super A , B > reducer ) { if ( reducer == null ) { throw new IllegalArgumentException ( "Can't fold with a null reduction function." ) ; } // Construct an optimized array of OpRuns (mutable operations for this run) RunList runList = toRunList ( ) ; return _fold ( runList , runList . opArray ( ) , 0 , ident , reducer ) ; }


Input: Thit implementation should be correct but could be slow in the case where previous operations are slow and the terminateWhen operation is fast and terminates early . It actually renders items to a mutable List then runs through the list performing the requested reduction checking for early termination on the result . If you can to a takeWhile () or take () earlier in the transform chain instead of doing it here always do that . If you really need early termination based on the * result * of a fold and the operations are expensive or the input is huge try using a View instead . If you don t care about those things then this method is perfect for you . [CODESPLIT] @ Override public < G , B > Or < G , B > foldUntil ( G accum , Fn2 < ? super G , ? super A , B > terminator , Fn2 < ? super G , ? super A , G > reducer ) { if ( terminator == null ) { return Or . good ( fold ( accum , reducer ) ) ; } if ( reducer == null ) { throw new IllegalArgumentException ( "Can't fold with a null reduction function." ) ; } // Yes, this is a cheap plastic imitation of what you'd hope for if you really need this // method.  The trouble is that when I implemented it correctly in _fold, I found // it was going to be incredibly difficult, or more likely impossible to implement // when the previous operation was flatMap, since you don't have the right result type to // check against when you recurse in to the flat mapping function, and if you check the // return from the recursion, it may have too many elements already. // In XformTest.java, there's something marked "Early termination test" that illustrates // this exact problem. List < A > as = this . toMutableList ( ) ; for ( A a : as ) { B term = terminator . apply ( accum , a ) ; if ( term != null ) { return Or . bad ( term ) ; } accum = reducer . apply ( accum , a ) ; } return Or . good ( accum ) ; }


Input: Returns a new PersistentTreeSet of the given comparator . Always use this instead of starting with empty () because there is no way to assign a comparator to an existing set . [CODESPLIT] public static < T > PersistentTreeSet < T > ofComp ( Comparator < ? super T > comp ) { return new PersistentTreeSet <> ( PersistentTreeMap . empty ( comp ) ) ; }


Input: Returns a new PersistentTreeSet of the given comparator and items . [CODESPLIT] public static < T > PersistentTreeSet < T > ofComp ( Comparator < ? super T > comp , Iterable < T > elements ) { PersistentTreeSet < T > ret = new PersistentTreeSet <> ( PersistentTreeMap . empty ( comp ) ) ; if ( elements == null ) { return ret ; } for ( T element : elements ) { ret = ret . put ( element ) ; } return ret ; }


Input: Returns a new PersistentTreeSet of the given comparable items . [CODESPLIT] public static < T extends Comparable < T > > PersistentTreeSet < T > of ( Iterable < T > items ) { // empty() uses default comparator if ( items == null ) { return empty ( ) ; } PersistentTreeSet < T > ret = empty ( ) ; for ( T item : items ) { ret = ret . put ( item ) ; } return ret ; }


Input: { [CODESPLIT] @ Override public PersistentTreeSet < E > without ( E key ) { return ( impl . containsKey ( key ) ) ? new PersistentTreeSet <> ( impl . without ( key ) ) : this ; }


Input: { [CODESPLIT] @ Override public UnmodSortedIterator < E > iterator ( ) { return new UnmodSortedIterator < E > ( ) { UnmodSortedIterator < ? extends UnmodMap . UnEntry < E , ? > > iter = impl . iterator ( ) ; @ Override public boolean hasNext ( ) { return iter . hasNext ( ) ; } @ Override public E next ( ) { UnmodMap . UnEntry < E , ? > e = iter . next ( ) ; return e == null ? null : e . getKey ( ) ; } } ; }


Input: { [CODESPLIT] @ Override public Option < E > head ( ) { return size ( ) > 0 ? Option . some ( impl . firstKey ( ) ) : Option . none ( ) ; }


Input: { [CODESPLIT] @ Override public PersistentTreeSet < E > put ( E e ) { return ( impl . containsKey ( e ) ) ? this : new PersistentTreeSet <> ( impl . assoc ( e , null ) ) ; }


Input: { [CODESPLIT] @ Override public ImSortedSet < E > subSet ( E fromElement , E toElement ) { return PersistentTreeSet . ofMap ( impl . subMap ( fromElement , toElement ) ) ; }


Input: { [CODESPLIT] @ Override public ImSortedSet < E > tailSet ( E fromElement ) { return PersistentTreeSet . ofMap ( impl . tailMap ( fromElement ) ) ; }


Input: { [CODESPLIT] @ Override public < U > U match ( Fn1 < T , U > has , Fn0 < U > hasNot ) { return hasNot . get ( ) ; }


Input: Public static factory method [CODESPLIT] public static < A , B > Tuple2 < A , B > of ( A a , B b ) { return new Tuple2 <> ( a , b ) ; }


Input: Map . Entry factory method [CODESPLIT] public static < K , V > Tuple2 < K , V > of ( Map . Entry < K , V > entry ) { // Protect against multiple-instantiation if ( entry instanceof Tuple2 ) { return ( Tuple2 < K , V > ) entry ; } return new Tuple2 <> ( entry . getKey ( ) , entry . getValue ( ) ) ; }


Input: Returns a new RrbTree minus the given item ( all items to the right are shifted left one ) This is O ( log n ) . [CODESPLIT] public RrbTree < E > without ( int index ) { if ( ( index > 0 ) && ( index < size ( ) - 1 ) ) { Tuple2 < ? extends RrbTree < E > , ? extends RrbTree < E > > s1 = split ( index ) ; Tuple2 < ? extends RrbTree < E > , ? extends RrbTree < E > > s2 = s1 . _2 ( ) . split ( 1 ) ; return s1 . _1 ( ) . join ( s2 . _2 ( ) ) ; } else if ( index == 0 ) { return split ( 1 ) . _2 ( ) ; } else if ( index == size ( ) - 1 ) { return split ( size ( ) - 1 ) . _1 ( ) ; } else { throw new IndexOutOfBoundsException ( "Failed test: 0 <= index < size" ) ; } }


Input: Helper function to avoid type warnings . [CODESPLIT] @ SuppressWarnings ( "unchecked" ) private static < T > Node < T > [ ] genericNodeArray ( int size ) { return ( Node < T > [ ] ) new Node < ? > [ size ] ; }


Input: =============================== Debugging and pretty - printing =============================== [CODESPLIT] private static StringBuilder showSubNodes ( StringBuilder sB , Object [ ] items , int nextIndent ) { boolean isFirst = true ; for ( Object n : items ) { if ( isFirst ) { isFirst = false ; } else { //                sB.append(" "); if ( items [ 0 ] instanceof Leaf ) { sB . append ( " " ) ; } else { sB . append ( "\n" ) . append ( indentSpace ( nextIndent ) ) ; } } sB . append ( ( ( Node ) n ) . indentedStr ( nextIndent ) ) ; } return sB ; }


Input: If sel is managed correctly it ensures that the cast is accurate . [CODESPLIT] @ SuppressWarnings ( "unchecked" ) public < R > R match ( Fn1 < A , R > fa , Fn1 < B , R > fb , Fn1 < C , R > fc ) { if ( sel == 0 ) { return fa . apply ( ( A ) item ) ; } else if ( sel == 1 ) { return fb . apply ( ( B ) item ) ; } else { return fc . apply ( ( C ) item ) ; } }


Input: } [CODESPLIT] public static RangeOfInt of ( Number s , Number e ) { if ( ( s == null ) || ( e == null ) ) { throw new IllegalArgumentException ( "Nulls not allowed" ) ; } if ( e . longValue ( ) < s . longValue ( ) ) { throw new IllegalArgumentException ( "end of range must be >= start of range" ) ; } return new RangeOfInt ( s . intValue ( ) , e . intValue ( ) ) ; }


Input: Though this overrides List . contains ( Object o ) it is effectively a convenience method for calling contains ( int i ) . Therefore it only accepts Integers Longs BigIntegers and Strings that parse as signed decimal Integers . It does not accept Numbers since they can t easily be checked for truncation and floating - point might not round properly with respect to bounds or might not make sense if you are using your range to define a set of integers . Handles truncation ( returns false ) for the types it accepts . Throws exceptions for types it does not accept . [CODESPLIT] @ SuppressWarnings ( "deprecation" ) @ Override public boolean contains ( Object o ) { // Only accept classes where we can convert to an integer while preventing // overflow/underflow.  If there were a way to reliably test for overflow/underflow in // Numbers, we could accept them too, but with the rounding errors of floats and doubles // that's impractical. if ( o instanceof Integer ) { return contains ( ( ( Integer ) o ) . intValue ( ) ) ; } else if ( o instanceof Long ) { long l = ( Long ) o ; return ( l <= ( ( long ) Integer . MAX_VALUE ) ) && ( l >= ( ( long ) Integer . MIN_VALUE ) ) && contains ( ( int ) l ) ; } else if ( o instanceof BigInteger ) { try { // Throws an exception if it's more than 32 bits. return contains ( ( ( BigInteger ) o ) . intValueExact ( ) ) ; } catch ( ArithmeticException ignore ) { return false ; } } else if ( o instanceof String ) { return contains ( Integer . valueOf ( ( String ) o ) ) ; } else { throw new IllegalArgumentException ( "Don't know how to convert to a primitive int" + " without risking accidental truncation.  Pass an" + " Integer, Long, BigInteger, or String that parses" + " within Integer bounds instead." ) ; } }


Input: Unlike most implementations of List this method has excellent O ( 1 ) performance! { [CODESPLIT] @ Override public int indexOf ( Object o ) { if ( o instanceof Number ) { int i = ( ( Number ) o ) . intValue ( ) ; if ( ( i >= start ) && ( i < end ) ) { return i - start ; } } return - 1 ; }


Input: { [CODESPLIT] @ Override public UnmodListIterator < Integer > listIterator ( final int startIdx ) { if ( ( startIdx < 0 ) || ( startIdx > size ) ) { // To match ArrayList and other java.util.List expectations throw new IndexOutOfBoundsException ( "Index: " + startIdx ) ; } return new UnmodListIterator < Integer > ( ) { int val = start + startIdx ; @ Override public boolean hasNext ( ) { return val < end ; } @ Override public Integer next ( ) { if ( val >= end ) { // To match ArrayList and other java.util.List expectations throw new NoSuchElementException ( ) ; } Integer t = val ; val = val + 1 ; return t ; } @ Override public boolean hasPrevious ( ) { return val > start ; } @ Override public Integer previous ( ) { if ( val <= start ) { // To match ArrayList and other java.util.List expectations throw new NoSuchElementException ( ) ; } val = val - 1 ; return val ; } @ Override public int nextIndex ( ) { return val - start ; } } ; }


Input: { [CODESPLIT] @ Override public RangeOfInt subList ( int fromIndex , int toIndex ) { if ( ( fromIndex == 0 ) && ( toIndex == size ) ) { return this ; } // Note that this is an IllegalArgumentException, not IndexOutOfBoundsException in order to // match ArrayList. if ( fromIndex > toIndex ) { throw new IllegalArgumentException ( "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")" ) ; } // The text of this matches ArrayList if ( fromIndex < 0 ) { throw new IndexOutOfBoundsException ( "fromIndex = " + fromIndex ) ; } if ( toIndex > size ) { throw new IndexOutOfBoundsException ( "toIndex = " + toIndex ) ; } // Look very closely at the second parameter because the bounds checking is *different* // from the get() method.  get(toIndex) can throw an exception if toIndex >= start+size. // But since a range is exclusive of it's right-bound, we can create a new sub-range // with a right bound index of size, as opposed to size minus 1.  I spent hours // understanding this before fixing a bug with it.  In the end, subList should do the same // thing on a Range that it does on the equivalent ArrayList.  I made tests for the same. return RangeOfInt . of ( start + fromIndex , start + toIndex ) ; }