001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.html;
014
015import java.lang.annotation.*;
016import java.lang.reflect.*;
017import java.nio.charset.*;
018import java.util.*;
019import java.util.concurrent.*;
020
021import org.apache.juneau.*;
022import org.apache.juneau.internal.*;
023import org.apache.juneau.utils.*;
024import org.apache.juneau.xml.*;
025
026/**
027 * Parses text generated by the {@link HtmlSerializer} class back into a POJO model.
028 *
029 * <h5 class='topic'>Media types</h5>
030 *
031 * Handles <c>Content-Type</c> types:  <bc>text/html</bc>
032 *
033 * <h5 class='topic'>Description</h5>
034 *
035 * See the {@link HtmlSerializer} class for a description of the HTML generated.
036 * <p>
037 * This class is used primarily for automated testing of the {@link HtmlSerializer} class.
038 *
039 * <h5 class='section'>Notes:</h5><ul>
040 *    <li class='note'>This class is thread safe and reusable.
041 * </ul>
042 *
043 * <h5 class='section'>See Also:</h5><ul>
044 *    <li class='link'><a class="doclink" href="../../../../index.html#jm.HtmlDetails">HTML Details</a>
045
046 * </ul>
047 */
048public class HtmlParser extends XmlParser implements HtmlMetaProvider {
049
050   //-------------------------------------------------------------------------------------------------------------------
051   // Static
052   //-------------------------------------------------------------------------------------------------------------------
053
054   /** Default parser, all default settings.*/
055   public static final HtmlParser DEFAULT = new HtmlParser(create());
056
057   /**
058    * Creates a new builder for this object.
059    *
060    * @return A new builder.
061    */
062   public static Builder create() {
063      return new Builder();
064   }
065
066   //-------------------------------------------------------------------------------------------------------------------
067   // Builder
068   //-------------------------------------------------------------------------------------------------------------------
069
070   /**
071    * Builder class.
072    */
073   @FluentSetters
074   public static class Builder extends XmlParser.Builder {
075
076      private static final Cache<HashKey,HtmlParser> CACHE = Cache.of(HashKey.class, HtmlParser.class).build();
077
078      /**
079       * Constructor, default settings.
080       */
081      protected Builder() {
082         consumes("text/html,text/html+stripped");
083      }
084
085      /**
086       * Copy constructor.
087       *
088       * @param copyFrom The bean to copy from.
089       */
090      protected Builder(HtmlParser copyFrom) {
091         super(copyFrom);
092      }
093
094      /**
095       * Copy constructor.
096       *
097       * @param copyFrom The builder to copy from.
098       */
099      protected Builder(Builder copyFrom) {
100         super(copyFrom);
101      }
102
103      @Override /* Context.Builder */
104      public Builder copy() {
105         return new Builder(this);
106      }
107
108      @Override /* Context.Builder */
109      public HtmlParser build() {
110         return cache(CACHE).build(HtmlParser.class);
111      }
112
113      @Override /* Context.Builder */
114      public HashKey hashKey() {
115         return super.hashKey();
116      }
117
118      //-----------------------------------------------------------------------------------------------------------------
119      // Properties
120      //-----------------------------------------------------------------------------------------------------------------
121
122      // <FluentSetters>
123
124      @Override /* GENERATED - org.apache.juneau.Context.Builder */
125      public Builder annotations(Annotation...values) {
126         super.annotations(values);
127         return this;
128      }
129
130      @Override /* GENERATED - org.apache.juneau.Context.Builder */
131      public Builder apply(AnnotationWorkList work) {
132         super.apply(work);
133         return this;
134      }
135
136      @Override /* GENERATED - org.apache.juneau.Context.Builder */
137      public Builder applyAnnotations(java.lang.Class<?>...fromClasses) {
138         super.applyAnnotations(fromClasses);
139         return this;
140      }
141
142      @Override /* GENERATED - org.apache.juneau.Context.Builder */
143      public Builder applyAnnotations(Method...fromMethods) {
144         super.applyAnnotations(fromMethods);
145         return this;
146      }
147
148      @Override /* GENERATED - org.apache.juneau.Context.Builder */
149      public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
150         super.cache(value);
151         return this;
152      }
153
154      @Override /* GENERATED - org.apache.juneau.Context.Builder */
155      public Builder debug() {
156         super.debug();
157         return this;
158      }
159
160      @Override /* GENERATED - org.apache.juneau.Context.Builder */
161      public Builder debug(boolean value) {
162         super.debug(value);
163         return this;
164      }
165
166      @Override /* GENERATED - org.apache.juneau.Context.Builder */
167      public Builder impl(Context value) {
168         super.impl(value);
169         return this;
170      }
171
172      @Override /* GENERATED - org.apache.juneau.Context.Builder */
173      public Builder type(Class<? extends org.apache.juneau.Context> value) {
174         super.type(value);
175         return this;
176      }
177
178      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
179      public Builder beanClassVisibility(Visibility value) {
180         super.beanClassVisibility(value);
181         return this;
182      }
183
184      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
185      public Builder beanConstructorVisibility(Visibility value) {
186         super.beanConstructorVisibility(value);
187         return this;
188      }
189
190      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
191      public Builder beanContext(BeanContext value) {
192         super.beanContext(value);
193         return this;
194      }
195
196      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
197      public Builder beanContext(BeanContext.Builder value) {
198         super.beanContext(value);
199         return this;
200      }
201
202      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
203      public Builder beanDictionary(java.lang.Class<?>...values) {
204         super.beanDictionary(values);
205         return this;
206      }
207
208      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
209      public Builder beanFieldVisibility(Visibility value) {
210         super.beanFieldVisibility(value);
211         return this;
212      }
213
214      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
215      public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) {
216         super.beanInterceptor(on, value);
217         return this;
218      }
219
220      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
221      public Builder beanMapPutReturnsOldValue() {
222         super.beanMapPutReturnsOldValue();
223         return this;
224      }
225
226      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
227      public Builder beanMethodVisibility(Visibility value) {
228         super.beanMethodVisibility(value);
229         return this;
230      }
231
232      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
233      public Builder beanProperties(Map<String,Object> values) {
234         super.beanProperties(values);
235         return this;
236      }
237
238      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
239      public Builder beanProperties(Class<?> beanClass, String properties) {
240         super.beanProperties(beanClass, properties);
241         return this;
242      }
243
244      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
245      public Builder beanProperties(String beanClassName, String properties) {
246         super.beanProperties(beanClassName, properties);
247         return this;
248      }
249
250      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
251      public Builder beanPropertiesExcludes(Map<String,Object> values) {
252         super.beanPropertiesExcludes(values);
253         return this;
254      }
255
256      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
257      public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) {
258         super.beanPropertiesExcludes(beanClass, properties);
259         return this;
260      }
261
262      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
263      public Builder beanPropertiesExcludes(String beanClassName, String properties) {
264         super.beanPropertiesExcludes(beanClassName, properties);
265         return this;
266      }
267
268      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
269      public Builder beanPropertiesReadOnly(Map<String,Object> values) {
270         super.beanPropertiesReadOnly(values);
271         return this;
272      }
273
274      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
275      public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) {
276         super.beanPropertiesReadOnly(beanClass, properties);
277         return this;
278      }
279
280      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
281      public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
282         super.beanPropertiesReadOnly(beanClassName, properties);
283         return this;
284      }
285
286      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
287      public Builder beanPropertiesWriteOnly(Map<String,Object> values) {
288         super.beanPropertiesWriteOnly(values);
289         return this;
290      }
291
292      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
293      public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) {
294         super.beanPropertiesWriteOnly(beanClass, properties);
295         return this;
296      }
297
298      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
299      public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
300         super.beanPropertiesWriteOnly(beanClassName, properties);
301         return this;
302      }
303
304      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
305      public Builder beansRequireDefaultConstructor() {
306         super.beansRequireDefaultConstructor();
307         return this;
308      }
309
310      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
311      public Builder beansRequireSerializable() {
312         super.beansRequireSerializable();
313         return this;
314      }
315
316      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
317      public Builder beansRequireSettersForGetters() {
318         super.beansRequireSettersForGetters();
319         return this;
320      }
321
322      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
323      public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) {
324         super.dictionaryOn(on, values);
325         return this;
326      }
327
328      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
329      public Builder disableBeansRequireSomeProperties() {
330         super.disableBeansRequireSomeProperties();
331         return this;
332      }
333
334      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
335      public Builder disableIgnoreMissingSetters() {
336         super.disableIgnoreMissingSetters();
337         return this;
338      }
339
340      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
341      public Builder disableIgnoreTransientFields() {
342         super.disableIgnoreTransientFields();
343         return this;
344      }
345
346      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
347      public Builder disableIgnoreUnknownNullBeanProperties() {
348         super.disableIgnoreUnknownNullBeanProperties();
349         return this;
350      }
351
352      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
353      public Builder disableInterfaceProxies() {
354         super.disableInterfaceProxies();
355         return this;
356      }
357
358      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
359      public <T> Builder example(Class<T> pojoClass, T o) {
360         super.example(pojoClass, o);
361         return this;
362      }
363
364      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
365      public <T> Builder example(Class<T> pojoClass, String json) {
366         super.example(pojoClass, json);
367         return this;
368      }
369
370      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
371      public Builder findFluentSetters() {
372         super.findFluentSetters();
373         return this;
374      }
375
376      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
377      public Builder findFluentSetters(Class<?> on) {
378         super.findFluentSetters(on);
379         return this;
380      }
381
382      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
383      public Builder ignoreInvocationExceptionsOnGetters() {
384         super.ignoreInvocationExceptionsOnGetters();
385         return this;
386      }
387
388      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
389      public Builder ignoreInvocationExceptionsOnSetters() {
390         super.ignoreInvocationExceptionsOnSetters();
391         return this;
392      }
393
394      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
395      public Builder ignoreUnknownBeanProperties() {
396         super.ignoreUnknownBeanProperties();
397         return this;
398      }
399
400      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
401      public Builder ignoreUnknownEnumValues() {
402         super.ignoreUnknownEnumValues();
403         return this;
404      }
405
406      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
407      public Builder implClass(Class<?> interfaceClass, Class<?> implClass) {
408         super.implClass(interfaceClass, implClass);
409         return this;
410      }
411
412      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
413      public Builder implClasses(Map<Class<?>,Class<?>> values) {
414         super.implClasses(values);
415         return this;
416      }
417
418      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
419      public Builder interfaceClass(Class<?> on, Class<?> value) {
420         super.interfaceClass(on, value);
421         return this;
422      }
423
424      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
425      public Builder interfaces(java.lang.Class<?>...value) {
426         super.interfaces(value);
427         return this;
428      }
429
430      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
431      public Builder locale(Locale value) {
432         super.locale(value);
433         return this;
434      }
435
436      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
437      public Builder mediaType(MediaType value) {
438         super.mediaType(value);
439         return this;
440      }
441
442      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
443      public Builder notBeanClasses(java.lang.Class<?>...values) {
444         super.notBeanClasses(values);
445         return this;
446      }
447
448      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
449      public Builder notBeanPackages(String...values) {
450         super.notBeanPackages(values);
451         return this;
452      }
453
454      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
455      public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) {
456         super.propertyNamer(value);
457         return this;
458      }
459
460      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
461      public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) {
462         super.propertyNamer(on, value);
463         return this;
464      }
465
466      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
467      public Builder sortProperties() {
468         super.sortProperties();
469         return this;
470      }
471
472      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
473      public Builder sortProperties(java.lang.Class<?>...on) {
474         super.sortProperties(on);
475         return this;
476      }
477
478      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
479      public Builder stopClass(Class<?> on, Class<?> value) {
480         super.stopClass(on, value);
481         return this;
482      }
483
484      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
485      public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) {
486         super.swap(normalClass, swappedClass, swapFunction);
487         return this;
488      }
489
490      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
491      public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) {
492         super.swap(normalClass, swappedClass, swapFunction, unswapFunction);
493         return this;
494      }
495
496      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
497      public Builder swaps(java.lang.Class<?>...values) {
498         super.swaps(values);
499         return this;
500      }
501
502      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
503      public Builder timeZone(TimeZone value) {
504         super.timeZone(value);
505         return this;
506      }
507
508      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
509      public Builder typeName(Class<?> on, String value) {
510         super.typeName(on, value);
511         return this;
512      }
513
514      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
515      public Builder typePropertyName(String value) {
516         super.typePropertyName(value);
517         return this;
518      }
519
520      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
521      public Builder typePropertyName(Class<?> on, String value) {
522         super.typePropertyName(on, value);
523         return this;
524      }
525
526      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
527      public Builder useEnumNames() {
528         super.useEnumNames();
529         return this;
530      }
531
532      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
533      public Builder useJavaBeanIntrospector() {
534         super.useJavaBeanIntrospector();
535         return this;
536      }
537
538      @Override /* GENERATED - org.apache.juneau.parser.Parser.Builder */
539      public Builder autoCloseStreams() {
540         super.autoCloseStreams();
541         return this;
542      }
543
544      @Override /* GENERATED - org.apache.juneau.parser.Parser.Builder */
545      public Builder autoCloseStreams(boolean value) {
546         super.autoCloseStreams(value);
547         return this;
548      }
549
550      @Override /* GENERATED - org.apache.juneau.parser.Parser.Builder */
551      public Builder consumes(String value) {
552         super.consumes(value);
553         return this;
554      }
555
556      @Override /* GENERATED - org.apache.juneau.parser.Parser.Builder */
557      public Builder debugOutputLines(int value) {
558         super.debugOutputLines(value);
559         return this;
560      }
561
562      @Override /* GENERATED - org.apache.juneau.parser.Parser.Builder */
563      public Builder listener(Class<? extends org.apache.juneau.parser.ParserListener> value) {
564         super.listener(value);
565         return this;
566      }
567
568      @Override /* GENERATED - org.apache.juneau.parser.Parser.Builder */
569      public Builder strict() {
570         super.strict();
571         return this;
572      }
573
574      @Override /* GENERATED - org.apache.juneau.parser.Parser.Builder */
575      public Builder strict(boolean value) {
576         super.strict(value);
577         return this;
578      }
579
580      @Override /* GENERATED - org.apache.juneau.parser.Parser.Builder */
581      public Builder trimStrings() {
582         super.trimStrings();
583         return this;
584      }
585
586      @Override /* GENERATED - org.apache.juneau.parser.Parser.Builder */
587      public Builder trimStrings(boolean value) {
588         super.trimStrings(value);
589         return this;
590      }
591
592      @Override /* GENERATED - org.apache.juneau.parser.Parser.Builder */
593      public Builder unbuffered() {
594         super.unbuffered();
595         return this;
596      }
597
598      @Override /* GENERATED - org.apache.juneau.parser.Parser.Builder */
599      public Builder unbuffered(boolean value) {
600         super.unbuffered(value);
601         return this;
602      }
603
604      @Override /* GENERATED - org.apache.juneau.parser.ReaderParser.Builder */
605      public Builder fileCharset(Charset value) {
606         super.fileCharset(value);
607         return this;
608      }
609
610      @Override /* GENERATED - org.apache.juneau.parser.ReaderParser.Builder */
611      public Builder streamCharset(Charset value) {
612         super.streamCharset(value);
613         return this;
614      }
615
616      @Override /* GENERATED - org.apache.juneau.xml.XmlParser.Builder */
617      public Builder eventAllocator(Class<? extends javax.xml.stream.util.XMLEventAllocator> value) {
618         super.eventAllocator(value);
619         return this;
620      }
621
622      @Override /* GENERATED - org.apache.juneau.xml.XmlParser.Builder */
623      public Builder preserveRootElement() {
624         super.preserveRootElement();
625         return this;
626      }
627
628      @Override /* GENERATED - org.apache.juneau.xml.XmlParser.Builder */
629      public Builder preserveRootElement(boolean value) {
630         super.preserveRootElement(value);
631         return this;
632      }
633
634      @Override /* GENERATED - org.apache.juneau.xml.XmlParser.Builder */
635      public Builder reporter(Class<? extends javax.xml.stream.XMLReporter> value) {
636         super.reporter(value);
637         return this;
638      }
639
640      @Override /* GENERATED - org.apache.juneau.xml.XmlParser.Builder */
641      public Builder resolver(Class<? extends javax.xml.stream.XMLResolver> value) {
642         super.resolver(value);
643         return this;
644      }
645
646      @Override /* GENERATED - org.apache.juneau.xml.XmlParser.Builder */
647      public Builder validating() {
648         super.validating();
649         return this;
650      }
651
652      @Override /* GENERATED - org.apache.juneau.xml.XmlParser.Builder */
653      public Builder validating(boolean value) {
654         super.validating(value);
655         return this;
656      }
657
658      // </FluentSetters>
659   }
660
661   //-------------------------------------------------------------------------------------------------------------------
662   // Instance
663   //-------------------------------------------------------------------------------------------------------------------
664
665   private final Map<ClassMeta<?>,HtmlClassMeta> htmlClassMetas = new ConcurrentHashMap<>();
666   private final Map<BeanPropertyMeta,HtmlBeanPropertyMeta> htmlBeanPropertyMetas = new ConcurrentHashMap<>();
667
668   /**
669    * Constructor.
670    *
671    * @param builder The builder for this object.
672    */
673   public HtmlParser(Builder builder) {
674      super(builder);
675   }
676
677   @Override /* Context */
678   public Builder copy() {
679      return new Builder(this);
680   }
681
682   @Override /* Context */
683   public HtmlParserSession.Builder createSession() {
684      return HtmlParserSession.create(this);
685   }
686
687   @Override /* Context */
688   public HtmlParserSession getSession() {
689      return createSession().build();
690   }
691
692   //-----------------------------------------------------------------------------------------------------------------
693   // Extended metadata
694   //-----------------------------------------------------------------------------------------------------------------
695
696   @Override /* HtmlMetaProvider */
697   public HtmlClassMeta getHtmlClassMeta(ClassMeta<?> cm) {
698      HtmlClassMeta m = htmlClassMetas.get(cm);
699      if (m == null) {
700         m = new HtmlClassMeta(cm, this);
701         htmlClassMetas.put(cm, m);
702      }
703      return m;
704   }
705
706   @Override /* HtmlMetaProvider */
707   public HtmlBeanPropertyMeta getHtmlBeanPropertyMeta(BeanPropertyMeta bpm) {
708      if (bpm == null)
709         return HtmlBeanPropertyMeta.DEFAULT;
710      HtmlBeanPropertyMeta m = htmlBeanPropertyMetas.get(bpm);
711      if (m == null) {
712         m = new HtmlBeanPropertyMeta(bpm.getDelegateFor(), this);
713         htmlBeanPropertyMetas.put(bpm, m);
714      }
715      return m;
716   }
717}