How to process "data" part of GCP PubSub message into a HashMap? - google-cloud-platform

I'm getting pubsub message as below :
{
"data": {
"systemId": "system-1",
"userId": "userId-1",
"departmentId": "090",
"enrolmentDateTime": "2022-08-19T15:44:29.080Z",
"event_type": "REGISTRATION"
}
}
I want to further process this message in my springboot application based on the "event_type".
How can I just fetch "event_type" from this message and use it for comparison?
Any suggestions?
For eg I want to have processing like this :
if(event_type.equals("REGISTRATION")) { registrationHandler.handle(message); else { }
I have tried converting a PubSubMessage into string and then further map it to HashMap using ObjectMapper, but that gives me "data" as key and rest of the json part as a value.
public void process(final PubsubMessage message) throws ConsumerException {
String data = message.getData().toStringUtf8();
try {
ObjectMapper mapper = new ObjectMapper();
HashMap<String, String> dataMap = mapper.readValue(data, HashMap.class);
} ....

Instead of using a Map, you can use a typed object, example :
PubSubData.java file :
public class PubSubData {
private String systemId;
private String userId;
private String departmentId;
private String enrolmentDateTime;
private String event_type;
public PubSubData() {
}
public String getSystemId() {
return systemId;
}
public void setSystemId(String systemId) {
this.systemId = systemId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getDepartmentId() {
return departmentId;
}
public void setDepartmentId(String departmentId) {
this.departmentId = departmentId;
}
public String getEnrolmentDateTime() {
return enrolmentDateTime;
}
public void setEnrolmentDateTime(String enrolmentDateTime) {
this.enrolmentDateTime = enrolmentDateTime;
}
public String getEvent_type() {
return event_type;
}
public void setEvent_type(String event_type) {
this.event_type = event_type;
}
}
PubSubResult.java file :
public class PubSubResult {
private PubSubData data;
public PubSubResult() {
}
public PubSubData getData() {
return data;
}
public void setData(PubSubData data) {
this.data = data;
}
}
Example of an unit test that deserializes data from PubsubMessage to the PubSubResult object :
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.protobuf.ByteString;
import com.google.pubsub.v1.PubsubMessage;
import org.junit.Test;
public class MyTest {
private static final ObjectMapper OBJECT_MAPPER;
static {
final ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
OBJECT_MAPPER = mapper;
}
#Test
public void testDeserializePubSubData() {
final String data = "{\n" +
" \"data\": {\n" +
" \"systemId\": \"system-1\",\n" +
" \"userId\": \"userId-1\",\n" +
" \"departmentId\": \"090\",\n" +
" \"enrolmentDateTime\": \"2022-08-19T15:44:29.080Z\",\n" +
" \"event_type\": \"REGISTRATION\"\n" +
" }\n" +
"}";
final PubsubMessage message = PubsubMessage.newBuilder()
.setData(ByteString.copyFrom(data.getBytes()))
.build();
final String dataResult = message.getData().toStringUtf8();
final PubSubResult resultData = deserialize(dataResult);
// Access to the event type.
final String eventType = resultData.getData().getEvent_type();
}
private PubSubResult deserialize(final String value) {
try {
return OBJECT_MAPPER.readValue(value, PubSubResult.class);
} catch (JsonProcessingException e) {
throw new IllegalStateException("Error !!", e);
}
}
}

Related

DynamoDB: Enum as partition key giving error "Missing the key id in the item" when putItem

I am using the enum as the partition key and my model looks like below
#DynamoDbBean
public class Item {
public enum Key {
KEY_A(false),
KEY_B(2),
private final Object defaultValue;
private Key(Object defaultValue) {
this.defaultValue = defaultValue;
}
public Object getDefaultValue() {
return this.defaultValue;
}
}
private Key key;
private Object value;
public Item() {
}
public Item(Key key) {
this.key = key;
this.value = key.getDefaultValue();
}
#DynamoDbConvertedBy(KeyEnumConverter.class)
#DynamoDbPartitionKey
public Key getKey() {
return key;
}
public void setKey(Key key) {
this.key = key;
}
#DynamoDbConvertedBy(ValueConverter.class)
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
My Converter classes to convert between java object and DDB data type is as below:
public class KeyEnumConverter implements AttributeConverter<Item.Key> {
#Override
public AttributeValue transformFrom(Item.Key key) {
return EnhancedAttributeValue.fromString(key.toString()).toAttributeValue();
}
#Override
public Item.Key transformTo(AttributeValue attributeValue) {
return Item.Key.valueOf(attributeValue.s());
}
#Override
public EnhancedType<Item.Key> type() {
return EnhancedType.of(Item.Key.class);
}
#Override
public AttributeValueType attributeValueType() {
return AttributeValueType.S;
}
public class ValueConverter implements AttributeConverter<Object> {
#Override
public AttributeValue transformFrom(Object Value) {
return getEnhancedAttributeValue(Value).toAttributeValue();
}
#Override
public Object transformTo(AttributeValue attributeValue) {
return JsonConvertor.getObjectFromJsonString(attributeValue.s(), Object.class);
}
#Override
public EnhancedType<Object> type() {
return EnhancedType.of(Object.class);
}
#Override
public AttributeValueType attributeValueType() {
return AttributeValueType.S;
}
private EnhancedAttributeValue getEnhancedAttributeValue (Object value) {
if (Value instanceof Boolean) {
return EnhancedAttributeValue.fromBoolean((Boolean)Value);
} else if(value instanceof Number) {
return EnhancedAttributeValue.fromNumber(String.valueOf(value));
} else {
throw new IllegalArgumentException("Please add support for type " + value.getClass().getSimpleName());
}
}
}
When I am putting an item into the table:
public void saveItem (String itemKey) {
Table.putItem(new Item(Item.Key.valueOf(itemKey)));
}
I got the error:
One or more parameter values were invalid: Missing the key id in the item
The partitionKey is defined in the model, why the key id still missing

Is there a Hamcrest macher that matches public fields?

I have different value objects, each with a different set of fields. How can I check against these with a Hamcrest matcher?
public class ValueObjectA {
public Integer field1;
public String field2;
public long filed3;
public Object filed4;
}
public class ValueObjectB {
public String field1;
public int field2;
}
This is, what I want to do:
resultA = getResultA();
ValueObjectA expectedA = new ValueObjectA();
expectedA.field1 = 4;
resultB = getResultB();
ValueObjectB expectedB = new ValueObjectB();
expectedB.field1 = "foo";
assertThat(resultA, new ValueObjectMatcher(expectedA));
assertThat(resultB, new ValueObjectMatcher(expectedB));
I found a PropertyMatcher but that only uses public getters. I can write something similar, that uses reflection to get the public fields. But is there a readymade one?
You can use a library we recent open sourced for doing this. It works similar to the PropertyMatcher but was designed to do deep object graphs. An upshot is that it "just works" on public fields.
shazamcrest on github
Anyway, I wrote something based on the PropertyMatcher, in case someone wants to write unit tests for eg. com.j256.ormlite :
public class ValueObjectMatcher extends TypeSafeDiagnosingMatcher {
private final Object expectedVo;
private final Set<String> fieldNames;
private final List<FieldMatcher> fieldMatchers;
public ValueObjectMatcher(final Object expectedVo) {
Field[] fieldsToMatch = expectedVo.getClass().getFields();
this.expectedVo = expectedVo;
this.fieldNames = fieldNamesFrom(fieldsToMatch);
this.fieldMatchers = fieldMatchersFor(expectedVo, fieldsToMatch);
}
#Override
protected boolean matchesSafely(final Object item, final Description mismatchDescription) {
return hasAllFields(item, mismatchDescription) && hasMatchingValues(item, mismatchDescription);
}
#Override
public void describeTo(final Description description) {
description.appendText("same field values as " + expectedVo.getClass().getSimpleName())
.appendList(" <", ", ", ">", fieldMatchers);
}
private boolean hasMatchingValues(final Object item, final Description mismatchDescription) {
mismatchDescription.appendText(item + " has <");
int mismatchCount = 0;
for (FieldMatcher fieldMatcher : fieldMatchers) {
if (!fieldMatcher.matches(item)) {
if (mismatchCount != 0) {
mismatchDescription.appendText(", ");
}
fieldMatcher.describeMismatch(item, mismatchDescription);
mismatchCount++;
}
}
mismatchDescription.appendText(">");
return mismatchCount == 0;
}
private boolean hasAllFields(final Object item, final Description mismatchDescription) {
final Field[] fields = item.getClass().getFields();
final Set<String> itemsFieldNames = fieldNamesFrom(fields);
boolean result = true;
for (String fieldName : fieldNames) {
if (!itemsFieldNames.contains(fieldName)) {
result = false;
mismatchDescription.appendText("missing field: " + fieldName);
}
}
return result;
}
private List<FieldMatcher> fieldMatchersFor(final Object expectedVo, final Field[] fields) {
List<FieldMatcher> result = new ArrayList<FieldMatcher>(fields.length);
try {
for (Field field : fields) {
result.add(new FieldMatcher(field, expectedVo));
}
}
catch (NoSuchFieldException e) {
throw new IllegalStateException("Programmer exception, pls replace programmer: " +
"field list doesn't match with the fields of the provided expectedVo", e);
}
catch (IllegalAccessException e) {
throw new IllegalStateException("Programmer exception, pls replace programmer: " +
"field list doesn't match with the fields of the provided expectedVo", e);
}
return result;
}
private Set<String> fieldNamesFrom(final Field[] fieldsToMatch) {
HashSet<String> result = new HashSet<String>();
for (Field field : fieldsToMatch) {
result.add(field.getName());
}
return result;
}
public class FieldMatcher extends DiagnosingMatcher<Object> {
private final Object expectedFieldValue;
private final String fieldName;
private FieldMatcher(Field field, Object expectedVo) throws NoSuchFieldException, IllegalAccessException {
this.fieldName = field.getName();
this.expectedFieldValue = expectedVo.getClass().getField(fieldName).get(expectedVo);
}
#Override
protected boolean matches(final Object item, final Description mismatchDescription) {
try {
final Field fieldItem = item.getClass().getField(fieldName);
final Object fieldObjectItem = fieldItem.get(item);
if (fieldObjectItem == null) {
if (expectedFieldValue != null) {
mismatchDescription.appendText(fieldName + ": " + fieldObjectItem);
}
} else if (!fieldObjectItem.equals(expectedFieldValue)) {
mismatchDescription.appendText(fieldName + ": " + fieldObjectItem);
}
}
catch (IllegalAccessException e) {
mismatchDescription.appendText(fieldName + " is inaccessible");
e.printStackTrace();
}
catch (NoSuchFieldException e) {
mismatchDescription.appendText(fieldName + " doesn't exist");
e.printStackTrace();
}
return false;
}
#Override
public void describeTo(final Description description) {
description.appendText(fieldName + ": " + expectedFieldValue);
}
}
}

Error on Spring REST webservice call

I have following webservice call
#RequestMapping(value = "modifyUser/{userDn}", method = RequestMethod.POST, headers="Accept=application/json")
public #ResponseBody
JSONObject modifyUser(#PathVariable String userDn, #RequestBody DirectoryUser directoryUser) {
// Modify User
boolean modifiedUser = this.authenticationService.modifyUser(userDn, directoryUser.getPassword(), directoryUser);
// Build JSONObject
JSONObject jsonObject = new JSONObject();
jsonObject.put("modifyUser", modifiedUser);
return jsonObject;
}
I am using following client method to access above REST webservice.
String url = "http://www.local.com:8080/CommonAuth-1.0-SNAPSHOT/api/authentication/modifyUser/";
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url + "user6.external")
JSONObject ob = new JSONObject();
ob.put("description", "updated");
System.out.println(ob.toString());
StringEntity entity = new StringEntity(ob.toString());
entity.setContentType("application/json");
httpPost.setEntity(entity);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
I always get "The server refused this request because the request entity is in a format not supported by the requested resource for the requested method" error. What is wrong in my code. I am able to access other webservice calls without using #RequestBody and using simple path variables. The issue is with #RequestBody and how i am using HttpPost.
public class DirectoryUser {
private String displayName;
private String fullName;
private String userName;
private String firstName;
private String lastName;
private String description;
private String country;
private String company;
private String phone;
private String emailAddress;
private String password;
private boolean expirePassword = true;
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isExpirePassword() {
return expirePassword;
}
public void setExpirePassword(boolean expirePassword) {
this.expirePassword = expirePassword;
}
}
JSON string i am posting is {"description":"updated"}
try {
/* your code */
if (httpResponse != null) {
InputStream in = httpResponse.getEntity().getContent();
StringBuffer out = new StringBuffer();
int n = 1;
while (n > 0) {
byte[] b = new byte[4096];
n = in.read(b);
if (n > 0)
out.append(new String(b, 0, n));
}
System.out.println(out.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
Can you check what the status code says? Also, please check if it is HTTPS.
By default Spring try to use Jackson for json marshall/unmarshall:
private static final boolean jackson2Present =
ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", WebMvcConfigurationSupport.class.getClassLoader()) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", WebMvcConfigurationSupport.class.getClassLoader());
you need to add Jackson libs to your project.

List Serialization and Deserialization by binary formatter

I have a class. I wanna serialize and the serialize a list that contains object of that class. I want to use binary formatter.
This is my class:
[Serializable]
public class Section :ISerializable
{
private double ClearCover;
private string SectionName;
private double Diameter;
public double Height;
private double Width;
private double InternalDiameter;
private double ExternalDiameter;
private double InternalHeight;
private double ExternalHeight;
private double InternalWidth;
private double ExternalWidth;
private double WebWidth;
private double FlangeWidth;
private double FlangeThickness;
public double clearCover
{
get { return ClearCover; }
set { ClearCover = value; }
}
public string sectionName
{
get{return SectionName;}
set{SectionName=value;}
}
public double diameter
{
get { return Diameter; }
set { Diameter = value; }
}
public double height
{
set { Height = value; }
get { return Height; }
}
public double width
{
set { Width = value; }
get { return Width; }
}
public double internalDiameter
{
set { InternalDiameter = value; }
get { return InternalDiameter; }
}
public double externalDiameter
{
set { ExternalDiameter = value; }
get { return ExternalDiameter; }
}
public double internalHeight
{
set { InternalHeight = value; }
get { return InternalHeight; }
}
public double externalHeight
{
set { ExternalHeight = value; }
get { return ExternalHeight; }
}
public double internalWidth
{
set { InternalWidth = value; }
get { return InternalWidth; }
}
public double externalWidth
{
set { ExternalWidth = value; }
get { return ExternalWidth; }
}
public double flangeWidth
{
set { FlangeWidth = value; }
get { return FlangeWidth; }
}
public double flangeThickness
{
set { FlangeThickness = value; }
get { return FlangeThickness; }
}
public double webWidth
{
set { WebWidth = value; }
get { return WebWidth; }
}
public Section() { }
protected Section(SerializationInfo info, StreamingContext context)
{
sectionName = info.GetString("Section Name");
clearCover = info.GetDouble("Clear Cover");
diameter = info.GetDouble("Diameter");
//internalDiameter = info.GetDouble("Internal Diameter");
//externalDiameter = info.GetDouble("External Diameter");
height = info.GetDouble("Height");
width = info.GetDouble("Width");
internalHeight = info.GetDouble("Internal Height");
externalHeight = info.GetDouble("External Height");
internalWidth = info.GetDouble("Internal Width");
externalWidth = info.GetDouble("External Width");
flangeWidth = info.GetDouble("Flange Width");
flangeThickness = info.GetDouble("Flange Thickness");
webWidth = info.GetDouble("Web Width");
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Section Name", sectionName);
info.AddValue("Clear Cover", clearCover);
info.AddValue("Diameter",diameter);
//info.AddValue("Internal Diameter", internalDiameter);
//info.AddValue("External Diameter", externalDiameter);
info.AddValue("Height",height);
info.AddValue("Width",width);
info.AddValue("Internal Height",internalHeight);
info.AddValue("External Height",externalHeight);
info.AddValue("Internal Width",internalWidth);
info.AddValue("External Width",externalWidth);
info.AddValue("Flange Width",flangeWidth);
info.AddValue("Flange Thickness", flangeThickness);
info.AddValue("Web Width", webWidth);
}
}
I don't have any problem in serialization. But for deserialize, it can just deserialize first object not all of them. What should I do, please help me!
From a separate email from the OP, the following methods were obtained (I've tidied them a little, not much):
static void Serialize(object obj, string filename)
{
using (FileStream streamOut = new FileStream(filename, FileMode.Append))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(streamOut, obj);
}
}
public static List<Section> DeserializeList(string filename)
{
using (FileStream streamIn = File.OpenRead(filename))
{
BinaryFormatter formatter = new BinaryFormatter();
return (List<Section>) formatter.Deserialize(streamIn);
}
}
The key observation here is that it is assuming that BinaryFormatter is an appendable format, and that serializing two objects sequentially is the same as serializing 2 items at the same time (a list), for example:
if(File.Exists("foo.bin")) File.Delete("foo.bin"); // start afresh
Serialize(new Section { Diameter = 1.2, ClearCover = 3.4 }, "foo.bin");
Serialize(new Section { Diameter = 5.6, ClearCover = 7.8 }, "foo.bin");
var clone = DeserializeList("foo.bin");
However, that simply is not the case. To deserialize the items in this way, we would have to do something like:
public static List<Section> DeserializeList(string filename)
{
using (FileStream streamIn = File.OpenRead(filename))
{
List<Section> list = new List<Section>();
BinaryFormatter formatter = new BinaryFormatter();
while(streamIn.Position != streamIn.Length)
{
list.Add((Section) formatter.Deserialize(streamIn));
}
return list;
}
}
which it a little vexing - not least because it can't be applied to all streams (.Length and even .Position are not universally available).
The above should work, but I would strongly advise using an appendable format, such as protobuf. In fact, protobuf-net makes this scenario effortless, both in terms of the model:
[ProtoContract]
public class Section
{
[ProtoMember(1)] public double ClearCover { get; set; }
[ProtoMember(2)] public string SectionName { get; set; }
[ProtoMember(3)] public double Diameter { get; set; }
[ProtoMember(4)] public double Height { get; set; }
[ProtoMember(5)] public double Width { get; set; }
[ProtoMember(6)] public double InternalDiameter { get; set; }
[ProtoMember(7)] public double ExternalDiameter { get; set; }
[ProtoMember(8)] public double InternalHeight { get; set; }
[ProtoMember(9)] public double ExternalHeight { get; set; }
[ProtoMember(10)] public double InternalWidth { get; set; }
[ProtoMember(11)] public double ExternalWidth { get; set; }
[ProtoMember(12)] public double FlangeWidth { get; set; }
[ProtoMember(13)] public double FlangeThickness { get; set; }
[ProtoMember(14)] public double WebWidth { get; set; }
}
and the serialization / deserialization:
static void Main()
{
if (File.Exists("foo.bin")) File.Delete("foo.bin"); // start afresh
Serialize(new Section { Diameter = 1.2, ClearCover = 3.4 }, "foo.bin");
Serialize(new Section { Diameter = 5.6, ClearCover = 7.8 }, "foo.bin");
var clone = DeserializeList("foo.bin");
}
static void Serialize(object obj, string filename)
{
using (FileStream streamOut = new FileStream(filename, FileMode.Append))
{
Serializer.NonGeneric.SerializeWithLengthPrefix(
streamOut, obj, PrefixStyle.Base128, Serializer.ListItemTag);
}
}
public static List<Section> DeserializeList(string filename)
{
using (FileStream streamIn = File.OpenRead(filename))
{
return Serializer.DeserializeItems<Section>(
streamIn, PrefixStyle.Base128, Serializer.ListItemTag).ToList();
}
}
Finally, the BinaryFormatter data for those 2 rows was 750 bytes; with protobuf-net: 40 bytes.

IList List is null in my Composition Class .. WHY?

I am usling IList List property to get a list of students class in University class .. as i try to access this list in department Class which is a part of university class .. the List is Null .. can anyone tell the reason?
namespace UniversitySystem
{
class University : CollectionBase
{
private string _uniName;
Departments _depart = new Departments();
public University(string un, string dn, string cp, List<Student> Slist)
{
this._uniName = un;
this.CED.DepartName = dn;
this.CED.ChairPerson = cp;
foreach (Student s in Slist)
{
List.Add(s);
}
}
#region properties
public string UniName
{
get { return _uniName; }
set { _uniName = value; }
}
public Departments CED
{
get { return _depart; }
set { _depart = value; }
}
#endregion
public class Departments : CollectionBase
{
private string _departName;
public string DepartName
{
get { return _departName; }
set { _departName = value; }
}
private string _chairPerson;
public string ChairPerson
{
get { return _chairPerson; }
set { _chairPerson = value; }
}
public List<Student> StudentListForCED = new List<Student>();
public Departments()
{
_departName = null;
_chairPerson = null;
StudentListForCED = null;
}
public Departments(string dn, string cp, List<Student> Slist)
{
this._departName = dn;
this._chairPerson = cp;
foreach (Student s in Slist)
{
List.Add(s);
}
}
public void showDetails()
{
Console.WriteLine("Departmental Info");
Console.WriteLine("DepartmentName: " + _departName);
Console.WriteLine("Chairperson Name: " + _chairPerson);
Console.WriteLine("Student Info:");
foreach (Student item in List)
{
Console.WriteLine("Name: " + item.Name);
Console.WriteLine("deptName: " + item.RegNo);
Console.WriteLine("total marks: " + item.TotalMarksObtained);
Console.WriteLine("percentage: " + item.GetPercentage());
}
}
}
}
}
THE main() part is
namespace UniversitySystem
{
class Program
{
static void Main(string[] args)
{
List<Student> slist = new List<Student>();
slist.Add(new Student("sana", 1234, "CIS", 650));
slist.Add(new Student("anam", 2345, "BCIT", 400));
slist.Add(new Student("fizzza", 2670, "Electrical", 670));
University u1 = new University("NED", "computer", "UKP", slist);
Console.WriteLine(u1.CED.DepartName);
u1.CED.showDetails();
}
}
}
The initializing code for University does not store the list you give it as a parameter.
try storing the list in a variable in either the department or the university object itself, and when you are showing the details for either of those object you can reference that list, the one you stored upon creating the object.
Hope that helps!
I made a couple changes that should work.
public Departments(string dn, string cp, List<Student> Slist)
{
this._departName = dn;
this._chairPerson = cp;
foreach (Student s in Slist)
{
StudentListForCED.Add(s);
}
}
public void showDetails()
{
Console.WriteLine("Departmental Info");
Console.WriteLine("DepartmentName: " + _departName);
Console.WriteLine("Chairperson Name: " + _chairPerson);
Console.WriteLine("Student Info:");
foreach (Student item in StudentListForCED)
{
Console.WriteLine("Name: " + item.Name);
Console.WriteLine("deptName: " + item.RegNo);
Console.WriteLine("total marks: " + item.TotalMarksObtained);
Console.WriteLine("percentage: " + item.GetPercentage());
}
}
Please read this a little more thoroughly.