Pass parameter value from my implementation service to my RestController java springboot - java

I'm having a trouble passing the value of error i get when im returning the results of a table.
I have a method in my ServiceImpl class which return results for the table and also counts the amount of errors.
public List<Flow> getAllProcessContextWithCriteriaAndFlowCode(
String startDate, String endDate, String flowCode) {
List<FlowDto> flowDtos = new ArrayList<>(500);
flowDtos = processContextRepository
.fetch(startDate,
endDate, flowCode);
List<Flow> flows = new ArrayList();
// bodyguard
if (flowDtos == null || flowDtos.size() == 0) {
return flows;
}
int counter = 0;
StringBuilder idFonctionnelBuilder = new StringBuilder();
FlowDto currentFlowDto = null;
FlowState flowState = new FlowState();
FlowDto nextFlowDto = null;
Flow flowTemp = null;
Map<String, String> mapFlowIdsAndIdF = new HashMap<>();
int iNbreError = 0;
String sTempError = "";
for (int i = 0; i < flowDtos.size(); i++) {
currentFlowDto = flowDtos.get(i);
if ((i + 1) < flowDtos.size()) {
nextFlowDto = flowDtos.get(i + 1);
if (((nextFlowDto.getFlowId()
.equals(currentFlowDto.getFlowId())))) {
idFonctionnelBuilder.append(currentFlowDto.getIdf() + ", ");
continue;
} else {
flowTemp = new Flow();
flowTemp.setFlowId(currentFlowDto.getFlowId());
flowTemp.setLogRole(currentFlowDto.getLogRole());
Date date = null;
try {
date = inputFormat.parse(currentFlowDto
.getContextTime());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
flowTemp.setContextTime(outputFormat.format(date));
if (currentFlowDto.getLogRole() != null) {
iNbreError++;
flowTemp.setNbreError(iNbreError);
} else {
flowTemp.setNbreError(iNbreError);
}
flowTemp.setNbreError(iNbreError);
flows.add(flowTemp);
}
} else {
flowTemp = new Flow();
if (currentFlowDto.getLogRole() != null) {
iNbreError++;
flowTemp.setNbreError(iNbreError);
} else {
flowTemp.setNbreError(iNbreError);
}
flowTemp.setContextTime(outputFormat.format(date));
flows.add(flowTemp);
}
}
LOGGER.info("[ getAllProcessContextWithCriteriaAndFlowCode ] iNbreError : "
+ iNbreError);
getNbreError(iNbreError);
return flows;
}
Then i have another method in the same class ServiceImpl who get the number of errors and set it in a variable, the result print is always the right one here.
public int getNbreError( int iNbreError){
System.out.println("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH");
System.out.println(iNbreError);
setCountError(iNbreError);
System.out.println("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH");
System.out.println(countError);
return countError;
}
What i want to do is send this value(counterror) to my RestController which is in another class called RestController so i can send it to my angular front
#GetMapping(value = "/nbreError")
public int getCountError() {
FMServiceImpl flows = new FMServiceImpl();
int countError = 0;
int iNbreError = 0;
return fmService.getNbreError( iNbreError);
}
}
Actually the result is always 0.
Thanks for your any help or advice :)

Don't use getMethod to modify data, check principle Command–query separation (CQS)
Don't create FMServiceImpl manually, Inject FMServiceImpl as dependence to your controller. in spring, Service keeps the state by default.

Related

Java opencsv library: remove quotations from empty values(null values)

I use this library for exporting to CSV file
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.3</version>
</dependency>
I created Builder:
writer = new StatefulBeanToCsvBuilder<T>(printWriter)
.withQuotechar(CSVWriter.DEFAULT_QUOTE_CHARACTER)
.withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.withOrderedResults(false)
.withMappingStrategy(mappingStrategy)
.build();
It Is my POJO:
#Data
public class ReportCsvDto {
#CsvBindByName(column = "NAME")
#CsvBindByPosition(position = 0)
private String name;
#CsvBindByName(column = "ID")
#CsvBindByPosition(position = 1)
private String id;
#CsvBindByName(column = "GENDER")
#CsvBindByPosition(position = 3)
private String gender;
}
How can I remove quotations from empty values?
I have this: "Bill","","male"
I want this: "Bill",,"male"
I want to remove quotations only from empty values
I have looked through the code of opencsv library. And most simple decision which I can come up with now it is just override transmuteBean method in MappingStrategy and passing this new stategy to the builder. For example for ColumnPositionMappingStrategy:
public class CustomColumnPositionMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
#Override
public String[] transmuteBean(T bean) throws CsvFieldAssignmentException, CsvChainedException {
int numColumns = headerIndex.findMaxIndex()+1;
BeanField<T, Integer> firstBeanField, subsequentBeanField;
Integer firstIndex, subsequentIndex;
List<String> contents = new ArrayList<>(Math.max(numColumns, 0));
// Create a map of types to instances of subordinate beans
Map<Class<?>, Object> instanceMap;
try {
instanceMap = indexBean(bean);
}
catch(IllegalAccessException | InvocationTargetException e) {
// Our testing indicates these exceptions probably can't be thrown,
// but they're declared, so we have to deal with them. It's an
// alibi catch block.
CsvBeanIntrospectionException csve = new CsvBeanIntrospectionException(
ResourceBundle.getBundle(
ICSVParser.DEFAULT_BUNDLE_NAME, errorLocale)
.getString("error.introspecting.beans"));
csve.initCause(e);
throw csve;
}
CsvChainedException chainedException = null;
for(int i = 0; i < numColumns;) {
// Determine the first value
firstBeanField = findField(i);
firstIndex = chooseMultivaluedFieldIndexFromHeaderIndex(i);
String[] fields = ArrayUtils.EMPTY_STRING_ARRAY;
if(firstBeanField != null) {
try {
fields = firstBeanField.write(instanceMap.get(firstBeanField.getType()), firstIndex);
}
catch(CsvDataTypeMismatchException | CsvRequiredFieldEmptyException e) {
if(chainedException != null) {
chainedException.add(e);
}
else {
chainedException = new CsvChainedException(e);
}
}
}
if(fields.length == 0) {
// Write the only value
contents.add(null);
i++; // Advance the index
}
else {
// Multiple values. Write the first.
contents.add(fields[0]);
// Now write the rest.
// We must make certain that we don't write more fields
// than we have columns of the correct type to cover them.
int j = 1;
int displacedIndex = i+j;
subsequentBeanField = findField(displacedIndex);
subsequentIndex = chooseMultivaluedFieldIndexFromHeaderIndex(displacedIndex);
while(j < fields.length
&& displacedIndex < numColumns
&& Objects.equals(firstBeanField, subsequentBeanField)
&& Objects.equals(firstIndex, subsequentIndex)) {
// This field still has a header, so add it
contents.add(fields[j]);
// Prepare for the next loop through
displacedIndex = i + (++j);
subsequentBeanField = findField(displacedIndex);
subsequentIndex = chooseMultivaluedFieldIndexFromHeaderIndex(displacedIndex);
}
i = displacedIndex; // Advance the index
// And here's where we fill in any fields that are missing to
// cover the number of columns of the same type
if(i < numColumns) {
subsequentBeanField = findField(i);
subsequentIndex = chooseMultivaluedFieldIndexFromHeaderIndex(i);
while(Objects.equals(firstBeanField, subsequentBeanField)
&& Objects.equals(firstIndex, subsequentIndex)
&& i < numColumns) {
contents.add(null);
subsequentBeanField = findField(++i);
subsequentIndex = chooseMultivaluedFieldIndexFromHeaderIndex(i);
}
}
}
}
// If there were exceptions, throw them
if(chainedException != null) {
if (chainedException.hasOnlyOneException()) {
throw chainedException.getFirstException();
}
throw chainedException;
}
return contents.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
}
}
And for your example it will produce the following output:
"Bill",,"male"
This overridden method is a simple copy of the original method. But instead of writing empty string on null value it writes null value. And CSVWriter.writeNext method then skips the output of the quotes for null value. This decision can be extended to handle blank lines in the original data too.
As an option you can implement MappingStrategy entirely of course. But I think this is not what you need.
Or you can just implement ICSVWriter for your case or redefine writeNext method for existing subclass. And then you need to pass this CSVWriter to builder. For example CSVWriter.writeNext:
public class CustomCSVWriter extends CSVWriter {
public CustomCSVWriter(Writer writer) {
super(writer);
}
public CustomCSVWriter(Writer writer, char separator, char quotechar, char escapechar, String lineEnd) {
super(writer, separator, quotechar, escapechar, lineEnd);
}
#Override
protected void writeNext(String[] nextLine, boolean applyQuotesToAll, Appendable appendable) throws IOException {
if (nextLine == null) {
return;
}
for (int i = 0; i < nextLine.length; i++) {
if (i != 0) {
appendable.append(separator);
}
String nextElement = nextLine[i];
if (StringUtils.isEmpty(nextElement)) {
continue;
}
Boolean stringContainsSpecialCharacters = stringContainsSpecialCharacters(nextElement);
appendQuoteCharacterIfNeeded(applyQuotesToAll, appendable, stringContainsSpecialCharacters);
if (stringContainsSpecialCharacters) {
processLine(nextElement, appendable);
} else {
appendable.append(nextElement);
}
appendQuoteCharacterIfNeeded(applyQuotesToAll, appendable, stringContainsSpecialCharacters);
}
appendable.append(lineEnd);
writer.write(appendable.toString());
}
private void appendQuoteCharacterIfNeeded(boolean applyQuotesToAll, Appendable appendable, Boolean stringContainsSpecialCharacters) throws IOException {
if ((applyQuotesToAll || stringContainsSpecialCharacters) && quotechar != NO_QUOTE_CHARACTER) {
appendable.append(quotechar);
}
}
}
Overridden method is a simple copy of the original method again. But it skips processing of empty strings (StringUtils.isEmpty(nextElement) check instead of checking for null).
And, of course, you can redefine this behavior in the following way:
public class CustomCSVWriter extends CSVWriter {
public CustomCSVWriter(Writer writer) {
super(writer);
}
public CustomCSVWriter(Writer writer, char separator, char quotechar, char escapechar, String lineEnd) {
super(writer, separator, quotechar, escapechar, lineEnd);
}
#Override
protected void writeNext(String[] nextLine, boolean applyQuotesToAll, Appendable appendable) throws IOException {
if (nextLine != null) {
for (int i = 0; i < nextLine.length; i++) {
if (StringUtils.isEmpty(nextLine[i])) {
nextLine[i] = null;
}
}
}
super.writeNext(nextLine, applyQuotesToAll, appendable);
}
}
Here empty strings are simply replaced with null values. And for me, this method would be more preferable if you do not need to separate empty strings and null values from the original data. Otherwise, the first option (with redefining MappingStrategy) is the only one possible.

Remove nulls from an array in java

I have a method what should delete values from an array...
public Application[] deleteApp(String id) {
int count = 0;
for (int i = 0; i < this.apps.length; i++) {
if (this.apps[i] != null && this.apps[i].getId().equals(id)) {
this.apps[i] = null;
if (this.apps[i] == null)
count++;
}
}
Application[] withoutNulls = new Application[this.apps.length - count];
int index = 0;
for (Application app : this.apps) {
if (app != null) {
withoutNulls[index] = app;
index++;
}
}
return withoutNulls;
}
But final result is smth like:
Application[] app = {app1, app2, null};
What's wrong? I'm counting nulls, creating new array[sizeOfArray - countOfNulls], and recording only not-null values :(
upd
I have a test of that.
#Test
public void deleteAppTest() {
Tracker tracker = new Tracker();
Application testing_1 = new Application();
Application testing_2 = new Application();
Application[] test = {testing_1};
tracker.addApp(testing_1);
tracker.addApp(testing_2);
tracker.deleteApp(testing_2.getId());
assertThat(tracker.showApps(), is(test));
But method does not pass the test.
Expected: is []
but: was [, null]
Try with Lambdas
public Application[] deleteApp(String id) {
List<Application> result = Arrays.asList(apps).stream().
filter(app -> app != null &&!id.equals(app.getId())).collect(Collectors.toList());
return result.toArray(new Application[result.size()]);
}
Here it is as #Erwin Bolwidt suggested
public Application[] deleteApp(String id) {
int count = 0;
for (int i = 0; i < this.apps.length; i++) {
if (this.apps[i] != null && this.apps[i].getId().equals(id)) {
this.apps[i] = null;
count++;
}
// Move this if out into an else if
else if (this.apps[i] == null){
count++;
}
}
Application[] withoutNulls = new Application[this.apps.length - count];
int index = 0;
for (Application app : this.apps) {
if (app != null) {
withoutNulls[index] = app;
index++;
}
}
return withoutNulls;
}

Autocomplete unmatched results

I am trying to do autocomplete when I type in characters in ice:selectInputText
Issue I am facing is when I type in characters it brings even names which is not matching with the characters I type.
See the below screen shot for reference.
Ideally autocomplete should display only the first row from the result, however it displays rows which are not matching my typed characters.
Only Abell Maryland 20606 should display.
This is the code which is using for the comparison, how can I modify this to suit to my requirement which is to display only those results which is matching to what I type.
public int compare(Object o1, Object o2) {
if (o1 instanceof SelectItem) {
s1 = ((SelectItem) o1).getLabel();
} else {
s1 = o1.toString();
}
if (o2 instanceof SelectItem) {
s2 = ((SelectItem) o2).getLabel();
} else {
s2 = o2.toString();
}
return s1.compareToIgnoreCase(s2);
}
};
I am following this tutorial from Icefaces
http://wiki.icefaces.org/display/ICE/Auto-Complete
Update
My code in autocomplete.jspx
<ice:selectInputText rows="10" width="300"
listVar="emp"
valueChangeListener="#{mybean.updateList}"
listValue="#{mybean.list}">
<f:facet name="selectInputText">
<ice:panelGrid columns="3" columnClasses="empNameCol">
<ice:outputText value="#{emp.empName}"/>
</ice:panelGrid>
method updateList
public void updateList(ValueChangeEvent event) {
setMatches(event);
if (event.getComponent() instanceof SelectInputText) {
SelectInputText autoComplete = (SelectInputText)event.getComponent();
if (autoComplete.getSelectedItem() != null) {
bean = (Bean)autoComplete.getSelectedItem().getValue();
}
else {
Bean tempCity = getMatch(autoComplete.getValue().toString());
if (tempCity != null) {
bean = tempCity;
}
}
}
}
Method setMatches
private void setMatches(ValueChangeEvent event) {
Object searchWord = event.getNewValue();
int maxMatches = ((SelectInputText)event.getComponent()).getRows();
List matchList = new ArrayList(maxMatches);
try {
int insert =
Collections.binarySearch(dictionary, searchWord, AutoCompleteDictionary.LABEL_COMPARATOR);
if (insert < 0) {
insert = Math.abs(insert) - 1;
}
for (int i = 0; i < maxMatches; i++) {
if ((insert + i) >= dictionary.size() || i >= maxMatches) {
break;
}
matchList.add(dictionary.get(insert + i));
}
} catch (Throwable e) {
e.printStackTrace();
logger.error("Erorr finding autocomplete matches" + e.getMessage());
}
if (this.matchesList != null) {
this.matchesList.clear();
this.matchesList = null;
}
this.matchesList = matchList;
}
Update 2
Modified setMatches method
private void setMatches(ValueChangeEvent event) {
Object searchWord = event.getNewValue();
int maxMatches = ((SelectInputText) event.getComponent()).getRows();
List matchList = new ArrayList(maxMatches);
try {
for(int i = 0; i < dictionary.size(); i++) {
SelectItem s = (SelectItem)dictionary.get(i);
if(s.getLabel().startsWith(searchWord.toString())) {
matchList.add(s);
if(matchList.size() == maxMatches)
break;
}
}
} catch (Throwable e) {
e.printStackTrace();
logger.error("Erorr finding autocomplete matches" + e.getMessage());
}
if (this.matchesList != null) {
this.matchesList.clear();
this.matchesList = null;
}
this.matchesList = matchList;
}
You have to update the list of SelectItems. Instead of just odering the list you have to filter the list (or creating a new one which only contains the matches). The next time the autocomplete-list renders it will evaluate the bound list again.
The tutorial of icefaces has some sources attached (bottom). Take a look at AutoCompleteBean . The method updateList(ValueChangeEvent e) calls setMatches(e). Within this method the list is assigned with a new one.
// assign new matchList
if (this.matchesList != null) {
this.matchesList.clear();
this.matchesList = null;
}
this.matchesList = matchList;
This causes the ui component to show only items which match the input.
To sum it up: ice:selectInputList will always show the items contained in its list, so reduce the items in the list to show the relevant ones only.
Regards
Update
private void setMatches(ValueChangeEvent event) {
Object searchWord = event.getNewValue();
int maxMatches = ((SelectInputText)event.getComponent()).getRows();
List matchList = new ArrayList(maxMatches);
try {
for(int i = 0; i < dictionary.size(); i++) {
SelectItem s = dictionary.get(i);
if(s.getLabel().startsWith(searchWord)) {
matchList.add(s);
if(matchList.size() == maxMatches)
break;
}
}
} catch (Throwable e) {
e.printStackTrace();
logger.error("Erorr finding autocomplete matches" + e.getMessage());
}
if (this.matchesList != null) {
this.matchesList.clear();
this.matchesList = null;
}
this.matchesList = matchList;
}
// note: not optimized, just to explain how to do.
Update 2 (short version)
/**
* Fills the suggestionList with the given luceneResult.
*
* #param suggestionList The list to fill.
* #param luceneResult The previously computed luceneResult.
*/
private static void fillLookupSuggestionList(final List<SelectItem> suggestionList,
LuceneResult luceneResult)
{
suggestionList.clear();
String searchQuery = luceneResult.getLuceneResultConfig().getSearchQuery();
if (luceneResult.getResultSize() <= 0)
{
suggestionList.add(new SelectItem(null, BundleHelper.i18n(LuceneLookupController.BUNDLE,
LuceneLookupController.NO_ITEM_FOUND)));
}
else
{
List<LuceneResultEntry> results = luceneResult.getResult();
for (LuceneResultEntry entry : results)
{
suggestionList.add(new SelectItem(entry.getMetaInfo(),
entry.getInfo().getDescription()));
}
}
}

read line using java & maped filterd data [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
public class Reader {
public static void main(String[] args) throws IOException, ParseException {
BufferedReader reader;
String animalName="cat";
String animal = null;
try {
reader = new BufferedReader(new InputStreamReader(
new FileInputStream("C:/dila.txt")));
Map<String, Integer> result = new LinkedHashMap<String, Integer>();
Map<String, Integer> result2 = new LinkedHashMap<String, Integer>();
while (reader.ready()) {
String line = reader.readLine();
/split a line with spaces/
String[] values = line.split(",");
String key = null;
if(values[1].compareTo(animalName)==0){
key = values[0];
animal=""+values[1].compareTo(animalName);
int sum = 0;
int count = 0;
/get a last counter and sum/
if (result.containsKey(key)) {
sum = result.get(key);
count = result2.get(key);
} else{
}
/increment sum a count and save in the map with key/
result.put(key, sum + Integer.parseInt(values[2]));
result2.put(key, count + 1);
}
}
/interate and print new output/
for (String key : result.keySet()) {
Integer sum = result.get(key);
Integer count = result2.get(key);
System.out.println(key +" "+animalName+ " " + sum + "\t" + count);
}
reader.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
i have below text file
11/2/2010,cat,6
11/2/2010,cat,3
11/2/2010,dog,4
11/2/2010,cat,11
11/3/2010,cat,1
11/3/2010,dog,3
11/3/2010,cat,8
11/3/2010,cat,80
The above code is currently printing this summary data
11/2/2010 cat 20 3
11/3/2010 cat 104 4
11/4/2010 cat 26 2
I need help is printing the summary as shown below
11/01/2010
11/02/2010 cat 20 3
11/03/2010 cat 104 4
11/04/2010 cat 26 2
11/05/2010
11/06/2010
11/07/2010
11/08/2010
11/09/2010
11/10/2010
11/11/2010
11/12/2010
11/13/2010
11/14/2010
11/15/2010
11/16/2010
11/17/2010
11/18/2010
11/19/2010
11/20/2010
11/21/2010
11/22/2010
11/23/2010
11/24/2010
11/25/2010
11/26/2010
11/27/2010
11/28/2010
11/29/2010
11/30/2010
i hav bulk of data seperated from "," . so iwant to read line and split. & i hav done it. but my requrment is above shown result.
Below is the code to do it. I am taking help of google-guava libraries as it helps me write less code ;-). If you just want in plain java then you can modify the code also if the logic needs some tweaking then look at processLine(...) method, that is where the change will go
Ok the only missing code I see is printing empty data for the dates that are not part of the input file in a sorted order. That is simple and leave it to you. Here is the hint: Increment date by 1 & loop until end of the month
I have run your sample file and it prints the below summary
11/3/2010 cat 89 3
11/3/2010 dog 3 1
11/2/2010 dog 4 1
11/2/2010 cat 20 3
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import com.google.common.base.CharMatcher;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.google.common.io.LineProcessor;
public class AnimalSummaryBuilder
{
private static final Splitter SPLITTER = Splitter.on(CharMatcher.anyOf(","));
private static final Joiner JOINER = Joiner.on("\t");
#SuppressWarnings("unchecked")
public static void main(final String[] args) throws Exception
{
#SuppressWarnings("rawtypes")
Map<Animal, Summary> result = Files.readLines(new File("c:/1.txt"), Charsets.ISO_8859_1, new LineProcessor() {
private final Map<Animal, Summary> result = Maps.newHashMap();
public Object getResult()
{
return result;
}
public boolean processLine(final String line) throws IOException
{
Iterator<String> columns = SPLITTER.split(line).iterator();
String date = columns.next();
String name = columns.next();
int value = Integer.valueOf(columns.next()).intValue();
Animal currentRow = new Animal(date, name);
if (result.containsKey(currentRow))
{
Summary summary = result.get(currentRow);
summary.increaseCount();
summary.addToTotal(value);
}
else
{
Summary initialSummary = new Summary();
initialSummary.setCount(1);
initialSummary.setTotal(value);
result.put(currentRow, initialSummary);
}
return true;
}
});
for (Map.Entry<Animal, Summary> entry : result.entrySet())
{
Animal animal = entry.getKey();
Summary summary = entry.getValue();
System.out.println(JOINER.join(animal.date, animal.name, summary.total, summary.count));
}
}
final static class Animal
{
String date;
String name;
public Animal(final String date, final String n)
{
this.date = date;
this.name = n;
}
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((date == null) ? 0 : date.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (!(obj instanceof Animal))
{
return false;
}
Animal other = (Animal) obj;
if (date == null)
{
if (other.date != null)
{
return false;
}
}
else if (!date.equals(other.date))
{
return false;
}
if (name == null)
{
if (other.name != null)
{
return false;
}
}
else if (!name.equals(other.name))
{
return false;
}
return true;
}
}
final static class Summary
{
private int total;
private int count;
void setTotal(int value)
{
total = value;
}
void setCount(int i)
{
count = i;
}
void increaseCount()
{
count++;
}
void addToTotal(int valueToAdd)
{
total += valueToAdd;
}
}
}
You could use another map with the date as the key, and the results you got as value. Then you just loop through all the days in the month, and if the map contains the current date key, you print the corresponding value, else you only print the date.
Here is the dirty solution. The assumption is that the "result" map contains only 1 month.
public class Reader
{
public static void main(final String[] args) throws ParseException
{
BufferedReader reader = null;
String animalName = "cat";
// String animal = null;
try
{
reader = new BufferedReader(new InputStreamReader(new FileInputStream("C:/1.txt")));
Map<String, Integer> result = new LinkedHashMap<String, Integer>();
Map<String, Integer> result2 = new LinkedHashMap<String, Integer>();
while (reader.ready())
{
String line = reader.readLine();
// split a line with spaces
String[] values = line.split(",");
String key = null;
if (values[1].compareTo(animalName) == 0)
{
key = values[0];
// animal=""+ ""+values[1].compareTo(animalName);
int sum = 0;
int count = 0;
// get a last counter and sum
if (result.containsKey(key))
{
sum = result.get(key);
count = result2.get(key);
}
else
{
}
// increment sum a count and save in the map with key
result.put(key, sum + Integer.parseInt(values[2]));
result2.put(key, count + 1);
}
}
String date = result.keySet().iterator().next();
DateFormat df = new SimpleDateFormat("mm/dd/yyyy");
Calendar calendar = Calendar.getInstance();
calendar.setTime(df.parse(date));
int monthStart = calendar.getActualMinimum(Calendar.DAY_OF_MONTH);
int monthEnd = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
calendar.set(Calendar.DAY_OF_MONTH, 0);
// interate and print new output
for (int i = monthStart; i < monthEnd; i++)
{
calendar.add(Calendar.DAY_OF_MONTH, 1);
String key = df.format(calendar.getTime());
if (result.containsKey(key))
{
Integer sum = result.get(key);
Integer count = result2.get(key);
System.out.println(key + " " + animalName + " " + sum + "\t" + count);
}
System.out.println(key);
}
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try
{
reader.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

Null Pointer Error Again

So I have this compiler class that compiles some .mjava files but others it fails on and wondering if anyone can help me figure out why. I have two methods that break for two different files. The first consts.mjava file I try to compile is:
// demo of true local and global variables
int glob0;
int glob1;
final int two = 2;
final int three = 3;
main() {
int loc1;
int loc2;
int loc3;
final int four = 4;
glob0 = three;
//print("glob0=", glob0, "\n");
loc1 = glob0*two+1;
glob1 = glob0*loc1;
loc2 = glob1+1;
loc3 = glob1*loc2/four;
print("glob0=", glob0, " (should be 3)\n");
print("glob1=", glob1, " (should be 21)\n");
print("loc1=", loc1, " (should be 7)\n");
print("loc2=", loc2, " (should be 22)\n");
print("loc3=", loc3, " (should be 115)\n");
}
When I try to compile this with my compiler class it breaks here:
private void compileFactor() {
if (isIdent(theToken)) {
String ident = theToken;
theToken = t.token();
IdentInfo theInfo = symTable.lookup(ident);
boolean its_a_variable = theInfo.isVar(); ***//Breaks Here for consts.mjava Null Exception***
int theAddr;
boolean isGlobal = theInfo.getIsGlobal();
int constValue;
int theNumber = 0;
if (its_a_variable) { // pld12: CHANGE THIS!!
theAddr = theInfo.getAddr();
isGlobal = theInfo.getIsGlobal();
if (theAddr == -1) t.error("undeclared identifier used in expr: "+ident);
if (isGlobal) cs.emit(Machine.LOAD, theAddr);
else cs.emit(Machine.LOADF, theAddr);
} else {
constValue = theInfo.getValue();
if (constValue == 0)
t.error("undeclared identifier used in expr: "+ident);
else {
cs.emitLOADINT(theNumber);
}
}
} else if (isNumber(theToken)) {
int theNumber = new Integer(theToken).intValue();
cs.emitLOADINT(theNumber);
theToken = t.token();
} else if (equals(theToken, "(")) {
accept("(");
compileExpr();
accept(")");
}
}
The next locs.mjava file I try to run breaks on this method:
private void compileIdentStmt() {
String ident = theToken;
boolean isGlobal = true;
int location = 0;
int entryPoint = 0;
IdentInfo varInfo = null;
if (!isIdent(ident)) t.error("expected identifier, got " + theToken);
theToken = t.token();
if (equals(theToken, "=")) {
accept("=");
varInfo = symTable.lookup(ident);
if (varInfo.isVar() == true) { ***//Breaks Here on locs.mjava: Null Exception***
location = varInfo.getAddr();
isGlobal = varInfo.getIsGlobal();
}
/*
if (varInfo==null) {
location = GHack(ident);
isGlobal = true;
}
if (location == -1) {
location = LHack(ident);
isGlobal = false;
}
/* */
compileExpr();
if (isGlobal) cs.emit(Machine.STOR, location);
else cs.emit(Machine.STORF, location);
accept(";");
} else if (equals(theToken, "(")) {
varInfo = symTable.lookup(ident);
if (varInfo.isProc() == true) {
entryPoint = varInfo.getEntryPoint();
dprint("call to function " + ident + "; generating JSR to location " + entryPoint);
accept("(");
}
/*
if (!equals(theToken, ")")) {
compileExpr();
while (equals(theToken, ",")) {
accept(",");
compileExpr();
}
}
/* */
accept(")");
accept(";");
cs.emit(Machine.JSR, entryPoint);
} else t.error("expected \"=\" or \"(\", got " + theToken);
}
I will even supply my lookup method from my symTable() to help:
public IdentInfo lookup(String ident) {
IdentInfo ii;
if (HMLocal != null) {
ii = HMLocal.get(ident);
if (ii != null) {
return ii;
}
ii = HMGlobal.get(ident);
if (ii != null) {
return ii;
}
}
return null;
}
If you're getting NullPointerExceptions then it's because theInfo and varInfo are null in your examples.
After
IdentInfo theInfo = symTable.lookup(ident);
you should check if theInfo is null before trying to work with it, since your lookup method clearly states it can return null.

Categories