View Javadoc
1   package org.imageconverter.config.health;
2   
3   import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase;
4   
5   import java.io.ByteArrayInputStream;
6   import java.io.IOException;
7   import java.util.HashMap;
8   import java.util.LinkedHashMap;
9   import java.util.Map;
10  import java.util.Objects;
11  
12  import javax.imageio.ImageIO;
13  
14  import org.apache.commons.collections4.MapUtils;
15  import org.imageconverter.util.BeanUtil;
16  import org.springframework.beans.factory.annotation.Autowired;
17  import org.springframework.beans.factory.annotation.Value;
18  import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
19  import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
20  import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
21  import org.springframework.cloud.endpoint.RefreshEndpoint;
22  import org.springframework.core.env.ConfigurableEnvironment;
23  import org.springframework.core.env.MapPropertySource;
24  import org.springframework.core.io.Resource;
25  import org.springframework.lang.Nullable;
26  import org.springframework.stereotype.Component;
27  
28  import com.fasterxml.jackson.annotation.JsonAnyGetter;
29  import com.fasterxml.jackson.annotation.JsonInclude;
30  
31  import net.sourceforge.tess4j.ITesseract;
32  import net.sourceforge.tess4j.TesseractException;
33  
34  /**
35   * Component to show informations about tesseract configs.
36   * 
37   * @author Fernando Romulo da Silva
38   */
39  @Component
40  @Endpoint(id = "tesseract")
41  // @Endpoint, @JmxEndpoint, and @WebEndpoint
42  public class TesseractInfoService {
43  
44      private final Resource imageFile;
45  
46      private final RefreshEndpoint refreshEndpoint;
47  
48      /**
49       * Default constructor.
50       * 
51       * @param newImageFile       Image to check if the tesseract works
52       * @param newRefreshEndpoint Represh point to update infos
53       */
54      TesseractInfoService( //
55  		    @Value("classpath:check-image.png") //
56  		    final Resource newImageFile, //
57  		    //
58  		    @Autowired //
59  		    final RefreshEndpoint newRefreshEndpoint) {
60  	super();
61  	this.imageFile = newImageFile;
62  	this.refreshEndpoint = newRefreshEndpoint;
63      }
64  
65      /**
66       * Read data about tesseract configs.
67       * 
68       * @return A {@link TesseractDetailsData} with the data
69       */
70      @ReadOperation
71      public TesseractDetailsData read() {
72  
73  	final var details = new LinkedHashMap<String, Object>();
74  
75  	details.put("tesseractVersion", "4.11");
76  	details.put("tesseractFolder", BeanUtil.getPropertyValue("tesseract.folder"));
77  	details.put("tesseractLanguage", BeanUtil.getPropertyValue("tesseract.language"));
78  	details.put("tesseractDpi", BeanUtil.getPropertyValue("tesseract.dpi"));
79  
80  	if (checkTesseract()) {
81  	    details.put("tesseractInit", "SUCCESSFUL");
82  	} else {
83  	    details.put("tesseractInit", "FAIL");
84  	}
85  
86  	return new TesseractDetailsData(details);
87      }
88  
89  //    @ReadOperation
90  //    public String health(@Selector String name) {
91  //	return "custom-end-point";
92  //    }
93  
94      /**
95       * Update values from request http, JMX, etc.
96       * 
97       * @param tesseractFolder   The tesseract intalled dictionary
98       * @param tesseractLanguage The tesseract language
99       * @param tesseractDpi      The resolution quality
100      */
101     @WriteOperation
102     public void writeOperation(@Nullable final String tesseractFolder, @Nullable final String tesseractLanguage, @Nullable final String tesseractDpi) {
103 	final var env = (ConfigurableEnvironment) BeanUtil.getEnvironment();
104 
105 	final var propertySources = env.getPropertySources();
106 	final var map = new HashMap<String, Object>();
107 
108 	if (Objects.nonNull(tesseractFolder)) {
109 	    map.put("tesseract.folder", tesseractFolder);
110 	}
111 
112 	if (Objects.nonNull(tesseractLanguage)) {
113 	    map.put("tesseract.language", tesseractLanguage);
114 	}
115 
116 	if (Objects.nonNull(tesseractDpi)) {
117 	    map.put("tesseract.dpi", tesseractDpi);
118 	}
119 
120 	propertySources.addFirst(new MapPropertySource("newmap", map));
121 
122 	if (!map.isEmpty()) {
123 	    refreshEndpoint.refresh();
124 	}
125 
126     }
127 
128 //    @DeleteOperation
129 //    public void deleteOperation(@Selector final String name) {
130 //	// delete operation
131 //    }
132 
133     private boolean checkTesseract() {
134 
135 	final var tesseractBeanProvider = BeanUtil.getBeanProviderFrom(ITesseract.class);
136 	final var tesseract = tesseractBeanProvider.getObject();
137 
138 	boolean result = false;
139 
140 	if (Objects.isNull(tesseract)) {
141 
142 	    result = false;
143 
144 	} else {
145 
146 	    try {
147 		
148 		final var bufferedImage = ImageIO.read(new ByteArrayInputStream(imageFile.getInputStream().readAllBytes()));
149 
150 		final var numberOne = tesseract.doOCR(bufferedImage).replaceAll("\\D+", "");
151 
152 		if (equalsIgnoreCase(numberOne, "033")) {
153 		    result = true;
154 		}
155 
156 	    } catch (final TesseractException | IOException | IllegalArgumentException ex) {
157 		result = false;
158 	    }
159 	}
160 
161 	return result;
162     }
163 
164     @JsonInclude(JsonInclude.Include.NON_EMPTY)
165     public static class TesseractDetailsData {
166 
167 	private final Map<String, Object> tesseractDetails;
168 
169 	TesseractDetailsData(final Map<String, Object> tesseractDetails) {
170 	    super();
171 	    this.tesseractDetails = tesseractDetails;
172 	}
173 
174 	@JsonAnyGetter
175 	public Map<String, Object> getTesseractDetails() {
176 	    return MapUtils.unmodifiableMap(tesseractDetails);
177 	}
178     }
179 }