001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.soap;
018
019import static org.apache.juneau.collections.JsonMap.*;
020
021import java.lang.annotation.*;
022import java.nio.charset.*;
023import java.util.*;
024import java.util.concurrent.*;
025
026import org.apache.juneau.*;
027import org.apache.juneau.collections.*;
028import org.apache.juneau.internal.*;
029import org.apache.juneau.utils.*;
030import org.apache.juneau.xml.*;
031
032/**
033 * Serializes POJOs to HTTP responses as XML+SOAP.
034 *
035 * <h5 class='topic'>Media types</h5>
036 *
037 * Handles <c>Accept</c> types:  <bc>text/xml+soap</bc>
038 * <p>
039 * Produces <c>Content-Type</c> types:  <bc>text/xml+soap</bc>
040 *
041 * <h5 class='topic'>Description</h5>
042 *
043 * Essentially the same output as {@link XmlDocSerializer}, except wrapped in a standard SOAP envelope.
044 *
045 * <h5 class='section'>Notes:</h5><ul>
046 *    <li class='note'>This class is thread safe and reusable.
047 * </ul>
048 *
049 * <h5 class='section'>See Also:</h5><ul>
050
051 * </ul>
052 */
053public class SoapXmlSerializer extends XmlSerializer implements SoapXmlMetaProvider {
054
055   //-------------------------------------------------------------------------------------------------------------------
056   // Static
057   //-------------------------------------------------------------------------------------------------------------------
058
059   /**
060    * Creates a new builder for this object.
061    *
062    * @return A new builder.
063    */
064   public static Builder create() {
065      return new Builder();
066   }
067
068   //-------------------------------------------------------------------------------------------------------------------
069   // Builder
070   //-------------------------------------------------------------------------------------------------------------------
071
072   /**
073    * Builder class.
074    */
075   public static class Builder extends XmlSerializer.Builder {
076
077      private static final Cache<HashKey,SoapXmlSerializer> CACHE = Cache.of(HashKey.class, SoapXmlSerializer.class).build();
078
079      String soapAction;
080
081      /**
082       * Constructor, default settings.
083       */
084      protected Builder() {
085         produces("text/xml");
086         accept("text/xml+soap");
087         soapAction = "http://www.w3.org/2003/05/soap-envelope";
088      }
089
090      /**
091       * Copy constructor.
092       *
093       * @param copyFrom The bean to copy from.
094       */
095      protected Builder(SoapXmlSerializer copyFrom) {
096         super(copyFrom);
097         soapAction = copyFrom.soapAction;
098      }
099
100      /**
101       * Copy constructor.
102       *
103       * @param copyFrom The builder to copy from.
104       */
105      protected Builder(Builder copyFrom) {
106         super(copyFrom);
107         soapAction = copyFrom.soapAction;
108      }
109
110      @Override /* Context.Builder */
111      public Builder copy() {
112         return new Builder(this);
113      }
114
115      @Override /* Context.Builder */
116      public SoapXmlSerializer build() {
117         return cache(CACHE).build(SoapXmlSerializer.class);
118      }
119
120      @Override /* Context.Builder */
121      public HashKey hashKey() {
122         return HashKey.of(
123            super.hashKey(),
124            soapAction
125         );
126      }
127
128      //-----------------------------------------------------------------------------------------------------------------
129      // Properties
130      //-----------------------------------------------------------------------------------------------------------------
131
132      /**
133       * The <c>SOAPAction</c> HTTP header value to set on responses.
134       *
135       * @param value
136       *    The new value for this property.
137       *    <br>The default is <js>"http://www.w3.org/2003/05/soap-envelope"</js>.
138       * @return This object.
139       */
140      public Builder soapAction(String value) {
141         soapAction = value;
142         return this;
143      }
144      @Override /* Overridden from Builder */
145      public Builder annotations(Annotation...values) {
146         super.annotations(values);
147         return this;
148      }
149
150      @Override /* Overridden from Builder */
151      public Builder apply(AnnotationWorkList work) {
152         super.apply(work);
153         return this;
154      }
155
156      @Override /* Overridden from Builder */
157      public Builder applyAnnotations(Object...from) {
158         super.applyAnnotations(from);
159         return this;
160      }
161
162      @Override /* Overridden from Builder */
163      public Builder applyAnnotations(Class<?>...from) {
164         super.applyAnnotations(from);
165         return this;
166      }
167
168      @Override /* Overridden from Builder */
169      public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
170         super.cache(value);
171         return this;
172      }
173
174      @Override /* Overridden from Builder */
175      public Builder debug() {
176         super.debug();
177         return this;
178      }
179
180      @Override /* Overridden from Builder */
181      public Builder debug(boolean value) {
182         super.debug(value);
183         return this;
184      }
185
186      @Override /* Overridden from Builder */
187      public Builder impl(Context value) {
188         super.impl(value);
189         return this;
190      }
191
192      @Override /* Overridden from Builder */
193      public Builder type(Class<? extends org.apache.juneau.Context> value) {
194         super.type(value);
195         return this;
196      }
197
198      @Override /* Overridden from Builder */
199      public Builder beanClassVisibility(Visibility value) {
200         super.beanClassVisibility(value);
201         return this;
202      }
203
204      @Override /* Overridden from Builder */
205      public Builder beanConstructorVisibility(Visibility value) {
206         super.beanConstructorVisibility(value);
207         return this;
208      }
209
210      @Override /* Overridden from Builder */
211      public Builder beanContext(BeanContext value) {
212         super.beanContext(value);
213         return this;
214      }
215
216      @Override /* Overridden from Builder */
217      public Builder beanContext(BeanContext.Builder value) {
218         super.beanContext(value);
219         return this;
220      }
221
222      @Override /* Overridden from Builder */
223      public Builder beanDictionary(java.lang.Class<?>...values) {
224         super.beanDictionary(values);
225         return this;
226      }
227
228      @Override /* Overridden from Builder */
229      public Builder beanFieldVisibility(Visibility value) {
230         super.beanFieldVisibility(value);
231         return this;
232      }
233
234      @Override /* Overridden from Builder */
235      public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) {
236         super.beanInterceptor(on, value);
237         return this;
238      }
239
240      @Override /* Overridden from Builder */
241      public Builder beanMapPutReturnsOldValue() {
242         super.beanMapPutReturnsOldValue();
243         return this;
244      }
245
246      @Override /* Overridden from Builder */
247      public Builder beanMethodVisibility(Visibility value) {
248         super.beanMethodVisibility(value);
249         return this;
250      }
251
252      @Override /* Overridden from Builder */
253      public Builder beanProperties(Map<String,Object> values) {
254         super.beanProperties(values);
255         return this;
256      }
257
258      @Override /* Overridden from Builder */
259      public Builder beanProperties(Class<?> beanClass, String properties) {
260         super.beanProperties(beanClass, properties);
261         return this;
262      }
263
264      @Override /* Overridden from Builder */
265      public Builder beanProperties(String beanClassName, String properties) {
266         super.beanProperties(beanClassName, properties);
267         return this;
268      }
269
270      @Override /* Overridden from Builder */
271      public Builder beanPropertiesExcludes(Map<String,Object> values) {
272         super.beanPropertiesExcludes(values);
273         return this;
274      }
275
276      @Override /* Overridden from Builder */
277      public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) {
278         super.beanPropertiesExcludes(beanClass, properties);
279         return this;
280      }
281
282      @Override /* Overridden from Builder */
283      public Builder beanPropertiesExcludes(String beanClassName, String properties) {
284         super.beanPropertiesExcludes(beanClassName, properties);
285         return this;
286      }
287
288      @Override /* Overridden from Builder */
289      public Builder beanPropertiesReadOnly(Map<String,Object> values) {
290         super.beanPropertiesReadOnly(values);
291         return this;
292      }
293
294      @Override /* Overridden from Builder */
295      public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) {
296         super.beanPropertiesReadOnly(beanClass, properties);
297         return this;
298      }
299
300      @Override /* Overridden from Builder */
301      public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
302         super.beanPropertiesReadOnly(beanClassName, properties);
303         return this;
304      }
305
306      @Override /* Overridden from Builder */
307      public Builder beanPropertiesWriteOnly(Map<String,Object> values) {
308         super.beanPropertiesWriteOnly(values);
309         return this;
310      }
311
312      @Override /* Overridden from Builder */
313      public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) {
314         super.beanPropertiesWriteOnly(beanClass, properties);
315         return this;
316      }
317
318      @Override /* Overridden from Builder */
319      public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
320         super.beanPropertiesWriteOnly(beanClassName, properties);
321         return this;
322      }
323
324      @Override /* Overridden from Builder */
325      public Builder beansRequireDefaultConstructor() {
326         super.beansRequireDefaultConstructor();
327         return this;
328      }
329
330      @Override /* Overridden from Builder */
331      public Builder beansRequireSerializable() {
332         super.beansRequireSerializable();
333         return this;
334      }
335
336      @Override /* Overridden from Builder */
337      public Builder beansRequireSettersForGetters() {
338         super.beansRequireSettersForGetters();
339         return this;
340      }
341
342      @Override /* Overridden from Builder */
343      public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) {
344         super.dictionaryOn(on, values);
345         return this;
346      }
347
348      @Override /* Overridden from Builder */
349      public Builder disableBeansRequireSomeProperties() {
350         super.disableBeansRequireSomeProperties();
351         return this;
352      }
353
354      @Override /* Overridden from Builder */
355      public Builder disableIgnoreMissingSetters() {
356         super.disableIgnoreMissingSetters();
357         return this;
358      }
359
360      @Override /* Overridden from Builder */
361      public Builder disableIgnoreTransientFields() {
362         super.disableIgnoreTransientFields();
363         return this;
364      }
365
366      @Override /* Overridden from Builder */
367      public Builder disableIgnoreUnknownNullBeanProperties() {
368         super.disableIgnoreUnknownNullBeanProperties();
369         return this;
370      }
371
372      @Override /* Overridden from Builder */
373      public Builder disableInterfaceProxies() {
374         super.disableInterfaceProxies();
375         return this;
376      }
377
378      @Override /* Overridden from Builder */
379      public <T> Builder example(Class<T> pojoClass, T o) {
380         super.example(pojoClass, o);
381         return this;
382      }
383
384      @Override /* Overridden from Builder */
385      public <T> Builder example(Class<T> pojoClass, String json) {
386         super.example(pojoClass, json);
387         return this;
388      }
389
390      @Override /* Overridden from Builder */
391      public Builder findFluentSetters() {
392         super.findFluentSetters();
393         return this;
394      }
395
396      @Override /* Overridden from Builder */
397      public Builder findFluentSetters(Class<?> on) {
398         super.findFluentSetters(on);
399         return this;
400      }
401
402      @Override /* Overridden from Builder */
403      public Builder ignoreInvocationExceptionsOnGetters() {
404         super.ignoreInvocationExceptionsOnGetters();
405         return this;
406      }
407
408      @Override /* Overridden from Builder */
409      public Builder ignoreInvocationExceptionsOnSetters() {
410         super.ignoreInvocationExceptionsOnSetters();
411         return this;
412      }
413
414      @Override /* Overridden from Builder */
415      public Builder ignoreUnknownBeanProperties() {
416         super.ignoreUnknownBeanProperties();
417         return this;
418      }
419
420      @Override /* Overridden from Builder */
421      public Builder ignoreUnknownEnumValues() {
422         super.ignoreUnknownEnumValues();
423         return this;
424      }
425
426      @Override /* Overridden from Builder */
427      public Builder implClass(Class<?> interfaceClass, Class<?> implClass) {
428         super.implClass(interfaceClass, implClass);
429         return this;
430      }
431
432      @Override /* Overridden from Builder */
433      public Builder implClasses(Map<Class<?>,Class<?>> values) {
434         super.implClasses(values);
435         return this;
436      }
437
438      @Override /* Overridden from Builder */
439      public Builder interfaceClass(Class<?> on, Class<?> value) {
440         super.interfaceClass(on, value);
441         return this;
442      }
443
444      @Override /* Overridden from Builder */
445      public Builder interfaces(java.lang.Class<?>...value) {
446         super.interfaces(value);
447         return this;
448      }
449
450      @Override /* Overridden from Builder */
451      public Builder locale(Locale value) {
452         super.locale(value);
453         return this;
454      }
455
456      @Override /* Overridden from Builder */
457      public Builder mediaType(MediaType value) {
458         super.mediaType(value);
459         return this;
460      }
461
462      @Override /* Overridden from Builder */
463      public Builder notBeanClasses(java.lang.Class<?>...values) {
464         super.notBeanClasses(values);
465         return this;
466      }
467
468      @Override /* Overridden from Builder */
469      public Builder notBeanPackages(String...values) {
470         super.notBeanPackages(values);
471         return this;
472      }
473
474      @Override /* Overridden from Builder */
475      public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) {
476         super.propertyNamer(value);
477         return this;
478      }
479
480      @Override /* Overridden from Builder */
481      public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) {
482         super.propertyNamer(on, value);
483         return this;
484      }
485
486      @Override /* Overridden from Builder */
487      public Builder sortProperties() {
488         super.sortProperties();
489         return this;
490      }
491
492      @Override /* Overridden from Builder */
493      public Builder sortProperties(java.lang.Class<?>...on) {
494         super.sortProperties(on);
495         return this;
496      }
497
498      @Override /* Overridden from Builder */
499      public Builder stopClass(Class<?> on, Class<?> value) {
500         super.stopClass(on, value);
501         return this;
502      }
503
504      @Override /* Overridden from Builder */
505      public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) {
506         super.swap(normalClass, swappedClass, swapFunction);
507         return this;
508      }
509
510      @Override /* Overridden from Builder */
511      public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) {
512         super.swap(normalClass, swappedClass, swapFunction, unswapFunction);
513         return this;
514      }
515
516      @Override /* Overridden from Builder */
517      public Builder swaps(Object...values) {
518         super.swaps(values);
519         return this;
520      }
521
522      @Override /* Overridden from Builder */
523      public Builder swaps(Class<?>...values) {
524         super.swaps(values);
525         return this;
526      }
527
528      @Override /* Overridden from Builder */
529      public Builder timeZone(TimeZone value) {
530         super.timeZone(value);
531         return this;
532      }
533
534      @Override /* Overridden from Builder */
535      public Builder typeName(Class<?> on, String value) {
536         super.typeName(on, value);
537         return this;
538      }
539
540      @Override /* Overridden from Builder */
541      public Builder typePropertyName(String value) {
542         super.typePropertyName(value);
543         return this;
544      }
545
546      @Override /* Overridden from Builder */
547      public Builder typePropertyName(Class<?> on, String value) {
548         super.typePropertyName(on, value);
549         return this;
550      }
551
552      @Override /* Overridden from Builder */
553      public Builder useEnumNames() {
554         super.useEnumNames();
555         return this;
556      }
557
558      @Override /* Overridden from Builder */
559      public Builder useJavaBeanIntrospector() {
560         super.useJavaBeanIntrospector();
561         return this;
562      }
563
564      @Override /* Overridden from Builder */
565      public Builder detectRecursions() {
566         super.detectRecursions();
567         return this;
568      }
569
570      @Override /* Overridden from Builder */
571      public Builder detectRecursions(boolean value) {
572         super.detectRecursions(value);
573         return this;
574      }
575
576      @Override /* Overridden from Builder */
577      public Builder ignoreRecursions() {
578         super.ignoreRecursions();
579         return this;
580      }
581
582      @Override /* Overridden from Builder */
583      public Builder ignoreRecursions(boolean value) {
584         super.ignoreRecursions(value);
585         return this;
586      }
587
588      @Override /* Overridden from Builder */
589      public Builder initialDepth(int value) {
590         super.initialDepth(value);
591         return this;
592      }
593
594      @Override /* Overridden from Builder */
595      public Builder maxDepth(int value) {
596         super.maxDepth(value);
597         return this;
598      }
599
600      @Override /* Overridden from Builder */
601      public Builder accept(String value) {
602         super.accept(value);
603         return this;
604      }
605
606      @Override /* Overridden from Builder */
607      public Builder addBeanTypes() {
608         super.addBeanTypes();
609         return this;
610      }
611
612      @Override /* Overridden from Builder */
613      public Builder addBeanTypes(boolean value) {
614         super.addBeanTypes(value);
615         return this;
616      }
617
618      @Override /* Overridden from Builder */
619      public Builder addRootType() {
620         super.addRootType();
621         return this;
622      }
623
624      @Override /* Overridden from Builder */
625      public Builder addRootType(boolean value) {
626         super.addRootType(value);
627         return this;
628      }
629
630      @Override /* Overridden from Builder */
631      public Builder keepNullProperties() {
632         super.keepNullProperties();
633         return this;
634      }
635
636      @Override /* Overridden from Builder */
637      public Builder keepNullProperties(boolean value) {
638         super.keepNullProperties(value);
639         return this;
640      }
641
642      @Override /* Overridden from Builder */
643      public Builder listener(Class<? extends org.apache.juneau.serializer.SerializerListener> value) {
644         super.listener(value);
645         return this;
646      }
647
648      @Override /* Overridden from Builder */
649      public Builder produces(String value) {
650         super.produces(value);
651         return this;
652      }
653
654      @Override /* Overridden from Builder */
655      public Builder sortCollections() {
656         super.sortCollections();
657         return this;
658      }
659
660      @Override /* Overridden from Builder */
661      public Builder sortCollections(boolean value) {
662         super.sortCollections(value);
663         return this;
664      }
665
666      @Override /* Overridden from Builder */
667      public Builder sortMaps() {
668         super.sortMaps();
669         return this;
670      }
671
672      @Override /* Overridden from Builder */
673      public Builder sortMaps(boolean value) {
674         super.sortMaps(value);
675         return this;
676      }
677
678      @Override /* Overridden from Builder */
679      public Builder trimEmptyCollections() {
680         super.trimEmptyCollections();
681         return this;
682      }
683
684      @Override /* Overridden from Builder */
685      public Builder trimEmptyCollections(boolean value) {
686         super.trimEmptyCollections(value);
687         return this;
688      }
689
690      @Override /* Overridden from Builder */
691      public Builder trimEmptyMaps() {
692         super.trimEmptyMaps();
693         return this;
694      }
695
696      @Override /* Overridden from Builder */
697      public Builder trimEmptyMaps(boolean value) {
698         super.trimEmptyMaps(value);
699         return this;
700      }
701
702      @Override /* Overridden from Builder */
703      public Builder trimStrings() {
704         super.trimStrings();
705         return this;
706      }
707
708      @Override /* Overridden from Builder */
709      public Builder trimStrings(boolean value) {
710         super.trimStrings(value);
711         return this;
712      }
713
714      @Override /* Overridden from Builder */
715      public Builder uriContext(UriContext value) {
716         super.uriContext(value);
717         return this;
718      }
719
720      @Override /* Overridden from Builder */
721      public Builder uriRelativity(UriRelativity value) {
722         super.uriRelativity(value);
723         return this;
724      }
725
726      @Override /* Overridden from Builder */
727      public Builder uriResolution(UriResolution value) {
728         super.uriResolution(value);
729         return this;
730      }
731
732      @Override /* Overridden from Builder */
733      public Builder fileCharset(Charset value) {
734         super.fileCharset(value);
735         return this;
736      }
737
738      @Override /* Overridden from Builder */
739      public Builder maxIndent(int value) {
740         super.maxIndent(value);
741         return this;
742      }
743
744      @Override /* Overridden from Builder */
745      public Builder quoteChar(char value) {
746         super.quoteChar(value);
747         return this;
748      }
749
750      @Override /* Overridden from Builder */
751      public Builder quoteCharOverride(char value) {
752         super.quoteCharOverride(value);
753         return this;
754      }
755
756      @Override /* Overridden from Builder */
757      public Builder sq() {
758         super.sq();
759         return this;
760      }
761
762      @Override /* Overridden from Builder */
763      public Builder streamCharset(Charset value) {
764         super.streamCharset(value);
765         return this;
766      }
767
768      @Override /* Overridden from Builder */
769      public Builder useWhitespace() {
770         super.useWhitespace();
771         return this;
772      }
773
774      @Override /* Overridden from Builder */
775      public Builder useWhitespace(boolean value) {
776         super.useWhitespace(value);
777         return this;
778      }
779
780      @Override /* Overridden from Builder */
781      public Builder ws() {
782         super.ws();
783         return this;
784      }
785
786      @Override /* Overridden from Builder */
787      public Builder addBeanTypesXml() {
788         super.addBeanTypesXml();
789         return this;
790      }
791
792      @Override /* Overridden from Builder */
793      public Builder addBeanTypesXml(boolean value) {
794         super.addBeanTypesXml(value);
795         return this;
796      }
797
798      @Override /* Overridden from Builder */
799      public Builder addNamespaceUrisToRoot() {
800         super.addNamespaceUrisToRoot();
801         return this;
802      }
803
804      @Override /* Overridden from Builder */
805      public Builder addNamespaceUrisToRoot(boolean value) {
806         super.addNamespaceUrisToRoot(value);
807         return this;
808      }
809
810      @Override /* Overridden from Builder */
811      public Builder defaultNamespace(Namespace value) {
812         super.defaultNamespace(value);
813         return this;
814      }
815
816      @Override /* Overridden from Builder */
817      public Builder disableAutoDetectNamespaces() {
818         super.disableAutoDetectNamespaces();
819         return this;
820      }
821
822      @Override /* Overridden from Builder */
823      public Builder disableAutoDetectNamespaces(boolean value) {
824         super.disableAutoDetectNamespaces(value);
825         return this;
826      }
827
828      @Override /* Overridden from Builder */
829      public Builder enableNamespaces() {
830         super.enableNamespaces();
831         return this;
832      }
833
834      @Override /* Overridden from Builder */
835      public Builder enableNamespaces(boolean value) {
836         super.enableNamespaces(value);
837         return this;
838      }
839
840      @Override /* Overridden from Builder */
841      public Builder namespaces(Namespace...values) {
842         super.namespaces(values);
843         return this;
844      }
845
846      @Override /* Overridden from Builder */
847      public Builder ns() {
848         super.ns();
849         return this;
850      }
851   }
852
853   //-------------------------------------------------------------------------------------------------------------------
854   // Instance
855   //-------------------------------------------------------------------------------------------------------------------
856
857   final String soapAction;
858
859   private final Map<ClassMeta<?>,SoapXmlClassMeta> soapXmlClassMetas = new ConcurrentHashMap<>();
860   private final Map<BeanPropertyMeta,SoapXmlBeanPropertyMeta> soapXmlBeanPropertyMetas = new ConcurrentHashMap<>();
861
862   /**
863    * Constructor.
864    *
865    * @param builder The builder for this object.
866    */
867   public SoapXmlSerializer(Builder builder) {
868      super(builder);
869      soapAction = builder.soapAction;
870   }
871
872   @Override /* Context */
873   public Builder copy() {
874      return new Builder(this);
875   }
876
877   @Override /* Context */
878   public SoapXmlSerializerSession.Builder createSession() {
879      return SoapXmlSerializerSession.create(this);
880   }
881
882   @Override /* Context */
883   public SoapXmlSerializerSession getSession() {
884      return createSession().build();
885   }
886
887   //-----------------------------------------------------------------------------------------------------------------
888   // Extended metadata
889   //-----------------------------------------------------------------------------------------------------------------
890
891   @Override /* SoapXmlMetaProvider */
892   public SoapXmlClassMeta getSoapXmlClassMeta(ClassMeta<?> cm) {
893      SoapXmlClassMeta m = soapXmlClassMetas.get(cm);
894      if (m == null) {
895         m = new SoapXmlClassMeta(cm, this);
896         soapXmlClassMetas.put(cm, m);
897      }
898      return m;
899   }
900
901   @Override /* SoapXmlMetaProvider */
902   public SoapXmlBeanPropertyMeta getSoapXmlBeanPropertyMeta(BeanPropertyMeta bpm) {
903      if (bpm == null)
904         return SoapXmlBeanPropertyMeta.DEFAULT;
905      SoapXmlBeanPropertyMeta m = soapXmlBeanPropertyMetas.get(bpm);
906      if (m == null) {
907         m = new SoapXmlBeanPropertyMeta(bpm.getDelegateFor(), this);
908         soapXmlBeanPropertyMetas.put(bpm, m);
909      }
910      return m;
911   }
912
913   //-----------------------------------------------------------------------------------------------------------------
914   // Properties
915   //-----------------------------------------------------------------------------------------------------------------
916
917   /**
918    * The SOAPAction HTTP header value to set on responses.
919    *
920    * @see Builder#soapAction(String)
921    * @return
922    *    The SOAPAction HTTP header value to set on responses.
923    */
924   public String getSoapAction() {
925      return soapAction;
926   }
927
928   //-----------------------------------------------------------------------------------------------------------------
929   // Other methods
930   //-----------------------------------------------------------------------------------------------------------------
931
932   @Override /* Context */
933   protected JsonMap properties() {
934      return filteredMap("soapAction", soapAction);
935   }
936}